waterfurnace_aurora 0.4.5 → 0.5.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: 792824de511d596a9c0cacc0ef0eae5385e0ec72e4c9da1765292d4825256769
4
- data.tar.gz: 9cbd94692b1074e7430e6089348d07d5a31506f6e679d82aaa8762316efbf634
3
+ metadata.gz: 16b9a4ef085dc672bf6b360947c70a959f03b3406f0c2dae4eac614a2f12c412
4
+ data.tar.gz: 5a7ef967170bd5440b94407e05cfe6e2f1bae40d838a23de26d442a1e4fa9a14
5
5
  SHA512:
6
- metadata.gz: cec2a4f8ef4353a3c824af4d701dc6fe8ccc904d2ead6176b3507828023430ff335a6d2f2a5132e764d21adf8242973677d0b857079c74f16e8b49ae14a45977
7
- data.tar.gz: c52dfdbc4e6e18c636c3e61226b11f7b4cc056fd76413794a41235936783f07ea09f46db77a901c02957a50ba82555cf35e84794c8903d73b00cf2fd830b480b
6
+ metadata.gz: d31c1d4a82dc9420adedd8b5043ebde59845eb5cc90c14109ad51d533687e0fa7010e91c04858773d9f40523f534118d72f891fb673344810244e2d121c0b764
7
+ data.tar.gz: b83b92e7b7ad9ecb2dda5eae57d2d460a82285420e169acc317c54390234cc123bead659fc56e2be53dbb602dd24e0b4cce66bd4223bd52badd7d543d641a4a7
@@ -76,8 +76,10 @@ class MQTTBridge
76
76
  @abc.refresh
77
77
 
78
78
  components = { @homie_abc => @abc,
79
+ @compressor => @abc.compressor,
79
80
  @blower => @abc.blower,
80
- @pump => @abc.pump }
81
+ @pump => @abc.pump,
82
+ @dhw => @abc.dhw }.compact
81
83
  @abc.zones.each_with_index do |z, idx|
82
84
  homie_zone = @homie["zone#{idx + 1}"]
83
85
  components[homie_zone] = z
@@ -89,12 +91,6 @@ class MQTTBridge
89
91
  end
90
92
  end
91
93
 
92
- if @abc.dhw?
93
- @dhw["enabled"].value = @abc.dhw_enabled
94
- @dhw["water-temperature"].value = @abc.dhw_water_temperature
95
- @dhw["set-point"].value = @abc.dhw_setpoint
96
- end
97
-
98
94
  @abc.faults.each_with_index do |fault_count, i|
99
95
  @faults["e#{i + 1}"].value = fault_count
100
96
  end
@@ -109,8 +105,6 @@ class MQTTBridge
109
105
 
110
106
  def publish_basic_attributes
111
107
  @homie_abc = @homie.node("abc", "Aurora Basic Control", "ABC") do |node|
112
- node.property("compressor-speed", "Compressor Speed", :integer, @abc.compressor_speed,
113
- format: @abc.vs_drive? ? 0..12 : 0..2)
114
108
  node.property("current-mode", "Current Heating/Cooling Mode", :enum, @abc.current_mode,
115
109
  format: %w[lockout standby blower heating cooling eh1 eh2 emergency waiting dehumidify])
116
110
  node.property("entering-air-temperature", "Entering Air Temperature", :float, @abc.entering_air_temperature,
@@ -128,13 +122,29 @@ class MQTTBridge
128
122
  format: 0..100)
129
123
  node.property("fp1", "FP1 Sensor", :float, @abc.fp1, unit: "ºF")
130
124
  node.property("fp2", "FP2 Sensor", :float, @abc.fp2, unit: "ºF")
131
- %i[compressor aux_heat total].each do |component|
125
+ %i[aux_heat total].each do |component|
132
126
  component = "#{component}_watts"
133
127
  node.property(component.tr("_", "-"), component.tr("_", " ").titleize, :integer,
134
128
  @abc.public_send(component), unit: "W")
135
129
  end
136
130
  end
137
131
 
