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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8311d85ee1e300bcfbb3228a65cb98a69301f25f27569c36d898faf97c25fbd5
4
- data.tar.gz: 86eab096d17d12aa01bb56f253022d64bb806d5aec3b55c6efc16a895b75d111
3
+ metadata.gz: caf73ece152211ae227b1b628572d0dc43936b600c2d41a0a534178dc74385cd
4
+ data.tar.gz: d5ed42012eb9fc1e2aca036914cfd538e3342df0f34342e2c9c37d18ad6cce29
5
5
  SHA512:
6
- metadata.gz: 7edd9fd909c0b9fe316f306bf00a56eff1108f467718d71c1645596675938abd67c5e727b4f6312d79c1d706df0f22f7d65f475c35061f7b66405add92eec342
7
- data.tar.gz: b0a6f4af036ebcd003557777e1fd276e33e56e1cbfbde268ad42a5a5bfa729c9ffa718dd3fd08917aad8beba2bf4d894519de128a5ba1519b5988ba5ddc707f7
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("Use `known` to fetch all identified registers. Use `valid` to fetch all registers that will respond.")
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") { debug_modbus = true }
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($stdout)
47
- modbus_slave.logger.level = debug_modbus ? :debug : :warn
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
 
@@ -90,30 +90,33 @@ class MQTTBridge
90
90
  loop do
91
91
  begin
92
92
  @mutex.synchronize do
93
- @abc.refresh
94
-
95
- components = { @homie_abc => @abc,
96
- @aux_heat => @abc.aux_heat,
97
- @compressor => @abc.compressor,
98
- @blower => @abc.blower,
99
- @pump => @abc.pump,
100
- @dhw => @abc.dhw,
101
- @humidistat => @abc.humidistat }.compact
102
- @abc.zones.each_with_index do |z, idx|
103
- homie_zone = @homie["zone#{idx + 1}"]
104
- components[homie_zone] = z
105
- end
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
- components.each do |(node, object)|
108
- node.each do |property|
109
- property.value = object.public_send(property.id.tr("-", "_"))
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
- @abc.faults.each_with_index do |fault_count, i|
114
- next if fault_count == 0xffff
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
- @faults["e#{i + 1}"].value = fault_count
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("fp1",
197
- "FP1 Sensor",
235
+ node.property("air-coil-temperature",
236
+ "Air Coil Temperature (FP2)",
198
237
  :float,
199
- @abc.fp1,
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
 
@@ -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
- return Aurora::MockABC.new(YAML.load_file(uri.path)) if File.file?(uri.path)
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, ::ModBus::Errors::IllegalFunction
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
- :fp1,
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
- @registers_to_read = [6, 19..20, 25, 30, 112, 344, 567, 1104, 1110..1111, 1114, 1150..1153, 1165]
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[567]
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
- @fp1 = registers[19]
192
- @fp2 = registers[20]
193
- @locked_out = registers[25] & 0x8000
194
- @error = registers[25] & 0x7fff
195
- @derated = (41..46).cover?(@error)
196
- @safe_mode = [47, 48, 49, 72, 74].include?(@error)
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
 
@@ -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
- if abc.energy_monitoring?
25
- [1146..1147]
26
- else
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, :inverter_temperature, :ambient_temperature, :iz2_desired_speed, :fan_speed
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, 3326..3327, 3522, 3524]
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
@@ -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
@@ -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 => "FP1 (Cooling Liquid Line) Temperature",
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 SuperHeat Percent",
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",
@@ -15,9 +15,9 @@ module Aurora
15
15
  :fan_intermittent_off
16
16
 
17
17
  def registers_to_read
18
- return [31] unless @abc.awl_thermostat?
18
+ return [] unless @abc.awl_thermostat?
19
19
 
20
- [31, 502, 745..746, 12_005..12_006]
20
+ [502, 745..746, 12_005..12_006]
21
21
  end
22
22
 
23
23
  def refresh(registers)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Aurora
4
- VERSION = "1.0.1"
4
+ VERSION = "1.2.2"
5
5
  end
data/lib/aurora.rb CHANGED
@@ -15,4 +15,7 @@ ModBus::Client::Slave.prepend(Aurora::ModBus::Slave)
15
15
  ModBus::RTUSlave.prepend(Aurora::ModBus::RTU)
16
16
 
17
17
  module Aurora
18
+ class << self
19
+ attr_accessor :logger
20
+ end
18
21
  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: 1.0.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-01-28 00:00:00.000000000 Z
11
+ date: 2022-02-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ccutrer-serialport