waterfurnace_aurora 0.3.3 → 0.3.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c3127c610617c1008b2de42b4b03fc89867d12233548fc0baf6ea0ebb5ea08e8
4
- data.tar.gz: '0190fccfece31159a9c5acdd14b648521c32e7b64f7cb596daeb3548b882393a'
3
+ metadata.gz: beb1fa2f6415ac6723e0725460e8fbc6f5c8f04c76848034821176ce834f2cf3
4
+ data.tar.gz: 7a697e8d8bcf8b2abf83bf13c7294498947653f4b4237ede075d1bf01b338bc1
5
5
  SHA512:
6
- metadata.gz: 5d8ae25889bcea9d6f6e7adfe8e242da729bc5172102688d4790c20a594e094f2aa27c78dfc7104895109bf4dc1636e357e6a03f60cb20918085f95fb8059211
7
- data.tar.gz: 72682b009c4f19ff335d1b19759ccd813130148e9d5cfabfb9c915c88a497dbcc3290b2a36e1ef173e513843fd9e19827080236c092fd311618f88ac128e3de4
6
+ metadata.gz: 4a15073444778a08e9e46c8bedfaf957c7e055d11202e767d592439dfc8ae71f436d89550649a1e6040264e4a81c7189464fa6f9b3e2dc50fe4581a6368d950d
7
+ data.tar.gz: 722b3a899a1626458dc31c9b0345e85ea64d9e80cd8b40fd5cb6f64241f74752938123eee8b841259496803e6b12643eb014e25b737798aa2e198867e0b37d88
data/exe/aurora_fetch CHANGED
@@ -7,20 +7,23 @@ require "uri"
7
7
 
8
8
  uri = URI.parse(ARGV[0])
9
9
 
10
- args = if uri.scheme == "telnet" || uri.scheme == "rfc2217"
10
+ args = case uri.scheme
11
+ when "tcp"
12
+ require "socket"
13
+ [TCPSocket.new(uri.host, uri.port)]
14
+ when "telnet", "rfc2217"
11
15
  require "net/telnet/rfc2217"
12
- [Net::Telnet::RFC2217.new("Host" => uri.host,
13
- "Port" => uri.port || 23,
14
- "baud" => 19_200,
15
- "parity" => Net::Telnet::RFC2217::EVEN)]
16
+ [Net::Telnet::RFC2217.new(uri.host,
17
+ port: uri.port || 23,
18
+ baud: 19_200,
19
+ parity: :even)]
16
20
  else
17
21
  [CCutrer::SerialPort.new(uri.path, baud: 19_200, parity: :even)]
18
22
  end
19
23
 
20
24
  client = ModBus::RTUClient.new(*args)
21
- client.logger = Logger.new($stdout, :debug)
22
25
  slave = client.with_slave(1)
26
+ abc = Aurora::ABCClient.new(slave)
27
+ registers = abc.query_registers(ARGV[1])
23
28
 
24
- registers = slave.holding_registers[ARGV[1].to_i]
25
-
26
- puts registers.inspect
29
+ puts Aurora.print_registers(registers)
data/exe/aurora_mock CHANGED
@@ -8,12 +8,16 @@ require "yaml"
8
8
 
9
9
  uri = URI.parse(ARGV[0])
10
10
 
11
- args = if uri.scheme == "telnet" || uri.scheme == "rfc2217"
11
+ args = case uri.scheme
12
+ when "tcp"
13
+ require "socket"
14
+ [TCPSocket.new(uri.host, uri.port)]
15
+ when "telnet", "rfc2217"
12
16
  require "net/telnet/rfc2217"
13
- [Net::Telnet::RFC2217.new("Host" => uri.host,
14
- "Port" => uri.port || 23,
15
- "baud" => 19_200,
16
- "parity" => Net::Telnet::RFC2217::EVEN)]
17
+ [Net::Telnet::RFC2217.new(uri.host,
18
+ port: uri.port || 23,
19
+ baud: 19_200,
20
+ parity: :even)]
17
21
  else
18
22
  [CCutrer::SerialPort.new(uri.path, baud: 19_200, parity: :even)]
19
23
  end