132
+ @compressor = @homie.node("compressor", "Compressor", @abc.compressor.type) do |node|
133
+ node.property("speed", "Current compressor speed", :integer, @abc.compressor.speed,
134
+ format: @abc.compressor.speed_range)
135
+ node.property("watts", "Energy Usage", :integer, @abc.compressor.watts, unit: "W") if @abc.energy_monitoring?
136
+
137
+ next unless @abc.compressor.is_a?(Aurora::Compressor::VSDrive)
138
+
139
+ node.property("ambient-temperature", "Compressor ambient temperature", :float,
140
+ @abc.compressor.ambient_temperature, unit: "ºF")
141
+
142
+ next unless @abc.iz2?
143
+
144
+ node.property("iz2-desired-speed", "IZ2 Desired Speed", :integer, @abc.compressor.iz2_desired_speed,
145
+ format: 0..12)
146
+ end
147
+
138
148
  @blower = @homie.node("blower", "Blower", @abc.blower.type) do |node|
139
149
  if @abc.blower.respond_to?(:running)
140
150
  node.property("running", "Blower is running", :boolean, @abc.blower.running?)
@@ -154,10 +164,11 @@ class MQTTBridge
154
164
  @mutex.synchronize { property.value = @abc.blower.public_send("#{field}=", value) }
155
165
  end
156
166
  end
157
- if @abc.iz2?
158
- node.property("iz2-desired-speed", "IZ2 Desired Speed", :integer, @abc.blower.iz2_desired_speed,
159
- format: 0..100, unit: "%")
160
- end
167
+
168
+ next unless @abc.iz2?
169
+
170
+ node.property("iz2-desired-speed", "IZ2 Desired Speed", :integer, @abc.blower.iz2_desired_speed,
171
+ format: 0..100, unit: "%")
161
172
  end
162
173
 
163
174
  @pump = @homie.node("pump", "Loop Pump", @abc.pump.type) do |node|
@@ -183,16 +194,16 @@ class MQTTBridge
183
194
  end
184
195
  end
185
196
 
186
- if @abc.dhw?
197
+ if @abc.dhw
187
198
  @dhw = @homie.node("dhw", "Domestic Hot Water Generator", "DHW") do |node|
188
- node.property("enabled", "Enabled", :boolean, @abc.dhw_enabled) do |value, property|
189
- @mutex.synchronize { property.value = @abc.dhw_enabled = value }
199
+ node.property("enabled", "Enabled", :boolean, @abc.dhw.enabled) do |value, property|
200
+ @mutex.synchronize { property.value = @abc.dhw.enabled = value }
190
201
  end
191
- node.property("water-temperature", "DHW Water Temperature", :float,
192
- @abc.dhw_water_temperature, unit: "ºF")
193
- node.property("set-point", "DHW Set Point", :float, @abc.dhw_setpoint, format: 100..140,
194
- unit: "ºF") do |value, property|
195
- @mutex.synchronize { property.value = @abc.dhw_setpoint = value }
202
+ node.property("water-temperature", "Water Temperature", :float,
203
+ @abc.dhw.water_temperature, unit: "ºF")
204
+ node.property("set-point", "Set Point", :float, @abc.dhw.set_point, format: 100..140,
205
+ unit: "ºF") do |value, property|
206
+ @mutex.synchronize { property.value = @abc.dhw.set_point = value }
196
207
  end
197
208
  end
198
209
  end
@@ -213,25 +224,21 @@ class MQTTBridge
213
224
  format: allowed_modes) do |value, property|
214
225
  @mutex.synchronize { property.value = zone.target_mode = value.to_sym }
215
226
  end
216
- if zone.respond_to?(:current_mode) # TODO: implement for non-IZ2
217
- node.property("current-mode", "Current Heating/Cooling Mode Requested", :enum, zone.current_mode,
218
- format: %w[standby h1 h2 h3 c1 c2])
219
- end
227
+ node.property("current-mode", "Current Heating/Cooling Mode Requested", :enum, zone.current_mode,
228
+ format: %w[standby h1 h2 h3 c1 c2])
220
229
  node.property("target-fan-mode", "Target Fan Mode", :enum, zone.target_fan_mode,
221
230
  format: %w[auto continuous intermittent]) do |value, property|
222
231
  @mutex.synchronize { property.value = zone.target_fan_mode = value.to_sym }
