waterfurnace_aurora 0.3.1 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fde3dc688654c589d5638b794484035f3ab7ca8c102fe1ef27bb6365ddd51d22
4
- data.tar.gz: 6d679712a9375c94f8a1f7b2fe3fa6102c606a433c0449049ae289773cdaf735
3
+ metadata.gz: 85309a61ae279d3255db42a0ff3d53a038c1fdcb3c7e02e3febf6b533992a2c3
4
+ data.tar.gz: be76ef3d6821fbd8535192fd4a55f770234f1736fb280a7a3736fa6c134a1085
5
5
  SHA512:
6
- metadata.gz: dd90afd3a8f15ddec22ec29f23679d4def25b768b47eaf7adc37c37ab0a5b98bfb98a11811133d67dbbb1afd23b03ea5689fe4be55c2966eb19b68b9b8827667
7
- data.tar.gz: 9c855a9730f2a86678876f3866ea7a6583925781e2397e13738b9f413e4b318a89c7860706e22e88c94d090f37afccd775b2b54242b9555530993e7021b995c6
6
+ metadata.gz: a45f409c8573e02e7b761c6363abfea445f6e86fe58fab96b5e2ed427564ba791ff83c8817c74d2ff90028eae0c35fb4f090c0a28d3e9c6931aab45e2658c580
7
+ data.tar.gz: b5d793acc1dbca113c11205198b6ad6623b29543b5c5cc095ab8f4ddf0d5d9fbcf98fc5ca586e534d516027bc446bec2ee164fd3bb7f36ba6309b63517b13524
data/exe/aurora_fetch CHANGED
@@ -18,7 +18,7 @@ args = if uri.scheme == "telnet" || uri.scheme == "rfc2217"
18
18
  end
19
19
 
20
20
  client = ModBus::RTUClient.new(*args)
21
- client.debug = true
21
+ client.logger = Logger.new($stdout, :debug)
22
22
  slave = client.with_slave(1)
23
23
 
24
24
  registers = slave.holding_registers[ARGV[1].to_i]
data/exe/aurora_mock CHANGED
@@ -21,7 +21,7 @@ args = if uri.scheme == "telnet" || uri.scheme == "rfc2217"
21
21
  port = ARGV[1]&.to_i || 502
22
22
 
23
23
  server1 = ModBus::RTUServer.new(*args)
24
- server1.debug = true
24
+ server1.logger = Logger.new($stdout, :debug)
25
25
  # AID Tool queries slave 1, AWL queries slave 2; just use both
26
26
  slave1 = server1.with_slave(1)
27
27
  slave2 = server1.with_slave(2)
data/exe/aurora_monitor CHANGED
@@ -3,6 +3,7 @@
3
3
 
4
4
  require "aurora"
5
5
  require "ccutrer-serialport"
6
+ require "logger"
6
7
  require "optparse"
7
8
  require "socket"
8
9
  require "uri"
@@ -47,7 +48,8 @@ args = if uri.scheme == "telnet" || uri.scheme == "rfc2217"
47
48
 
48
49
  server = ModBus::RTUServer.new(*args)
49
50
  server.promiscuous = true
50
- server.debug = debug_modbus
51
+ server.logger = Logger.new($stdout)
52
+ server.logger.level = :debug if debug_modbus
51
53
 
52
54
  diff_and_print = lambda do |registers|
53
55
  registers = registers.slice(*(registers.keys - SENSOR_REGISTERS)) if ignore_sensors
@@ -29,7 +29,7 @@ class MQTTBridge
29
29
  @homie = homie
30
30
  @mutex = Mutex.new
31
31
 
32
- @homie.instance_variable_set(:@block, lambda do |topic, value|
32
+ @homie.out_of_band_topic_proc = lambda do |topic, value|
33
33
  @mutex.synchronize do
34
34
  case topic
35
35
  when /\$modbus$/
@@ -37,8 +37,8 @@ class MQTTBridge
37
37
  case addr
38
38
  when "known"
39
39
  Aurora::REGISTER_NAMES.keys
40
- when /^(\d+)\.\.(\d+)$/
41
- Regexp.last_match(1).to_i..Regexp.last_match(2).to_i
40
+ when /^(\d+)(?:\.\.|-)(\d+)$/
41
+ $1.to_i..$2.to_i
42
42
  else
43
43
  addr.to_i
44
44
  end
@@ -48,47 +48,37 @@ class MQTTBridge
48
48
  queries.each do |subquery|
49
49
  registers.merge!(@abc.modbus_slave.read_multiple_holding_registers(*subquery))
50
50
  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
51
+ Aurora.print_registers(registers) do |register, v|
52
+ @homie.mqtt.publish("#{@homie.topic}/$modbus/#{register}", v, retain: false, qos: 1)
53
+ end
54
+ when %r{\$modbus/(\d+)/set$}
55
+ register = $1.to_i
55
56
  value = case value
56
57
  when /\d+/
57
58
  value.to_i
58
59
  when /0x(\d+)/
59
- Regexp.last_match(1).to_i(16)
60
+ $1.to_i(16)
60
61
  end
61
62
  @abc.modbus_slave.holding_registers[register] = value if value
63
+ registers = { register => @abc.modbus_slave.holding_registers[register] }
64
+ Aurora.print_registers(registers) do |r, v|
65
+ @homie.mqtt.publish("#{@homie.topic}/$modbus/#{r}", v, retain: false, qos: 1)
66
+ end
62
67
  end
63
68
  end
64
69
  rescue StandardError => e
65
- puts "failed processing message: #{e}\n#{e.backtrace}"
66
- end)
70
+ warn "failed processing message: #{e}\n#{e.backtrace}"
71
+ end
67
72
 