data/exe/aurora_monitor CHANGED
@@ -36,12 +36,16 @@ last_registers = {}
36
36
  SENSOR_REGISTERS = [16, 19, 20, 740, 900, 1109, 1105, 1106, 1107, 1108, 1110, 1111, 1114, 1117, 1134, 1147, 1149, 1151,
37
37
  1153, 1165].freeze
38
38
 
39
- args = if uri.scheme == "telnet" || uri.scheme == "rfc2217"
39
+ args = case uri.scheme
40
+ when "tcp"
41
+ require "socket"
42
+ [TCPSocket.new(uri.host, uri.port)]
43
+ when "telnet", "rfc2217"
40
44
  require "net/telnet/rfc2217"
41
- [Net::Telnet::RFC2217.new("Host" => uri.host,
42
- "Port" => uri.port || 23,
43
- "baud" => 19_200,
44
- "parity" => Net::Telnet::RFC2217::EVEN)]
45
+ [Net::Telnet::RFC2217.new(uri.host,
46
+ port: uri.port || 23,
47
+ baud: 19_200,
48
+ parity: :even)]
45
49
  else
46
50
  [CCutrer::SerialPort.new(uri.path, baud: 19_200, parity: :even)]
47
51
  end
@@ -49,7 +53,7 @@ args = if uri.scheme == "telnet" || uri.scheme == "rfc2217"
49
53
  server = ModBus::RTUServer.new(*args)
50
54
  server.promiscuous = true
51
55
  server.logger = Logger.new($stdout)
52
- server.logger.level = :debug if debug_modbus
56
+ server.logger.level = debug_modbus ? :debug : :warn
53
57
 
54
58
  diff_and_print = lambda do |registers|
55
59
  registers = registers.slice(*(registers.keys - SENSOR_REGISTERS)) if ignore_sensors
@@ -10,12 +10,16 @@ require "aurora/core_ext/string"
10
10
  uri = URI.parse(ARGV[0])
11
11
  mqtt_uri = ARGV[1]
12
12
 
13
- args = if uri.scheme == "telnet" || uri.scheme == "rfc2217"
13
+ args = case uri.scheme
14
+ when "tcp"
15
+ require "socket"
16
+ [TCPSocket.new(uri.host, uri.port)]
17
+ when "telnet", "rfc2217"
14
18
  require "net/telnet/rfc2217"
15
- [Net::Telnet::RFC2217.new("Host" => uri.host,
16
- "Port" => uri.port || 23,
17
- "baud" => 19_200,
18
- "parity" => Net::Telnet::RFC2217::EVEN)]
19
+ [Net::Telnet::RFC2217.new(uri.host,
20
+ port: uri.port || 23,
21
+ baud: 19_200,
22
+ parity: :even)]
19
23
  else
20
24
  [CCutrer::SerialPort.new(uri.path, baud: 19_200, parity: :even)]
21
25
  end
@@ -33,36 +37,27 @@ class MQTTBridge
33
37
  @mutex.synchronize do
34
38
  case topic
35
39
  when /\$modbus$/
36
- query = value.split(",").map do |addr|
37
- case addr
38
- when "known"
39
- Aurora::REGISTER_NAMES.keys
40
- when /^(\d+)\.\.(\d+)$/
41
- Regexp.last_match(1).to_i..Regexp.last_match(2).to_i
42
- else
43
- addr.to_i
44
- end
45
- end
46
- queries = Aurora.normalize_ranges(query)
47
- registers = {}
48
- queries.each do |subquery|
49
- registers.merge!(@abc.modbus_slave.read_multiple_holding_registers(*subquery))
40
+ registers = @abc.query_registers(value)
41
+ Aurora.print_registers(registers) do |register, v|
42
+ @homie.mqtt.publish("#{@homie.topic}/$modbus/#{register}", v, retain: false, qos: 1)
50
43
  end
51
- result = Aurora.print_registers(registers)
52
- @homie.mqtt.publish("#{@homie.topic}/$modbus/response", result, retain: false, qos: 1)
53
- when %r{\$modbus/(\d+)$}
54
- register = Regexp.last_match(1).to_i
44
+ when %r{\$modbus/(\d+)/set$}
45
+ register = $1.to_i
55
46
  value = case value
56
47
  when /\d+/
57
48
  value.to_i
58
49
  when /0x(\d+)/