223
232
  end
224
- if zone.respond_to?(:current_fan_mode) # TODO: implement for non-IZ2
225
- node.property("current-fan-mode", "Current Fan Status", :boolean, zone.current_fan_mode)
226
- node.property("fan-intermittent-on", "Fan Intermittent Mode On Duration", :enum, zone.fan_intermittent_on,
227
- unit: "M", format: %w[0 5 10 15 20]) do |value, property|
228
- @mutex.synchronize { property.value = zone.fan_intermittent_on = value.to_i }
229
- end
230
- node.property("fan-intermittent-off", "Fan Intermittent Mode Off Duration", :enum, zone.fan_intermittent_on,
231
- unit: "M", format: %w[0 5 10 15 20 25 30 35 40]) do |value, property|
232
- @mutex.synchronize { property.value = zone.fan_intermittent_on = value.to_i }
233
- end
233
+ node.property("fan-intermittent-on", "Fan Intermittent Mode On Duration", :enum, zone.fan_intermittent_on,
234
+ unit: "M", format: %w[0 5 10 15 20]) do |value, property|
235
+ @mutex.synchronize { property.value = zone.fan_intermittent_on = value.to_i }
236
+ end
237
+ node.property("fan-intermittent-off", "Fan Intermittent Mode Off Duration", :enum, zone.fan_intermittent_on,
238
+ unit: "M", format: %w[0 5 10 15 20 25 30 35 40]) do |value, property|
239
+ @mutex.synchronize { property.value = zone.fan_intermittent_on = value.to_i }
234
240
  end
241
+ node.property("current-fan-mode", "Current Fan Status", :boolean, zone.current_fan_mode)
235
242
  if zone.is_a?(Aurora::IZ2Zone)
236
243
  node.property("priority", "Zone Priority", :enum, zone.priority, format: %w[economy comfort])
237
244
  node.property("size", "Size", :enum, zone.size, format: %w[0 25 45 70])
@@ -4,6 +4,8 @@ require "yaml"
4
4
  require "uri"
5
5
 
6
6
  require "aurora/blower"
7
+ require "aurora/compressor"
8
+ require "aurora/dhw"
7
9
  require "aurora/iz2_zone"
8
10
  require "aurora/pump"
9
11
  require "aurora/thermostat"
@@ -40,23 +42,20 @@ module Aurora
40
42
  attr_reader :modbus_slave,
41
43
  :serial_number,
42
44
  :zones,
45
+ :compressor,
43
46
  :blower,
44
47
  :pump,
48
+ :dhw,
45
49
  :faults,
46
50
  :current_mode,
47
- :dhw_enabled,
48
- :dhw_setpoint,
49
51
  :entering_air_temperature,
50
52
  :relative_humidity,
51
53
  :leaving_air_temperature,
52
54
  :leaving_water_temperature,
53
55
  :entering_water_temperature,
54
- :dhw_water_temperature,
55
- :compressor_speed,
56
56
  :outdoor_temperature,
57
57
  :fp1,
58
58
  :fp2,
59
- :compressor_watts,
60
59
  :aux_heat_watts,
61
60
  :total_watts
62
61
 
@@ -68,9 +67,16 @@ module Aurora
68
67
  registers = Aurora.transform_registers(raw_registers.dup)
69
68
  @program = registers[88]
70
69
  @serial_number = registers[105]
71
- @dhw_water_temperature = registers[1114]
72
70
  @energy_monitor = raw_registers[412]
73
71
 
72
+ @zones = if iz2?
73
+ iz2_zone_count = @modbus_slave.holding_registers[483]
74
+ (0...iz2_zone_count).map { |i| IZ2Zone.new(self, i + 1) }
75
+ else
76
+ [Thermostat.new(self)]
77
+ end
78
+
79
+ @compressor = @program == "ABCVSP" ? Compressor::VSDrive.new(self) : Compressor::GenericCompressor.new(self)
74
80
  @blower = case raw_registers[404]
75
81
  when 1, 2 then Blower::ECM.new(self, registers[404])
76
82
  when 3 then Blower::FiveSpeed.new(self, registers[404])
