waterfurnace_aurora 0.5.3 → 0.6.0

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: a372b51d3240840ae96269020f73728fb049f3e6c0438613c9659d4158d21aa6
4
- data.tar.gz: 249e26d5764a0ab670a60b5de7ed6da0796344fd71896c6c33d353fc4a7d95ed
3
+ metadata.gz: 77762dc2957715e4f0a1dc4f608158b5f17a4801624f50d8af01ba26c8dc7410
4
+ data.tar.gz: 338fd829fb1bb364900242d2a4cdacada3e08a3b87214377f81f04b0c5f9eb66
5
5
  SHA512:
6
- metadata.gz: c5c5ef5a5e1d6ec3d393913ca1b717a5a53a5f17c51f2c9b8ea0f6aeb627cdc873fa25e22511a779d7b9c0e9a60fdc21bc63dbb1fb0d8f6baa41c3dada85cb91
7
- data.tar.gz: ee787175c344db12fe11f0dab4131505e5692ca360adeee78bcd0931bd4b28660de9c0d09817c5f30632808b374a3695f8a8cbf9f1e965bf410648f411ffa958
6
+ metadata.gz: 1a16b1f69d3b5720bdc323ae27b7de9908573e6a959857dce575273129fcfa5a42e7754ea87a072d28afbc47aa5e8ec9e46b40682fcc9a88dca30c36ec2aa207
7
+ data.tar.gz: 0d221ae7e69561ab79dd0f9591751492c4282dc4fd33a658cc8bf99ee6973587616f199c6228e7ca2506eb99fb7a622bc77a33d0272cea942ff99177dae22c90
@@ -92,7 +92,7 @@ class MQTTBridge
92
92
  @blower => @abc.blower,
93
93
  @pump => @abc.pump,
94
94
  @dhw => @abc.dhw,
95
- @humidifier => @abc.humidifier }.compact
95
+ @humidistat => @abc.humidistat }.compact
96
96
  @abc.zones.each_with_index do |z, idx|
97
97
  homie_zone = @homie["zone#{idx + 1}"]
98
98
  components[homie_zone] = z
@@ -105,6 +105,8 @@ class MQTTBridge
105
105
  end
106
106
 
107
107
  @abc.faults.each_with_index do |fault_count, i|
108
+ next if fault_count == 0xffff
109
+
108
110
  @faults["e#{i + 1}"].value = fault_count
109
111
  end
110
112
  end
@@ -118,8 +120,10 @@ class MQTTBridge
118
120
 
119
121
  def publish_basic_attributes
120
122
  @homie_abc = @homie.node("abc", "Aurora Basic Control", "ABC") do |node|
123
+ allowed_modes = %w[lockout standby blower heating cooling eh1 eh2 emergency waiting]
124
+ allowed_modes << "dehumidify" if @abc.compressor.is_a?(Aurora::Compressor::VSDrive)
121
125
  node.property("current-mode", "Current Heating/Cooling Mode", :enum, @abc.current_mode,
122
- format: %w[lockout standby blower heating cooling eh1 eh2 emergency waiting dehumidify])
126
+ format: allowed_modes)
123
127
  node.property("entering-air-temperature", "Entering Air Temperature", :float, @abc.entering_air_temperature,
124
128
  unit: "ºF")
