waterfurnace_aurora 0.5.2 → 0.6.2

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: 5c89c3d73941d7574fbe1088bf792676f772abfb98dab07be0de27a61323ec96
4
- data.tar.gz: 13a5a82be919ee67bbbc87357eac1cf6aaba1b34514fbd808b9411dfc37bcb45
3
+ metadata.gz: 2e4165620d720c36045b8f8aa29a553d6de03aa555ac9083f5491ea47087ee4b
4
+ data.tar.gz: 8532386c1f010471d2d99a2318540eada6a9aa670f9efd1251f632c2db12c11d
5
5
  SHA512:
6
- metadata.gz: ce768bdc79fc4cd2a406ebf15757f587d373030cec21efc64076b3951a7c97f631f1e47a0e810005b24553fdd78eb4aec869022c8e0f6f33e409522f473e942b
7
- data.tar.gz: ab5cba75479435f32a42bca6fd8155a5954674996b75a4a2afe397241bce519720a083aaaf0ccf3976a8c289170ec39553f63e9ba036248bdadcf408022e7ffb
6
+ metadata.gz: 023b5180a5a35524670d954be623a6b806d0be96070eb26c6820277544948316583d4b698843bd937f8e0c583f933398dcb6a0c91356872967092cfcb6ff4955
7
+ data.tar.gz: 15033ae835c70fc3532ddaadef932e0498bb8504938066cfd9fbfca494772b5642f6e21b6483ca52499db5baf506d03aeb458b3a1cf899970eb128fd8fc4cf26
data/exe/aurora_fetch CHANGED
@@ -15,6 +15,10 @@ options = OptionParser.new do |opts|
15
15
 
16
16
  opts.on("--debug-modbus", "Print actual protocol bytes") { debug_modbus = true }
17
17
  opts.on("-y", "--yaml", "Output raw values as YAML") { yaml = true }
18
+ opts.on("-v", "--version", "Print version") do
19
+ puts Aurora::VERSION
20
+ exit
21
+ end
18
22
  opts.on("-h", "--help", "Prints this help") do
19
23
  puts opts
20
24
  exit
data/exe/aurora_monitor CHANGED
@@ -22,6 +22,10 @@ options = OptionParser.new do |opts|
22
22
  opts.on("--debug-modbus", "Print actual protocol bytes") { debug_modbus = true }
23
23
  opts.on("--ignore-awl-heartbeat", "Don't print AWL heartbeat requests") { ignore_awl_heartbeat = true }
24
24
  opts.on("--ignore-sensors", "Don't print sensor registers (i.e. because they change a lot)") { ignore_sensors = true }
25
+ opts.on("-v", "--version", "Print version") do
26
+ puts Aurora::VERSION
27
+ exit
28
+ end
25
29
  opts.on("-h", "--help", "Prints this help") do
26
30
  puts opts
27
31
  exit
@@ -15,6 +15,10 @@ options = OptionParser.new do |opts|
15
15
  opts.banner = "Usage: aurora_mqtt_bridge /path/to/serial/port [options]"
16
16
 
17
17
  opts.on("--debug-modbus", "Print actual protocol bytes") { debug_modbus = true }
18
+ opts.on("-v", "--version", "Print version") do
19
+ puts Aurora::VERSION
20
+ exit
21
+ end
18
22
  opts.on("-h", "--help", "Prints this help") do
19
23
  puts opts
20
24
  exit
@@ -91,7 +95,8 @@ class MQTTBridge
91
95
  @compressor => @abc.compressor,
92
96
  @blower => @abc.blower,
93
97
  @pump => @abc.pump,
94
- @dhw => @abc.dhw }.compact
98
+ @dhw => @abc.dhw,
99
+ @humidistat => @abc.humidistat }.compact
95
100
  @abc.zones.each_with_index do |z, idx|
96
101
  homie_zone = @homie["zone#{idx + 1}"]
97
102
  components[homie_zone] = z
@@ -104,6 +109,8 @@ class MQTTBridge
104
109
  end
105
110
 
106
111
  @abc.faults.each_with_index do |fault_count, i|
112
+ next if fault_count == 0xffff
113
+
107
114
  @faults["e#{i + 1}"].value = fault_count
108
115
  end
109
116
  end
@@ -117,8 +124,10 @@ class MQTTBridge
117
124
 
118
125
  def publish_basic_attributes