@@ -83,13 +89,8 @@ module Aurora
83
89
  Pump::GenericPump.new(self,
84
90
  registers[413])
85
91
  end
92
+ @dhw = DHW.new(self) if (-999..999).include?(registers[1114])
86
93
 
87
- @zones = if iz2?
88
- iz2_zone_count = @modbus_slave.holding_registers[483]
89
- (0...iz2_zone_count).map { |i| IZ2Zone.new(self, i + 1) }
90
- else
91
- [Thermostat.new(self)]
92
- end
93
94
  @faults = []
94
95
  end
95
96
 
@@ -128,26 +129,18 @@ module Aurora
128
129
  end
129
130
 
130
131
  def refresh
131
- registers_to_read = [6, 19..20, 25, 30, 344, 740..741, 900, 1110..1111, 1114, 1147..1153, 1165,
132
+ registers_to_read = [6, 19..20, 25, 30, 344, 740..741, 900, 1110..1111, 1114, 1150..1153, 1165,
132
133
  31_003]
133
- registers_to_read << (400..401) if dhw?
134
+ zones.each do |z|
135
+ registers_to_read.concat(z.registers_to_read)
136
+ end
137
+ registers_to_read.concat(compressor.registers_to_read)
134
138
  registers_to_read.concat(blower.registers_to_read)
135
139
  registers_to_read.concat(pump.registers_to_read)
136
- registers_to_read.concat([362, 3001]) if vs_drive?
137
-
138
- if zones.first.is_a?(IZ2Zone)
139
- zones.each_with_index do |_z, i|
140
- base1 = 21_203 + i * 9
141
- base2 = 31_007 + i * 3
142
- base3 = 31_200 + i * 3
143
- registers_to_read << (base1..(base1 + 1))
144
- registers_to_read << (base2..(base2 + 2))
145
- registers_to_read << base3
146
- end
147
- else
148
- registers_to_read << 502
149
- registers_to_read << (745..746)
150
- end
140
+ registers_to_read.concat(dhw.registers_to_read) if dhw
141
+ # need dehumidify mode to calculate final current mode;
142
+ # apparently non-VSD doesn't have this register at all?
143
+ registers_to_read.concat([362]) if compressor.is_a?(Compressor::VSDrive)
151
144
 
152
145
  @faults = @modbus_slave.holding_registers[601..699]
153
146
 
@@ -156,23 +149,11 @@ module Aurora
156
149
 
157
150
  outputs = registers[30]
158
151
 
159
- @dhw_enabled = registers[400]
160
- @dhw_setpoint = registers[401]
161
152
  @entering_air_temperature = registers[740]
162
153
  @relative_humidity = registers[741]
163
154
  @leaving_air_temperature = registers[900]
164
155
  @leaving_water_temperature = registers[1110]
165
156
  @entering_water_temperature = registers[1111]
166
- @dhw_water_temperature = registers[1114]
167
- @compressor_speed = if vs_drive?
168
- registers[3001]
169
- elsif outputs.include?(:cc2)
170
- 2
171
- elsif outputs.include?(:cc)
172
- 1
173
- else
174
- 0
175
- end
176
157
  @outdoor_temperature = registers[31_003]
177
158
  @fp1 = registers[19]
178
159
  @fp2 = registers[20]
@@ -180,7 +161,6 @@ module Aurora
180
161
  @error = registers[25] & 0x7fff
181
162
  @derated = (41..46).include?(@error)
182
163
  @safe_mode = [47, 48, 49, 72, 74].include?(@error)
183
- @compressor_watts = registers[1147]
184
164
  @aux_heat_watts = registers[1151]
185
165
  @total_watts = registers[1153]
186
166
 
@@ -202,12 +182,13 @@ module Aurora
202
182
  :standby
203
183
  end
204
184
 
205
- blower.refresh(registers)
206
- pump.refresh(registers)
207
-
208
185
  zones.each do |z|
209
186
  z.refresh(registers)
210
187
  end
188
+ compressor.refresh(registers)
189
+ blower.refresh(registers)
190
+ pump.refresh(registers)
191
+ dhw&.refresh(registers)
211
192
  end
212
193
 
213
194
  def cooling_airflow_adjustment=(value)
@@ -215,16 +196,6 @@ module Aurora
215
196
  @modbus_slave.holding_registers[346] = value
216
197
  end
217
198
 
218
- def dhw_enabled=(value)
219
- @modbus_slave.holding_registers[400] = value ? 1 : 0
220
- end
221
-
222
- def dhw_setpoint=(value)
223
- raise ArgumentError unless (100..140).include?(value)
224
-
225
- @modbus_slave.holding_registers[401] = (value * 10).to_i
226
- end
227
-
228
199
  def loop_pressure_trip=(value)
229
200
  @modbus_slave.holding_registers[419] = (value * 10).to_i
230
201
  end
@@ -270,14 +241,6 @@ module Aurora
270
241
  @energy_monitor == 2
271
242
  end
272
243
 
273
- def vs_drive?
274
- @program == "ABCVSP"
275
- end
276
-
277
- def dhw?
278
- (-999..999).include?(dhw_water_temperature)
279
- end
280
-
281
244
  # config aurora system
282
245
  { thermostat: 800, axb: 806, iz2: 812, aoc: 815, moc: 818, eev2: 824 }.each do |(component, register)|
283
246
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
@@ -6,6 +6,12 @@ module Aurora
6
6
  @abc = abc
7
7
  end
8
8
 
9
+ def inspect
10
+ "#<Aurora::#{self.class.name} #{(instance_variables - [:@abc]).map do |iv|
11
+ "#{iv}=#{instance_variable_get(iv).inspect}"
12
+ end.join(', ')}>"
13
+ end
14
+
9
15
  private