59
- Regexp.last_match(1).to_i(16)
50
+ $1.to_i(16)
60
51
  end
61
52
  @abc.modbus_slave.holding_registers[register] = value if value
53
+ registers = { register => @abc.modbus_slave.holding_registers[register] }
54
+ Aurora.print_registers(registers) do |r, v|
55
+ @homie.mqtt.publish("#{@homie.topic}/$modbus/#{r}", v, retain: false, qos: 1)
56
+ end
62
57
  end
63
58
  end
64
59
  rescue StandardError => e
65
- logger.error("failed processing message: #{e}\n#{e.backtrace}")
60
+ warn "failed processing message: #{e}\n#{e.backtrace}"
66
61
  end
67
62
 
68
63
  @abc.refresh
@@ -72,25 +67,8 @@ class MQTTBridge
72
67
  begin
73
68
  @mutex.synchronize do
74
69
  @abc.refresh
75
- %i[compressor_speed
76
- current_mode
77
- dhw_water_temperature
78
- entering_air_temperature
79
- entering_water_temperature
80
- fan_speed
81
- leaving_air_temperature
82
- leaving_water_temperature
83
- outdoor_temperature
84
- relative_humidity
85
- waterflow
86
- fp1
87
- fp2
88
- compressor_watts
89
- blower_watts
90
- aux_heat_watts
91
- loop_pump_watts
92
- total_watts].each do |property|
93
- @homie_abc[property.to_s.tr("_", "-")].value = @abc.public_send(property)
70
+ @homie_abc.each do |property|
71
+ property.value = @abc.public_send(property.id.tr("-", "_"))
94
72
  end
95
73
 
96
74
  @abc.zones.each_with_index do |z, idx|
@@ -101,7 +79,7 @@ class MQTTBridge
101
79
  end
102
80
  end
103
81
  rescue => e
104
- logger.error("got garbage: #{e}; #{e.backtrace}")
82
+ warn "got garbage: #{e}; #{e.backtrace}"
105
83
  exit 1
106
84
  end
107
85
  sleep(5)
@@ -123,7 +101,9 @@ class MQTTBridge
123
101
  unit: "ºF")
124
102
  node.property("leaving-water-temperature", "Leaving Water Temperature", :float, @abc.leaving_water_temperature,
125
103
  unit: "ºF")
126
- node.property("outdoor-temperature", "Outdoor Temperature", :float, @abc.outdoor_temperature, unit: "ºF")
104
+ unless @abc.outdoor_temperature.zero? # TODO: figure out the config if this actually exists
105
+ node.property("outdoor-temperature", "Outdoor Temperature", :float, @abc.outdoor_temperature, unit: "ºF")
106
+ end
127
107
  node.property("relative-humidity", "Relative Humidity", :integer, @abc.relative_humidity, unit: "%",
128
108
  format: 0..100)
129
109
  node.property("waterflow", "Waterflow", :float, unit: "gpm")
@@ -134,6 +114,15 @@ class MQTTBridge
134
114
  node.property(component.tr("_", "-"), component.tr("_", " ").titleize, :integer,
135
115
  @abc.public_send(component), unit: "W")
136
116
  end
117
+
118
+ node.property("blower-only-ecm-speed", "Blower Only ECM Speed", :integer, @abc.blower_only_ecm_speed,
119
+ format: 1..12) do |value, property|
120
+ @mutex.synchronize { property.value = @abc.blower_only_ecm_speed = value }
121
+ end
122
+ node.property("aux-heat-ecm-speed", "Aux Heat ECM Speed", :integer, @abc.aux_heat_ecm_speed,
123
+ format: 1..12) do |value, property|
124
+ @mutex.synchronize { property.value = @abc.aux_heat_ecm_speed = value }
125
+ end
137
126
  end
138
127
 
139
128
  @abc.zones.each_with_index do |zone, i|
@@ -183,7 +172,7 @@ class MQTTBridge
183
172
 
184
173
  # direct access to modbus registers for debugging purposes
185
174
  @homie.mqtt.subscribe("#{@homie.topic}/$modbus")
186
- @homie.mqtt.subscribe("#{@homie.topic}/$modbus/+")
175
+ @homie.mqtt.subscribe("#{@homie.topic}/$modbus/+/set")
187
176
  @homie.publish