119
126
  @homie_abc = @homie.node("abc", "Aurora Basic Control", "ABC") do |node|
127
+ allowed_modes = %w[lockout standby blower heating cooling eh1 eh2 emergency waiting]
128
+ allowed_modes << "dehumidify" if @abc.compressor.is_a?(Aurora::Compressor::VSDrive)
120
129
  node.property("current-mode", "Current Heating/Cooling Mode", :enum, @abc.current_mode,
121
- format: %w[lockout standby blower heating cooling eh1 eh2 emergency waiting dehumidify])
130
+ format: allowed_modes)
122
131
  node.property("entering-air-temperature", "Entering Air Temperature", :float, @abc.entering_air_temperature,
123
132
  unit: "ºF")
124
133
  node.property("entering-water-temperature", "Entering Water Temperature", :float,
@@ -130,8 +139,7 @@ class MQTTBridge
130
139
  unless @abc.outdoor_temperature.zero? # TODO: figure out the config if this actually exists
131
140
  node.property("outdoor-temperature", "Outdoor Temperature", :float, @abc.outdoor_temperature, unit: "ºF")
132
141
  end
133
- node.property("relative-humidity", "Relative Humidity", :integer, @abc.relative_humidity, unit: "%",
134
- format: 0..100)
142
+
135
143
  node.property("fp1", "FP1 Sensor", :float, @abc.fp1, unit: "ºF")
136
144
  node.property("fp2", "FP2 Sensor", :float, @abc.fp2, unit: "ºF")
137
145
  %i[aux_heat total].each do |component|
@@ -158,9 +166,8 @@ class MQTTBridge
158
166
  end
159
167
 
160
168
  @blower = @homie.node("blower", "Blower", @abc.blower.type) do |node|
161
- if @abc.blower.respond_to?(:running)
162
- node.property("running", "Blower is running", :boolean, @abc.blower.running?)
163
- else
169
+ node.property("running", "Blower is running", :boolean, @abc.blower.running?)
170
+ if @abc.blower.respond_to?(:speed)
164
171
  node.property("speed", "Current blower speed", :integer, @abc.blower.speed, format: @abc.blower.speed_range)
165
172
  end
166
173
  node.property("watts", "Energy Usage", :integer, @abc.blower.watts, unit: "W") if @abc.energy_monitoring?
@@ -189,6 +196,7 @@ class MQTTBridge
189
196
 
190
197
  next unless @abc.pump.is_a?(Aurora::Pump::VSPump)
191
198
 
199
+ node.property("running", "Pump is running", :boolean, @abc.pump.running)
192
200
  node.property("speed", "Speed", :integer, @abc.pump.speed, format: 0..100, unit: "%") do |value, property|
193
201
  @mutex.synchronize { property.value = @abc.pump.speed = value }
194
202
  end
@@ -211,6 +219,7 @@ class MQTTBridge
211
219
  node.property("enabled", "Enabled", :boolean, @abc.dhw.enabled) do |value, property|
212
220
  @mutex.synchronize { property.value = @abc.dhw.enabled = value }
213
221
  end
222
+ node.property("running", "DHW Pump is running", :boolean, @abc.dhw.running?)
214
223
  node.property("water-temperature", "Water Temperature", :float,
215
224
  @abc.dhw.water_temperature, unit: "ºF")
216
225
  node.property("set-point", "Set Point", :float, @abc.dhw.set_point, format: 100..140,
@@ -220,11 +229,45 @@ class MQTTBridge
220
229
  end
221
230
  end
222
231
 
232
+ @humidistat = @homie.node("humidistat", "Humidistat", "Humidistat") do |node|
233
+ node.property("relative-humidity", "Relative Humidity", :integer, @abc.humidistat.relative_humidity,
234
+ unit: "%", format: 0..100)
235
+ if @abc.humidistat.humidifier?
236
+ node.property("humidifier-running", "Humidifier is running", :boolean, @abc.humidistat.humidifier_running?)
237
+ node.property("humidifier-mode", "Humidifier Mode", :enum, @abc.humidistat.humidifier_mode,
238
+ format: %i[auto manual]) do |value, property|
239
+ @mutex.synchronize { property.value = @abc.humidistat.humidifier_mode = value.to_sym }
240
+ end
241
+ node.property("humidification-target", "Humidification target relative humidity", :integer,
242
+ @abc.humidistat.humidification_target, unit: "%", format: 15..50) do |value, property|
243
+ @mutex.synchronize { property.value = @abc.humidistat.humidification_target = value }
244
+ end
245
+ end
246
+
247
+ # VSDrive can perform active dehumidification, even without a dedicated dehumidifier
248
+ if @abc.humidistat.dehumidifier? || @abc.compressor.is_a?(Aurora::Compressor::VSDrive)
249
+ node.property("dehumidifier-mode", "Dehumidifier Mode", :enum, @abc.humidistat.dehumidifier_mode,
250
+ format: %i[auto manual]) do |value, property|
251
+ @mutex.synchronize { property.value = @abc.humidistat.dehumidifier_mode = value.to_sym }
252
+ end
253
+ node.property("dehumidification-target", "Dehumidification target relative humidity", :integer,
254
+ @abc.humidistat.dehumidification_target, unit: "%", format: 35..65) do |value, property|
255
+ @mutex.synchronize { property.value = @abc.humidistat.dehumidification_target = value }
256
+ end
257
+ end
258
+
259
+ next unless @abc.humidistat.dehumidifier?
260
+
261
+ node.property("dehumidifier-running", "Dehumidifier is running", :boolean, @abc.humidistat.dehumidifier_running?)
262
+ end
263
+
223
264
  @faults = @homie.node("faults", "Fault History", "ABC") do |node|
224
265
  node.property("clear-history", "Reset fault counts", :enum, retained: false, format: "clear") do |_|
225
266
  @mutex.synchronize { @abc.clear_fault_history }
226
267
  end
227
268
  @abc.faults.each_with_index do |count, i|
269
+ next if count == 0xffff
270
+
228
271
  name = Aurora::FAULTS[i + 1]
229
272
  node.property("e#{i + 1}", name || "E#{i + 1}", :integer, count)
230
273
  end
data/exe/web_aid_tool CHANGED
@@ -14,6 +14,10 @@ options = OptionParser.new do |opts|
14
14
 
15
15
  opts.on("--debug-modbus", "Print actual protocol bytes") { debug_modbus = true }
16
16
  opts.on("--monitor", "Print interpreted registers as they are requested, like aurora_monitor") { monitor = true }
17
+ opts.on("-v", "--version", "Print version") do
18
+ puts Aurora::VERSION
19
+ exit
20
+ end
17
21
  opts.on("-h", "--help", "Prints this help") do
18
22
  puts opts
19
23
  exit
@@ -6,6 +6,7 @@ require "uri"
6
6
  require "aurora/blower"
7
7
  require "aurora/compressor"
8
8
  require "aurora/dhw"
9
+ require "aurora/humidistat"
9
10
  require "aurora/iz2_zone"
10
11
  require "aurora/pump"
11
12
  require "aurora/thermostat"
@@ -48,10 +49,10 @@ module Aurora
48
49
  :blower,
49
50
  :pump,
50
51
  :dhw,
52
+ :humidistat,
51
53
  :faults,
52
54
  :current_mode,
53
55
  :entering_air_temperature,
54
- :relative_humidity,
55
56
  :leaving_air_temperature,
56
57
  :leaving_water_temperature,
57
58
  :entering_water_temperature,
@@ -65,7 +66,7 @@ module Aurora
65
66
  @modbus_slave = self.class.open_modbus_slave(uri)
66
67
  @modbus_slave.read_retry_timeout = 15
67
68
  @modbus_slave.read_retries = 2
68
- raw_registers = @modbus_slave.holding_registers[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]
69
70
  registers = Aurora.transform_registers(raw_registers.dup)
70
71
  @program = registers[88]
71
72
  @serial_number = registers[105]
@@ -78,7 +79,14 @@ module Aurora
78
79
  [Thermostat.new(self)]
79
80
  end
80
81
 
81
- @compressor = @program == "ABCVSP" ? Compressor::VSDrive.new(self) : Compressor::GenericCompressor.new(self)
82
+ @abc_dipswitches = registers[33]
83
+ @axb_dipswitches = registers[1103]
84
+ @compressor = if @program == "ABCVSP"
85
+ Compressor::VSDrive.new(self)
86
+ else
87
+ Compressor::GenericCompressor.new(self,
88
+ @abc_dipswitches[:compressor])
89
+ end
82
90
  @blower = case raw_registers[404]
83
91
  when 1, 2 then Blower::ECM.new(self, registers[404])
84
92
  when 3 then Blower::FiveSpeed.new(self, registers[404])
@@ -92,8 +100,23 @@ module Aurora
92
100
  registers[413])
93
101
  end
94
102
  @dhw = DHW.new(self) if (-999..999).include?(registers[1114])
103
+ @humidistat = Humidistat.new(self,
104
+ @abc_dipswitches[:accessory_relay] == :humidifier,
105
+ @axb_dipswitches[:accessory_relay2] == :dehumidifier)
95
106
 
96
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)
97
120
  end
