waterfurnace_aurora 0.4.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/exe/aurora_monitor +9 -5
- data/exe/aurora_mqtt_bridge +85 -53
- data/lib/aurora/abc_client.rb +37 -93
- data/lib/aurora/component.rb +6 -0
- data/lib/aurora/compressor.rb +65 -0
- data/lib/aurora/dhw.rb +31 -0
- data/lib/aurora/iz2_zone.rb +16 -12
- data/lib/aurora/mock_abc.rb +1 -0
- data/lib/aurora/pump.rb +60 -0
- data/lib/aurora/registers.rb +29 -11
- data/lib/aurora/thermostat.rb +39 -7
- data/lib/aurora/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 16b9a4ef085dc672bf6b360947c70a959f03b3406f0c2dae4eac614a2f12c412
|
4
|
+
data.tar.gz: 5a7ef967170bd5440b94407e05cfe6e2f1bae40d838a23de26d442a1e4fa9a14
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d31c1d4a82dc9420adedd8b5043ebde59845eb5cc90c14109ad51d533687e0fa7010e91c04858773d9f40523f534118d72f891fb673344810244e2d121c0b764
|
7
|
+
data.tar.gz: b83b92e7b7ad9ecb2dda5eae57d2d460a82285420e169acc317c54390234cc123bead659fc56e2be53dbb602dd24e0b4cce66bd4223bd52badd7d543d641a4a7
|
data/exe/aurora_monitor
CHANGED
@@ -30,7 +30,7 @@ end
|
|
30
30
|
|
31
31
|
options.parse!
|
32
32
|
|
33
|
-
unless ARGV.length ==
|
33
|
+
unless ARGV.length == 1
|
34
34
|
puts options
|
35
35
|
exit 1
|
36
36
|
end
|
@@ -39,8 +39,8 @@ uri = URI.parse(ARGV[0])
|
|
39
39
|
|
40
40
|
last_registers = {}
|
41
41
|
|
42
|
-
SENSOR_REGISTERS = [16, 19, 20, 740, 900, 1109, 1105, 1106, 1107, 1108, 1110, 1111, 1114, 1117,
|
43
|
-
1153, 1165].freeze
|
42
|
+
SENSOR_REGISTERS = [16, 19, 20, 740, 900, 901, 903, 908, 909, 1109, 1105, 1106, 1107, 1108, 1110, 1111, 1114, 1117,
|
43
|
+
1134, 1148, 1149, 1150, 1151, 1152, 1153, 1164, 1165, 3326, 3330].freeze
|
44
44
|
|
45
45
|
io = case uri.scheme
|
46
46
|
when "tcp"
|
@@ -76,7 +76,11 @@ diff_and_print = lambda do |registers|
|
|
76
76
|
end
|
77
77
|
|
78
78
|
server.request_callback = lambda { |uid, func, req|
|
79
|
-
if func ==
|
79
|
+
if func == 6
|
80
|
+
puts "#{Time.now} ===== write register to #{uid}:"
|
81
|
+
registers = { req[:addr] => req[:val] }
|
82
|
+
puts Aurora.print_registers(registers)
|
83
|
+
elsif func == 68
|
80
84
|
puts "#{Time.now} ===== no idea to #{uid}: #{req.inspect}" unless diff_only
|
81
85
|
elsif func == 67
|
82
86
|
puts "#{Time.now} ===== write discontiguous registers to #{uid}:"
|
@@ -125,7 +129,7 @@ server.response_callback = lambda { |uid, func, res, req|
|
|
125
129
|
puts "#{Time.now} ===== read discontiguous registers from #{uid}" unless diff_only
|
126
130
|
registers = req.zip(res).to_h
|
127
131
|
diff_and_print.call(registers)
|
128
|
-
elsif [16, 67, 68].include?(func)
|
132
|
+
elsif [6, 16, 67, 68].include?(func)
|
129
133
|
# no output
|
130
134
|
else
|
131
135
|
puts "#{Time.now} **** new func #{func}"
|
data/exe/aurora_mqtt_bridge
CHANGED
@@ -74,30 +74,26 @@ class MQTTBridge
|
|
74
74
|
begin
|
75
75
|
@mutex.synchronize do
|
76
76
|
@abc.refresh
|
77
|
-
@homie_abc.each do |property|
|
78
|
-
property.value = @abc.public_send(property.id.tr("-", "_"))
|
79
|
-
end
|
80
77
|
|
81
|
-
@
|
82
|
-
|
78
|
+
components = { @homie_abc => @abc,
|
79
|
+
@compressor => @abc.compressor,
|
80
|
+
@blower => @abc.blower,
|
81
|
+
@pump => @abc.pump,
|
82
|
+
@dhw => @abc.dhw }.compact
|
83
|
+
@abc.zones.each_with_index do |z, idx|
|
84
|
+
homie_zone = @homie["zone#{idx + 1}"]
|
85
|
+
components[homie_zone] = z
|
83
86
|
end
|
84
87
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
88
|
+
components.each do |(node, object)|
|
89
|
+
node.each do |property|
|
90
|
+
property.value = object.public_send(property.id.tr("-", "_"))
|
91
|
+
end
|
89
92
|
end
|
90
93
|
|
91
94
|
@abc.faults.each_with_index do |fault_count, i|
|
92
95
|
@faults["e#{i + 1}"].value = fault_count
|
93
96
|
end
|
94
|
-
|
95
|
-
@abc.zones.each_with_index do |z, idx|
|
96
|
-
homie_zone = @homie["zone#{idx + 1}"]
|
97
|
-
homie_zone.each do |property|
|
98
|
-
property.value = z.public_send(property.id.tr("-", "_"))
|
99
|
-
end
|
100
|
-
end
|
101
97
|
end
|
102
98
|
rescue => e
|
103
99
|
warn "got garbage: #{e}; #{e.backtrace}"
|
@@ -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,
|
@@ -126,16 +120,31 @@ class MQTTBridge
|
|
126
120
|
end
|
127
121
|
node.property("relative-humidity", "Relative Humidity", :integer, @abc.relative_humidity, unit: "%",
|
128
122
|
format: 0..100)
|
129
|
-
node.property("waterflow", "Waterflow", :float, @abc.waterflow, unit: "gpm")
|
130
123
|
node.property("fp1", "FP1 Sensor", :float, @abc.fp1, unit: "ºF")
|
131
124
|
node.property("fp2", "FP2 Sensor", :float, @abc.fp2, unit: "ºF")
|
132
|
-
%i[
|
125
|
+
%i[aux_heat total].each do |component|
|
133
126
|
component = "#{component}_watts"
|
134
127
|
node.property(component.tr("_", "-"), component.tr("_", " ").titleize, :integer,
|
135
128
|
@abc.public_send(component), unit: "W")
|
136
129
|
end
|
137
130
|
end
|
138
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
|
+
|
139
148
|
@blower = @homie.node("blower", "Blower", @abc.blower.type) do |node|
|
140
149
|
if @abc.blower.respond_to?(:running)
|
141
150
|
node.property("running", "Blower is running", :boolean, @abc.blower.running?)
|
@@ -143,31 +152,58 @@ class MQTTBridge
|
|
143
152
|
node.property("speed", "Current blower speed", :integer, @abc.blower.speed, format: @abc.blower.speed_range)
|
144
153
|
end
|
145
154
|
node.property("watts", "Energy Usage", :integer, @abc.blower.watts, unit: "W") if @abc.energy_monitoring?
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
format: 0..100, unit: "%")
|
155
|
+
|
156
|
+
next unless @abc.blower.is_a?(Aurora::Blower::ECM)
|
157
|
+
|
158
|
+
presets = %w[blower-only aux-heat]
|
159
|
+
presets.concat %w[low-compressor high-compressor] unless @abc.iz2?
|
160
|
+
presets.each do |setting|
|
161
|
+
field = "#{setting.tr('-', '_')}_speed"
|
162
|
+
node.property("#{setting}-speed", "#{setting.tr('-', ' ').titleize} Preset Speed", :integer,
|
163
|
+
@abc.blower.public_send(field), format: 1..12) do |value, property|
|
164
|
+
@mutex.synchronize { property.value = @abc.blower.public_send("#{field}=", value) }
|
157
165
|
end
|
158
166
|
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: "%")
|
172
|
+
end
|
173
|
+
|
174
|
+
@pump = @homie.node("pump", "Loop Pump", @abc.pump.type) do |node|
|
175
|
+
node.property("waterflow", "Waterflow", :float, @abc.pump.waterflow, unit: "gpm")
|
176
|
+
node.property("watts", "Energy Usage", :integer, @abc.pump.watts, unit: "W") if @abc.energy_monitoring?
|
177
|
+
|
178
|
+
next unless @abc.pump.is_a?(Aurora::Pump::VSPump)
|
179
|
+
|
180
|
+
node.property("speed", "Speed", :integer, @abc.pump.speed, format: 0..100, unit: "%") do |value, property|
|
181
|
+
@mutex.synchronize { property.value = @abc.pump.speed = value }
|
182
|
+
end
|
183
|
+
node.property("manual-control", "If manual control is enabled", :boolean,
|
184
|
+
@abc.pump.manual_control?) do |value, property|
|
185
|
+
@mutex.synchronize { property.value = @abc.pump.manual_control = value }
|
186
|
+
end
|
187
|
+
node.property("minimum-speed", "Speed pump runs at compressor speed 0", :integer, @abc.pump.minimum_speed,
|
188
|
+
format: 0..100, unit: "%") do |value, property|
|
189
|
+
@mutex.synchronize { property.value = @abc.pump.minimum_speed = value }
|
190
|
+
end
|
191
|
+
node.property("maximum-speed", "Speed pump runs at compressor speed 12", :integer, @abc.pump.minimum_speed,
|
192
|
+
format: 0..100, unit: "%") do |value, property|
|
193
|
+
@mutex.synchronize { property.value = @abc.pump.maximum_speed = value }
|
194
|
+
end
|
159
195
|
end
|
160
196
|
|
161
|
-
if @abc.dhw
|
197
|
+
if @abc.dhw
|
162
198
|
@dhw = @homie.node("dhw", "Domestic Hot Water Generator", "DHW") do |node|
|
163
|
-
node.property("enabled", "Enabled", :boolean, @abc.
|
164
|
-
@mutex.synchronize { property.value = @abc.
|
199
|
+
node.property("enabled", "Enabled", :boolean, @abc.dhw.enabled) do |value, property|
|
200
|
+
@mutex.synchronize { property.value = @abc.dhw.enabled = value }
|
165
201
|
end
|
166
|
-
node.property("water-temperature", "
|
167
|
-
@abc.
|
168
|
-
node.property("set-point", "
|
169
|
-
|
170
|
-
@mutex.synchronize { property.value = @abc.
|
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 }
|
171
207
|
end
|
172
208
|
end
|
173
209
|
end
|
@@ -188,25 +224,21 @@ class MQTTBridge
|
|
188
224
|
format: allowed_modes) do |value, property|
|
189
225
|
@mutex.synchronize { property.value = zone.target_mode = value.to_sym }
|
190
226
|
end
|
191
|
-
|
192
|
-
|
193
|
-
format: %w[standby h1 h2 h3 c1 c2])
|
194
|
-
end
|
227
|
+
node.property("current-mode", "Current Heating/Cooling Mode Requested", :enum, zone.current_mode,
|
228
|
+
format: %w[standby h1 h2 h3 c1 c2])
|
195
229
|
node.property("target-fan-mode", "Target Fan Mode", :enum, zone.target_fan_mode,
|
196
230
|
format: %w[auto continuous intermittent]) do |value, property|
|
197
231
|
@mutex.synchronize { property.value = zone.target_fan_mode = value.to_sym }
|
198
232
|
end
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
unit: "M", format: %w[0 5 10 15 20 25 30 35 40]) do |value, property|
|
207
|
-
@mutex.synchronize { property.value = zone.fan_intermittent_on = value.to_i }
|
208
|
-
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 }
|
209
240
|
end
|
241
|
+
node.property("current-fan-mode", "Current Fan Status", :boolean, zone.current_fan_mode)
|
210
242
|
if zone.is_a?(Aurora::IZ2Zone)
|
211
243
|
node.property("priority", "Zone Priority", :enum, zone.priority, format: %w[economy comfort])
|
212
244
|
node.property("size", "Size", :enum, zone.size, format: %w[0 25 45 70])
|
data/lib/aurora/abc_client.rb
CHANGED
@@ -4,7 +4,10 @@ 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"
|
10
|
+
require "aurora/pump"
|
8
11
|
require "aurora/thermostat"
|
9
12
|
|
10
13
|
module Aurora
|
@@ -39,50 +42,55 @@ module Aurora
|
|
39
42
|
attr_reader :modbus_slave,
|
40
43
|
:serial_number,
|
41
44
|
:zones,
|
45
|
+
:compressor,
|
42
46
|
:blower,
|
47
|
+
:pump,
|
48
|
+
:dhw,
|
43
49
|
:faults,
|
44
50
|
:current_mode,
|
45
|
-
:dhw_enabled,
|
46
|
-
:dhw_setpoint,
|
47
51
|
:entering_air_temperature,
|
48
52
|
:relative_humidity,
|
49
53
|
:leaving_air_temperature,
|
50
54
|
:leaving_water_temperature,
|
51
55
|
:entering_water_temperature,
|
52
|
-
:dhw_water_temperature,
|
53
|
-
:waterflow,
|
54
|
-
:compressor_speed,
|
55
56
|
:outdoor_temperature,
|
56
57
|
:fp1,
|
57
58
|
:fp2,
|
58
|
-
:compressor_watts,
|
59
59
|
:aux_heat_watts,
|
60
|
-
:loop_pump_watts,
|
61
60
|
:total_watts
|
62
61
|
|
63
62
|
def initialize(uri)
|
64
63
|
@modbus_slave = self.class.open_modbus_slave(uri)
|
65
64
|
@modbus_slave.read_retry_timeout = 15
|
66
65
|
@modbus_slave.read_retries = 2
|
67
|
-
raw_registers = @modbus_slave.holding_registers[88..91, 105...110, 404, 412, 1114]
|
66
|
+
raw_registers = @modbus_slave.holding_registers[88..91, 105...110, 404, 412..413, 1114]
|
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
|
|
74
|
-
@blower = case raw_registers[404]
|
75
|
-
when 1, 2 then Blower::ECM.new(self, registers[404])
|
76
|
-
when 3 then Blower::FiveSpeed.new(self, registers[404])
|
77
|
-
else; Blower::PSC.new(self, registers[404])
|
78
|
-
end
|
79
|
-
|
80
72
|
@zones = if iz2?
|
81
73
|
iz2_zone_count = @modbus_slave.holding_registers[483]
|
82
74
|
(0...iz2_zone_count).map { |i| IZ2Zone.new(self, i + 1) }
|
83
75
|
else
|
84
76
|
[Thermostat.new(self)]
|
85
77
|
end
|
78
|
+
|
79
|
+
@compressor = @program == "ABCVSP" ? Compressor::VSDrive.new(self) : Compressor::GenericCompressor.new(self)
|
80
|
+
@blower = case raw_registers[404]
|
81
|
+
when 1, 2 then Blower::ECM.new(self, registers[404])
|
82
|
+
when 3 then Blower::FiveSpeed.new(self, registers[404])
|
83
|
+
else; Blower::PSC.new(self, registers[404])
|
84
|
+
end
|
85
|
+
@pump = if (3..5).include?(raw_registers[413])
|
86
|
+
Pump::VSPump.new(self,
|
87
|
+
registers[413])
|
88
|
+
else
|
89
|
+
Pump::GenericPump.new(self,
|
90
|
+
registers[413])
|
91
|
+
end
|
92
|
+
@dhw = DHW.new(self) if (-999..999).include?(registers[1114])
|
93
|
+
|
86
94
|
@faults = []
|
87
95
|
end
|
88
96
|
|
@@ -121,25 +129,18 @@ module Aurora
|
|
121
129
|
end
|
122
130
|
|
123
131
|
def refresh
|
124
|
-
registers_to_read = [6, 19..20, 25, 30, 344, 740..741, 900, 1110..1111, 1114,
|
132
|
+
registers_to_read = [6, 19..20, 25, 30, 344, 740..741, 900, 1110..1111, 1114, 1150..1153, 1165,
|
125
133
|
31_003]
|
126
|
-
|
127
|
-
|
128
|
-
registers_to_read.concat([362, 3001]) if vs_drive?
|
129
|
-
|
130
|
-
if zones.first.is_a?(IZ2Zone)
|
131
|
-
zones.each_with_index do |_z, i|
|
132
|
-
base1 = 21_203 + i * 9
|
133
|
-
base2 = 31_007 + i * 3
|
134
|
-
base3 = 31_200 + i * 3
|
135
|
-
registers_to_read << (base1..(base1 + 1))
|
136
|
-
registers_to_read << (base2..(base2 + 2))
|
137
|
-
registers_to_read << base3
|
138
|
-
end
|
139
|
-
else
|
140
|
-
registers_to_read << 502
|
141
|
-
registers_to_read << (745..746)
|
134
|
+
zones.each do |z|
|
135
|
+
registers_to_read.concat(z.registers_to_read)
|
142
136
|
end
|
137
|
+
registers_to_read.concat(compressor.registers_to_read)
|
138
|
+
registers_to_read.concat(blower.registers_to_read)
|
139
|
+
registers_to_read.concat(pump.registers_to_read)
|
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)
|
143
144
|
|
144
145
|
@faults = @modbus_slave.holding_registers[601..699]
|
145
146
|
|
@@ -148,24 +149,11 @@ module Aurora
|
|
148
149
|
|
149
150
|
outputs = registers[30]
|
150
151
|
|
151
|
-
@dhw_enabled = registers[400]
|
152
|
-
@dhw_setpoint = registers[401]
|
153
152
|
@entering_air_temperature = registers[740]
|
154
153
|
@relative_humidity = registers[741]
|
155
154
|
@leaving_air_temperature = registers[900]
|
156
155
|
@leaving_water_temperature = registers[1110]
|
157
156
|
@entering_water_temperature = registers[1111]
|
158
|
-
@dhw_water_temperature = registers[1114]
|
159
|
-
@waterflow = registers[1117]
|
160
|
-
@compressor_speed = if vs_drive?
|
161
|
-
registers[3001]
|
162
|
-
elsif outputs.include?(:cc2)
|
163
|
-
2
|
164
|
-
elsif outputs.include?(:cc)
|
165
|
-
1
|
166
|
-
else
|
167
|
-
0
|
168
|
-
end
|
169
157
|
@outdoor_temperature = registers[31_003]
|
170
158
|
@fp1 = registers[19]
|
171
159
|
@fp2 = registers[20]
|
@@ -173,9 +161,7 @@ module Aurora
|
|
173
161
|
@error = registers[25] & 0x7fff
|
174
162
|
@derated = (41..46).include?(@error)
|
175
163
|
@safe_mode = [47, 48, 49, 72, 74].include?(@error)
|
176
|
-
@compressor_watts = registers[1147]
|
177
164
|
@aux_heat_watts = registers[1151]
|
178
|
-
@loop_pump_watts = registers[1165]
|
179
165
|
@total_watts = registers[1153]
|
180
166
|
|
181
167
|
@current_mode = if outputs.include?(:lockout)
|
@@ -196,23 +182,13 @@ module Aurora
|
|
196
182
|
:standby
|
197
183
|
end
|
198
184
|
|
199
|
-
blower.refresh(registers)
|
200
|
-
|
201
185
|
zones.each do |z|
|
202
186
|
z.refresh(registers)
|
203
187
|
end
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
@modbus_slave.holding_registers[340] = value
|
210
|
-
end
|
211
|
-
|
212
|
-
def aux_heat_ecm_speed=(value)
|
213
|
-
return unless (1..12).include?(value)
|
214
|
-
|
215
|
-
@modbus_slave.holding_registers[347] = value
|
188
|
+
compressor.refresh(registers)
|
189
|
+
blower.refresh(registers)
|
190
|
+
pump.refresh(registers)
|
191
|
+
dhw&.refresh(registers)
|
216
192
|
end
|
217
193
|
|
218
194
|
def cooling_airflow_adjustment=(value)
|
@@ -220,34 +196,10 @@ module Aurora
|
|
220
196
|
@modbus_slave.holding_registers[346] = value
|
221
197
|
end
|
222
198
|
|
223
|
-
def dhw_enabled=(value)
|
224
|
-
@modbus_slave.holding_registers[400] = value ? 1 : 0
|
225
|
-
end
|
226
|
-
|
227
|
-
def dhw_setpoint=(value)
|
228
|
-
raise ArgumentError unless (100..140).include?(value)
|
229
|
-
|
230
|
-
@modbus_slave.holding_registers[401] = (value * 10).to_i
|
231
|
-
end
|
232
|
-
|
233
199
|
def loop_pressure_trip=(value)
|
234
200
|
@modbus_slave.holding_registers[419] = (value * 10).to_i
|
235
201
|
end
|
236
202
|
|
237
|
-
def vs_pump_control=(value)
|
238
|
-
raise ArgumentError unless (value = VS_PUMP_CONTROL.invert[value])
|
239
|
-
|
240
|
-
@modbus_slave.holding_registers[323] = value
|
241
|
-
end
|
242
|
-
|
243
|
-
def vs_pump_min=(value)
|
244
|
-
@modbus_slave.holding_registers[321] = value
|
245
|
-
end
|
246
|
-
|
247
|
-
def vs_pump_max=(value)
|
248
|
-
@modbus_slave.holding_registers[322] = value
|
249
|
-
end
|
250
|
-
|
251
203
|
def line_voltage=(value)
|
252
204
|
raise ArgumentError unless (90..635).include?(value)
|
253
205
|
|
@@ -289,14 +241,6 @@ module Aurora
|
|
289
241
|
@energy_monitor == 2
|
290
242
|
end
|
291
243
|
|
292
|
-
def vs_drive?
|
293
|
-
@program == "ABCVSP"
|
294
|
-
end
|
295
|
-
|
296
|
-
def dhw?
|
297
|
-
(-999..999).include?(dhw_water_temperature)
|
298
|
-
end
|
299
|
-
|
300
244
|
# config aurora system
|
301
245
|
{ thermostat: 800, axb: 806, iz2: 812, aoc: 815, moc: 818, eev2: 824 }.each do |(component, register)|
|
302
246
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
data/lib/aurora/component.rb
CHANGED
@@ -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
|
data/lib/aurora/iz2_zone.rb
CHANGED
@@ -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,
|
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
|
|
@@ -41,28 +45,28 @@ module Aurora
|
|
41
45
|
def target_mode=(value)
|
42
46
|
return unless (raw_value = Aurora::HEATING_MODE.invert[value])
|
43
47
|
|
44
|
-
|
48
|
+
holding_registers[21_202 + (zone_number - 1) * 9] = raw_value
|
45
49
|
@target_mode = value
|
46
50
|
end
|
47
51
|
|
48
52
|
def target_fan_mode=(value)
|
49
53
|
return unless (raw_value = Aurora::FAN_MODE.invert[value])
|
50
54
|
|
51
|
-
|
55
|
+
holding_registers[21_205 + (zone_number - 1) * 9] = raw_value
|
52
56
|
@target_fan_mode = value
|
53
57
|
end
|
54
58
|
|
55
59
|
def fan_intermittent_on=(value)
|
56
60
|
return unless value >= 0 && value <= 25 && (value % 5).zero?
|
57
61
|
|
58
|
-
|
62
|
+
holding_registers[21_206 + (zone_number - 1) * 9] = value
|
59
63
|
@fan_intermittent_on = value
|
60
64
|
end
|
61
65
|
|
62
66
|
def fan_intermittent_off=(value)
|
63
67
|
return unless value >= 0 && value <= 40 && (value % 5).zero?
|
64
68
|
|
65
|
-
|
69
|
+
holding_registers[21_207 + (zone_number - 1) * 9] = value
|
66
70
|
@fan_intermittent_off = value
|
67
71
|
end
|
68
72
|
|
@@ -70,7 +74,7 @@ module Aurora
|
|
70
74
|
return unless value >= 40 && value <= 90
|
71
75
|
|
72
76
|
raw_value = (value * 10).to_i
|
73
|
-
|
77
|
+
holding_registers[21_203 + (zone_number - 1) * 9] = raw_value
|
74
78
|
@heating_target_temperature = value
|
75
79
|
end
|
76
80
|
|
@@ -78,8 +82,8 @@ module Aurora
|
|
78
82
|
return unless value >= 54 && value <= 99
|
79
83
|
|
80
84
|
raw_value = (value * 10).to_i
|
81
|
-
|
82
|
-
@cooling_target_temperature =
|
85
|
+
holding_registers[21_204 + (zone_number - 1) * 9] = raw_value
|
86
|
+
@cooling_target_temperature = value
|
83
87
|
end
|
84
88
|
end
|
85
89
|
end
|
data/lib/aurora/mock_abc.rb
CHANGED
data/lib/aurora/pump.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "aurora/component"
|
4
|
+
|
5
|
+
module Aurora
|
6
|
+
module Pump
|
7
|
+
class GenericPump < Component
|
8
|
+
attr_reader :type, :watts, :waterflow
|
9
|
+
|
10
|
+
def initialize(abc, type)
|
11
|
+
super(abc)
|
12
|
+
@type = type
|
13
|
+
end
|
14
|
+
|
15
|
+
def registers_to_read
|
16
|
+
result = [1117]
|
17
|
+
result.concat([1164..1165]) if abc.energy_monitoring?
|
18
|
+
result
|
19
|
+
end
|
20
|
+
|
21
|
+
def refresh(registers)
|
22
|
+
@waterflow = registers[1117]
|
23
|
+
@watts = registers[1164] if abc.energy_monitoring?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class VSPump < GenericPump
|
28
|
+
attr_reader :speed, :minimum_speed, :maximum_speed, :manual_control
|
29
|
+
alias manual_control? manual_control
|
30
|
+
|
31
|
+
def registers_to_read
|
32
|
+
super + [321..325]
|
33
|
+
end
|
34
|
+
|
35
|
+
def refresh(registers)
|
36
|
+
super
|
37
|
+
@minimum_speed = registers[321]
|
38
|
+
@maximum_speed = registers[322]
|
39
|
+
@manual_control = registers[323] != :off
|
40
|
+
@speed = registers[325]
|
41
|
+
end
|
42
|
+
|
43
|
+
def manual_control=(value)
|
44
|
+
holding_registers[323] = value ? speed : 0x7fff
|
45
|
+
end
|
46
|
+
|
47
|
+
{ speed: 323,
|
48
|
+
minimum_speed: 321,
|
49
|
+
maximum_speed: 322 }.each do |(setting, register)|
|
50
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
51
|
+
def #{setting}=(value)
|
52
|
+
raise ArgumentError unless (1..100).include?(value)
|
53
|
+
|
54
|
+
holding_registers[#{register}] = value
|
55
|
+
end
|
56
|
+
RUBY
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/aurora/registers.rb
CHANGED
@@ -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 &
|
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?
|
@@ -476,7 +485,7 @@ module Aurora
|
|
476
485
|
REGISTER_CONVERTERS = {
|
477
486
|
TO_HUNDREDTHS => [2, 3, 417, 418, 801, 804, 807, 813, 816, 817, 819, 820, 825, 828],
|
478
487
|
method(:dipswitch_settings) => [4, 33],
|
479
|
-
TO_TENTHS => [19, 20, 401, 419, 501, 502, 567, 740, 745, 746, 747, 900,
|
488
|
+
TO_TENTHS => [19, 20, 401, 419, 501, 502, 567, 740, 745, 746, 747, 900, 901, 903,
|
480
489
|
1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1119, 1124, 1125, 1134,
|
481
490
|
3322, 3323, 3325, 3326, 3327, 3330, 3522, 3903, 3905, 3906,
|
482
491
|
12_619, 12_620,
|
@@ -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
|
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],
|
@@ -540,7 +550,7 @@ module Aurora
|
|
540
550
|
REGISTER_FORMATS = {
|
541
551
|
"%ds" => [1, 6, 9, 15, 84, 85, 110],
|
542
552
|
"%dV" => [16, 112, 3331, 3424, 3523],
|
543
|
-
"%0.1fºF" => [19, 20, 401, 501, 502, 567, 740, 745, 746, 747, 900,
|
553
|
+
"%0.1fºF" => [19, 20, 401, 501, 502, 567, 740, 745, 746, 747, 900, 903,
|
544
554
|
1109, 1110, 1111, 1112, 1113, 1114, 1124, 1125, 1134, 1135, 1136,
|
545
555
|
3325, 3326, 3327, 3330, 3522, 3903, 3905, 3906,
|
546
556
|
12_619, 12_620,
|
@@ -553,8 +563,8 @@ module Aurora
|
|
553
563
|
31_003,
|
554
564
|
31_007, 31_010, 31_013, 31_016, 31_019, 31_022],
|
555
565
|
"E%d" => [25, 26],
|
556
|
-
"%d%%" => [282, 321, 322, 325, 346, 565, 741, 1126, 3332, 3524, 3808],
|
557
|
-
"%0.1f psi" => [419, 1115, 1116, 1119, 3322, 3323],
|
566
|
+
"%d%%" => [282, 321, 322, 325, 346, 565, 741, 908, 1126, 3332, 3524, 3808],
|
567
|
+
"%0.1f psi" => [419, 901, 1115, 1116, 1119, 3322, 3323],
|
558
568
|
"%0.1fA" => [1105, 1106, 1107, 1108],
|
559
569
|
"%0.1fgpm" => [1117],
|
560
570
|
"%dW" => [1146, 1148, 1150, 1152, 1164, 3422],
|
@@ -812,6 +822,10 @@ module Aurora
|
|
812
822
|
828 => "AWL Version",
|
813
823
|
829 => "AWL Revision",
|
814
824
|
900 => "Leaving Air",
|
825
|
+
901 => "Suction Pressure",
|
826
|
+
903 => "SuperHeat Temperature",
|
827
|
+
908 => "EEV Open %",
|
828
|
+
909 => "SubCooling (Cooling)",
|
815
829
|
1103 => "AXB Inputs",
|
816
830
|
1104 => "AXB Outputs",
|
817
831
|
1105 => "Blower Amps",
|
@@ -841,10 +855,6 @@ module Aurora
|
|
841
855
|
1154 => "Heat of Extraction",
|
842
856
|
1156 => "Heat of Rejection",
|
843
857
|
1164 => "Pump Watts",
|
844
|
-
12_606 => "Heating Mode (write)",
|
845
|
-
12_619 => "Heating Setpoint (write)",
|
846
|
-
12_620 => "Cooling Setpoint (write)",
|
847
|
-
12_621 => "Fan Mode (write)",
|
848
858
|
3000 => "Compressor Speed Desired",
|
849
859
|
3001 => "Compressor Speed Actual",
|
850
860
|
3002 => "Manual Operation",
|
@@ -876,6 +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",
|
891
|
+
12_606 => "Heating Mode (write)",
|
892
|
+
12_619 => "Heating Setpoint (write)",
|
893
|
+
12_620 => "Cooling Setpoint (write)",
|
894
|
+
12_621 => "Fan Mode (write)",
|
895
|
+
12_622 => "Intermittent Fan On Time (write)",
|
896
|
+
12_623 => "Intermittent Fan Off Time (write)",
|
879
897
|
31_003 => "Outdoor Temp",
|
880
898
|
31_005 => "IZ2 Demand",
|
881
899
|
31_109 => "Humidifier Mode", # write to 21114
|
data/lib/aurora/thermostat.rb
CHANGED
@@ -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
|
-
@heating_target_temperature = registers[
|
16
|
-
@cooling_target_temperature = registers[
|
23
|
+
@heating_target_temperature = registers[745]
|
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
|
50
|
-
|
51
|
-
|
52
|
-
|
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
|
data/lib/aurora/version.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: 0.
|
4
|
+
version: 0.5.0
|
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-
|
11
|
+
date: 2021-09-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ccutrer-serialport
|
@@ -136,11 +136,14 @@ 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
|
143
145
|
- lib/aurora/modbus/slave.rb
|
146
|
+
- lib/aurora/pump.rb
|
144
147
|
- lib/aurora/registers.rb
|
145
148
|
- lib/aurora/thermostat.rb
|
146
149
|
- lib/aurora/version.rb
|