73
+ @abc.refresh
68
74
  publish_basic_attributes
69
75
 
70
76
  loop do
71
77
  begin
72
78
  @mutex.synchronize do
73
79
  @abc.refresh
74
- %i[compressor_speed
75
- current_mode
76
- dhw_water_temperature
77
- entering_air_temperature
78
- fan_speed
79
- leaving_air_temperature
80
- leaving_water_temperature
81
- outdoor_temperature
82
- relative_humidity
83
- waterflow
84
- fp1
85
- fp2
86
- compressor_watts
87
- blower_watts
88
- aux_heat_watts
89
- loop_pump_watts
90
- total_watts].each do |property|
91
- @homie_abc[property.to_s.tr("_", "-")].value = @abc.public_send(property)
80
+ @homie_abc.each do |property|
81
+ property.value = @abc.public_send(property.id.tr("-", "_"))
92
82
  end
93
83
 
94
84
  @abc.zones.each_with_index do |z, idx|
@@ -99,7 +89,7 @@ class MQTTBridge
99
89
  end
100
90
  end
101
91
  rescue => e
102
- puts "got garbage: #{e}; #{e.backtrace}"
92
+ warn "got garbage: #{e}; #{e.backtrace}"
103
93
  exit 1
104
94
  end
105
95
  sleep(5)
@@ -121,7 +111,9 @@ class MQTTBridge
121
111
  unit: "ºF")
122
112
  node.property("leaving-water-temperature", "Leaving Water Temperature", :float, @abc.leaving_water_temperature,
123
113
  unit: "ºF")
124
- node.property("outdoor-temperature", "Outdoor Temperature", :float, @abc.outdoor_temperature, unit: "ºF")
114
+ unless @abc.outdoor_temperature.zero? # TODO: figure out the config if this actually exists
115
+ node.property("outdoor-temperature", "Outdoor Temperature", :float, @abc.outdoor_temperature, unit: "ºF")
116
+ end
125
117
  node.property("relative-humidity", "Relative Humidity", :integer, @abc.relative_humidity, unit: "%",
126
118
  format: 0..100)
127
119
  node.property("waterflow", "Waterflow", :float, unit: "gpm")
@@ -132,6 +124,15 @@ class MQTTBridge
132
124
  node.property(component.tr("_", "-"), component.tr("_", " ").titleize, :integer,
133
125
  @abc.public_send(component), unit: "W")
134
126
  end
127
+
128
+ node.property("blower-only-ecm-speed", "Blower Only ECM Speed", :integer, @abc.blower_only_ecm_speed,
129
+ format: 1..12) do |value, property|
130
+ @mutex.synchronize { property.value = @abc.blower_only_ecm_speed = value }
131
+ end
132
+ node.property("aux-heat-ecm-speed", "Aux Heat ECM Speed", :integer, @abc.aux_heat_ecm_speed,
133
+ format: 1..12) do |value, property|
134
+ @mutex.synchronize { property.value = @abc.aux_heat_ecm_speed = value }
135
+ end
135
136
  end
136
137
 
137
138
  @abc.zones.each_with_index do |zone, i|
@@ -181,9 +182,18 @@ class MQTTBridge
181
182
 
182
183
  # direct access to modbus registers for debugging purposes
183
184
  @homie.mqtt.subscribe("#{@homie.topic}/$modbus")
184
- @homie.mqtt.subscribe("#{@homie.topic}/$modbus/+")
185
+ @homie.mqtt.subscribe("#{@homie.topic}/$modbus/+/set")
185
186
  @homie.publish
186
187
  end
187
188
  end
188
189
 
189
- MQTTBridge.new(abc, MQTT::Homie::Device.new("aurora", "Aurora MQTT Bridge", mqtt: mqtt_uri))
190
+ log_level = ARGV.include?("--debug") ? :debug : :warn
191
+ logger = Logger.new($stdout)
192
+ logger.level = log_level
193
+ slave.logger = logger
194
+
195
+ device = "aurora-#{abc.serial_number}"
196
+ homie = MQTT::Homie::Device.new(device, "Aurora MQTT Bridge", mqtt: mqtt_uri)
197
+ homie.logger = logger
198
+
199
+ MQTTBridge.new(abc, homie)
@@ -3,6 +3,7 @@
3
3
  module Aurora