98
121
 
99
122
  def query_registers(query)
@@ -131,29 +154,15 @@ module Aurora
131
154
  end
132
155
 
133
156
  def refresh
134
- registers_to_read = [6, 19..20, 25, 30, 344, 740..741, 900, 1110..1111, 1114, 1150..1153, 1165,
135
- 31_003]
136
- zones.each do |z|
137
- registers_to_read.concat(z.registers_to_read)
138
- end
139
- registers_to_read.concat(compressor.registers_to_read)
140
- registers_to_read.concat(blower.registers_to_read)
141
- registers_to_read.concat(pump.registers_to_read)
142
- registers_to_read.concat(dhw.registers_to_read) if dhw
143
- # need dehumidify mode to calculate final current mode;
144
- # apparently non-VSD doesn't have this register at all?
145
- registers_to_read.concat([362]) if compressor.is_a?(Compressor::VSDrive)
146
-
147
157
  faults = @modbus_slave.read_multiple_holding_registers(601..699)
148
158
  @faults = Aurora.transform_registers(faults).values
149
159
 
150
- registers = @modbus_slave.holding_registers[*registers_to_read]
160
+ registers = @modbus_slave.holding_registers[*@registers_to_read]
151
161
  Aurora.transform_registers(registers)
152
162
 
153
163
  outputs = registers[30]
