waterfurnace_aurora 0.4.0 → 0.4.4

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: 2d7a11b389793a826e3dc602b69ea7aea2ee73afc9839eb1b9df41f38895222e
4
- data.tar.gz: c30fad75a07bded088cb3a961e88bf298f5c482eafcb681309693ae00b079de0
3
+ metadata.gz: c2fb8894c93d6a099f927e91a025fff0faf6a159b29808d089431640f60376b8
4
+ data.tar.gz: edb0f65d15fdb706aa7471a4f3df1247e8ba354d841b9ef35c1f6874b7376eb0
5
5
  SHA512:
6
- metadata.gz: 7b0d336748b78005248f5b9b64afb573345a6a0426346bb2d1053d3fdaa4a814a313e5f621ca632d02358f0ec3d2a0c4c2506cb4dada0551c344a595be1f944b
7
- data.tar.gz: 0d46028195f215edfe1a1dcf0ec1b7ea50071ba1a7638ba9a2fd0bc3418cd4f451c88e7fb461c741970d683f94eef0c25ec5f2b64db4b80e1ae7ecc0b702a9f4
6
+ metadata.gz: 2ed469c2b2cb39a166b8664e735579c7f8541eed4f9c3a2c5d7b22046321948925a8bdd2fe08bed455856cf5b36f113040bf9f8f18632f70cdbf9abca9078278
7
+ data.tar.gz: a01d310d261571b7e2d1aa9537c56072820de03708eb7b9188ccae9d303f5ab54d8c6832f5949667c274247d7ef59066af3c69bd58cc80352d55db27daafbbcc
@@ -74,8 +74,19 @@ 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("-", "_"))
77
+
78
+ components = { @homie_abc => @abc,
79
+ @blower => @abc.blower,
80
+ @pump => @abc.pump }
81
+ @abc.zones.each_with_index do |z, idx|
82
+ homie_zone = @homie["zone#{idx + 1}"]
83
+ components[homie_zone] = z
84
+ end
85
+
86
+ components.each do |(node, object)|
87
+ node.each do |property|
88
+ property.value = object.public_send(property.id.tr("-", "_"))
89
+ end
79
90
  end
80
91
 
81
92
  if @abc.dhw?
@@ -87,13 +98,6 @@ class MQTTBridge
87
98
  @abc.faults.each_with_index do |fault_count, i|
88
99
  @faults["e#{i + 1}"].value = fault_count
89
100
  end
90
-
91
- @abc.zones.each_with_index do |z, idx|
92
- homie_zone = @homie["zone#{idx + 1}"]
93
- homie_zone.each do |property|
94
- property.value = z.public_send(property.id.tr("-", "_"))
95
- end
96
- end
97
101
  end
98
102
  rescue => e
99
103
  warn "got garbage: #{e}; #{e.backtrace}"
@@ -113,7 +117,6 @@ class MQTTBridge
113
117
  unit: "ºF")
114
118
  node.property("entering-water-temperature", "Entering Water Temperature", :float,
115
119
  @abc.entering_water_temperature, unit: "ºF")
116
- node.property("fan-speed", "Fan Speed", :integer, @abc.fan_speed, format: 0..11)
117
120
  node.property("leaving-air-temperature", "Leaving Air Temperature", :float, @abc.leaving_air_temperature,
118
121
  unit: "ºF")