125
129
  node.property("entering-water-temperature", "Entering Water Temperature", :float,
@@ -131,8 +135,7 @@ class MQTTBridge
131
135
  unless @abc.outdoor_temperature.zero? # TODO: figure out the config if this actually exists
132
136
  node.property("outdoor-temperature", "Outdoor Temperature", :float, @abc.outdoor_temperature, unit: "ºF")
133
137
  end
134
- node.property("relative-humidity", "Relative Humidity", :integer, @abc.relative_humidity, unit: "%",
135
- format: 0..100)
138
+
136
139
  node.property("fp1", "FP1 Sensor", :float, @abc.fp1, unit: "ºF")
137
140
  node.property("fp2", "FP2 Sensor", :float, @abc.fp2, unit: "ºF")
138
141
  %i[aux_heat total].each do |component|
@@ -190,6 +193,7 @@ class MQTTBridge
190
193
 
191
194
  next unless @abc.pump.is_a?(Aurora::Pump::VSPump)
192
195
 
196
+ node.property("running", "Pump is running", :boolean, @abc.pump.running)
193
197
  node.property("speed", "Speed", :integer, @abc.pump.speed, format: 0..100, unit: "%") do |value, property|
194
198
  @mutex.synchronize { property.value = @abc.pump.speed = value }
195
199
  end
@@ -212,6 +216,7 @@ class MQTTBridge
212
216
  node.property("enabled", "Enabled", :boolean, @abc.dhw.enabled) do |value, property|
213
217
  @mutex.synchronize { property.value = @abc.dhw.enabled = value }
214
218
  end
219
+ node.property("running", "DHW Pump is running", :boolean, @abc.dhw.running?)
215
220
  node.property("water-temperature", "Water Temperature", :float,
216
221
  @abc.dhw.water_temperature, unit: "ºF")
217
222
  node.property("set-point", "Set Point", :float, @abc.dhw.set_point, format: 100..140,
@@ -221,10 +226,36 @@ class MQTTBridge
221
226
  end
222
227
  end
223
228
 
224
- if @abc.humidifier
225
- @humidifier = @homie.node("humidifier", "Humidifier", "Humidifier") do |node|
226
- node.property("running", "Humidifier is running", :boolean, @abc.humidifier.running?)
229
+ @humidistat = @homie.node("humidistat", "Humidistat", "Humidistat") do |node|
230
+ node.property("relative-humidity", "Relative Humidity", :integer, @abc.humidistat.relative_humidity,
231
+ unit: "%", format: 0..100)
232
+ if @abc.humidistat.humidifier?
233
+ node.property("humidifier-running", "Humidifier is running", :boolean, @abc.humidistat.humidifier_running?)
234
+ node.property("humidifier-mode", "Humidifier Mode", :enum, @abc.humidistat.humidifier_mode,
235
+ format: %i[auto manual]) do |value, property|
236
+ @mutex.synchronize { property.value = @abc.humidistat.humidifier_mode = value.to_sym }
237
+ end
238
+ node.property("humidification-target", "Humidification target relative humidity", :integer,
239
+ @abc.humidistat.humidification_target, unit: "%", format: 15..50) do |value, property|
240
+ @mutex.synchronize { property.value = @abc.humidistat.humidification_target = value }
241
+ end
227
242
  end
243
+
244
+ # VSDrive can perform active dehumidification, even without a dedicated dehumidifier
245
+ if @abc.humidistat.dehumidifier? || @abc.compressor.is_a?(Aurora::Compressor::VSDrive)
246
+ node.property("dehumidifier-mode", "Dehumidifier Mode", :enum, @abc.humidistat.dehumidifier_mode,
247
+ format: %i[auto manual]) do |value, property|
248
+ @mutex.synchronize { property.value = @abc.humidistat.dehumidifier_mode = value.to_sym }
249
+ end
250
+ node.property("dehumidification-target", "Dehumidification target relative humidity", :integer,
251
+ @abc.humidistat.dehumidification_target, unit: "%", format: 35..65) do |value, property|
252
+ @mutex.synchronize { property.value = @abc.humidistat.dehumidification_target = value }
253
+ end
254
+ end
255
+
256
+ next unless @abc.humidistat.dehumidifier?
257
+
258
+ node.property("dehumidifier-running", "Dehumidifier is running", :boolean, @abc.humidistat.dehumidifier_running?)
228
259
  end
229
260
 
230
261
  @faults = @homie.node("faults", "Fault History", "ABC") do |node|
@@ -232,6 +263,8 @@ class MQTTBridge
232
263
  @mutex.synchronize { @abc.clear_fault_history }
233
264
  end
234
265
  @abc.faults.each_with_index do |count, i|
266
+ next if count == 0xffff
267
+
235
268
  name = Aurora::FAULTS[i + 1]
236
269
  node.property("e#{i + 1}", name || "E#{i + 1}", :integer, count)
237
270
  end
@@ -6,7 +6,7 @@ require "uri"
6
6
  require "aurora/blower"
7
7
  require "aurora/compressor"
8
8
  require "aurora/dhw"
9
- require "aurora/humidifier"
9
+ require "aurora/humidistat"
10
10
  require "aurora/iz2_zone"
11
11
  require "aurora/pump"
12
12
  require "aurora/thermostat"
@@ -49,11 +49,10 @@ module Aurora
49
49
  :blower,
50
50
  :pump,
51
51
  :dhw,
52
- :humidifier,
52
+ :humidistat,
53
53
  :faults,
54
54
  :current_mode,
55
55
  :entering_air_temperature,
56
- :relative_humidity,
57
56
  :leaving_air_temperature,
58
57
  :leaving_water_temperature,
59
58
  :entering_water_temperature,
@@ -67,7 +66,7 @@ module Aurora
67
66
  @modbus_slave = self.class.open_modbus_slave(uri)
68
67
  @modbus_slave.read_retry_timeout = 15
69
68
  @modbus_slave.read_retries = 2
70
- raw_registers = @modbus_slave.holding_registers[33, 88..91, 105...110, 404, 412..413, 1114]
69
+ raw_registers = @modbus_slave.holding_registers[33, 88..91, 105...110, 404, 412..413, 1103, 1114]
71
70
  registers = Aurora.transform_registers(raw_registers.dup)
72
71
  @program = registers[88]
73
72
  @serial_number = registers[105]
@@ -81,6 +80,7 @@ module Aurora
81
80
  end
82
81
 
83
82
  @abc_dipswitches = registers[33]
83
+ @axb_dipswitches = registers[1103]
84
84
  @compressor = if @program == "ABCVSP"
85
85
  Compressor::VSDrive.new(self)
86
86
  else
@@ -100,9 +100,23 @@ module Aurora
100
100
  registers[413])
101
101
  end
102
102
  @dhw = DHW.new(self) if (-999..999).include?(registers[1114])
103
- @humidifier = Humidifier.new(self) if @abc_dipswitches[:accessory_relay] == :humidifier
103
+ @humidistat = Humidistat.new(self,
104
+ @abc_dipswitches[:accessory_relay] == :humidifier,
105
+ @axb_dipswitches[:accessory_relay2] == :dehumidifier)
104
106
 
105
107
  @faults = []
108
+
109
+ @registers_to_read = [6, 19..20, 25, 30, 344, 740..741, 900, 1104, 1110..1111, 1114, 1150..1153, 1165,
110
+ 31_003]
111
+ zones.each do |z|
112
+ @registers_to_read.concat(z.registers_to_read)
113
+ end
114
+ @components = [compressor, blower, pump, dhw, humidistat].compact
115
+ @components.each do |component|
116
+ @registers_to_read.concat(component.registers_to_read)
117
+ end
118
+ # need dehumidify mode to calculate final current mode
119
+ @registers_to_read.concat([362]) if compressor.is_a?(Compressor::VSDrive)
106
120
  end
107
121
 
108
122
  def query_registers(query)
@@ -140,29 +154,15 @@ module Aurora
140
154
  end
141
155
 
142
156
  def refresh
143
- registers_to_read = [6, 19..20, 25, 30, 344, 740..741, 900, 1110..1111, 1114, 1150..1153, 1165,
144
- 31_003]
145
- zones.each do |z|
146
- registers_to_read.concat(z.registers_to_read)
147
- end
148
- registers_to_read.concat(compressor.registers_to_read)
149
- registers_to_read.concat(blower.registers_to_read)
150
- registers_to_read.concat(pump.registers_to_read)
151
- registers_to_read.concat(dhw.registers_to_read) if dhw
152
- # need dehumidify mode to calculate final current mode;
153
- # apparently non-VSD doesn't have this register at all?
154
- registers_to_read.concat([362]) if compressor.is_a?(Compressor::VSDrive)
155
-
156
157
  faults = @modbus_slave.read_multiple_holding_registers(601..699)
157
158
  @faults = Aurora.transform_registers(faults).values
158
159
 
159
- registers = @modbus_slave.holding_registers[*registers_to_read]
160
+ registers = @modbus_slave.holding_registers[*@registers_to_read]
160
161
  Aurora.transform_registers(registers)
161
162
 
162
163
  outputs = registers[30]
163
164
 
164
165
  @entering_air_temperature = registers[740]
165
- @relative_humidity = registers[741]
166
166
  @leaving_air_temperature = registers[900]
167
167
  @leaving_water_temperature = registers[1110]
168
168
  @entering_water_temperature = registers[1111]
@@ -197,11 +197,9 @@ module Aurora
197
197
  zones.each do |z|
198
198
  z.refresh(registers)
199
199
  end
200
- compressor.refresh(registers)
201
- blower.refresh(registers)
202
- pump.refresh(registers)
203
- dhw&.refresh(registers)
204
- humidifier&.refresh(registers)
200
+ @components.each do |component|
201
+ component.refresh(registers)
202
+ end
205
203
  end
206
204
 
207
205
  def cooling_airflow_adjustment=(value)
data/lib/aurora/dhw.rb CHANGED
@@ -4,7 +4,8 @@ require "aurora/component"
4
4
 
5
5
  module Aurora
6
6
  class DHW < Component
7
- attr_reader :enabled, :set_point, :water_temperature
7
+ attr_reader :enabled, :running, :set_point, :water_temperature
8
+ alias running? running
8
9
 
9
10
  def registers_to_read
10
11
  [400..401, 1114]
@@ -12,6 +13,7 @@ module Aurora
12
13
 
13
14
  def refresh(registers)
14
15
  @enabled = registers[400]
16
+ @running = registers[1104].include?(:dhw)
15
17
  @set_point = registers[401]
16
18
  @water_temperature = registers[1114]
17
19
  end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "aurora/component"
4
+
5
+ module Aurora
6
+ class Humidistat < Component
7
+ attr_reader :humidifier_running, :humidifier_mode, :humidification_target,
8
+ :dehumidifier_running, :dehumidifier_mode, :dehumidification_target,
9
+ :relative_humidity
10
+ alias humidifier_running? humidifier_running
11
+ alias dehumidifer_running? dehumidifier_running
12
+
13
+ def initialize(abc, has_humidifier, has_dehumidifier)
14
+ super(abc)
15
+ @humidifier = has_humidifier
16
+ @dehumidifier = has_dehumidifier
17
+ end
18
+
19
+ def humidifier?
20
+ @humidifier
21
+ end
22
+
23
+ def dehumidifier?
24
+ @dehumidifier
25
+ end
26
+
27
+ def registers_to_read
28
+ result = [741]
29
+ if humidifier? || dehumidifier? || abc.compressor.is_a?(Compressor::VSDrive)
30
+ result.concat(abc.iz2? ? [21_114, 31_109..31_110] : [12_309..12_310])
31
+ end
32
+ result
33
+ end
34
+
35
+ def refresh(registers)
36
+ @relative_humidity = registers[741]
37
+
38
+ outputs = registers[30]
39
+ @humidifier_running = humidifier? && outputs.include?(:accessory)
40
+
41
+ outputs = registers[1104]
42
+ @dehumidifer_running = dehumidifier? && outputs.include?(:accessory2)
43
+
44
+ base = abc.iz2? ? 31_109 : 12_309
45
+ @humidifier_settings = registers[abc.iz2? ? 21_114 : 12_309]
46
+ @humidifier_mode = @humidifier_settings&.include?(:auto_humidification) ? :auto : :manual
47
+ @dehumidifier_mode = @humidifier_settings&.include?(:auto_dehumidification) ? :auto : :manual
48
+
49
+ @humidification_target = registers[base + 1]&.[](:humidification_target)
50
+ @dehumidification_target = registers[base + 1]&.[](:dehumidification_target)
51
+ end
52
+
53
+ def humidifier_mode=(mode)
54
+ set_humidistat_mode(mode, dehumidifier_mode)
55
+ end
56
+
57
+ def dehumidifier_mode=(mode)
58
+ set_humidistat_mode(humidifier_mode, mode)
59
+ end
60
+
61
+ def set_humidistat_mode(humidifier_mode, dehumidifier_mode)
62
+ allowed = %i[auto manual]
63
+ raise ArgumentError unless allowed.include?(humidifier_mode) && allowed.include?(dehumidifier_mode)
64
+
65
+ # start with the prior value of the register, since I'm not sure what
66
+ # else is stuffed in there
67
+ raw_value = @humidifier_settings &= ~0xc000
68
+ raw_value |= 0x4000 if humidifier_mode == :auto
69
+ raw_value |= 0x8000 if dehumidifier_mode == :auto
70
+ holding_registers[abc.iz2? ? 21_114 : 12_309] = raw_value
71
+ @humidifier_mode = humidifier_mode
72
+ @dehumidifier_mode = dehumidifier_mode
73
+ end
74
+
75
+ def humidification_target=(value)
76
+ set_humidistat_targets(value, dehumidification_target)
77
+ end
78
+
79
+ def dehumidification_target=(value)
80
+ set_humidistat_targets(humidification_target, value)
81
+ end
82
+
83
+ def set_humidistat_targets(humidification_target, dehumidification_target)
84
+ raise ArgumentError unless (15..50).include?(humidification_target)
85
+ raise ArgumentError unless (35..65).include?(dehumidification_target)
86
+
87
+ holding_registers[iz2? ? 21_115 : 12_310] = (humidification_target << 8) + dehumidification_target
88
+ @humidification_target = humidification_target
89
+ @dehumidification_target = dehumidification_target
90
+ end
91
+ end
92
+ end
data/lib/aurora/pump.rb CHANGED
@@ -5,7 +5,8 @@ require "aurora/component"
5
5
  module Aurora
6
6
  module Pump
7
7
  class GenericPump < Component
8
- attr_reader :type, :watts, :waterflow
8
+ attr_reader :type, :watts, :waterflow, :running
9
+ alias running? running
9
10
 
10
11
  def initialize(abc, type)
11
12
  super(abc)
@@ -21,6 +22,7 @@ module Aurora
21
22
  def refresh(registers)
22
23
  @waterflow = registers[1117]
23
24
  @watts = registers[1164] if abc.energy_monitoring?
25
+ @running = registers[1104].include?(:loop_pump)
24
26
  end
25
27
  end
26
28
 
@@ -302,23 +302,23 @@ module Aurora
302
302
 
303
303
  def axb_inputs(value)
304
304
  result = {}
305
- result["Smart Grid"] = value & 0x001 == 0x001
306
- result["Home Automation 1"] = value & 0x002 == 0x002
307
- result["Home Automation 2"] = value & 0x004 == 0x004
308
- result["Pump Slave"] = value & 0x008 == 0x008
305
+ result[:smart_grid] = value & 0x001 == 0x001
306
+ result[:ha1] = value & 0x002 == 0x002
307
+ result[:ha2] = value & 0x004 == 0x004
308
+ result[:pump_slave] = value & 0x008 == 0x008
309
309
 
310
310
  result[:mb_address] = value & 0x010 == 0x010 ? 3 : 4
311
311
  result[:sw1_2] = value & 0x020 == 0x020 # future use # rubocop:disable Naming/VariableNumber
312
312
  result[:sw1_3] = value & 0x040 == 0x040 # future use # rubocop:disable Naming/VariableNumber
313
- result[:cycle_with] = if value & 0x080 == 0x080 && value & 0x100 == 0x100
314
- "Blower"
315
- elsif value & 0x100 == 0x100
316
- "Low Capacity Compressor"
317
- elsif value & 0x080 == 0x080
318
- "High Capacity Compressor"
319
- else
320
- "Thermostat Dehumidifier"
321
- end
313
+ result[:accessory_relay2] = if value & 0x080 == 0x080 && value & 0x100 == 0x100
314
+ :blower
315
+ elsif value & 0x100 == 0x100
316
+ :low_capacity_compressor
317
+ elsif value & 0x080 == 0x080
318
+ :high_capacity_compressor
319
+ else
320
+ :dehumidifier
321
+ end
322
322
  leftover = value & ~0x1ff
323
323
  result[:unknown] = format("0x%04x", leftover) unless leftover.zero?
324
324
  result
@@ -523,7 +523,6 @@ module Aurora
523
523
  ->(v) { PUMP_TYPE[v] } => [413],
524
524
  ->(v) { PHASE_TYPE[v] } => [416],
525
525
  method(:iz2_fan_desired) => [565],
526
- ->(v) { v == 0xffff ? 0 : v } => 601..699,
527
526
  ->(registers, idx) { to_string(registers, idx, 8) } => [710],
528
527
  ->(v) { COMPONENT_STATUS[v] } => [800, 803, 806, 812, 815, 818, 824, 827],
529
528
  method(:axb_inputs) => [1103],
@@ -534,8 +533,8 @@ module Aurora
534
533
  method(:thermostat_configuration2) => [12_006],
535
534
  ->(v) { HEATING_MODE[v] } => [12_606, 21_202, 21_211, 21_220, 21_229, 21_238, 21_247],
536
535
  ->(v) { FAN_MODE[v] } => [12_621, 21_205, 21_214, 21_223, 21_232, 21_241, 21_250],
537
- ->(v) { from_bitmask(v, HUMIDIFIER_SETTINGS) } => [31_109],
538
- ->(v) { { humidification_target: v >> 8, dehumidification_target: v & 0xff } } => [31_110],
536
+ ->(v) { from_bitmask(v, HUMIDIFIER_SETTINGS) } => [12_309, 21_114, 31_109],
537
+ ->(v) { { humidification_target: v >> 8, dehumidification_target: v & 0xff } } => [12_310, 21_115, 31_110],
539
538
  method(:iz2_demand) => [31_005],
540
539
  method(:zone_configuration1) => [12_005, 31_008, 31_011, 31_014, 31_017, 31_020, 31_023],
541
540
  method(:zone_configuration2) => [31_009, 31_012, 31_015, 31_018, 31_021, 31_024],
@@ -889,16 +888,20 @@ module Aurora
889
888
  3906 => "VS Drive SuperHeat Temperature",
890
889
  12_005 => "Fan Configuration",
891
890
  12_006 => "Heating Mode",
891
+ 12_309 => "De/Humidifier Mode",
892
+ 12_310 => "De/Humidifier Setpoints",
892
893
  12_606 => "Heating Mode (write)",
893
894
  12_619 => "Heating Setpoint (write)",
894
895
  12_620 => "Cooling Setpoint (write)",
895
896
  12_621 => "Fan Mode (write)",
896
897
  12_622 => "Intermittent Fan On Time (write)",
897
898
  12_623 => "Intermittent Fan Off Time (write)",
899
+ 21_114 => "IZ2 De/Humidifier Mode (write)",
900
+ 21_115 => "IZ2 De/Humidifier Setpoints (write)",
898
901
  31_003 => "Outdoor Temp",
899
902
  31_005 => "IZ2 Demand",
900
- 31_109 => "Humidifier Mode", # write to 21114
901
- 31_110 => "Manual De/Humidification Target", # write to 21115
903
+ 31_109 => "De/Humidifier Mode",
904
+ 31_110 => "Manual De/Humidification Setpoints",
902
905
  31_400 => "Dealer Name",
903
906
  31_413 => "Dealer Phone",
904
907
  31_421 => "Dealer Address 1",
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Aurora
4
- VERSION = "0.5.3"
4
+ VERSION = "0.6.0"
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.5.3
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cody Cutrer
@@ -139,7 +139,7 @@ files:
139
139
  - lib/aurora/compressor.rb
140
140
  - lib/aurora/core_ext/string.rb
141
141
  - lib/aurora/dhw.rb
142
- - lib/aurora/humidifier.rb
142
+ - lib/aurora/humidistat.rb
143
143
  - lib/aurora/iz2_zone.rb
144
144
  - lib/aurora/mock_abc.rb
145
145
  - lib/aurora/modbus/server.rb
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "aurora/component"
4
-
5
- module Aurora
6
- class Humidifier < Component
7
- attr_reader :running
8
- alias running? running
9
-
10
- def refresh(registers)
11
- outputs = registers[30]
12
- @running = outputs.include?(:accessory)
13
- end
14
- end
15
- end