154
164
 
155
165
  @entering_air_temperature = registers[740]
156
- @relative_humidity = registers[741]
157
166
  @leaving_air_temperature = registers[900]
158
167
  @leaving_water_temperature = registers[1110]
159
168
  @entering_water_temperature = registers[1111]
@@ -188,10 +197,9 @@ module Aurora
188
197
  zones.each do |z|
189
198
  z.refresh(registers)
190
199
  end
191
- compressor.refresh(registers)
192
- blower.refresh(registers)
193
- pump.refresh(registers)
194
- dhw&.refresh(registers)
200
+ @components.each do |component|
201
+ component.refresh(registers)
202
+ end
195
203
  end
196
204
 
197
205
  def cooling_airflow_adjustment=(value)
data/lib/aurora/blower.rb CHANGED
@@ -4,8 +4,9 @@ require "aurora/component"
4
4
 
5
5
  module Aurora
6
6
  module Blower
7
- class GenericBlower < Component
8
- attr_reader :type, :watts
7
+ class PSC < Component
8
+ attr_reader :type, :watts, :running
9
+ alias running? running
9
10
 
10
11
  def initialize(abc, type)
11
12
  super(abc)
@@ -22,19 +23,11 @@ module Aurora
22
23
 
23
24
  def refresh(registers)
24
25
  @watts = registers[1148] if abc.energy_monitoring?
26
+ @running = registers[30].include?(:blower)
25
27
  end
26
28
  end
27
29
 
28
- class PSC < GenericBlower
29
- attr_reader :running
30
- alias running? running
31
-
32
- def refresh(registers)
33
- @running = registers[30].include?(:g)
34
- end
35
- end
36
-
37
- class FiveSpeed < GenericBlower
30
+ class FiveSpeed < PSC
38
31
  attr_reader :speed
39
32
 
40
33
  def speed_range
@@ -49,7 +42,7 @@ module Aurora
49
42
  3
50
43
  elsif outputs.include?(:cc)
51
44
  2
52
- elsif outputs.include?(:g)
45
+ elsif outputs.include?(:blower)
53
46
  1
54
47
  else
55
48
  0
@@ -57,7 +50,7 @@ module Aurora
57
50
  end
58
51
  end
59
52
 
60
- class ECM < GenericBlower
53
+ class ECM < PSC
61
54
  attr_reader :speed, :blower_only_speed, :low_compressor_speed, :high_compressor_speed, :aux_heat_speed,
62
55
  :iz2_desired_speed
63
56
 