10
16
 
11
17
  attr_reader :abc
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "aurora/component"
4
+
5
+ module Aurora
6
+ module Compressor
7
+ class GenericCompressor < Component
8
+ attr_reader :speed, :watts
9
+
10
+ def type
11
+ "Compressor"
12
+ end
13
+
14
+ def speed_range
15
+ 0..2
16
+ end
17
+
18
+ def registers_to_read
19
+ if abc.energy_monitoring?
20
+ [1146..1147]
21
+ else
22
+ []
23
+ end
24
+ end
25
+
26
+ def refresh(registers)
27
+ outputs = registers[30]
28
+ @speed = if outputs.include?(:cc2)
29
+ 2
30
+ elsif outputs.include?(:cc)
31
+ 1
32
+ else
33
+ 0
34
+ end
35
+ @watts = registers[1146] if abc.energy_monitoring?
36
+ end
37
+ end
38
+
39
+ class VSDrive < GenericCompressor
40
+ attr_reader :ambient_temperature, :iz2_desired_speed
41
+
42
+ def type
43
+ "Variable Speed Drive"
44
+ end
45
+
46
+ def speed_range
47
+ 0..12
48
+ end
49
+
50
+ def registers_to_read
51
+ result = super + [209, 3001, 3326]
52
+ result << 564 if abc.iz2?
53
+ result
54
+ end
55
+
56
+ def refresh(registers)
57
+ super
58
+
59
+ @speed = registers[3001]
60
+ @ambient_temperature = registers[3326]
61
+ @iz2_desired_speed = registers[564] if abc.iz2?
62
+ end
63
+ end
64
+ end
65
+ end
data/lib/aurora/dhw.rb ADDED
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "aurora/component"
4
+
5
+ module Aurora
6
+ class DHW < Component
7
+ attr_reader :enabled, :set_point, :water_temperature
8
+
9
+ def registers_to_read
10
+ [400..401, 1114]
11
+ end
12
+
13
+ def refresh(registers)
14
+ @enabled = registers[400]
15
+ @set_point = registers[401]
16
+ @water_temperature = registers[1114]
17
+ end
18
+
19
+ def enabled=(value)
20
+ holding_registers[400] = value ? 1 : 0
21
+ end
22
+
23
+ def set_point=(value) # rubocop:disable Naming/AccessorMethodName
24
+ raise ArgumentError unless (100..140).include?(value)
25
+
26
+ raw_value = (value * 10).to_i
27
+ holding_registers[401] = raw_value
28
+ @set_point = value
29
+ end
30
+ end
31
+ end
@@ -5,18 +5,22 @@ require "aurora/thermostat"
5
5
  module Aurora