188
177
  end
189
178
  end
@@ -18,6 +18,8 @@ module Aurora
18
18
  :outdoor_temperature,
19
19
  :fp1,
20
20
  :fp2,
21
+ :blower_only_ecm_speed,
22
+ :aux_heat_ecm_speed,
21
23
  :compressor_watts,
22
24
  :blower_watts,
23
25
  :aux_heat_watts,
@@ -31,17 +33,37 @@ module Aurora
31
33
  registers_array = @modbus_slave.holding_registers[105...110]
32
34
  registers = registers_array.each_with_index.map { |r, i| [i + 105, r] }.to_h
33
35
  @serial_number = Aurora.transform_registers(registers)[105]
34
- iz2_zone_count = @modbus_slave.holding_registers[483]
35
- # TODO: better detect IZ2/Non-IZ2
36
- @zones = if iz2_zone_count > 1
37
- (0...iz2_zone_count).map { |i| IZ2Zone.new(self, i + 1) }
38
- else
36
+
37
+ @zones = if @modbus_slave.holding_registers[813].zero?
39
38
  [Thermostat.new(self)]
39
+ else
40
+ iz2_zone_count = @modbus_slave.holding_registers[483]
41
+ (0...iz2_zone_count).map { |i| IZ2Zone.new(self, i + 1) }
40
42
  end
41
43
  end
42
44
 
45
+ def query_registers(query)
46
+ ranges = query.split(",").map do |addr|
47
+ case addr
48
+ when "known"
49
+ Aurora::REGISTER_NAMES.keys
50
+ when /^(\d+)(?:\.\.|-)(\d+)$/
51
+ $1.to_i..$2.to_i
52
+ else
53
+ addr.to_i
54
+ end
55
+ end
56
+ queries = Aurora.normalize_ranges(ranges)
57
+ registers = {}
58
+ queries.each do |subquery|
59
+ registers.merge!(@modbus_slave.read_multiple_holding_registers(*subquery))
60
+ end
61
+ registers
62
+ end
63
+
43
64
  def refresh
44
- registers_to_read = [19..20, 30, 344, 740..741, 900, 1110..1111, 1114, 1117, 1147..1153, 1165, 3027, 31_003]
65
+ registers_to_read = [19..20, 30, 340, 344, 347, 740..741, 900, 1110..1111, 1114, 1117, 1147..1153, 1165, 3027,
66
+ 31_003]
45
67
  if zones.first.is_a?(IZ2Zone)
46
68
  zones.each_with_index do |_z, i|
47
69
  base1 = 21_203 + i * 9
@@ -52,7 +74,7 @@ module Aurora
52
74
  registers_to_read << base3
53
75
  end
54
76
  else
55
- registers_to_read << 745..747
77
+ registers_to_read << (745..747)
56
78
  end
57
79
 
58
80
  registers = @modbus_slave.holding_registers[*registers_to_read]
@@ -71,6 +93,8 @@ module Aurora
71
93
  @fp1 = registers[19]
72
94
  @fp2 = registers[20]
73
95
  @locked_out = registers[1117]
96
+ @blower_only_ecm_speed = registers[340]
97
+ @aux_heat_ecm_speed = registers[347]
74
98
  @compressor_watts = registers[1147]
75
99
  @blower_watts = registers[1149]
76
100
  @aux_heat_watts = registers[1151]
@@ -99,6 +123,18 @@ module Aurora
99
123
  end
100
124
  end
101
125
 
126
+ def blower_only_ecm_speed=(value)
127
+ return unless (1..12).include?(value)
128
+
129
+ @modbus_slave.holding_registers[340] = value
130
+ end
131
+
132
+ def aux_heat_ecm_speed=(value)
133
+ return unless (1..12).include?(value)
134
+
135
+ @modbus_slave.holding_registers[347] = value
136
+ end
137
+
102
138
  def inspect
103
139
  "#<Aurora::ABCClient #{(instance_variables - [:@modbus_slave]).map do |iv|
104
140
  "#{iv}=#{instance_variable_get(iv).inspect}"
@@ -348,7 +348,7 @@ module Aurora
348
348
  ->(v) { from_bitmask(v, AXB_INPUTS) } => [1103],
349
349
  ->(v) { from_bitmask(v, AXB_OUTPUTS) } => [1104],