@@ -7,12 +7,17 @@ module Aurora
7
7
  class GenericCompressor < Component
8
8
  attr_reader :speed, :watts
9
9
 
10
+ def initialize(abc, stages)
11
+ super(abc)
12
+ @stages = stages
13
+ end
14
+
10
15
  def type
11
- "Compressor"
16
+ "#{@stages == 2 ? 'Dual' : 'Single'} Stage Compressor"
12
17
  end
13
18
 
14
19
  def speed_range
15
- 0..2
20
+ 0..@stages
16
21
  end
17
22
 
18
23
  def registers_to_read
@@ -39,12 +44,12 @@ module Aurora
39
44
  class VSDrive < GenericCompressor
40
45
  attr_reader :ambient_temperature, :iz2_desired_speed
41
46
 
42
- def type
43
- "Variable Speed Drive"
47
+ def initialize(abc)
48
+ super(abc, 12)
44
49
  end
45
50
 
46
- def speed_range
47
- 0..12
51
+ def type
52
+ "Variable Speed Drive"
48
53
  end
49
54
 
50
55
  def registers_to_read
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,93 @@
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_register = abc.iz2? ? 21_114 : 12_309
46
+ @humidifier_settings = registers[humidifier_settings_register]&.last&.[](2..-1)&.to_i(16)
47
+ @humidifier_mode = registers[humidifier_settings_register]&.include?(:auto_humidification) ? :auto : :manual
48
+ @dehumidifier_mode = registers[humidifier_settings_register]&.include?(:auto_dehumidification) ? :auto : :manual
49
+
50
+ @humidification_target = registers[base + 1]&.[](:humidification_target)
51
+ @dehumidification_target = registers[base + 1]&.[](:dehumidification_target)
52
+ end
53
+
54
+ def humidifier_mode=(mode)
55
+ set_humidistat_mode(mode, dehumidifier_mode)
56
+ end
57
+
58
+ def dehumidifier_mode=(mode)
59
+ set_humidistat_mode(humidifier_mode, mode)
60
+ end
61
+
62
+ def set_humidistat_mode(humidifier_mode, dehumidifier_mode)
63
+ allowed = %i[auto manual]
64
+ raise ArgumentError unless allowed.include?(humidifier_mode) && allowed.include?(dehumidifier_mode)
65
+
66
+ # start with the prior value of the register, since I'm not sure what
67
+ # else is stuffed in there
68
+ raw_value = @humidifier_settings
69
+ raw_value |= 0x4000 if humidifier_mode == :auto
70
+ raw_value |= 0x8000 if dehumidifier_mode == :auto
71
+ holding_registers[abc.iz2? ? 21_114 : 12_309] = raw_value
72
+ @humidifier_mode = humidifier_mode
73
+ @dehumidifier_mode = dehumidifier_mode
74
+ end
75
+
76
+ def humidification_target=(value)
77
+ set_humidistat_targets(value, dehumidification_target)
78
+ end
79
+
80
+ def dehumidification_target=(value)
81
+ set_humidistat_targets(humidification_target, value)
82
+ end
83
+
84
+ def set_humidistat_targets(humidification_target, dehumidification_target)
85
+ raise ArgumentError unless (15..50).include?(humidification_target)
86
+ raise ArgumentError unless (35..65).include?(dehumidification_target)
87
+
88
+ holding_registers[abc.iz2? ? 21_115 : 12_310] = (humidification_target << 8) + dehumidification_target
89
+ @humidification_target = humidification_target
90
+ @dehumidification_target = dehumidification_target
91
+ end
92
+ end
93
+ end
@@ -10,20 +10,20 @@ module Aurora
10
10
  return unless ((req.length - 1) % 4).zero?
11
11
 
12
12
  params = []
13
- req[1..].unpack("n*").each_slice(2) do |(addr, quant)|
13
+ req[1..-1].unpack("n*").each_slice(2) do |(addr, quant)|
14
14
  params << { addr: addr, quant: quant }
15
15
  end
16
16
  params
17
17
  when 66
18
18
  return unless ((req.length - 1) % 2).zero?
19
19
 
20
- req[1..].unpack("n*")
20
+ req[1..-1].unpack("n*")
21
21
  when 67
22
22
  # 1 function register, a multiple of two words
23
23
  return unless ((req.length - 1) % 4).zero?
24
24
 
25
25
  params = []