6
6
  class IZ2Zone < Thermostat
7
7
  attr_reader :zone_number,
8
- :current_mode,
9
- :current_fan_mode,
10
- :fan_intermittent_on,
11
- :fan_intermittent_off,
12
8
  :priority,
13
- :size, :normalized_size
9
+ :size,
10
+ :normalized_size
14
11
 
15
12
  def initialize(abc, zone_number)
16
13
  super(abc)
17
14
  @zone_number = zone_number
18
15
  end
19
16
 
17
+ def registers_to_read
18
+ base1 = 21_203 + (zone_number - 1) * 9
19
+ base2 = 31_007 + (zone_number - 1) * 3
20
+ base3 = 31_200 + (zone_number - 1) * 3
21
+ [base1..(base1 + 1), base2..(base2 + 2), base3]
22
+ end
23
+
20
24
  def refresh(registers)
21
25
  @ambient_temperature = registers[31_007 + (zone_number - 1) * 3]
22
26
 
@@ -420,6 +420,15 @@ module Aurora
420
420
  end
421
421
  end
422
422
 
423
+ def thermostat_configuration2(value)
424
+ result = {
425
+ mode: HEATING_MODE[(value >> 8) & 0x07]
426
+ }
427
+ leftover = value & ~0x0700
428
+ result[:unknown] = format("0x%04x", leftover) unless leftover.zero?
429
+ result
430
+ end
431
+
423
432
  def zone_configuration1(value)
424
433
  fan = if value & 0x80 == 0x80
425
434
  :continuous
@@ -433,7 +442,7 @@ module Aurora
433
442
  on_time: ((value >> 9) & 0x7) * 5,
434
443
  off_time: (((value >> 12) & 0x7) + 1) * 5,
435
444
  cooling_target_temperature: ((value & 0x7e) >> 1) + 36,
436
- heating_target_temperature_carry: value & 0o1
445
+ heating_target_temperature_carry: value & 0x01
437
446
  }
438
447
  leftover = value & ~0x7fff
439
448
  result[:unknown] = format("0x%04x", leftover) unless leftover.zero?
@@ -503,7 +512,7 @@ module Aurora
503
512
  ->(v) { from_bitmask(v, VS_ALARM2) } => [218, 3227],
504
513
  ->(v) { from_bitmask(v, VS_EEV2) } => [280, 3804],
505
514
  method(:vs_manual_control) => [323],
506
- NEGATABLE => [346, 1146],
515
+ NEGATABLE => [346],
507
516
  ->(v) { BRINE_TYPE[v] } => [402],
508
517
  ->(v) { FLOW_METER_TYPE[v] } => [403],
509
518
  ->(v) { BLOWER_TYPE[v] } => [404],
@@ -521,12 +530,13 @@ module Aurora
521
530
  ->(v) { TO_TENTHS.call(NEGATABLE.call(v)) } => [1135, 1136],
522
531
  method(:to_int32) => [1146, 1148, 1150, 1152, 1154, 1156, 1164, 3422, 3424],
523
532
  method(:manual_operation) => [3002],
533
+ method(:thermostat_configuration2) => [12_006],
524
534
  ->(v) { HEATING_MODE[v] } => [12_606, 21_202, 21_211, 21_220, 21_229, 21_238, 21_247],
525
535
  ->(v) { FAN_MODE[v] } => [12_621, 21_205, 21_214, 21_223, 21_232, 21_241, 21_250],
526
536
  ->(v) { from_bitmask(v, HUMIDIFIER_SETTINGS) } => [31_109],
527
537
  ->(v) { { humidification_target: v >> 8, dehumidification_target: v & 0xff } } => [31_110],
528
538
  method(:iz2_demand) => [31_005],
529
- method(:zone_configuration1) => [31_008, 31_011, 31_014, 31_017, 31_020, 31_023],
539
+ method(:zone_configuration1) => [12_005, 31_008, 31_011, 31_014, 31_017, 31_020, 31_023],
530
540
  method(:zone_configuration2) => [31_009, 31_012, 31_015, 31_018, 31_021, 31_024],