119
122
  node.property("leaving-water-temperature", "Leaving Water Temperature", :float, @abc.leaving_water_temperature,
@@ -123,22 +126,60 @@ class MQTTBridge
123
126
  end
124
127
  node.property("relative-humidity", "Relative Humidity", :integer, @abc.relative_humidity, unit: "%",
125
128
  format: 0..100)
126
- node.property("waterflow", "Waterflow", :float, unit: "gpm")
127
129
  node.property("fp1", "FP1 Sensor", :float, @abc.fp1, unit: "ºF")
128
130
  node.property("fp2", "FP2 Sensor", :float, @abc.fp2, unit: "ºF")
129
- %i[compressor blower aux_heat loop_pump total].each do |component|
131
+ %i[compressor aux_heat total].each do |component|
130
132
  component = "#{component}_watts"
131
133
  node.property(component.tr("_", "-"), component.tr("_", " ").titleize, :integer,
132
134
  @abc.public_send(component), unit: "W")
133
135
  end
136
+ end
137
+
138
+ @blower = @homie.node("blower", "Blower", @abc.blower.type) do |node|
139
+ if @abc.blower.respond_to?(:running)
140
+ node.property("running", "Blower is running", :boolean, @abc.blower.running?)
141
+ else
142
+ node.property("speed", "Current blower speed", :integer, @abc.blower.speed, format: @abc.blower.speed_range)
143
+ end
144
+ node.property("watts", "Energy Usage", :integer, @abc.blower.watts, unit: "W") if @abc.energy_monitoring?
145
+
146
+ next unless @abc.blower.is_a?(Aurora::Blower::ECM)
147
+
148
+ presets = %w[blower-only aux-heat]
149
+ presets.concat %w[low-compressor high-compressor] unless @abc.iz2?
150
+ presets.each do |setting|
151
+ field = "#{setting.tr('-', '_')}_speed"
152
+ node.property("#{setting}-speed", "#{setting.tr('-', ' ').titleize} Preset Speed", :integer,
153
+ @abc.blower.public_send(field), format: 1..12) do |value, property|
154
+ @mutex.synchronize { property.value = @abc.blower.public_send("#{field}=", value) }
155
+ end
156
+ end
157
+ if @abc.iz2?
158
+ node.property("iz2-desired-speed", "IZ2 Desired Speed", :integer, @abc.blower.iz2_desired_speed,
159
+ format: 0..100, unit: "%")
160
+ end
161
+ end
162
+
163
+ @pump = @homie.node("pump", "Loop Pump", @abc.pump.type) do |node|
164
+ node.property("waterflow", "Waterflow", :float, @abc.pump.waterflow, unit: "gpm")
165
+ node.property("watts", "Energy Usage", :integer, @abc.pump.watts, unit: "W") if @abc.energy_monitoring?
134
166
 
135
- node.property("blower-only-ecm-speed", "Blower Only ECM Speed", :integer, @abc.blower_only_ecm_speed,
136
- format: 1..12) do |value, property|
137
- @mutex.synchronize { property.value = @abc.blower_only_ecm_speed = value }
167
+ next unless @abc.pump.is_a?(Aurora::Pump::VSPump)
168
+
169
+ node.property("speed", "Speed", :integer, @abc.pump.speed, format: 0..100, unit: "%") do |value, property|
170
+ @mutex.synchronize { property.value = @abc.pump.speed = value }
171
+ end
172
+ node.property("manual-control", "If manual control is enabled", :boolean,
173
+ @abc.pump.manual_control?) do |value, property|
174
+ @mutex.synchronize { property.value = @abc.pump.manual_control = value }
175
+ end
176
+ node.property("minimum-speed", "Speed pump runs at compressor speed 0", :integer, @abc.pump.minimum_speed,
177
+ format: 0..100, unit: "%") do |value, property|
178
+ @mutex.synchronize { property.value = @abc.pump.minimum_speed = value }
138
179
  end
139
- node.property("aux-heat-ecm-speed", "Aux Heat ECM Speed", :integer, @abc.aux_heat_ecm_speed,
140
- format: 1..12) do |value, property|
141
- @mutex.synchronize { property.value = @abc.aux_heat_ecm_speed = value }
180
+ node.property("maximum-speed", "Speed pump runs at compressor speed 12", :integer, @abc.pump.minimum_speed,
181
+ format: 0..100, unit: "%") do |value, property|
182
+ @mutex.synchronize { property.value = @abc.pump.maximum_speed = value }
142
183
  end
143
184
  end
144
185
 
@@ -3,6 +3,11 @@
3
3
  require "yaml"
4
4
  require "uri"
5
5
 
6
+ require "aurora/blower"
7
+ require "aurora/iz2_zone"
8
+ require "aurora/pump"
9
+ require "aurora/thermostat"
10
+
6
11
  module Aurora
7
12
  class ABCClient
8
13
  class << self
@@ -35,9 +40,10 @@ module Aurora
35
40
  attr_reader :modbus_slave,
36
41
  :serial_number,
37
42
  :zones,
43
+ :blower,
44
+ :pump,
38
45
  :faults,
39
46
  :current_mode,
40
- :fan_speed,
41
47
  :dhw_enabled,
42
48
  :dhw_setpoint,
43
49
  :entering_air_temperature,
@@ -46,27 +52,37 @@ module Aurora
46
52
  :leaving_water_temperature,
47
53
  :entering_water_temperature,
48
54
  :dhw_water_temperature,
49
- :waterflow,
50
55
  :compressor_speed,
51
56
  :outdoor_temperature,
52
57
  :fp1,
53
58
  :fp2,
54
- :blower_only_ecm_speed,
55
- :aux_heat_ecm_speed,
56
59
  :compressor_watts,
57
- :blower_watts,
58
60
  :aux_heat_watts,
59
- :loop_pump_watts,
60
61
  :total_watts
61
62
 
62
63
  def initialize(uri)
63
64
  @modbus_slave = self.class.open_modbus_slave(uri)
64
65
  @modbus_slave.read_retry_timeout = 15
65
66
  @modbus_slave.read_retries = 2
66
- registers = Aurora.transform_registers(@modbus_slave.holding_registers[88..91, 105...110, 1114])
67
+ raw_registers = @modbus_slave.holding_registers[88..91, 105...110, 404, 412..413, 1114]
68
+ registers = Aurora.transform_registers(raw_registers.dup)
67
69
  @program = registers[88]
68
70
  @serial_number = registers[105]
69
71
  @dhw_water_temperature = registers[1114]
72
+ @energy_monitor = raw_registers[412]
73
+
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
+ @pump = if (3..5).include?(raw_registers[413])
80
+ Pump::VSPump.new(self,
81
+ registers[413])
82
+ else
83
+ Pump::GenericPump.new(self,
84
+ registers[413])
85
+ end
70
86
 
71
87
  @zones = if iz2?
72
88
  iz2_zone_count = @modbus_slave.holding_registers[483]
@@ -112,9 +128,11 @@ module Aurora
112
128
  end
113
129
 
114
130
  def refresh
115
- registers_to_read = [6, 19..20, 25, 30, 340, 344, 347, 740..741, 900, 1110..1111, 1114, 1147..1153, 1165,
131
+ registers_to_read = [6, 19..20, 25, 30, 344, 740..741, 900, 1110..1111, 1114, 1147..1153, 1165,
116
132
  31_003]
117
133
  registers_to_read << (400..401) if dhw?
134
+ registers_to_read.concat(blower.registers_to_read)
135
+ registers_to_read.concat(pump.registers_to_read)
118
136
  registers_to_read.concat([362, 3001]) if vs_drive?
119
137
 
120
138
  if zones.first.is_a?(IZ2Zone)
@@ -138,7 +156,6 @@ module Aurora
138
156
 
139
157
  outputs = registers[30]
140
158
 
141
- @fan_speed = registers[344]
142
159
  @dhw_enabled = registers[400]
143
160
  @dhw_setpoint = registers[401]
144
161
  @entering_air_temperature = registers[740]
@@ -147,7 +164,6 @@ module Aurora
147
164
  @leaving_water_temperature = registers[1110]
148
165
  @entering_water_temperature = registers[1111]
149
166
  @dhw_water_temperature = registers[1114]
150
- @waterflow = registers[1117]
151
167
  @compressor_speed = if vs_drive?
152
168
  registers[3001]
153
169
  elsif outputs.include?(:cc2)
@@ -164,12 +180,8 @@ module Aurora
164
180
  @error = registers[25] & 0x7fff
165
181
  @derated = (41..46).include?(@error)
166
182
  @safe_mode = [47, 48, 49, 72, 74].include?(@error)
167
- @blower_only_ecm_speed = registers[340]
168
- @aux_heat_ecm_speed = registers[347]
169
183
  @compressor_watts = registers[1147]
170
- @blower_watts = registers[1149]
171
184
  @aux_heat_watts = registers[1151]
172
- @loop_pump_watts = registers[1165]
173
185
  @total_watts = registers[1153]
174
186
 
175
187
  @current_mode = if outputs.include?(:lockout)
@@ -190,23 +202,14 @@ module Aurora
190
202
  :standby
191
203
  end
192
204
 
205
+ blower.refresh(registers)
206
+ pump.refresh(registers)
207
+
193
208
  zones.each do |z|
194
209
  z.refresh(registers)
195
210
  end
196
211
  end
197
212
 
198
- def blower_only_ecm_speed=(value)
199
- return unless (1..12).include?(value)
200
-
201
- @modbus_slave.holding_registers[340] = value
202
- end
203
-
204
- def aux_heat_ecm_speed=(value)
205
- return unless (1..12).include?(value)
206
-
207
- @modbus_slave.holding_registers[347] = value
208
- end
209
-
210
213
  def cooling_airflow_adjustment=(value)
211
214
  value = 0x10000 + value if value.negative?
212
215
  @modbus_slave.holding_registers[346] = value
@@ -226,20 +229,6 @@ module Aurora
226
229
  @modbus_slave.holding_registers[419] = (value * 10).to_i
227
230
  end
228
231
 
229
- def vs_pump_control=(value)
230
- raise ArgumentError unless (value = VS_PUMP_CONTROL.invert[value])
231
-
232
- @modbus_slave.holding_registers[323] = value
233
- end
234
-
235
- def vs_pump_min=(value)
236
- @modbus_slave.holding_registers[321] = value
237
- end
238
-
239
- def vs_pump_max=(value)
240
- @modbus_slave.holding_registers[322] = value
241
- end
242
-
243
232
  def line_voltage=(value)
244
233
  raise ArgumentError unless (90..635).include?(value)
245
234
 
@@ -277,6 +266,10 @@ module Aurora
277
266
  @modbus_slave.holding_registers[323] = pump_speed == :with_compressor ? 0x7fff : pump_speed
278
267
  end
279
268
 
269
+ def energy_monitoring?
270
+ @energy_monitor == 2
271
+ end
272
+
280
273
  def vs_drive?
281
274
  @program == "ABCVSP"
282
275
  end
@@ -289,7 +282,8 @@ module Aurora
289
282
  { thermostat: 800, axb: 806, iz2: 812, aoc: 815, moc: 818, eev2: 824 }.each do |(component, register)|
290
283
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
291
284
  def #{component}?
292
- @modbus_slave.holding_registers[#{register}] != 3
285
+ return @#{component} if instance_variable_defined?(:@#{component})
286
+ @#{component} = @modbus_slave.holding_registers[#{register}] != 3
293
287
  end
294
288
 
295
289
  def add_#{component}
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "aurora/component"
4
+
5
+ module Aurora
6
+ module Blower
7
+ class GenericBlower < Component
8
+ attr_reader :type, :watts
9
+
10
+ def initialize(abc, type)
11
+ super(abc)
12
+ @type = type
13
+ end
14
+
15
+ def registers_to_read
16
+ if abc.energy_monitoring?
17
+ [1148..1149]
18
+ else
19
+ []
20
+ end
21
+ end
22
+
23
+ def refresh(registers)
24
+ @watts = registers[1148] if abc.energy_monitoring?
25
+ end
26
+ end
27
+
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
38
+ attr_reader :speed
39
+
40
+ def speed_range
41
+ 0..4
42
+ end
43
+
44
+ def refresh(registers)
45
+ outputs = registers[30]
46
+ @speed = if outputs.include?(:eh1)
47
+ 4
48
+ elsif outputs.include?(:cc2)
49
+ 3
50
+ elsif outputs.include?(:cc)
51
+ 2
52
+ elsif outputs.include?(:g)
53
+ 1
54
+ else
55
+ 0
56
+ end
57
+ end
58
+ end
59
+
60
+ class ECM < GenericBlower
61
+ attr_reader :speed, :blower_only_speed, :low_compressor_speed, :high_compressor_speed, :aux_heat_speed,
62
+ :iz2_desired_speed
63
+
64
+ def speed_range
65
+ 0..12
66
+ end
67
+
68
+ def registers_to_read
69
+ result = super + [340..342, 344, 347]
70
+ result << 565 if abc.iz2?
71
+ result
72
+ end
73
+
74
+ def refresh(registers)
75
+ super
76
+
77
+ @speed = registers[344]
78
+ @blower_only_speed = registers[340]
79
+ @low_compressor_speed = registers[341]
80
+ @high_compressor_speed = registers[342]
81
+ @aux_heat_speed = registers[347]
82
+ @iz2_desired_speed = registers[565] if abc.iz2?
83
+ end
84
+
85
+ { blower_only: 340,
86
+ low_compressor: 341,
87
+ high_compressor: 342,
88
+ aux_heat: 347 }.each do |(setting, register)|
89
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
90
+ def #{setting}_speed=(value)
91
+ raise ArgumentError unless (1..12).include?(value)
92
+
93
+ holding_registers[#{register}] = value
94
+ end
95
+ RUBY
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aurora
4
+ class Component
5
+ def initialize(abc)
6
+ @abc = abc
7
+ end
8
+
9
+ private
10
+
11
+ attr_reader :abc
12
+
13
+ def holding_registers
14
+ abc.modbus_slave.holding_registers
15
+ end
16
+ end
17
+ end
@@ -44,5 +44,6 @@ module Aurora
44
44
  def write_holding_register(addr, value)
45
45
  @registers[addr] = value
46
46
  end
47
+ alias []= write_holding_register
47
48
  end
48
49
  end
@@ -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
@@ -234,13 +234,6 @@ module Aurora
234
234
  0x800 => :alarm
235
235
  }.freeze
236
236
 
237
- # 5-speed ECM shows
238
- # Aux if eh1 is on
239
- # High if cc2 is on
240
- # Med if cc1 is on
241
- # Low if blower is on
242
- # Off
243
-
244
237
  SYSTEM_INPUTS = {
245
238
  0x01 => :y1,
246
239
  0x02 => :y2,
@@ -1,21 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "aurora/component"
4
+
3
5
  module Aurora
4
- class Thermostat
6
+ class Thermostat < Component
5
7
  attr_reader :target_mode,
6
8
  :target_fan_mode,
7
9
  :ambient_temperature,
8
10
  :cooling_target_temperature,
9
11
  :heating_target_temperature
10
12
 
11
- def initialize(abc)
12
- @abc = abc
13
- end
14
-
15
13
  def refresh(registers)
16
14
  @ambient_temperature = registers[502]
17
- @heating_target_temperature = registers[746]
18
- @cooling_target_temperature = registers[745]
15
+ @heating_target_temperature = registers[745]
16
+ @cooling_target_temperature = registers[746]
19
17
  end
20
18
 
21
19
  def target_mode=(value)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Aurora
4
- VERSION = "0.4.0"
4
+ VERSION = "0.4.4"
5
5
  end
data/lib/aurora.rb CHANGED
@@ -3,9 +3,7 @@
3
3
  require "rmodbus"
4
4
 
5
5
  require "aurora/abc_client"
6
- require "aurora/iz2_zone"
7
6
  require "aurora/mock_abc"
8
- require "aurora/thermostat"
9
7
  require "aurora/modbus/server"
10
8
  require "aurora/modbus/slave"
11
9
  require "aurora/registers"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: waterfurnace_aurora
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cody Cutrer
@@ -134,11 +134,14 @@ files:
134
134
  - exe/web_aid_tool
135
135
  - lib/aurora.rb
136
136
  - lib/aurora/abc_client.rb
137
+ - lib/aurora/blower.rb
138
+ - lib/aurora/component.rb
137
139
  - lib/aurora/core_ext/string.rb
138
140
  - lib/aurora/iz2_zone.rb
139
141
  - lib/aurora/mock_abc.rb
140
142
  - lib/aurora/modbus/server.rb
141
143
  - lib/aurora/modbus/slave.rb
144
+ - lib/aurora/pump.rb
142
145
  - lib/aurora/registers.rb
143
146
  - lib/aurora/thermostat.rb
144
147
  - lib/aurora/version.rb