From 405add1fe0241e3b4e1093dec20f01c2c58a35b8 Mon Sep 17 00:00:00 2001 From: Philip Kheav Date: Thu, 5 Nov 2020 14:12:10 +0000 Subject: [PATCH 1/7] feat(gc): initial commit --- drivers/global_cache/gc_100.cr | 66 +++++++++++++++++++++++++++++ drivers/global_cache/gc_100_spec.cr | 2 + 2 files changed, 68 insertions(+) create mode 100644 drivers/global_cache/gc_100.cr create mode 100644 drivers/global_cache/gc_100_spec.cr diff --git a/drivers/global_cache/gc_100.cr b/drivers/global_cache/gc_100.cr new file mode 100644 index 00000000000..b266da17b05 --- /dev/null +++ b/drivers/global_cache/gc_100.cr @@ -0,0 +1,66 @@ +class GlobalCache::Gc100 < PlaceOS::Driver + # Discovery Information + tcp_port 4999 + descriptive_name "GlobalCache IO Gateway" + generic_name :DigitalIO + + DELIMITER = 0x0D_u8 + + def on_load + transport.tokenizer = Tokenizer.new(Bytes[DELIMITER]) + self[:num_relays] = 0 + self[:num_ir] = 0 + # For testing + self[:config] = { + relay: { + 0 => "2:1", + 1 => "2:2", + 2 => "2:3", + 3 => "3:1" + } + } + end + + def connected + end + + def disconnected + schedule.clear + end + + def received(data, task) + end + + def get_devices + do_send("getdevices")#, :max_waits => 100) + end + + def relay(index : Int32, state : Bool, **options) + if index < self[:num_relays].as_i + relays = self[:config]["relay"] || self[:config]["relaysensor"] + connector = relays[index] + do_send("setstate,#{connector},#{state ? 1 : 0}", **options) + else + logger.warn { "Attempted to set relay on GlobalCache that does not exist: #{index}" } + end + end + + def ir(index : Int32, command : String, **options) + do_send("sendir,1:#{index},#{command}", **options) + end + + def set_ir(index : Int32, mode : Int32, **options) + if index < self[:num_ir].as_i + connector = self[:config]["ir"][index] + do_send("set_IR,#{connector},#{mode}", **options) + else + logger.warn { "Attempted to set IR mode on GlobalCache that does not exist: #{index}" } + end + end + + private def do_send(command : String, **options) + logger.debug { "-- GlobalCache, sending: #{command}" } + command = "#{command}#{DELIMITER}" + send(command, **options) + end +end diff --git a/drivers/global_cache/gc_100_spec.cr b/drivers/global_cache/gc_100_spec.cr new file mode 100644 index 00000000000..35199ae5211 --- /dev/null +++ b/drivers/global_cache/gc_100_spec.cr @@ -0,0 +1,2 @@ +DriverSpecs.mock_driver "GlobalCache::Gc100" do +end From f42459b246929ab91da52559596d9506da9ba931 Mon Sep 17 00:00:00 2001 From: Philip Kheav Date: Thu, 5 Nov 2020 17:39:53 +0000 Subject: [PATCH 2/7] fix(gc): get code to compile --- drivers/global_cache/gc_100.cr | 124 ++++++++++++++++++++++++++-- drivers/global_cache/gc_100_spec.cr | 1 + 2 files changed, 116 insertions(+), 9 deletions(-) diff --git a/drivers/global_cache/gc_100.cr b/drivers/global_cache/gc_100.cr index b266da17b05..d6b9439f216 100644 --- a/drivers/global_cache/gc_100.cr +++ b/drivers/global_cache/gc_100.cr @@ -6,40 +6,51 @@ class GlobalCache::Gc100 < PlaceOS::Driver DELIMITER = 0x0D_u8 + @config : Hash(String, Hash(Int32, String) | Array(Int32 | String)) = {} of String => Hash(Int32, String) | Array(Int32 | String) + def on_load transport.tokenizer = Tokenizer.new(Bytes[DELIMITER]) self[:num_relays] = 0 self[:num_ir] = 0 # For testing self[:config] = { - relay: { + "relay" => { 0 => "2:1", 1 => "2:2", 2 => "2:3", - 3 => "3:1" + 3 => "3:1", } } end + # Config maps the GC100 into a linear set of ir and relays so models can be swapped in and out + # config => {:relay => {0 => '2:1',1 => '2:2',2 => '2:3',3 => '3:1'}} etc def connected + @config = {} of String => Hash(Int32, String) | Array(Int32 | String) + self[:config_indexed] = false + + schedule.every(10.seconds, true) do + logger.debug { "-- Polling GC100" } + get_devices unless self[:config_indexed].as_bool + + # Low priority sent to maintain the connection + do_send("get_NET,0:1", priority: 0) + end end def disconnected schedule.clear end - def received(data, task) - end - def get_devices - do_send("getdevices")#, :max_waits => 100) + do_send("getdevices") # , :max_waits => 100) end def relay(index : Int32, state : Bool, **options) if index < self[:num_relays].as_i - relays = self[:config]["relay"] || self[:config]["relaysensor"] - connector = relays[index] - do_send("setstate,#{connector},#{state ? 1 : 0}", **options) + relays = self[:config]["relay"] || self[:config]["relaysensor"] + connector = relays[index] + do_send("setstate,#{connector},#{state ? 1 : 0}", **options) else logger.warn { "Attempted to set relay on GlobalCache that does not exist: #{index}" } end @@ -58,6 +69,101 @@ class GlobalCache::Gc100 < PlaceOS::Driver end end + def relay_status?(index : Int32, **options, &block) + if index < self[:num_relays].as_i + connector = self[:config]["relay"][index] + options[:emit] = block if block_given? + do_send("getstate,#{connector}", options) + else + logger.warn "Attempted to check IO on GlobalCache that does not exist: #{index}" + end + end + + def io_status?(index : Int32, **options, &block) + if index < self[:num_ir].to_i + connector = self[:config]["ir"][index] + options[:emit] = block if block_given? + do_send("getstate,#{connector}", options) + else + logger.warn "Attempted to check IO on GlobalCache that does not exist: #{index}" + end + end + + def received(data, task) + data = String.new(data) + logger.debug { "GlobalCache sent #{data}" } + data = data.split(',') + task_name = task.try &.name + + case data[0] + when "state", "statechange" + type, index = self["config"][data[1]] + self["#{type}#{index}"] = data[2] == '1' # Is relay index on? + when "device" + address = data[1] + number, type = data[2].split(' ') # The response was "device,2,3 RELAY" + + type = type.downcase + + value = @config || {} of String => Hash(Int32, String) | Array(Int32 | String) + value[type] = value[type] || {} of Int32 => String + current = value[type].size + + dev_index = 1 + (current..(current + number.to_i - 1)).each do |i| + port = "#{address}:#{dev_index}" + value[type][i] = port + value[port] = [type, i] + dev_index += 1 + end + @config = value + + # return :ignore + return + when "endlistdevices" + self[:num_relays] = @config["relay"].size if @config["relay"]? + if @config["relaysensor"] + @config["relaysensor"][1] = "1:2" + @config["relaysensor"][2] = "1:3" + @config["relaysensor"][3] = "1:4" + self[:num_relays] = @config["relaysensor"].size + end + self[:num_ir] = @config["ir"].size if @config["ir"]? + self[:config] = @config + @config = {} of String => Hash(Int32, String) | Array(Int32 | String) + self[:config_indexed] = true + + return task.try &.success + end + + if data.size == 1 + error = case data[0].split(' ')[1].to_i + when 1 then "Command was missing the carriage return delimiter" + when 2 then "Invalid module address when looking for version" + when 3 then "Invalid module address" + when 4 then "Invalid connector address" + when 5 then "Connector address 1 is set up as \"sensor in\" when attempting to send an IR command" + when 6 then "Connector address 2 is set up as \"sensor in\" when attempting to send an IR command" + when 7 then "Connector address 3 is set up as \"sensor in\" when attempting to send an IR command" + when 8 then "Offset is set to an even transition number, but should be set to an odd transition number in the IR command" + when 9 then "Maximum number of transitions exceeded (256 total on/off transitions allowed)" + when 10 then "Number of transitions in the IR command is not even (the same number of on and off transitions is required)" + when 11 then "Contact closure command sent to a module that is not a relay" + when 12 then "Missing carriage return. All commands must end with a carriage return" + when 13 then "State was requested of an invalid connector address, or the connector is programmed as IR out and not sensor in." + when 14 then "Command sent to the unit is not supported by the GC-100" + when 15 then "Maximum number of IR transitions exceeded" + when 16 then "Invalid number of IR transitions (must be an even number)" + when 21 then "Attempted to send an IR command to a non-IR module" + when 23 then "Command sent is not supported by this type of module" + else "Unknown error" + end + return task.try &.abort("GlobalCache error for command #{task_name}: #{error}") + end + + task.try &.success + end + private def do_send(command : String, **options) logger.debug { "-- GlobalCache, sending: #{command}" } command = "#{command}#{DELIMITER}" diff --git a/drivers/global_cache/gc_100_spec.cr b/drivers/global_cache/gc_100_spec.cr index 35199ae5211..7ca23c8d952 100644 --- a/drivers/global_cache/gc_100_spec.cr +++ b/drivers/global_cache/gc_100_spec.cr @@ -1,2 +1,3 @@ DriverSpecs.mock_driver "GlobalCache::Gc100" do + exec(:get_devices) end From 28382de50d4896ec7af83cf849079448ced1fb6f Mon Sep 17 00:00:00 2001 From: Philip Kheav Date: Fri, 6 Nov 2020 14:41:31 +0000 Subject: [PATCH 3/7] fix(gc): remove delimiter --- drivers/global_cache/gc_100.cr | 41 ++++++++++++++++------------- drivers/global_cache/gc_100_spec.cr | 6 ++++- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/drivers/global_cache/gc_100.cr b/drivers/global_cache/gc_100.cr index d6b9439f216..b34c0a52868 100644 --- a/drivers/global_cache/gc_100.cr +++ b/drivers/global_cache/gc_100.cr @@ -4,12 +4,12 @@ class GlobalCache::Gc100 < PlaceOS::Driver descriptive_name "GlobalCache IO Gateway" generic_name :DigitalIO - DELIMITER = 0x0D_u8 + DELIMITER = "\r" - @config : Hash(String, Hash(Int32, String) | Array(Int32 | String)) = {} of String => Hash(Int32, String) | Array(Int32 | String) + @gc_config : Hash(String, Hash(Int32, String) | Array(Int32 | String)) = {} of String => Hash(Int32, String) | Array(Int32 | String) def on_load - transport.tokenizer = Tokenizer.new(Bytes[DELIMITER]) + transport.tokenizer = Tokenizer.new(DELIMITER) self[:num_relays] = 0 self[:num_ir] = 0 # For testing @@ -26,9 +26,11 @@ class GlobalCache::Gc100 < PlaceOS::Driver # Config maps the GC100 into a linear set of ir and relays so models can be swapped in and out # config => {:relay => {0 => '2:1',1 => '2:2',2 => '2:3',3 => '3:1'}} etc def connected - @config = {} of String => Hash(Int32, String) | Array(Int32 | String) + @gc_config = {} of String => Hash(Int32, String) | Array(Int32 | String) self[:config_indexed] = false + logger.debug { "config indexed = #{self[:config_indexed]}" } + schedule.every(10.seconds, true) do logger.debug { "-- Polling GC100" } get_devices unless self[:config_indexed].as_bool @@ -90,7 +92,8 @@ class GlobalCache::Gc100 < PlaceOS::Driver end def received(data, task) - data = String.new(data) + # Remove the delimiter + data = String.new(data[0..-2]) logger.debug { "GlobalCache sent #{data}" } data = data.split(',') task_name = task.try &.name @@ -105,8 +108,8 @@ class GlobalCache::Gc100 < PlaceOS::Driver type = type.downcase - value = @config || {} of String => Hash(Int32, String) | Array(Int32 | String) - value[type] = value[type] || {} of Int32 => String + value = @gc_config || {} of String => Hash(Int32, String) | Array(Int32 | String) + value[type] ||= {} of Int32 => String current = value[type].size dev_index = 1 @@ -116,21 +119,21 @@ class GlobalCache::Gc100 < PlaceOS::Driver value[port] = [type, i] dev_index += 1 end - @config = value + @gc_config = value + logger.debug { "config is #{@gc_config}" } - # return :ignore - return + return task.try &.success when "endlistdevices" - self[:num_relays] = @config["relay"].size if @config["relay"]? - if @config["relaysensor"] - @config["relaysensor"][1] = "1:2" - @config["relaysensor"][2] = "1:3" - @config["relaysensor"][3] = "1:4" - self[:num_relays] = @config["relaysensor"].size + self[:num_relays] = @gc_config["relay"].size if @gc_config["relay"]? + if @gc_config["relaysensor"] + @gc_config["relaysensor"][1] = "1:2" + @gc_config["relaysensor"][2] = "1:3" + @gc_config["relaysensor"][3] = "1:4" + self[:num_relays] = @gc_config["relaysensor"].size end - self[:num_ir] = @config["ir"].size if @config["ir"]? - self[:config] = @config - @config = {} of String => Hash(Int32, String) | Array(Int32 | String) + self[:num_ir] = @gc_config["ir"].size if @gc_config["ir"]? + self[:config] = @gc_config + @gc_config = {} of String => Hash(Int32, String) | Array(Int32 | String) self[:config_indexed] = true return task.try &.success diff --git a/drivers/global_cache/gc_100_spec.cr b/drivers/global_cache/gc_100_spec.cr index 7ca23c8d952..0b7d23feca4 100644 --- a/drivers/global_cache/gc_100_spec.cr +++ b/drivers/global_cache/gc_100_spec.cr @@ -1,3 +1,7 @@ DriverSpecs.mock_driver "GlobalCache::Gc100" do - exec(:get_devices) + # connected + # get_devices + should_send("getdevices\r") + responds("device,2,3 RELAY\r") + should_send("get_NET,0:1\r") end From c5028a49fba4b3d509492b11fc1bc00eb02a5f4a Mon Sep 17 00:00:00 2001 From: Philip Kheav Date: Fri, 6 Nov 2020 15:41:02 +0000 Subject: [PATCH 4/7] fix(gc): split relay and port config --- drivers/global_cache/gc_100.cr | 72 +++++++++++++---------------- drivers/global_cache/gc_100_spec.cr | 3 ++ 2 files changed, 35 insertions(+), 40 deletions(-) diff --git a/drivers/global_cache/gc_100.cr b/drivers/global_cache/gc_100.cr index b34c0a52868..3d46567c7a8 100644 --- a/drivers/global_cache/gc_100.cr +++ b/drivers/global_cache/gc_100.cr @@ -6,31 +6,23 @@ class GlobalCache::Gc100 < PlaceOS::Driver DELIMITER = "\r" - @gc_config : Hash(String, Hash(Int32, String) | Array(Int32 | String)) = {} of String => Hash(Int32, String) | Array(Int32 | String) + @relay_config : Hash(String, Hash(Int32, String)) = {} of String => Hash(Int32, String) + @port_config : Hash(String, Tuple(String, Int32)) = {} of String => Tuple(String, Int32) def on_load transport.tokenizer = Tokenizer.new(DELIMITER) self[:num_relays] = 0 self[:num_ir] = 0 - # For testing - self[:config] = { - "relay" => { - 0 => "2:1", - 1 => "2:2", - 2 => "2:3", - 3 => "3:1", - } - } end - # Config maps the GC100 into a linear set of ir and relays so models can be swapped in and out - # config => {:relay => {0 => '2:1',1 => '2:2',2 => '2:3',3 => '3:1'}} etc + # @relay_config maps the GC100 into a linear set of ir and relays so models can be swapped in and out + # Example + # @relay_config = {"relay" => {0 => '2:1',1 => '2:2',2 => '2:3',3 => '3:1'}} def connected - @gc_config = {} of String => Hash(Int32, String) | Array(Int32 | String) + @relay_config = {} of String => Hash(Int32, String) + @port_config = {} of String => Tuple(String, Int32) self[:config_indexed] = false - logger.debug { "config indexed = #{self[:config_indexed]}" } - schedule.every(10.seconds, true) do logger.debug { "-- Polling GC100" } get_devices unless self[:config_indexed].as_bool @@ -50,8 +42,9 @@ class GlobalCache::Gc100 < PlaceOS::Driver def relay(index : Int32, state : Bool, **options) if index < self[:num_relays].as_i - relays = self[:config]["relay"] || self[:config]["relaysensor"] - connector = relays[index] + logger.debug { "relays = #{(self[:relay_config]["relay"]? || self[:relay_config]["relaysensor"]?).not_nil!}" } + relays = (self[:relay_config]["relay"]? || self[:relay_config]["relaysensor"]?).not_nil!.as_h + connector = relays[index.to_s] do_send("setstate,#{connector},#{state ? 1 : 0}", **options) else logger.warn { "Attempted to set relay on GlobalCache that does not exist: #{index}" } @@ -64,7 +57,7 @@ class GlobalCache::Gc100 < PlaceOS::Driver def set_ir(index : Int32, mode : Int32, **options) if index < self[:num_ir].as_i - connector = self[:config]["ir"][index] + connector = self[:relay_config]["ir"][index] do_send("set_IR,#{connector},#{mode}", **options) else logger.warn { "Attempted to set IR mode on GlobalCache that does not exist: #{index}" } @@ -73,7 +66,7 @@ class GlobalCache::Gc100 < PlaceOS::Driver def relay_status?(index : Int32, **options, &block) if index < self[:num_relays].as_i - connector = self[:config]["relay"][index] + connector = self[:relay_config]["relay"][index] options[:emit] = block if block_given? do_send("getstate,#{connector}", options) else @@ -83,7 +76,7 @@ class GlobalCache::Gc100 < PlaceOS::Driver def io_status?(index : Int32, **options, &block) if index < self[:num_ir].to_i - connector = self[:config]["ir"][index] + connector = self[:relay_config]["ir"][index] options[:emit] = block if block_given? do_send("getstate,#{connector}", options) else @@ -96,7 +89,7 @@ class GlobalCache::Gc100 < PlaceOS::Driver data = String.new(data[0..-2]) logger.debug { "GlobalCache sent #{data}" } data = data.split(',') - task_name = task.try &.name + task_name = task.try &.name || "unknown" case data[0] when "state", "statechange" @@ -108,32 +101,31 @@ class GlobalCache::Gc100 < PlaceOS::Driver type = type.downcase - value = @gc_config || {} of String => Hash(Int32, String) | Array(Int32 | String) - value[type] ||= {} of Int32 => String - current = value[type].size + @relay_config[type] ||= {} of Int32 => String + current = @relay_config[type].size - dev_index = 1 - (current..(current + number.to_i - 1)).each do |i| + (current..(current + number.to_i - 1)).each_with_index(1) do |i, dev_index| port = "#{address}:#{dev_index}" - value[type][i] = port - value[port] = [type, i] - dev_index += 1 + @relay_config[type][i] = port + @port_config[port] = {type, i} end - @gc_config = value - logger.debug { "config is #{@gc_config}" } return task.try &.success when "endlistdevices" - self[:num_relays] = @gc_config["relay"].size if @gc_config["relay"]? - if @gc_config["relaysensor"] - @gc_config["relaysensor"][1] = "1:2" - @gc_config["relaysensor"][2] = "1:3" - @gc_config["relaysensor"][3] = "1:4" - self[:num_relays] = @gc_config["relaysensor"].size + self[:num_relays] = @relay_config["relay"].size if @relay_config["relay"]? + if @relay_config["relaysensor"]? + @relay_config["relaysensor"][1] = "1:2" + @relay_config["relaysensor"][2] = "1:3" + @relay_config["relaysensor"][3] = "1:4" + self[:num_relays] = @relay_config["relaysensor"].size end - self[:num_ir] = @gc_config["ir"].size if @gc_config["ir"]? - self[:config] = @gc_config - @gc_config = {} of String => Hash(Int32, String) | Array(Int32 | String) + self[:num_ir] = @relay_config["ir"].size if @relay_config["ir"]? + self[:relay_config] = @relay_config + self[:port_config] = @port_config + logger.debug { "self[:relay_config] is #{self[:relay_config]}" } + logger.debug { "self[:port_config] is #{self[:port_config]}" } + @relay_config = {} of String => Hash(Int32, String) + @port_config = {} of String => Tuple(String, Int32) self[:config_indexed] = true return task.try &.success diff --git a/drivers/global_cache/gc_100_spec.cr b/drivers/global_cache/gc_100_spec.cr index 0b7d23feca4..5fdfeb657d1 100644 --- a/drivers/global_cache/gc_100_spec.cr +++ b/drivers/global_cache/gc_100_spec.cr @@ -3,5 +3,8 @@ DriverSpecs.mock_driver "GlobalCache::Gc100" do # get_devices should_send("getdevices\r") responds("device,2,3 RELAY\r") + responds("endlistdevices\r") should_send("get_NET,0:1\r") + + exec(:relay, 1, true) end From ac96926cc3dd1241f3cf77825d7f779ac80714ac Mon Sep 17 00:00:00 2001 From: Philip Kheav Date: Fri, 6 Nov 2020 16:28:56 +0000 Subject: [PATCH 5/7] feat(gc): add more specs --- drivers/global_cache/gc_100.cr | 21 +++++++++++++-------- drivers/global_cache/gc_100_spec.cr | 20 ++++++++++++++++++++ 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/drivers/global_cache/gc_100.cr b/drivers/global_cache/gc_100.cr index 3d46567c7a8..a1c2e8913dc 100644 --- a/drivers/global_cache/gc_100.cr +++ b/drivers/global_cache/gc_100.cr @@ -6,6 +6,8 @@ class GlobalCache::Gc100 < PlaceOS::Driver DELIMITER = "\r" + # @relay_config maps the GC100 into a linear set of ir and relays so models can be swapped in and out + # E.g. @relay_config = {"relay" => {0 => "2:1",1 => "2:2",2 => "2:3",3 => "3:1"}} @relay_config : Hash(String, Hash(Int32, String)) = {} of String => Hash(Int32, String) @port_config : Hash(String, Tuple(String, Int32)) = {} of String => Tuple(String, Int32) @@ -15,9 +17,6 @@ class GlobalCache::Gc100 < PlaceOS::Driver self[:num_ir] = 0 end - # @relay_config maps the GC100 into a linear set of ir and relays so models can be swapped in and out - # Example - # @relay_config = {"relay" => {0 => '2:1',1 => '2:2',2 => '2:3',3 => '3:1'}} def connected @relay_config = {} of String => Hash(Int32, String) @port_config = {} of String => Tuple(String, Int32) @@ -42,8 +41,8 @@ class GlobalCache::Gc100 < PlaceOS::Driver def relay(index : Int32, state : Bool, **options) if index < self[:num_relays].as_i - logger.debug { "relays = #{(self[:relay_config]["relay"]? || self[:relay_config]["relaysensor"]?).not_nil!}" } relays = (self[:relay_config]["relay"]? || self[:relay_config]["relaysensor"]?).not_nil!.as_h + logger.debug { "relays = #{relays}" } connector = relays[index.to_s] do_send("setstate,#{connector},#{state ? 1 : 0}", **options) else @@ -55,9 +54,15 @@ class GlobalCache::Gc100 < PlaceOS::Driver do_send("sendir,1:#{index},#{command}", **options) end - def set_ir(index : Int32, mode : Int32, **options) + enum IrMode + IR + SENSOR + SENSOR_NOTIFY + IR_NOCARRIER + end + def set_ir(index : Int32, mode : IrMode, **options) if index < self[:num_ir].as_i - connector = self[:relay_config]["ir"][index] + connector = self[:relay_config]["ir"][index.to_s] do_send("set_IR,#{connector},#{mode}", **options) else logger.warn { "Attempted to set IR mode on GlobalCache that does not exist: #{index}" } @@ -93,8 +98,8 @@ class GlobalCache::Gc100 < PlaceOS::Driver case data[0] when "state", "statechange" - type, index = self["config"][data[1]] - self["#{type}#{index}"] = data[2] == '1' # Is relay index on? + type, index = self[:port_config][data[1]] + self["#{type}#{index}"] = data[2] == "1" # Is relay index on? when "device" address = data[1] number, type = data[2].split(' ') # The response was "device,2,3 RELAY" diff --git a/drivers/global_cache/gc_100_spec.cr b/drivers/global_cache/gc_100_spec.cr index 5fdfeb657d1..bf172dcdac8 100644 --- a/drivers/global_cache/gc_100_spec.cr +++ b/drivers/global_cache/gc_100_spec.cr @@ -3,8 +3,28 @@ DriverSpecs.mock_driver "GlobalCache::Gc100" do # get_devices should_send("getdevices\r") responds("device,2,3 RELAY\r") + responds("device,1,2 RELAYSENSOR\r") + responds("device,3,1 IR\r") responds("endlistdevices\r") should_send("get_NET,0:1\r") + status[:relay_config].should eq({ + "relay" => {"0" => "2:1", "1" => "2:2", "2" => "2:3"}, + "relaysensor" => {"0" => "1:1", "1" => "1:2", "2" => "1:3", "3" => "1:4"}, + "ir" => {"0" => "3:1"} + }) + status[:port_config].should eq({ + "2:1" => ["relay", 0], "2:2" => ["relay", 1], "2:3" => ["relay", 2], "1:1" => ["relaysensor", 0], "1:2" => ["relaysensor", 1], "3:1" => ["ir", 0] + }) exec(:relay, 1, true) + should_send("setstate,2:2,1\r") + responds("state,2:2,1\r") + status[:relay1].should eq(true) + + exec(:ir, 0, "4444") + should_send("sendir,1:0,4444\r") + responds("completeir,1:0,4444\r") + + exec(:set_ir, 0, "ir") + should_send("set_IR,3:1,IR\r") end From e636f14ca1651232a9d8853e202a0acc74955c1d Mon Sep 17 00:00:00 2001 From: Philip Kheav Date: Fri, 6 Nov 2020 17:12:24 +0000 Subject: [PATCH 6/7] feat(gc): add specs for all methods --- drivers/global_cache/gc_100.cr | 20 +++++++++----------- drivers/global_cache/gc_100_spec.cr | 11 +++++++++++ 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/global_cache/gc_100.cr b/drivers/global_cache/gc_100.cr index a1c2e8913dc..ef3c6909caf 100644 --- a/drivers/global_cache/gc_100.cr +++ b/drivers/global_cache/gc_100.cr @@ -69,23 +69,21 @@ class GlobalCache::Gc100 < PlaceOS::Driver end end - def relay_status?(index : Int32, **options, &block) + def relay_status?(index : Int32, **options) if index < self[:num_relays].as_i - connector = self[:relay_config]["relay"][index] - options[:emit] = block if block_given? - do_send("getstate,#{connector}", options) + connector = self[:relay_config]["relay"][index.to_s] + do_send("getstate,#{connector}", **options) else - logger.warn "Attempted to check IO on GlobalCache that does not exist: #{index}" + logger.warn { "Attempted to check IO on GlobalCache that does not exist: #{index}" } end end - def io_status?(index : Int32, **options, &block) - if index < self[:num_ir].to_i - connector = self[:relay_config]["ir"][index] - options[:emit] = block if block_given? - do_send("getstate,#{connector}", options) + def ir_status?(index : Int32, **options) + if index < self[:num_ir].as_i + connector = self[:relay_config]["ir"][index.to_s] + do_send("getstate,#{connector}", **options) else - logger.warn "Attempted to check IO on GlobalCache that does not exist: #{index}" + logger.warn { "Attempted to check IO on GlobalCache that does not exist: #{index}" } end end diff --git a/drivers/global_cache/gc_100_spec.cr b/drivers/global_cache/gc_100_spec.cr index bf172dcdac8..5b8c08f6110 100644 --- a/drivers/global_cache/gc_100_spec.cr +++ b/drivers/global_cache/gc_100_spec.cr @@ -27,4 +27,15 @@ DriverSpecs.mock_driver "GlobalCache::Gc100" do exec(:set_ir, 0, "ir") should_send("set_IR,3:1,IR\r") + responds("TODO 1\r") + + exec(:relay_status?, 2) + should_send("getstate,2:3\r") + responds("state,2:3,0\r") + status[:relay2].should eq(false) + + exec(:ir_status?, 0) + should_send("getstate,3:1\r") + responds("state,3:1,1\r") + status[:ir0].should eq(true) end From 5b8107ead38b30ff3994898a314e0721fb706bad Mon Sep 17 00:00:00 2001 From: Stephen von Takach Date: Tue, 23 Feb 2021 15:27:32 +1100 Subject: [PATCH 7/7] fix(global cache gc100 spec): requires delay before testing values --- drivers/global_cache/gc_100.cr | 1 + drivers/global_cache/gc_100_spec.cr | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/global_cache/gc_100.cr b/drivers/global_cache/gc_100.cr index ef3c6909caf..3541b414713 100644 --- a/drivers/global_cache/gc_100.cr +++ b/drivers/global_cache/gc_100.cr @@ -60,6 +60,7 @@ class GlobalCache::Gc100 < PlaceOS::Driver SENSOR_NOTIFY IR_NOCARRIER end + def set_ir(index : Int32, mode : IrMode, **options) if index < self[:num_ir].as_i connector = self[:relay_config]["ir"][index.to_s] diff --git a/drivers/global_cache/gc_100_spec.cr b/drivers/global_cache/gc_100_spec.cr index 5b8c08f6110..bc38de8280a 100644 --- a/drivers/global_cache/gc_100_spec.cr +++ b/drivers/global_cache/gc_100_spec.cr @@ -7,13 +7,16 @@ DriverSpecs.mock_driver "GlobalCache::Gc100" do responds("device,3,1 IR\r") responds("endlistdevices\r") should_send("get_NET,0:1\r") + + sleep 1 + status[:relay_config].should eq({ - "relay" => {"0" => "2:1", "1" => "2:2", "2" => "2:3"}, + "relay" => {"0" => "2:1", "1" => "2:2", "2" => "2:3"}, "relaysensor" => {"0" => "1:1", "1" => "1:2", "2" => "1:3", "3" => "1:4"}, - "ir" => {"0" => "3:1"} + "ir" => {"0" => "3:1"}, }) status[:port_config].should eq({ - "2:1" => ["relay", 0], "2:2" => ["relay", 1], "2:3" => ["relay", 2], "1:1" => ["relaysensor", 0], "1:2" => ["relaysensor", 1], "3:1" => ["ir", 0] + "2:1" => ["relay", 0], "2:2" => ["relay", 1], "2:3" => ["relay", 2], "1:1" => ["relaysensor", 0], "1:2" => ["relaysensor", 1], "3:1" => ["ir", 0], }) exec(:relay, 1, true)