350
350
  ->(v) { TO_TENTHS.call(NEGATABLE.call(v)) } => [1136],
351
- ->(v) { HEATING_MODE[v] } => [12_602, 21_202, 21_211, 21_220, 21_229, 21_238, 21_247],
351
+ ->(v) { HEATING_MODE[v] } => [12_606, 21_202, 21_211, 21_220, 21_229, 21_238, 21_247],
352
352
  ->(v) { FAN_MODE[v] } => [12_621, 21_205, 21_214, 21_223, 21_232, 21_241, 21_250],
353
353
  ->(v) { from_bitmask(v, HUMIDIFIER_SETTINGS) } => [31_109],
354
354
  ->(v) { { humidification_target: v >> 8, dehumidification_target: v & 0xff } } => [31_110],
@@ -497,7 +497,7 @@ module Aurora
497
497
  REGISTER_NAMES = {
498
498
  1 => "Random Start Delay",
499
499
  2 => "ABC Program Version",
500
- 3 => "IZ2 Version?",
500
+ 3 => "??? Version?",
501
501
  4 => "DIP Switch Override",
502
502
  6 => "Compressor Anti-Short Cycle Delay",
503
503
  8 => "Unit Type?",
@@ -563,7 +563,7 @@ module Aurora
563
563
  746 => "Cooling Set Point",
564
564
  747 => "Ambient Temperature",
565
565
  807 => "AXB Version",
566
- 813 => "IZ2 Version?",
566
+ 813 => "IZ2 Version",
567
567
  816 => "AOC Version 1?",
568
568
  817 => "AOC Version 2?",
569
569
  819 => "MOC Version 1?",
@@ -590,7 +590,7 @@ module Aurora
590
590
  1153 => "Total Watts",
591
591
  1157 => "Ht of Rej",
592
592
  1165 => "VS Pump Watts",
593
- 12_602 => "Heating Mode (write)",
593
+ 12_606 => "Heating Mode (write)",
594
594
  12_619 => "Heating Setpoint (write)",
595
595
  12_620 => "Cooling Setpoint (write)",
596
596
  12_621 => "Fan Mode (write)",
@@ -648,7 +648,7 @@ module Aurora
648
648
  end
649
649
 
650
650
  def print_registers(registers)
651
- result = []
651
+ result = [] unless block_given?
652
652
  registers.each do |(k, value)|
653
653
  # ignored
654
654
  next if REGISTER_NAMES.key?(k) && REGISTER_NAMES[k].nil?
@@ -665,8 +665,13 @@ module Aurora
665
665
 
666
666
  name ||= "???"
667
667
 
668
- result << "#{name} (#{k}): #{value}"
668
+ full_value = "#{name} (#{k}): #{value}"
669
+ if block_given?
670
+ yield(k, full_value)
671
+ else
672
+ result << full_value
673
+ end
669
674
  end
670
- result.join("\n")
675
+ result.join("\n") unless block_given?
671
676
  end
672
677
  end
@@ -21,7 +21,7 @@ module Aurora
21
21
  def target_mode=(value)
22
22
  return unless (raw_value = HEATING_MODE.invert[value])
23
23
 
24
- @abc.modbus_slave.holding_registers[12_602] = raw_value
24
+ @abc.modbus_slave.holding_registers[12_606] = raw_value
25
25
  @target_mode = value
26
26
  end
27
27
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Aurora
4
- VERSION = "0.3.3"
4
+ VERSION = "0.3.7"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: waterfurnace_aurora
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.3.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cody Cutrer
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-08-26 00:00:00.000000000 Z
11
+ date: 2021-08-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ccutrer-serialport
@@ -44,14 +44,20 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 0.0.4
47
+ version: '1.0'
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 1.0.1
48
51
  type: :runtime
49
52
  prerelease: false
50
53
  version_requirements: !ruby/object:Gem::Requirement
51
54
  requirements:
52
55
  - - "~>"
53
56
  - !ruby/object:Gem::Version
54
- version: 0.0.4
57
+ version: '1.0'
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 1.0.1
55
61
  - !ruby/object:Gem::Dependency
56
62
  name: rmodbus-ccutrer
57
63
  requirement: !ruby/object:Gem::Requirement