waterfurnace_aurora 1.0.1 → 1.2.2
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 +4 -4
- data/exe/aurora_fetch +17 -6
- data/exe/aurora_mqtt_bridge +150 -35
- data/exe/web_aid_tool +6 -2
- data/lib/aurora/abc_client.rb +60 -15
- data/lib/aurora/compressor.rb +28 -8
- data/lib/aurora/mock_abc.rb +4 -1
- data/lib/aurora/registers.rb +8 -3
- data/lib/aurora/thermostat.rb +2 -2
- data/lib/aurora/version.rb +1 -1
- data/lib/aurora.rb +3 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: caf73ece152211ae227b1b628572d0dc43936b600c2d41a0a534178dc74385cd
|
4
|
+
data.tar.gz: d5ed42012eb9fc1e2aca036914cfd538e3342df0f34342e2c9c37d18ad6cce29
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eaacad438ac440a004f8611b907f9eff3e453193884627178dc8608f66ff29640f5e355993069b34d83ef796cb6169f0d25bc4a1b06103a44194d339618f08a6
|
7
|
+
data.tar.gz: 00e3dfeba4fc12ec7804fcde37241ff93de9f60bb91f03e7182f309de383890454f83f959aeacfd5a3924874bd56ca1c5aaa853ca52b05abd56fd894aa3d0f38
|
data/exe/aurora_fetch
CHANGED
@@ -8,20 +8,31 @@ require "optparse"
|
|
8
8
|
require "uri"
|
9
9
|
require "yaml"
|
10
10
|
|
11
|
-
debug_modbus = yaml = false
|
11
|
+
debug_modbus = yaml = ignore_missing_registers = false
|
12
12
|
try_individual = nil
|
13
13
|
|
14
14
|
options = OptionParser.new do |opts|
|
15
15
|
opts.banner = "Usage: aurora_fetch /path/to/serial/port REGISTERS [options]"
|
16
16
|
|
17
17
|
opts.separator("")
|
18
|
-
opts.separator(
|
18
|
+
opts.separator(<<~TEXT)
|
19
|
+
Use `known` to fetch all identified registers. Use `valid` to fetch all registers
|
20
|
+
that should respond. Use `all` to search the entire ModBus address space. Note that
|
21
|
+
logging of current progress is only periodic, and does not log every register it's
|
22
|
+
trying to fetch.
|
23
|
+
TEXT
|
19
24
|
opts.separator("")
|
20
25
|
|
21
|
-
opts.on("--debug-modbus", "Print actual protocol bytes")
|
26
|
+
opts.on("--debug-modbus", "Print actual protocol bytes") do
|
27
|
+
debug_modbus = true
|
28
|
+
end
|
22
29
|
opts.on("--[no-]try-individual",
|
23
30
|
"Query registers one-by-one if a range has an illegal address. " \
|
24
31
|
"Defaults to true for `valid` and `known` special registers, false otherwise.") { |v| try_individual = v }
|
32
|
+
opts.on("--ignore-missing-registers",
|
33
|
+
"For YAML input only, just log a warning when a register doesn't exist, instead of failing") do
|
34
|
+
ignore_missing_registers = true
|
35
|
+
end
|
25
36
|
opts.on("-y", "--yaml", "Output raw values as YAML") { yaml = true }
|
26
37
|
opts.on("-v", "--version", "Print version") do
|
27
38
|
puts Aurora::VERSION
|
@@ -40,11 +51,11 @@ unless ARGV.length == 2
|
|
40
51
|
exit 1
|
41
52
|
end
|
42
53
|
|
43
|
-
modbus_slave = Aurora::ABCClient.open_modbus_slave(ARGV[0])
|
54
|
+
modbus_slave = Aurora::ABCClient.open_modbus_slave(ARGV[0], ignore_missing_registers: ignore_missing_registers)
|
44
55
|
modbus_slave.read_retry_timeout = 15
|
45
56
|
modbus_slave.read_retries = 2
|
46
|
-
modbus_slave.logger = Logger.new($
|
47
|
-
modbus_slave.logger.level = debug_modbus ? :debug : :
|
57
|
+
Aurora.logger = modbus_slave.logger = Logger.new($stderr)
|
58
|
+
modbus_slave.logger.level = debug_modbus ? :debug : :info
|
48
59
|
|
49
60
|
registers = Aurora::ABCClient.query_registers(modbus_slave, ARGV[1], try_individual: try_individual)
|
50
61
|
|
data/exe/aurora_mqtt_bridge
CHANGED
@@ -90,30 +90,33 @@ class MQTTBridge
|
|
90
90
|
loop do
|
91
91
|
begin
|
92
92
|
@mutex.synchronize do
|
93
|
-
@
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
93
|
+
@homie.mqtt.batch_publish do
|
94
|
+
@abc.refresh
|
95
|
+
|
96
|
+
components = { @homie_abc => @abc,
|
97
|
+
@aux_heat => @abc.aux_heat,
|
98
|
+
@compressor => @abc.compressor,
|
99
|
+
@blower => @abc.blower,
|
100
|
+
@pump => @abc.pump,
|
101
|
+
@dhw => @abc.dhw,
|
102
|
+
@humidistat => @abc.humidistat }.compact
|
103
|
+
@abc.zones.each_with_index do |z, idx|
|
104
|
+
homie_zone = @homie["zone#{idx + 1}"]
|
105
|
+
components[homie_zone] = z
|
106
|
+
end
|
106
107
|
|
107
|
-
|
108
|
-
|
109
|
-
|
108
|
+
components.each do |(node, object)|
|
109
|
+
node.each do |property|
|
110
|
+
property.value = object.public_send(property.id.tr("-", "_"))
|
111
|
+
end
|
110
112
|
end
|
111
|
-
end
|
112
113
|
|
113
|
-
|
114
|
-
|
114
|
+
@faults["current"].value = @abc.current_fault
|
115
|
+
@abc.faults.each_with_index do |fault_count, i|
|
116
|
+
next if fault_count == 0xffff
|
115
117
|
|
116
|
-
|
118
|
+
@faults["e#{i + 1}"].value = fault_count
|
119
|
+
end
|
117
120
|
end
|
118
121
|
end
|
119
122
|
rescue => e
|
@@ -140,6 +143,31 @@ class MQTTBridge
|
|
140
143
|
@abc.current_mode,
|
141
144
|
format: allowed_modes,
|
142
145
|
hass: { sensor: { state_class: :measurement } })
|
146
|
+
node.property("emergency-shutdown",
|
147
|
+
"Emergency Shutdown Requested",
|
148
|
+
:boolean,
|
149
|
+
@abc.emergency_shutdown?,
|
150
|
+
hass: :binary_sensor)
|
151
|
+
node.property("load-shed",
|
152
|
+
"Load Shed Requested",
|
153
|
+
:boolean,
|
154
|
+
@abc.load_shed?,
|
155
|
+
hass: :binary_sensor)
|
156
|
+
node.property("locked-out",
|
157
|
+
"Is the heat pump currently locked out?",
|
158
|
+
:boolean,
|
159
|
+
@abc.locked_out?,
|
160
|
+
hass: :binary_sensor)
|
161
|
+
node.property("derated",
|
162
|
+
"Is the compressor currently running at a derated level?",
|
163
|
+
:boolean,
|
164
|
+
@abc.derated?,
|
165
|
+
hass: :binary_sensor)
|
166
|
+
node.property("safe-mode",
|
167
|
+
"Is the heat pump currently in safe mode?",
|
168
|
+
:boolean,
|
169
|
+
@abc.safe_mode?,
|
170
|
+
hass: :binary_sensor)
|
143
171
|
node.property("entering-air-temperature",
|
144
172
|
"Entering Air Temperature",
|
145
173
|
:float,
|
@@ -156,6 +184,17 @@ class MQTTBridge
|
|
156
184
|
hass: { sensor: { device_class: :temperature,
|
157
185
|
state_class: :measurement,
|
158
186
|
entity_category: :diagnostic } })
|
187
|
+
node.property("low-pressure-switch",
|
188
|
+
"Low Pressure Switch Status",
|
189
|
+
:enum,
|
190
|
+
@abc.low_pressure_switch,
|
191
|
+
format: %w[open closed])
|
192
|
+
node.property("high-pressure-switch",
|
193
|
+
"High Pressure Switch Status",
|
194
|
+
:enum,
|
195
|
+
@abc.high_pressure_switch,
|
196
|
+
format: %w[open closed])
|
197
|
+
|
159
198
|
if @abc.awl_communicating?
|
160
199
|
node.property("leaving-air-temperature",
|
161
200
|
"Leaving Air Temperature",
|
@@ -193,18 +232,10 @@ class MQTTBridge
|
|
193
232
|
unit: "V") do |value|
|
194
233
|
@mutex.synchronize { @abc.line_voltage = value }
|
195
234
|
end
|
196
|
-
node.property("
|
197
|
-
"
|
235
|
+
node.property("air-coil-temperature",
|
236
|
+
"Air Coil Temperature (FP2)",
|
198
237
|
:float,
|
199
|
-
@abc.
|
200
|
-
unit: "°F",
|
201
|
-
hass: { sensor: { device_class: :temperature,
|
202
|
-
state_class: :measurement,
|
203
|
-
entity_category: :diagnostic } })
|
204
|
-
node.property("fp2",
|
205
|
-
"FP2 Sensor",
|
206
|
-
:float,
|
207
|
-
@abc.fp2,
|
238
|
+
@abc.air_coil_temperature,
|
208
239
|
unit: "°F",
|
209
240
|
hass: { sensor: { device_class: :temperature,
|
210
241
|
state_class: :measurement,
|
@@ -227,6 +258,22 @@ class MQTTBridge
|
|
227
258
|
@abc.compressor.speed,
|
228
259
|
format: @abc.compressor.speed_range,
|
229
260
|
hass: { sensor: { state_class: :measurement } })
|
261
|
+
node.property("cooling-liquid-line-temperature",
|
262
|
+
"Cooling Liquid Line Temperature (FP1)",
|
263
|
+
:float,
|
264
|
+
@abc.compressor.cooling_liquid_line_temperature,
|
265
|
+
unit: "°F",
|
266
|
+
hass: { sensor: { device_class: :temperature,
|
267
|
+
state_class: :measurement,
|
268
|
+
entity_category: :diagnostic } })
|
269
|
+
node.property("saturated-condensor-discharge-temperature",
|
270
|
+
"Saturated Condensor Discharge Temperature",
|
271
|
+
:float,
|
272
|
+
@abc.compressor.saturated_condensor_discharge_temperature,
|
273
|
+
unit: "°F",
|
274
|
+
hass: { sensor: { device_class: :temperature,
|
275
|
+
state_class: :measurement,
|
276
|
+
entity_category: :diagnostic } })
|
230
277
|
if @abc.energy_monitoring?
|
231
278
|
node.property("watts",
|
232
279
|
"Power Usage",
|
@@ -239,6 +286,12 @@ class MQTTBridge
|
|
239
286
|
|
240
287
|
next unless @abc.compressor.is_a?(Aurora::Compressor::VSDrive)
|
241
288
|
|
289
|
+
node.property("desired-speed",
|
290
|
+
"Desired Speed",
|
291
|
+
:integer,
|
292
|
+
@abc.compressor.desired_speed,
|
293
|
+
format: @abc.compressor.speed_range,
|
294
|
+
hass: { sensor: { state_class: :measurement } })
|
242
295
|
node.property("ambient-temperature",
|
243
296
|
"Ambient Temperature",
|
244
297
|
:float,
|
@@ -271,6 +324,62 @@ class MQTTBridge
|
|
271
324
|
format: 0..100,
|
272
325
|
hass: { sensor: { state_class: :measurement,
|
273
326
|
entity_category: :diagnostic } })
|
327
|
+
node.property("discharge-temperature",
|
328
|
+
"Discharge Temperature",
|
329
|
+
:float,
|
330
|
+
@abc.compressor.discharge_temperature,
|
331
|
+
unit: "°F",
|
332
|
+
hass: { sensor: { device_class: :temperature,
|
333
|
+
state_class: :measurement,
|
334
|
+
entity_category: :diagnostic } })
|
335
|
+
node.property("discharge-pressure",
|
336
|
+
"Discharge Pressure",
|
337
|
+
:float,
|
338
|
+
@abc.compressor.discharge_pressure,
|
339
|
+
unit: "psi",
|
340
|
+
hass: { sensor: { device_class: :pressure,
|
341
|
+
state_class: :measurement,
|
342
|
+
entity_category: :diagnostic } })
|
343
|
+
node.property("suction-temperature",
|
344
|
+
"Suction Temperature",
|
345
|
+
:float,
|
346
|
+
@abc.compressor.suction_temperature,
|
347
|
+
unit: "°F",
|
348
|
+
hass: { sensor: { device_class: :temperature,
|
349
|
+
state_class: :measurement,
|
350
|
+
entity_category: :diagnostic } })
|
351
|
+
node.property("suction-pressure",
|
352
|
+
"Suction Pressure",
|
353
|
+
:float,
|
354
|
+
@abc.compressor.suction_pressure,
|
355
|
+
unit: "psi",
|
356
|
+
hass: { sensor: { device_class: :pressure,
|
357
|
+
state_class: :measurement,
|
358
|
+
entity_category: :diagnostic } })
|
359
|
+
node.property("saturated-evaporator-discharge-temperature",
|
360
|
+
"Saturated Evaporator Discharge Temperature",
|
361
|
+
:float,
|
362
|
+
@abc.compressor.saturated_evaporator_discharge_temperature,
|
363
|
+
unit: "°F",
|
364
|
+
hass: { sensor: { device_class: :temperature,
|
365
|
+
state_class: :measurement,
|
366
|
+
entity_category: :diagnostic } })
|
367
|
+
node.property("superheat-temperature",
|
368
|
+
"SuperHeat Temperature",
|
369
|
+
:float,
|
370
|
+
@abc.compressor.superheat_temperature,
|
371
|
+
unit: "°F",
|
372
|
+
hass: { sensor: { device_class: :temperature,
|
373
|
+
state_class: :measurement,
|
374
|
+
entity_category: :diagnostic } })
|
375
|
+
node.property("eev-open-percentage",
|
376
|
+
"Electronic Expansion Valve Open Percentage",
|
377
|
+
:integer,
|
378
|
+
@abc.compressor.eev_percentage,
|
379
|
+
unit: "%",
|
380
|
+
format: 0..100,
|
381
|
+
hass: { sensor: { state_class: :measurement,
|
382
|
+
entity_category: :diagnostic } })
|
274
383
|
|
275
384
|
next unless @abc.iz2?
|
276
385
|
|
@@ -525,6 +634,12 @@ class MQTTBridge
|
|
525
634
|
end
|
526
635
|
|
527
636
|
@faults = @homie.node("faults", "Fault History", "ABC") do |node|
|
637
|
+
node.property("current",
|
638
|
+
"Current fault",
|
639
|
+
:integer,
|
640
|
+
@abc.current_fault,
|
641
|
+
format: 0..99,
|
642
|
+
hass: :sensor)
|
528
643
|
node.property("clear-history",
|
529
644
|
"Reset Fault Counts",
|
530
645
|
:enum,
|
@@ -669,12 +784,12 @@ class MQTTBridge
|
|
669
784
|
end
|
670
785
|
|
671
786
|
log_level = ARGV.include?("--debug") ? :debug : :warn
|
672
|
-
logger = Logger.new($stdout)
|
673
|
-
logger.level = log_level
|
674
|
-
abc.modbus_slave.logger = logger
|
787
|
+
Aurora.logger = Logger.new($stdout)
|
788
|
+
Aurora.logger.level = log_level
|
789
|
+
abc.modbus_slave.logger = Aurora.logger
|
675
790
|
|
676
791
|
device = "aurora-#{abc.serial_number}"
|
677
792
|
homie = MQTT::Homie::Device.new(device, "WaterFurnace", mqtt: mqtt_uri)
|
678
|
-
homie.logger = logger
|
793
|
+
homie.logger = Aurora.logger
|
679
794
|
|
680
795
|
MQTTBridge.new(abc, homie)
|
data/exe/web_aid_tool
CHANGED
@@ -7,13 +7,17 @@ require "logger"
|
|
7
7
|
require "optparse"
|
8
8
|
require "yaml"
|
9
9
|
|
10
|
-
debug_modbus = monitor = false
|
10
|
+
debug_modbus = monitor = ignore_missing_registers = false
|
11
11
|
|
12
12
|
options = OptionParser.new do |opts|
|
13
13
|
opts.banner = "Usage: web_aid_tool /path/to/serial/port [options]"
|
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("--ignore-missing-registers",
|
18
|
+
"For YAML input only, just log a warning when a register doesn't exist, instead of failing") do
|
19
|
+
ignore_missing_registers = true
|
20
|
+
end
|
17
21
|
opts.on("-v", "--version", "Print version") do
|
18
22
|
puts Aurora::VERSION
|
19
23
|
exit
|
@@ -31,7 +35,7 @@ unless ARGV.length == 1
|
|
31
35
|
exit 1
|
32
36
|
end
|
33
37
|
|
34
|
-
slave = Aurora::ABCClient.open_modbus_slave(ARGV[0])
|
38
|
+
slave = Aurora::ABCClient.open_modbus_slave(ARGV[0], ignore_missing_registers: ignore_missing_registers)
|
35
39
|
slave.logger = Logger.new($stdout)
|
36
40
|
slave.logger.level = debug_modbus ? :debug : :warn
|
37
41
|
|
data/lib/aurora/abc_client.rb
CHANGED
@@ -15,7 +15,7 @@ require "aurora/thermostat"
|
|
15
15
|
module Aurora
|
16
16
|
class ABCClient
|
17
17
|
class << self
|
18
|
-
def open_modbus_slave(uri)
|
18
|
+
def open_modbus_slave(uri, ignore_missing_registers: false)
|
19
19
|
uri = URI.parse(uri)
|
20
20
|
|
21
21
|
io = case uri.scheme
|
@@ -32,7 +32,10 @@ module Aurora
|
|
32
32
|
require "aurora/mqtt_modbus"
|
33
33
|
return Aurora::MQTTModBus.new(uri)
|
34
34
|
else
|
35
|
-
|
35
|
+
if File.file?(uri.path)
|
36
|
+
return Aurora::MockABC.new(YAML.load_file(uri.path),
|
37
|
+
ignore_missing_registers: ignore_missing_registers)
|
38
|
+
end
|
36
39
|
|
37
40
|
require "ccutrer-serialport"
|
38
41
|
CCutrer::SerialPort.new(uri.path, baud: 19_200, parity: :even)
|
@@ -54,6 +57,10 @@ module Aurora
|
|
54
57
|
implicit = true
|
55
58
|
try_individual = true if try_individual.nil?
|
56
59
|
break Aurora::REGISTER_RANGES
|
60
|
+
when "all"
|
61
|
+
implicit = true
|
62
|
+
try_individual = true if try_individual.nil?
|
63
|
+
break 0..65_535
|
57
64
|
when /^(\d+)(?:\.\.|-)(\d+)$/
|
58
65
|
$1.to_i..$2.to_i
|
59
66
|
else
|
@@ -62,28 +69,48 @@ module Aurora
|
|
62
69
|
end
|
63
70
|
queries = Aurora.normalize_ranges(ranges)
|
64
71
|
registers = {}
|
72
|
+
last_log_time = nil
|
65
73
|
queries.each do |subquery|
|
74
|
+
last_log_time = log_query(last_log_time, subquery.inspect)
|
66
75
|
registers.merge!(modbus_slave.read_multiple_holding_registers(*subquery))
|
67
|
-
rescue ::ModBus::Errors::IllegalDataAddress, ::ModBus::Errors::IllegalFunction
|
76
|
+
rescue ::ModBus::Errors::IllegalDataAddress, ::ModBus::Errors::IllegalFunction, ::ModBus::Errors::ModBusTimeout
|
68
77
|
# maybe this unit doesn't respond to all the addresses we want?
|
69
78
|
raise unless implicit
|
70
79
|
|
71
80
|
# try each query individually
|
72
81
|
subquery.each do |subsubquery|
|
82
|
+
last_log_time = log_query(last_log_time, subsubquery.inspect)
|
73
83
|
registers.merge!(modbus_slave.read_multiple_holding_registers(subsubquery))
|
74
|
-
rescue ::ModBus::Errors::IllegalDataAddress,
|
84
|
+
rescue ::ModBus::Errors::IllegalDataAddress,
|
85
|
+
::ModBus::Errors::IllegalFunction,
|
86
|
+
::ModBus::Errors::ModBusTimeout => e
|
87
|
+
raise if e.is_a?(::ModBus::Errors::ModBusTimeout) && !try_individual
|
75
88
|
next unless try_individual
|
76
89
|
|
77
90
|
# seriously?? try each register individually
|
78
|
-
subsubquery.each do |i|
|
91
|
+
Array(subsubquery).each do |i|
|
92
|
+
last_log_time = log_query(last_log_time, i.to_s)
|
79
93
|
registers[i] = modbus_slave.holding_registers[i]
|
80
94
|
rescue ::ModBus::Errors::IllegalDataAddress, ::ModBus::Errors::IllegalFunction
|
95
|
+
# don't catch ModBusTimeout here... it should have no problem responding to a single register request
|
81
96
|
next
|
82
97
|
end
|
83
98
|
end
|
84
99
|
end
|
85
100
|
registers
|
86
101
|
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def log_query(last_log_time, query)
|
106
|
+
last_log_time ||= Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
107
|
+
now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
108
|
+
if now - last_log_time > 5
|
109
|
+
Aurora&.logger&.info("Fetching register(s) #{query}...")
|
110
|
+
last_log_time = now
|
111
|
+
end
|
112
|
+
last_log_time
|
113
|
+
end
|
87
114
|
end
|
88
115
|
|
89
116
|
attr_reader :modbus_slave,
|
@@ -97,18 +124,31 @@ module Aurora
|
|
97
124
|
:pump,
|
98
125
|
:dhw,
|
99
126
|
:humidistat,
|
127
|
+
:current_fault,
|
100
128
|
:faults,
|
129
|
+
:locked_out,
|
130
|
+
:derated,
|
131
|
+
:safe_mode,
|
101
132
|
:current_mode,
|
133
|
+
:low_pressure_switch,
|
134
|
+
:high_pressure_switch,
|
135
|
+
:emergency_shutdown,
|
136
|
+
:load_shed,
|
102
137
|
:entering_air_temperature,
|
103
138
|
:leaving_air_temperature,
|
104
139
|
:leaving_water_temperature,
|
105
140
|
:entering_water_temperature,
|
106
141
|
:outdoor_temperature,
|
107
|
-
:
|
108
|
-
:fp2,
|
142
|
+
:air_coil_temperature,
|
109
143
|
:line_voltage,
|
110
144
|
:watts
|
111
145
|
|
146
|
+
alias_method :emergency_shutdown?, :emergency_shutdown
|
147
|
+
alias_method :load_shed?, :load_shed
|
148
|
+
alias_method :locked_out?, :locked_out
|
149
|
+
alias_method :derated?, :derated
|
150
|
+
alias_method :safe_mode?, :safe_mode
|
151
|
+
|
112
152
|
def initialize(uri)
|
113
153
|
@modbus_slave = self.class.open_modbus_slave(uri)
|
114
154
|
@modbus_slave.read_retry_timeout = 15
|
@@ -156,7 +196,9 @@ module Aurora
|
|
156
196
|
|
157
197
|
@faults = []
|
158
198
|
|
159
|
-
@
|
199
|
+
@entering_air_register = awl_axb? ? 740 : 567
|
200
|
+
@registers_to_read = [6, 19..20, 25, 30..31, 112, 344, @entering_air_register, 1104, 1110..1111, 1114, 1150..1153,
|
201
|
+
1165]
|
160
202
|
@registers_to_read.concat([741, 31_003]) if awl_communicating?
|
161
203
|
@registers_to_read << 900 if awl_axb?
|
162
204
|
zones.each do |z|
|
@@ -183,17 +225,20 @@ module Aurora
|
|
183
225
|
|
184
226
|
outputs = registers[30]
|
185
227
|
|
186
|
-
@entering_air_temperature = registers[
|
228
|
+
@entering_air_temperature = registers[@entering_air_register]
|
187
229
|
@leaving_air_temperature = registers[900] if awl_axb?
|
188
230
|
@leaving_water_temperature = registers[1110]
|
189
231
|
@entering_water_temperature = registers[1111]
|
190
232
|
@outdoor_temperature = registers[31_003]
|
191
|
-
@
|
192
|
-
@
|
193
|
-
@
|
194
|
-
@
|
195
|
-
@
|
196
|
-
@
|
233
|
+
@air_coil_temperature = registers[20]
|
234
|
+
@locked_out = !(registers[25] & 0x8000).zero?
|
235
|
+
@current_fault = registers[25] & 0x7fff
|
236
|
+
@derated = (41..46).cover?(@current_fault)
|
237
|
+
@safe_mode = [47, 48, 49, 72, 74].include?(@current_fault)
|
238
|
+
@low_pressure_switch = registers[31][:lps]
|
239
|
+
@high_pressure_switch = registers[31][:hps]
|
240
|
+
@emergency_shutdown = !!registers[31][:emergency_shutdown]
|
241
|
+
@load_shed = !!registers[31][:load_shed]
|
197
242
|
@line_voltage = registers[112]
|
198
243
|
@watts = registers[1153]
|
199
244
|
|
data/lib/aurora/compressor.rb
CHANGED
@@ -5,7 +5,7 @@ require "aurora/component"
|
|
5
5
|
module Aurora
|
6
6
|
module Compressor
|
7
7
|
class GenericCompressor < Component
|
8
|
-
attr_reader :speed, :watts
|
8
|
+
attr_reader :speed, :watts, :cooling_liquid_line_temperature, :saturated_condensor_discharge_temperature
|
9
9
|
|
10
10
|
def initialize(abc, stages)
|
11
11
|
super(abc)
|
@@ -21,11 +21,9 @@ module Aurora
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def registers_to_read
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
[]
|
28
|
-
end
|
24
|
+
result = [19, 1134]
|
25
|
+
result << (1146..1147) if abc.energy_monitoring?
|
26
|
+
result
|
29
27
|
end
|
30
28
|
|
31
29
|
def refresh(registers)
|
@@ -37,12 +35,26 @@ module Aurora
|
|
37
35
|
else
|
38
36
|
0
|
39
37
|
end
|
38
|
+
@cooling_liquid_line_temperature = registers[19]
|
39
|
+
@saturated_condensor_discharge_temperature = registers[1134]
|
40
40
|
@watts = registers[1146] if abc.energy_monitoring?
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
44
|
class VSDrive < GenericCompressor
|
45
|
-
attr_reader :drive_temperature,
|
45
|
+
attr_reader :drive_temperature,
|
46
|
+
:inverter_temperature,
|
47
|
+
:ambient_temperature,
|
48
|
+
:desired_speed,
|
49
|
+
:iz2_desired_speed,
|
50
|
+
:fan_speed,
|
51
|
+
:discharge_pressure,
|
52
|
+
:discharge_temperature,
|
53
|
+
:suction_pressure,
|
54
|
+
:suction_temperature,
|
55
|
+
:saturated_evaporator_discharge_temperature,
|
56
|
+
:superheat_temperature,
|
57
|
+
:eev_percentage
|
46
58
|
|
47
59
|
def initialize(abc)
|
48
60
|
super(abc, 12)
|
@@ -53,7 +65,7 @@ module Aurora
|
|
53
65
|
end
|
54
66
|
|
55
67
|
def registers_to_read
|
56
|
-
result = super + [209, 3001,
|
68
|
+
result = super + [209, 3000..3001, 3322..3327, 3522, 3524, 3808, 3903..3906]
|
57
69
|
result << 564 if abc.iz2?
|
58
70
|
result
|
59
71
|
end
|
@@ -61,11 +73,19 @@ module Aurora
|
|
61
73
|
def refresh(registers)
|
62
74
|
super
|
63
75
|
|
76
|
+
@desired_speed = registers[3000]
|
64
77
|
@speed = registers[3001]
|
78
|
+
@discharge_pressure = registers[3322]
|
79
|
+
@suction_pressure = registers[3323]
|
80
|
+
@discharge_temperature = registers[3325]
|
65
81
|
@ambient_temperature = registers[3326]
|
66
82
|
@drive_temperature = registers[3327]
|
67
83
|
@inverter_temperature = registers[3522]
|
68
84
|
@fan_speed = registers[3524]
|
85
|
+
@eev_percentage = registers[3808]
|
86
|
+
@suction_temperature = registers[3903]
|
87
|
+
@saturated_evaporator_discharge_temperature = registers[3905]
|
88
|
+
@superheat_temperature = registers[3906]
|
69
89
|
|
70
90
|
@iz2_desired_speed = registers[564] if abc.iz2?
|
71
91
|
end
|
data/lib/aurora/mock_abc.rb
CHANGED
@@ -4,7 +4,8 @@ module Aurora
|
|
4
4
|
class MockABC
|
5
5
|
attr_accessor :logger
|
6
6
|
|
7
|
-
def initialize(registers)
|
7
|
+
def initialize(registers, ignore_missing_registers: false)
|
8
|
+
@ignore_missing_registers = ignore_missing_registers
|
8
9
|
@registers = registers
|
9
10
|
end
|
10
11
|
|
@@ -59,6 +60,8 @@ module Aurora
|
|
59
60
|
private
|
60
61
|
|
61
62
|
def missing_register(idx)
|
63
|
+
raise ::ModBus::Errors::IllegalDataAddress unless @ignore_missing_registers
|
64
|
+
|
62
65
|
logger.warn("missing register #{idx}")
|
63
66
|
end
|
64
67
|
end
|
data/lib/aurora/registers.rb
CHANGED
@@ -60,6 +60,7 @@ module Aurora
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def to_int32(registers, idx)
|
63
|
+
Aurora&.logger&.warn("Missing register #{idx + 1}") unless registers[idx + 1]
|
63
64
|
(registers[idx] << 16) + registers[idx + 1]
|
64
65
|
end
|
65
66
|
|
@@ -708,8 +709,8 @@ module Aurora
|
|
708
709
|
17 => "Aux/E Heat Stage", # this is how long aux/eheat have been requested in seconds
|
709
710
|
# when in eheat mode (explicit on the thermostat), it will stage up to eh2 after 130s
|
710
711
|
# when in aux mode (thermostat set to heat; compressor at full capacity), it will stage up to eh2 after 310s
|
711
|
-
19 => "
|
712
|
-
20 => "FP2",
|
712
|
+
19 => "Cooling Liquid Line Temperature (FP1)",
|
713
|
+
20 => "Air Coil Temperature (FP2)",
|
713
714
|
21 => "Condensate", # >= 270 normal, otherwise fault
|
714
715
|
25 => "Last Fault Number", # high bit set if locked out
|
715
716
|
26 => "Last Lockout",
|
@@ -858,7 +859,11 @@ module Aurora
|
|
858
859
|
1154 => "Heat of Extraction",
|
859
860
|
1156 => "Heat of Rejection",
|
860
861
|
1164 => "Pump Watts",
|
862
|
+
# this combines thermostat/iz2 desired speed with manual operation override
|
861
863
|
3000 => "Compressor Speed Desired",
|
864
|
+
# this shows the actual speed
|
865
|
+
# it can differ from desired during a ramp to the desired speed, or
|
866
|
+
# the periodic ramp up to speed 6 that's not visible in the desired speed
|
862
867
|
3001 => "Compressor Speed Actual",
|
863
868
|
3002 => "Manual Operation",
|
864
869
|
3027 => "Compressor Speed",
|
@@ -884,7 +889,7 @@ module Aurora
|
|
884
889
|
3523 => "VS Drive UDC Voltage",
|
885
890
|
3524 => "VS Drive Fan Speed",
|
886
891
|
3804 => "VS Drive Details (EEV2 Ctl)",
|
887
|
-
3808 => "VS Drive
|
892
|
+
3808 => "VS Drive EEV2 % Open",
|
888
893
|
3903 => "VS Drive Suction Temperature",
|
889
894
|
3904 => "VS Drive Leaving Air Temperature?",
|
890
895
|
3905 => "VS Drive Saturated Evaporator Discharge Temperature",
|
data/lib/aurora/thermostat.rb
CHANGED
@@ -15,9 +15,9 @@ module Aurora
|
|
15
15
|
:fan_intermittent_off
|
16
16
|
|
17
17
|
def registers_to_read
|
18
|
-
return [
|
18
|
+
return [] unless @abc.awl_thermostat?
|
19
19
|
|
20
|
-
[
|
20
|
+
[502, 745..746, 12_005..12_006]
|
21
21
|
end
|
22
22
|
|
23
23
|
def refresh(registers)
|
data/lib/aurora/version.rb
CHANGED
data/lib/aurora.rb
CHANGED
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: 1.
|
4
|
+
version: 1.2.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: 2022-
|
11
|
+
date: 2022-02-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ccutrer-serialport
|