4
4
  class ABCClient
5
5
  attr_reader :modbus_slave,
6
+ :serial_number,
6
7
  :zones,
7
8
  :current_mode,
8
9
  :fan_speed,
@@ -17,6 +18,8 @@ module Aurora
17
18
  :outdoor_temperature,
18
19
  :fp1,
19
20
  :fp2,
21
+ :blower_only_ecm_speed,
22
+ :aux_heat_ecm_speed,
20
23
  :compressor_watts,
21
24
  :blower_watts,
22
25
  :aux_heat_watts,
@@ -27,17 +30,21 @@ module Aurora
27
30
  @modbus_slave = modbus_slave
28
31
  @modbus_slave.read_retry_timeout = 15
29
32
  @modbus_slave.read_retries = 2
30
- iz2_zone_count = @modbus_slave.holding_registers[483]
31
- # TODO: better detect IZ2/Non-IZ2
32
- @zones = if iz2_zone_count > 1
33
- (0...iz2_zone_count).map { |i| IZ2Zone.new(self, i + 1) }
34
- else
33
+ registers_array = @modbus_slave.holding_registers[105...110]
34
+ registers = registers_array.each_with_index.map { |r, i| [i + 105, r] }.to_h
35
+ @serial_number = Aurora.transform_registers(registers)[105]
36
+
37
+ @zones = if @modbus_slave.holding_registers[813].zero?
35
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) }
36
42
  end
37
43
  end
38
44
 
39
45
  def refresh
40
- registers_to_read = [19..20, 30, 344, 740..741, 900, 1110..1111, 1114, 1117, 1147..1153, 1165, 3027, 31_003]
46
+ registers_to_read = [19..20, 30, 340, 344, 347, 740..741, 900, 1110..1111, 1114, 1117, 1147..1153, 1165, 3027,
47
+ 31_003]
41
48
  if zones.first.is_a?(IZ2Zone)
42
49
  zones.each_with_index do |_z, i|
43
50
  base1 = 21_203 + i * 9
@@ -48,7 +55,7 @@ module Aurora
48
55
  registers_to_read << base3
49
56
  end
50
57
  else
51
- registers_to_read << 745..747
58
+ registers_to_read << (745..747)
52
59
  end
53
60
 
54
61
  registers = @modbus_slave.holding_registers[*registers_to_read]
@@ -67,6 +74,8 @@ module Aurora
67
74
  @fp1 = registers[19]
68
75
  @fp2 = registers[20]
69
76
  @locked_out = registers[1117]
77
+ @blower_only_ecm_speed = registers[340]
78
+ @aux_heat_ecm_speed = registers[347]
70
79
  @compressor_watts = registers[1147]
71
80
  @blower_watts = registers[1149]
72
81
  @aux_heat_watts = registers[1151]
@@ -95,6 +104,18 @@ module Aurora
95
104
  end
96
105
  end
97
106
 
107
+ def blower_only_ecm_speed=(value)
108
+ return unless (1..12).include?(value)
109
+
110
+ @modbus_slave.holding_registers[340] = value
111
+ end
112
+
113
+ def aux_heat_ecm_speed=(value)
114
+ return unless (1..12).include?(value)
115
+
116
+ @modbus_slave.holding_registers[347] = value
117
+ end
118
+
98
119
  def inspect
99
120
  "#<Aurora::ABCClient #{(instance_variables - [:@modbus_slave]).map do |iv|
100
121
  "#{iv}=#{instance_variable_get(iv).inspect}"
@@ -17,7 +17,7 @@ module Aurora
17
17
  end
18
18
 
19
19
  def holding_registers
20
- WFProxy.new(self, :holding_register)
20
+ @holding_registers ||= WFProxy.new(self, :holding_register)
21
21
  end
22
22
  end
23
23
 
@@ -33,7 +33,6 @@ module Aurora
33
33
  def read_rtu_response(io)
34
34
  # Read the slave_id and function code
35
35
  msg = read(io, 2)
36
- log logging_bytes(msg)
37
36
 
38
37
  function_code = msg.getbyte(1)
39
38
  case function_code
@@ -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.1"
4
+ VERSION = "0.3.5"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: waterfurnace_aurora
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cody Cutrer
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 1.4.2
33
+ version: 1.4.4
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 1.4.2
40
+ version: 1.4.4
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: net-telnet-rfc2217
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '2.0'
61
+ version: '2.1'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '2.0'
68
+ version: '2.1'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: byebug
71
71
  requirement: !ruby/object:Gem::Requirement