26
- req[1..].unpack("n*").each_slice(2) do |(addr, val)|
26
+ req[1..-1].unpack("n*").each_slice(2) do |(addr, val)|
27
27
  params << { addr: addr, val: val }
28
28
  end
29
29
  params
@@ -11,7 +11,7 @@ module Aurora
11
11
  @mqtt = MQTT::Client.new(uri)
12
12
  @mqtt.connect
13
13
 
14
- @base_topic = uri.path[1..]
14
+ @base_topic = uri.path[1..-1]
15
15
  @mqtt.subscribe("#{@base_topic}/getregs/response")
16
16
  end
17
17
 
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
 
@@ -186,7 +186,7 @@ module Aurora
186
186
  "RPM Sensor Signal Fault" => (78..82),
187
187
  "Under-Voltage Stop" => (83..87),
188
188
  "Rotor Locked" => (88..92),
189
- "Standby" => (93..)
189
+ "Standby" => (93..99) # should be infinite, but ruby 2.5 doesn't support it
190
190
  }.freeze
191
191
 
192
192
  def vs_fault(value)
@@ -194,24 +194,24 @@ module Aurora
194
194
  name ? "#{value} #{name}" : value.to_s
195
195
  end
196
196
 
197
- AR_SETTINGS = {
198
- 0 => "Cycle with Compressor",
199
- 1 => "Slow Opening Water Valve",
200
- 2 => "Cycle with Thermostat Humidification Call",
201
- 3 => "Cycle with Blower"
197
+ ACCESSORY_RELAY_SETTINGS = {
198
+ 0 => :compressor,
199
+ 1 => :slow_opening_water_valve,
200
+ 2 => :humidifier,
201
+ 3 => :blower
202
202
  }.freeze
203
203
 
204
204
  def dipswitch_settings(value)
205
205
  return :manual if value == 0x7fff
206
206
 
207
207
  {
208
- fp1: value & 0x01 == 0x01 ? "30ºF" : "15ºF",
209
- fp2: value & 0x02 == 0x02 ? "30ºF" : "15ºF",
210
- rv: value & 0x04 == 0x04 ? "O" : "B",
211
- ar: AR_SETTINGS[(value >> 3) & 0x3],
212
- cc: value & 0x20 == 0x20 ? "Single Stage" : "Dual Stage",
213
- lo: value & 0x40 == 0x40 ? "Continouous" : "Pulse",
214
- dh_rh: value & 0x80 == 0x80 ? "Dehumidifier On" : "Reheat On"
208
+ fp1: value & 0x01 == 0x01 ? 30 : 15,
209
+ fp2: value & 0x02 == 0x02 ? 30 : :off,
210
+ reversing_valve: value & 0x04 == 0x04 ? :o : :b, # cycle to cool on O, or !B
211
+ accessory_relay: ACCESSORY_RELAY_SETTINGS[(value >> 3) & 0x3],
212
+ compressor: value & 0x20 == 0x20 ? 1 : 2, # single or dual stage compressor
213
+ lockout: value & 0x40 == 0x40 ? :continuous : :pulse,
214
+ dehumidifier_reheat: value & 0x80 == 0x80 ? :dehumidifier : :reheat
215
215
  }
216
216
  end
217
217
 
@@ -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.2"
4
+ VERSION = "0.6.2"
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.5.2
4
+ version: 0.6.2
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-09-02 00:00:00.000000000 Z
11
+ date: 2021-09-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ccutrer-serialport
@@ -139,6 +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/humidistat.rb
142
143
  - lib/aurora/iz2_zone.rb
143
144
  - lib/aurora/mock_abc.rb
144
145
  - lib/aurora/modbus/server.rb
@@ -149,7 +150,7 @@ files:
149
150
  - lib/aurora/thermostat.rb
150
151
  - lib/aurora/version.rb
151
152
  - lib/waterfurnace_aurora.rb
152
- homepage: https://github.com/ccutrer/waterfurnace
153
+ homepage: https://github.com/ccutrer/waterfurnace_aurora
153
154
  licenses:
154
155
  - MIT
155
156
  metadata: {}
@@ -161,7 +162,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
161
162
  requirements:
162
163
  - - ">="
163
164
  - !ruby/object:Gem::Version
164
- version: '2.6'
165
+ version: '2.5'
165
166
  required_rubygems_version: !ruby/object:Gem::Requirement
166
167
  requirements:
167
168
  - - ">="