531
541
  method(:zone_configuration3) => [31_200, 31_203, 31_206, 31_209, 31_212, 31_215],
532
542
  ->(registers, idx) { to_string(registers, idx, 13) } => [31_400],
@@ -876,10 +886,14 @@ module Aurora
876
886
  3904 => "VS Drive Leaving Air Temperature?",
877
887
  3905 => "VS Drive Saturated Evaporator Discharge Temperature",
878
888
  3906 => "VS Drive SuperHeat Temperature",
889
+ 12_005 => "Fan Configuration",
890
+ 12_006 => "Heating Mode",
879
891
  12_606 => "Heating Mode (write)",
880
892
  12_619 => "Heating Setpoint (write)",
881
893
  12_620 => "Cooling Setpoint (write)",
882
894
  12_621 => "Fan Mode (write)",
895
+ 12_622 => "Intermittent Fan On Time (write)",
896
+ 12_623 => "Intermittent Fan Off Time (write)",
883
897
  31_003 => "Outdoor Temp",
884
898
  31_005 => "IZ2 Demand",
885
899
  31_109 => "Humidifier Mode", # write to 21114
@@ -5,15 +5,39 @@ require "aurora/component"
5
5
  module Aurora
6
6
  class Thermostat < Component
7
7
  attr_reader :target_mode,
8
+ :current_mode,
8
9
  :target_fan_mode,
10
+ :current_fan_mode,
9
11
  :ambient_temperature,
10
12
  :cooling_target_temperature,
11
- :heating_target_temperature
13
+ :heating_target_temperature,
14
+ :fan_intermittent_on,
15
+ :fan_intermittent_off
16
+
17
+ def registers_to_read
18
+ [31, 502, 745..746, 12_005..12_006]
19
+ end
12
20
 
13
21
  def refresh(registers)
14
22
  @ambient_temperature = registers[502]
15
23
  @heating_target_temperature = registers[745]
16
24
  @cooling_target_temperature = registers[746]
25
+ config1 = registers[12_005]
26
+ config2 = registers[12_006]
27
+ @target_fan_mode = config1[:fan]
28
+ @fan_intermittent_on = config1[:on_time]
29
+ @fan_intermittent_off = config1[:off_time]
30
+ @target_mode = config2[:mode]
31
+
32
+ inputs = registers[31]
33
+ @current_fan_mode = inputs.include?(:g)
34
+ @current_mode = if inputs[:y2]
35
+ inputs[:o] ? :c2 : :h2
36
+ elsif inputs[:y1]
37
+ inputs[:o] ? :c1 : :h1
38
+ else
39
+ :standby
40
+ end
17
41
  end
18
42
 
19
43
  def target_mode=(value)
@@ -46,10 +70,18 @@ module Aurora
46
70
  @cooling_target_temperature = value
47
71
  end
48
72
 
49
- def inspect
50
- "#<Aurora::#{self.class.name} #{(instance_variables - [:@abc]).map do |iv|
51
- "#{iv}=#{instance_variable_get(iv).inspect}"
52
- end.join(', ')}>"
73
+ def fan_intermittent_on=(value)
74
+ return unless value >= 0 && value <= 25 && (value % 5).zero?
75
+
76
+ holding_registers[12_622] = value
77
+ @fan_intermittent_on = value
78
+ end
79
+
80
+ def fan_intermittent_off=(value)
81
+ return unless value >= 0 && value <= 40 && (value % 5).zero?
82
+
83
+ holding_registers[12_623] = value
84
+ @fan_intermittent_off = value
53
85
  end
54
86
  end
55
87
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Aurora
4
- VERSION = "0.4.5"
4
+ VERSION = "0.5.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.4.5
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cody Cutrer
@@ -136,7 +136,9 @@ files:
136
136
  - lib/aurora/abc_client.rb
137
137
  - lib/aurora/blower.rb
138
138
  - lib/aurora/component.rb
139
+ - lib/aurora/compressor.rb
139
140
  - lib/aurora/core_ext/string.rb
141
+ - lib/aurora/dhw.rb
140
142
  - lib/aurora/iz2_zone.rb
141
143
  - lib/aurora/mock_abc.rb
142
144
  - lib/aurora/modbus/server.rb