waterfurnace_aurora 0.3.1 → 0.3.5

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: 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