waterfurnace_aurora 0.2.0 → 0.2.1

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.
@@ -1,17 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aurora
2
4
  class IZ2Zone
3
5
  attr_reader :zone_number,
4
- :target_mode,
5
- :current_mode,
6
- :target_fan_mode,
7
- :current_fan_mode,
8
- :fan_intermittent_on,
9
- :fan_intermittent_off,
10
- :priority,
11
- :size, :normalized_size,
12
- :ambient_temperature,
13
- :cooling_target_temperature,
14
- :heating_target_temperature
6
+ :target_mode,
7
+ :current_mode,
8
+ :target_fan_mode,
9
+ :current_fan_mode,
10
+ :fan_intermittent_on,
11
+ :fan_intermittent_off,
12
+ :priority,
13
+ :size, :normalized_size,
14
+ :ambient_temperature,
15
+ :cooling_target_temperature,
16
+ :heating_target_temperature
15
17
 
16
18
  def initialize(abc, zone_number)
17
19
  @abc = abc
@@ -19,11 +21,11 @@ module Aurora
19
21
  end
20
22
 
21
23
  def refresh(registers)
22
- @ambient_temperature = registers[31007 + (zone_number - 1) * 3]
24
+ @ambient_temperature = registers[31_007 + (zone_number - 1) * 3]
23
25
 
24
- config1 = registers[31008 + (zone_number - 1) * 3]
25
- config2 = registers[31009 + (zone_number - 1) * 3]
26
- config3 = registers[31200 + (zone_number - 1) * 3]
26
+ config1 = registers[31_008 + (zone_number - 1) * 3]
27
+ config2 = registers[31_009 + (zone_number - 1) * 3]
28
+ config3 = registers[31_200 + (zone_number - 1) * 3]
27
29
 
28
30
  @target_fan_mode = config1[:fan]
29
31
  @fan_intermittent_on = config1[:on_time]
@@ -42,41 +44,46 @@ module Aurora
42
44
  def target_mode=(value)
43
45
  value = Aurora::HEATING_MODE.invert[value]
44
46
  return unless value
45
- @abc.modbus_slave.holding_registers[21202 + (zone_number - 1) * 9] = value
46
- @target_mode = Aurora::HEATING_MODE[@abc.modbus_slave.holding_registers[21202 + (zone_number - 1) * 9]]
47
+
48
+ @abc.modbus_slave.holding_registers[21_202 + (zone_number - 1) * 9] = value
49
+ @target_mode = Aurora::HEATING_MODE[@abc.modbus_slave.holding_registers[21_202 + (zone_number - 1) * 9]]
47
50
  end
48
51
 
49
52
  def target_fan_mode=(value)
50
53
  value = Aurora::FAN_MODE.invert[value]
51
54
  return unless value
52
- @abc.modbus_slave.holding_registers[21205 + (zone_number - 1) * 9] = value
53
- registers = @abc.modbus_slave.read_multiple_holding_registers(31008 + (zone_number - 1) * 3)
55
+
56
+ @abc.modbus_slave.holding_registers[21_205 + (zone_number - 1) * 9] = value
57
+ registers = @abc.modbus_slave.read_multiple_holding_registers(31_008 + (zone_number - 1) * 3)
54
58
  Aurora.transform_registers(registers)
55
59
  @target_fan_mode = registers.first.last[:fan]
56
60
  end
57
61
 
58
62
  def fan_intermittent_on=(value)
59
- return unless value >= 0 && value <= 25 && value % 5 == 0
60
- @abc.modbus_slave.holding_registers[21206 + (zone_number - 1) * 9] = value
61
- registers = @abc.modbus_slave.read_multiple_holding_registers(31008 + (zone_number - 1) * 3)
63
+ return unless value >= 0 && value <= 25 && (value % 5).zero?
64
+
65
+ @abc.modbus_slave.holding_registers[21_206 + (zone_number - 1) * 9] = value
66
+ registers = @abc.modbus_slave.read_multiple_holding_registers(31_008 + (zone_number - 1) * 3)
62
67
  Aurora.transform_registers(registers)
63
68
  @fan_intermittent_on = registers.first.last[:on_time]
64
69
  end
65
70
 
66
71
  def fan_intermittent_off=(value)
67
- return unless value >= 0 && value <= 40 && value % 5 == 0
68
- @abc.modbus_slave.holding_registers[21207 + (zone_number - 1) * 9] = value
69
- registers = @abc.modbus_slave.read_multiple_holding_registers(31008 + (zone_number - 1) * 3)
72
+ return unless value >= 0 && value <= 40 && (value % 5).zero?
73
+
74
+ @abc.modbus_slave.holding_registers[21_207 + (zone_number - 1) * 9] = value
75
+ registers = @abc.modbus_slave.read_multiple_holding_registers(31_008 + (zone_number - 1) * 3)
70
76
  Aurora.transform_registers(registers)
71
77
  @fan_intermittent_on = registers.first.last[:off_time]
72
78
  end
73
79
 
74
80
  def heating_target_temperature=(value)
75
81
  return unless value >= 40 && value <= 90
82
+
76
83
  value = (value * 10).to_i
77
- @abc.modbus_slave.holding_registers[21203 + (zone_number - 1) * 9] = value
84
+ @abc.modbus_slave.holding_registers[21_203 + (zone_number - 1) * 9] = value
78
85
 
79
- base = 31008 + (zone_number - 1) * 3
86
+ base = 31_008 + (zone_number - 1) * 3
80
87
  registers = @abc.modbus_slave.read_multiple_holding_registers(base..(base + 1))
81
88
  Aurora.transform_registers(registers)
82
89
  registers[base + 1][:heating_target_temperature]
@@ -84,16 +91,19 @@ module Aurora
84
91
 
85
92
  def cooling_target_temperature=(value)
86
93
  return unless value >= 54 && value <= 99
94
+
87
95
  value = (value * 10).to_i
88
- @abc.modbus_slave.holding_registers[21204 + (zone_number - 1) * 9] = value
96
+ @abc.modbus_slave.holding_registers[21_204 + (zone_number - 1) * 9] = value
89
97
 
90
- registers = @abc.modbus_slave.read_multiple_holding_registers(31008 + (zone_number - 1) * 3)
98
+ registers = @abc.modbus_slave.read_multiple_holding_registers(31_008 + (zone_number - 1) * 3)
91
99
  Aurora.transform_registers(registers)
92
100
  registers.first.last[:cooling_target_temperature]
93
101
  end
94
102
 
95
103
  def inspect
96
- "#<Aurora::IZ2Zone #{(instance_variables - [:@abc]).map { |iv| "#{iv}=#{instance_variable_get(iv).inspect}" }.join(', ')}>"
104
+ "#<Aurora::IZ2Zone #{(instance_variables - [:@abc]).map do |iv|
105
+ "#{iv}=#{instance_variable_get(iv).inspect}"
106
+ end.join(', ')}>"
97
107
  end
98
108
  end
99
109
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aurora
2
4
  module ModBus
3
5
  module Server
@@ -5,26 +7,30 @@ module Aurora
5
7
  case func
6
8
  when 65
7
9
  # 1 function register, a multiple of two words
8
- return unless (req.length - 1) % 4 == 0
10
+ return unless ((req.length - 1) % 4).zero?
11
+
9
12
  params = []
10
- req[1..-1].unpack("n*").each_slice(2) do |(addr, quant)|
13
+ req[1..].unpack("n*").each_slice(2) do |(addr, quant)|
11
14
  params << { addr: addr, quant: quant }
12
15
  end
13
16
  params
14
17
  when 66
15
- return unless (req.length - 1) % 2 == 0
16
- req[1..-1].unpack("n*")
18
+ return unless ((req.length - 1) % 2).zero?
19
+
20
+ req[1..].unpack("n*")
17
21
  when 67
18
22
  # 1 function register, a multiple of two words
19
- return unless (req.length - 1) % 4 == 0
23
+ return unless ((req.length - 1) % 4).zero?
24
+
20
25
  params = []
21
- req[1..-1].unpack("n*").each_slice(2) do |(addr, val)|
26
+ req[1..].unpack("n*").each_slice(2) do |(addr, val)|
22
27
  params << { addr: addr, val: val }
23
28
  end
24
29
  params
25
30
  when 68
26
31
  return unless req.length == 5
27
- { noidea1: req[1,2].unpack("n"), noidea2: req[3,2].unpack("n") }
32
+
33
+ { noidea1: req[1, 2].unpack("n"), noidea2: req[3, 2].unpack("n") }
28
34
  else
29
35
  super
30
36
  end
@@ -33,7 +39,8 @@ module Aurora
33
39
  def parse_response(func, res)
34
40
  return {} if func == 67 && res.length == 1
35
41
  return { noidea: res[-1].ord } if func == 68 && res.length == 2
36
- func = 3 if func == 65 || func == 66
42
+
43
+ func = 3 if [65, 66].include?(func)
37
44
  super
38
45
  end
39
46
 
@@ -46,17 +53,17 @@ module Aurora
46
53
  return (func | 0x80).chr + err.chr
47
54
  end
48
55
 
49
- pdu += slave.holding_registers[param[:addr],param[:quant]].pack('n*')
56
+ pdu += slave.holding_registers[param[:addr], param[:quant]].pack("n*")
50
57
  end
51
- pdu = func.chr + pdu.length.chr + pdu
52
- pdu
58
+ func.chr + pdu.length.chr + pdu
59
+
53
60
  when 66
54
- pdu = params.map { |addr| slave.holding_registers[addr] }.pack('n*')
55
- pdu = func.chr + pdu.length.chr + pdu
56
- pdu
61
+ pdu = params.map { |addr| slave.holding_registers[addr] }.pack("n*")
62
+ func.chr + pdu.length.chr + pdu
63
+
57
64
  when 67
58
65
  slave.holding_registers[param[:addr]] = param[:val]
59
- pdu = req[0,2]
66
+ pdu = req[0, 2]
60
67
  else
61
68
  super
62
69
  end
@@ -1,13 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aurora
2
4
  module ModBus
3
5
  module Slave
4
6
  def read_multiple_holding_registers(*ranges)
5
7
  values = if ranges.any? { |r| r.is_a?(Range) }
6
- addrs_and_lengths = ranges.map { |r| r = Array(r); [r.first, r.last - r.first + 1] }.flatten
7
- query("\x41" + addrs_and_lengths.pack("n*")).unpack("n*")
8
- else
9
- query("\x42" + ranges.pack("n*")).unpack("n*")
10
- end
8
+ addrs_and_lengths = ranges.map do |r|
9
+ r = Array(r)
10
+ [r.first, r.last - r.first + 1]
11
+ end.flatten
12
+ query("A#{addrs_and_lengths.pack('n*')}").unpack("n*")
13
+ else
14
+ query("B#{ranges.pack('n*')}").unpack("n*")
15
+ end
11
16
  ranges.map { |r| Array(r) }.flatten.zip(values).to_h
12
17
  end
13
18
 
@@ -19,6 +24,7 @@ module Aurora
19
24
  class WFProxy < ::ModBus::ReadWriteProxy
20
25
  def [](*keys)
21
26
  return super if keys.length == 1
27
+
22
28
  @slave.read_multiple_holding_registers(*keys)
23
29
  end
24
30
  end
@@ -28,24 +34,25 @@ module Aurora
28
34
  # Read the slave_id and function code
29
35
  msg = read(io, 2)
30
36
  log logging_bytes(msg)
31
-
37
+
32
38
  function_code = msg.getbyte(1)
33
39
  case function_code
34
- when 1,2,3,4,65,66 then
35
- # read the third byte to find out how much more
36
- # we need to read + CRC
37
- msg += read(io, 1)
38
- msg += read(io, msg.getbyte(2)+2)
39
- when 5,6,15,16 then
40
- # We just read in an additional 6 bytes
41
- msg += read(io, 6)
42
- when 22 then
43
- msg += read(io, 8)
44
- when 0x80..0xff then
45
- msg += read(io, 3)
46
- else
47
- raise ModBus::Errors::IllegalFunction, "Illegal function: #{function_code}"
40
+ when 1, 2, 3, 4, 65, 66
41
+ # read the third byte to find out how much more
42
+ # we need to read + CRC
43
+ msg += read(io, 1)
44
+ msg += read(io, msg.getbyte(2) + 2)
45
+ when 5, 6, 15, 16
46
+ # We just read in an additional 6 bytes
47
+ msg += read(io, 6)
48
+ when 22
49
+ msg += read(io, 8)
50
+ when 0x80..0xff
51
+ msg += read(io, 3)
52
+ else
53
+ raise ModBus::Errors::IllegalFunction, "Illegal function: #{function_code}"
48
54
  end
55
+ msg
49
56
  end
50
57
  end
51
58
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aurora
2
- extend self
4
+ module_function
3
5
 
4
6
  def normalize_ranges(ranges)
5
7
  registers = ranges.map { |r| Array(r) }.flatten.sort.uniq
@@ -9,26 +11,26 @@ module Aurora
9
11
  count = 0
10
12
  registers.each_with_index do |r, i|
11
13
  run_start ||= r
12
- if i + 1 == registers.length || r + 1 != registers[i + 1]
13
- if r == run_start
14
- result << r
15
- if (count += 1) == 100
16
- totals << result
17
- result = []
18
- count = 0
19
- end
20
- else
21
- range = run_start..r
22
- if count + range.count > 100
23
- totals << result
24
- result = []
25
- count = 0
26
- end
27
- count += range.count
28
- result << range
14
+ next unless i + 1 == registers.length || r + 1 != registers[i + 1]
15
+
16
+ if r == run_start
17
+ result << r
18
+ if (count += 1) == 100
19
+ totals << result
20
+ result = []
21
+ count = 0
22
+ end
23
+ else
24
+ range = run_start..r
25
+ if count + range.count > 100
26
+ totals << result
27
+ result = []
28
+ count = 0
29
29
  end
30
- run_start = nil
30
+ count += range.count
31
+ result << range
31
32
  end
33
+ run_start = nil
32
34
  end
33
35
  totals << result unless result.empty?
34
36
  totals
@@ -39,13 +41,13 @@ module Aurora
39
41
  TO_LAST_LOCKOUT = ->(v) { v & 0x8000 == 0x8000 ? v & 0x7fff : nil }
40
42
  NEGATABLE = ->(v) { v & 0x8000 == 0x8000 ? v - 0x10000 : v }
41
43
 
42
- def from_bitmask(v, flags)
44
+ def from_bitmask(value, flags)
43
45
  result = []
44
46
  flags.each do |(bit, flag)|
45
- result << flag if v & bit == bit
46
- v &= ~bit
47
+ result << flag if value & bit == bit
48
+ value &= ~bit
47
49
  end
48
- result << "0x%04x" % v if v != 0
50
+ result << format("0x%04x", value) unless value.zero?
49
51
  result
50
52
  end
51
53
 
@@ -53,7 +55,7 @@ module Aurora
53
55
  puts "converting #{idx} of length #{length}"
54
56
  (idx...(idx + length)).map do |i|
55
57
  (registers[i] >> 8).chr + (registers[i] & 0xff).chr
56
- end.join.sub(/[ \0]+$/, '')
58
+ end.join.sub(/[ \0]+$/, "")
57
59
  end
58
60
 
59
61
  FAULTS = {
@@ -106,26 +108,27 @@ module Aurora
106
108
  75 => "Charge Loss",
107
109
  76 => "Suction Temperatur Sensor Limit",
108
110
  77 => "Leaving Air Temperature Sensor Limit",
109
- 78 => "Maximum Operating Pressure Limit",
110
- }
111
+ 78 => "Maximum Operating Pressure Limit"
112
+ }.freeze
111
113
 
112
114
  AR_SETTINGS = {
113
115
  0 => "Cycle with Compressor",
114
116
  1 => "Cycle with Thermostat Humidification Call",
115
117
  2 => "Slow Opening Water Valve",
116
118
  3 => "Cycle with Blower"
117
- }
119
+ }.freeze
120
+
121
+ def dipswitch_settings(value)
122
+ return :manual if value == 0x7fff
118
123
 
119
- def dipswitch_settings(v)
120
- return :manual if v == 0x7fff
121
124
  {
122
- fp1: v & 0x01 == 0x01 ? "30ºF" : "15ºF",
123
- fp2: v & 0x02 == 0x02 ? "30ºF" : "15ºF",
124
- rv: v & 0x04 == 0x04 ? "O" : "B",
125
- ar: AR_SETTINGS[(v >> 3) & 0x7],
126
- cc: v & 0x20 == 0x20 ? "Single Stage" : "Dual Stage",
127
- lo: v & 0x40 == 0x40 ? "Continouous" : "Pulse",
128
- dh_rh: v & 0x80 == 0x80 ? "Dehumdifier On" : "Reheat On",
125
+ fp1: value & 0x01 == 0x01 ? "30ºF" : "15ºF",
126
+ fp2: value & 0x02 == 0x02 ? "30ºF" : "15ºF",
127
+ rv: value & 0x04 == 0x04 ? "O" : "B",
128
+ ar: AR_SETTINGS[(value >> 3) & 0x7],
129
+ cc: value & 0x20 == 0x20 ? "Single Stage" : "Dual Stage",
130
+ lo: value & 0x40 == 0x40 ? "Continouous" : "Pulse",
131
+ dh_rh: value & 0x80 == 0x80 ? "Dehumdifier On" : "Reheat On"
129
132
  }
130
133
  end
131
134
 
@@ -138,8 +141,8 @@ module Aurora
138
141
  0x20 => :eh2,
139
142
  0x200 => :accessory,
140
143
  0x400 => :lockout,
141
- 0x800 => :alarm,
142
- }
144
+ 0x800 => :alarm
145
+ }.freeze
143
146
 
144
147
  SYSTEM_INPUTS = {
145
148
  0x01 => "Y1",
@@ -149,18 +152,18 @@ module Aurora
149
152
  0x10 => "G",
150
153
  0x20 => "Dehumidifer",
151
154
  0x40 => "Emergency Shutdown",
152
- 0x200 => "Load Shed",
153
- }
155
+ 0x200 => "Load Shed"
156
+ }.freeze
154
157
 
155
- def status(v)
158
+ def status(value)
156
159
  result = {
157
- lps: v & 0x80 == 0x80 ? :closed : :open,
158
- hps: v & 0x100 == 0x100 ? :closed : :open,
160
+ lps: value & 0x80 == 0x80 ? :closed : :open,
161
+ hps: value & 0x100 == 0x100 ? :closed : :open
159
162
  }
160
- result[:load_shed] = true if v & 0x0200 == 0x0200
161
- result[:emergency_shutdown] = true if v & 0x0040 == 0x0040
162
- leftover = v & ~0x03c0
163
- result[:unknown] = "0x%04x" % leftover unless leftover == 0
163
+ result[:load_shed] = true if value & 0x0200 == 0x0200
164
+ result[:emergency_shutdown] = true if value & 0x0040 == 0x0040
165
+ leftover = value & ~0x03c0
166
+ result[:unknown] = format("0x%04x", leftover) unless leftover.zero?
164
167
  result
165
168
  end
166
169
 
@@ -169,18 +172,18 @@ module Aurora
169
172
  0x04 => "Low Suction Pressure",
170
173
  0x10 => "Low Discharge Pressure",
171
174
  0x20 => "High Discharge Pressure",
172
- 0x40 => "Output Power Limit",
173
- }
175
+ 0x40 => "Output Power Limit"
176
+ }.freeze
174
177
 
175
178
  VS_SAFE_MODE = {
176
179
  0x01 => "EEV Indoor Failed",
177
180
  0x02 => "EEV Outdoor Failed",
178
- 0x04 => "Invalid Ambient Temp",
179
- }
181
+ 0x04 => "Invalid Ambient Temp"
182
+ }.freeze
180
183
 
181
184
  VS_ALARM1 = {
182
- 0x8000 => "Internal Error",
183
- }
185
+ 0x8000 => "Internal Error"
186
+ }.freeze
184
187
 
185
188
  VS_ALARM2 = {
186
189
  0x0001 => "Multi Safe Modes",
@@ -196,24 +199,24 @@ module Aurora
196
199
  0x0400 => "DC Under Voltage",
197
200
  0x0800 => "Invalid Suction Pressure",
198
201
  0x1000 => "Invalid Discharge Pressure",
199
- 0x2000 => "Low Discharge Pressure",
200
- }
202
+ 0x2000 => "Low Discharge Pressure"
203
+ }.freeze
201
204
 
202
205
  VS_EEV2 = {
203
206
  0x0010 => "Invalid Suction Temperature",
204
207
  0x0020 => "Invalid Leaving Air Temperature",
205
- 0x0040 => "Invalid Suction Pressure",
206
-
207
- }
208
+ 0x0040 => "Invalid Suction Pressure"
209
+
210
+ }.freeze
208
211
 
209
212
  AXB_INPUTS = {
210
- }
213
+ }.freeze
211
214
 
212
215
  AXB_OUTPUTS = {
213
216
  0x10 => "Accessory 2",
214
217
  0x02 => "Loop Pump",
215
218
  0x01 => "DHW"
216
- }
219
+ }.freeze
217
220
 
218
221
  HEATING_MODE = {
219
222
  0 => :off,
@@ -221,30 +224,30 @@ module Aurora
221
224
  2 => :cool,
222
225
  3 => :heat,
223
226
  4 => :eheat
224
- }
227
+ }.freeze
225
228
 
226
229
  FAN_MODE = {
227
230
  0 => :auto,
228
231
  1 => :continuous,
229
232
  2 => :intermittent
230
- }
233
+ }.freeze
231
234
 
232
235
  HUMIDIFIER_SETTINGS = {
233
236
  0x4000 => :auto_dehumidification,
234
- 0x8000 => :auto_humidification,
235
- }
237
+ 0x8000 => :auto_humidification
238
+ }.freeze
236
239
 
237
240
  INVERSE_HUMIDIFIER_SETTINGS = {
238
241
  0x4000 => :manual_dehumidification,
239
- 0x8000 => :manual_humidification,
240
- }
242
+ 0x8000 => :manual_humidification
243
+ }.freeze
241
244
 
242
245
  ZONE_SIZES = {
243
246
  0 => 0,
244
247
  1 => 25,
245
248
  2 => 45,
246
- 3 => 70,
247
- }
249
+ 3 => 70
250
+ }.freeze
248
251
 
249
252
  CALLS = {
250
253
  0x0 => :standby,
@@ -254,39 +257,39 @@ module Aurora
254
257
  0x4 => :h3,
255
258
  0x5 => :c1,
256
259
  0x6 => :c2,
257
- 0x7 => :unknown7,
258
- }
260
+ 0x7 => :unknown7
261
+ }.freeze
259
262
 
260
- def iz2_demand(v)
263
+ def iz2_demand(value)
261
264
  {
262
- fan_demand: v >> 8,
263
- unit_demand: v & 0xff,
265
+ fan_demand: value >> 8,
266
+ unit_demand: value & 0xff
264
267
  }
265
268
  end
266
269
 
267
- def zone_configuration1(v)
268
- fan = if v & 0x80 == 0x80
269
- :continuous
270
- elsif v & 0x100 == 0x100
271
- :intermittent
272
- else
273
- :auto
274
- end
270
+ def zone_configuration1(value)
271
+ fan = if value & 0x80 == 0x80
272
+ :continuous
273
+ elsif value & 0x100 == 0x100
274
+ :intermittent
275
+ else
276
+ :auto
277
+ end
275
278
  result = {
276
279
  fan: fan,
277
- on_time: ((v >> 9) & 0x7) * 5,
278
- off_time: (((v >> 12) & 0x7) + 1) * 5,
279
- cooling_target_temperature: ((v & 0x7e) >> 1) + 36,
280
- heating_target_temperature_carry: v & 01
280
+ on_time: ((value >> 9) & 0x7) * 5,
281
+ off_time: (((value >> 12) & 0x7) + 1) * 5,
282
+ cooling_target_temperature: ((value & 0x7e) >> 1) + 36,
283
+ heating_target_temperature_carry: value & 0o1
281
284
  }
282
- leftover = v & ~0x7fff
283
- result[:unknown] = "0x%04x" % leftover unless leftover == 0
285
+ leftover = value & ~0x7fff
286
+ result[:unknown] = format("0x%04x", leftover) unless leftover.zero?
284
287
  result
285
288
  end
286
289
 
287
- def zone_configuration2(registers, k)
288
- prior_v = registers[k - 1] if registers.key?(k - 1)
289
- v = registers[k]
290
+ def zone_configuration2(registers, key)
291
+ prior_v = registers[key - 1] if registers.key?(key - 1)
292
+ v = registers[key]
290
293
  result = {
291
294
  call: CALLS[(v >> 1) & 0x7],
292
295
  mode: HEATING_MODE[(v >> 8) & 0x03],
@@ -297,20 +300,20 @@ module Aurora
297
300
  result[:heating_target_temperature] = ((carry << 5) | ((v & 0xf800) >> 11)) + 36
298
301
  end
299
302
  leftover = v & ~0xfb1e
300
- result[:unknown] = "0x%04x" % leftover unless leftover == 0
303
+ result[:unknown] = format("0x%04x", leftover) unless leftover.zero?
301
304
  result
302
305
  end
303
306
 
304
307
  # hi order byte is normalized zone size
305
- def zone_configuration3(v)
306
- size = (v >> 3 ) & 0x3
308
+ def zone_configuration3(value)
309
+ size = (value >> 3) & 0x3
307
310
  result = {
308
- zone_priority: (v & 0x20) == 0x20 ? :economy : :comfort,
311
+ zone_priority: (value & 0x20) == 0x20 ? :economy : :comfort,
309
312
  zone_size: ZONE_SIZES[size],
310
- normalized_size: v >> 8,
313
+ normalized_size: value >> 8
311
314
  }
312
- leftover = v & ~0xff38
313
- result[:unknown] = "0x%04x" % leftover unless leftover == 0
315
+ leftover = value & ~0xff38
316
+ result[:unknown] = format("0x%04x", leftover) unless leftover.zero?
314
317
  result
315
318
  end
316
319
 
@@ -321,14 +324,14 @@ module Aurora
321
324
  TO_HUNDREDTHS => [2, 3, 807, 813, 816, 817, 819, 820, 825, 828],
322
325
  method(:dipswitch_settings) => [4, 33],
323
326
  TO_TENTHS => [19, 20, 401, 567, 740, 745, 746, 900, 1105, 1106, 1107, 1108, 1110, 1111, 1114, 1117, 1134, 1136,
324
- 21203, 21204,
325
- 21212, 21213,
326
- 21221, 21222,
327
- 21230, 22131,
328
- 21239, 21240,
329
- 21248, 21249,
330
- 31003,
331
- 31007, 31010, 31013, 31016, 31019, 31022],
327
+ 21_203, 21_204,
328
+ 21_212, 21_213,
329
+ 21_221, 21_222,
330
+ 21_230, 22_131,
331
+ 21_239, 21_240,
332
+ 21_248, 21_249,
333
+ 31_003,
334
+ 31_007, 31_010, 31_013, 31_016, 31_019, 31_022],
332
335
  TO_LAST_LOCKOUT => [26],
333
336
  ->(v) { from_bitmask(v, SYSTEM_OUTPUTS) } => [27, 30],
334
337
  ->(v) { from_bitmask(v, SYSTEM_INPUTS) } => [28],
@@ -345,41 +348,41 @@ module Aurora
345
348
  ->(v) { from_bitmask(v, AXB_INPUTS) } => [1103],
346
349
  ->(v) { from_bitmask(v, AXB_OUTPUTS) } => [1104],
347
350
  ->(v) { TO_TENTHS.call(NEGATABLE.call(v)) } => [1136],
348
- ->(v) { HEATING_MODE[v] } => [21202, 21211, 21220, 21229, 21238, 21247],
349
- ->(v) { FAN_MODE[v] } => [21205, 21214, 21223, 21232, 21241, 21250],
350
- ->(v) { from_bitmask(v, HUMIDIFIER_SETTINGS) } => [31109],
351
- ->(v) { { humidification_target: v >> 8, dehumidification_target: v & 0xff } } => [31110],
352
- method(:iz2_demand) => [31005],
353
- method(:zone_configuration1) => [31008, 31011, 31014, 31017, 31020, 31023],
354
- method(:zone_configuration2) => [31009, 31012, 31015, 31018, 31021, 31024],
355
- method(:zone_configuration3) => [31200, 31203, 31206, 31209, 31212, 31215],
356
- ->(registers, idx) { to_string(registers, idx, 13) } => [31400],
357
- ->(registers, idx) { to_string(registers, idx, 8) } => [31413],
358
- ->(registers, idx) { to_string(registers, idx, 13) } => [31421],
359
- ->(registers, idx) { to_string(registers, idx, 13) } => [31434],
360
- ->(registers, idx) { to_string(registers, idx, 13) } => [31447],
361
- ->(registers, idx) { to_string(registers, idx, 13) } => [31460],
362
- }
351
+ ->(v) { HEATING_MODE[v] } => [21_202, 21_211, 21_220, 21_229, 21_238, 21_247],
352
+ ->(v) { FAN_MODE[v] } => [21_205, 21_214, 21_223, 21_232, 21_241, 21_250],
353
+ ->(v) { from_bitmask(v, HUMIDIFIER_SETTINGS) } => [31_109],
354
+ ->(v) { { humidification_target: v >> 8, dehumidification_target: v & 0xff } } => [31_110],
355
+ method(:iz2_demand) => [31_005],
356
+ method(:zone_configuration1) => [31_008, 31_011, 31_014, 31_017, 31_020, 31_023],
357
+ method(:zone_configuration2) => [31_009, 31_012, 31_015, 31_018, 31_021, 31_024],
358
+ method(:zone_configuration3) => [31_200, 31_203, 31_206, 31_209, 31_212, 31_215],
359
+ ->(registers, idx) { to_string(registers, idx, 13) } => [31_400],
360
+ ->(registers, idx) { to_string(registers, idx, 8) } => [31_413],
361
+ ->(registers, idx) { to_string(registers, idx, 13) } => [31_421],
362
+ ->(registers, idx) { to_string(registers, idx, 13) } => [31_434],
363
+ ->(registers, idx) { to_string(registers, idx, 13) } => [31_447],
364
+ ->(registers, idx) { to_string(registers, idx, 13) } => [31_460]
365
+ }.freeze
363
366
 
364
367
  REGISTER_FORMATS = {
365
368
  "%ds" => [1, 6, 9, 15, 84, 85],
366
369
  "%dV" => [16, 112],
367
370
  "%0.1fºF" => [19, 20, 401, 567, 740, 745, 746, 900, 1110, 1111, 1114, 1134, 1136,
368
- 21203, 21204,
369
- 21212, 21213,
370
- 21221, 21222,
371
- 21230, 21231,
372
- 21239, 21240,
373
- 21248, 21249,
374
- 31003,
375
- 31007, 31010, 31013, 31016, 31019, 31022],
371
+ 21_203, 21_204,
372
+ 21_212, 21_213,
373
+ 21_221, 21_222,
374
+ 21_230, 21_231,
375
+ 21_239, 21_240,
376
+ 21_248, 21_249,
377
+ 31_003,
378
+ 31_007, 31_010, 31_013, 31_016, 31_019, 31_022],
376
379
  "E%d" => [25, 26],
377
380
  "%d%%" => [282, 321, 322, 346, 565, 741],
378
381
  "%0.1fA" => [1105, 1106, 1107, 1108],
379
382
  "%0.1fgpm" => [1117],
380
383
  "%dW" => [1147, 1149, 1151, 1153, 1165],
381
- "%dBtuh" => [1157],
382
- }
384
+ "%dBtuh" => [1157]
385
+ }.freeze
383
386
 
384
387
  def ignore(range)
385
388
  range.zip(Array.new(range.count)).to_h
@@ -391,9 +394,9 @@ module Aurora
391
394
 
392
395
  def zone_registers
393
396
  (1..6).map do |i|
394
- base1 = 21202 + (i - 1) * 9
395
- base2 = 31007 + (i - 1) * 3
396
- base3 = 31200 + (i - 1) * 3
397
+ base1 = 21_202 + (i - 1) * 9
398
+ base2 = 31_007 + (i - 1) * 3
399
+ base3 = 31_200 + (i - 1) * 3
397
400
  {
398
401
  base1 => "Zone #{i} Heating Mode",
399
402
  (base1 + 1) => "Zone #{i} Heating Setpoint (write)",
@@ -404,12 +407,12 @@ module Aurora
404
407
  base2 => "Zone #{i} Ambient Temperature",
405
408
  (base2 + 1) => "Zone #{i} Configuration 1",
406
409
  (base2 + 2) => "Zone #{i} Configuration 2",
407
- base3 => "Zone #{i} Configuration 3",
410
+ base3 => "Zone #{i} Configuration 3"
408
411
  }
409
412
  end.inject({}, &:merge)
410
413
  end
411
414
 
412
- WRITEABLE = [112, 340, 341, 342, 346, 347]
415
+ WRITEABLE = [112, 340, 341, 342, 346, 347].freeze
413
416
 
414
417
  # these are the valid ranges (i.e. the ABC will return _some_ value)
415
418
  # * means 6 sequential ranges of equal size (i.e. must be repeated for each
@@ -453,42 +456,42 @@ module Aurora
453
456
  3800..3809,
454
457
  3818..3834,
455
458
  3900..3914,
456
- 12000..12019,
457
- 12098..12099,
458
- 12100..12119,
459
- 12200..12239,
460
- 12300..12319,
461
- 12400..12569,
462
- 12600..12639,
463
- 12700..12799,
464
- 20000..20099,
465
- 21100..21136,
466
- 21200..21265,
467
- 21400..21472,
468
- 21500..21589,
469
- 22100..22162, # *
470
- 22200..22262, # *
471
- 22300..22362, # *
472
- 22400..22462, # *
473
- 22500..22562, # *
474
- 22600..22662, # *
475
- 30000..30099,
476
- 31000..31034,
477
- 31100..31129,
478
- 31200..31229,
479
- 31300..31329,
480
- 31400..31472,
481
- 32100..32162, # *
482
- 32200..32262, # *
483
- 32300..32362, # *
484
- 32400..32462, # *
485
- 32500..32562, # *
486
- 32600..32662, # *
487
- 60050..60053,
488
- 60100..60109,
489
- 60200..60200,
490
- 61000..61009
491
- ]
459
+ 12_000..12_019,
460
+ 12_098..12_099,
461
+ 12_100..12_119,
462
+ 12_200..12_239,
463
+ 12_300..12_319,
464
+ 12_400..12_569,
465
+ 12_600..12_639,
466
+ 12_700..12_799,
467
+ 20_000..20_099,
468
+ 21_100..21_136,
469
+ 21_200..21_265,
470
+ 21_400..21_472,
471
+ 21_500..21_589,
472
+ 22_100..22_162, # *
473
+ 22_200..22_262, # *
474
+ 22_300..22_362, # *
475
+ 22_400..22_462, # *
476
+ 22_500..22_562, # *
477
+ 22_600..22_662, # *
478
+ 30_000..30_099,
479
+ 31_000..31_034,
480
+ 31_100..31_129,
481
+ 31_200..31_229,
482
+ 31_300..31_329,
483
+ 31_400..31_472,
484
+ 32_100..32_162, # *
485
+ 32_200..32_262, # *
486
+ 32_300..32_362, # *
487
+ 32_400..32_462, # *
488
+ 32_500..32_562, # *
489
+ 32_600..32_662, # *
490
+ 60_050..60_053,
491
+ 60_100..60_109,
492
+ 60_200..60_200,
493
+ 61_000..61_009
494
+ ].freeze
492
495
 
493
496
  def read_all_registers(modbus_slave)
494
497
  result = []
@@ -501,10 +504,10 @@ module Aurora
501
504
  REGISTER_RANGES.map(&:to_a).flatten.zip(result).to_h
502
505
  end
503
506
 
504
- def diff_registers(r1, r2)
507
+ def diff_registers(lhs, rhs)
505
508
  diff = {}
506
- r1.each_key do |k|
507
- diff[k] = [r1[k], r2[k]] if r1[k] != r2[k]
509
+ lhs.each_key do |k|
510
+ diff[k] = [lhs[k], rhs[k]] if lhs[k] != rhs[k]
508
511
  end
509
512
  diff
510
513
  end
@@ -539,7 +542,7 @@ module Aurora
539
542
  92 => "Model Number",
540
543
  105 => "Serial Number",
541
544
  112 => "Setup Line Voltage",
542
- 201 => "Discharge Pressure", # I can't figure out how this number is represented;
545
+ 201 => "Discharge Pressure", # I can't figure out how this number is represented;
543
546
  203 => "Suction Pressure",
544
547
  205 => "Discharge Temperature",
545
548
  207 => "Loop Entering Water Temperature",
@@ -565,7 +568,7 @@ module Aurora
565
568
  344 => "ECM Speed",
566
569
  346 => "Cooling Airflow Adjustment",
567
570
  347 => "Aux Heat ECM Speed",
568
- 362 => "Active Dehumidify", # any value is true
571
+ 362 => "Active Dehumidify", # any value is true
569
572
  401 => "DHW Setpoint",
570
573
  414 => "On Peak/SmartGrid 2", # 0x0001 only
571
574
  483 => "Number of IZ2 Zones",
@@ -605,27 +608,27 @@ module Aurora
605
608
  1157 => "Ht of Rej",
606
609
  1165 => "VS Pump Watts",
607
610
  3027 => "Compressor Speed",
608
- 31003 => "Outdoor Temp",
609
- 31005 => "IZ2 Demand",
610
- 31109 => "Humidifier Mode", # write to 21114
611
- 31110 => "Manual De/Humidification Target", # write to 21115
612
- 31400 => "Dealer Name",
613
- 31413 => "Dealer Phone",
614
- 31421 => "Dealer Address 1",
615
- 31434 => "Dealer Address 2",
616
- 31447 => "Dealer Email",
617
- 31460 => "Dealer Website",
618
- }.merge(ignore(89..91)).
619
- merge(ignore(93..104)).
620
- merge(ignore(106..109)).
621
- merge(faults(601..699)).
622
- merge(zone_registers).
623
- merge(ignore(31401..31412)).
624
- merge(ignore(31414..31420)).
625
- merge(ignore(31422..31433)).
626
- merge(ignore(31435..31446)).
627
- merge(ignore(31447..31459)).
628
- merge(ignore(31461..31472))
611
+ 31_003 => "Outdoor Temp",
612
+ 31_005 => "IZ2 Demand",
613
+ 31_109 => "Humidifier Mode", # write to 21114
614
+ 31_110 => "Manual De/Humidification Target", # write to 21115
615
+ 31_400 => "Dealer Name",
616
+ 31_413 => "Dealer Phone",
617
+ 31_421 => "Dealer Address 1",
618
+ 31_434 => "Dealer Address 2",
619
+ 31_447 => "Dealer Email",
620
+ 31_460 => "Dealer Website"
621
+ }.merge(ignore(89..91))
622
+ .merge(ignore(93..104))
623
+ .merge(ignore(106..109))
624
+ .merge(faults(601..699))
625
+ .merge(zone_registers)
626
+ .merge(ignore(31_401..31_412))
627
+ .merge(ignore(31_414..31_420))
628
+ .merge(ignore(31_422..31_433))
629
+ .merge(ignore(31_435..31_446))
630
+ .merge(ignore(31_447..31_459))
631
+ .merge(ignore(31_461..31_472))
629
632
 
630
633
  def transform_registers(registers)
631
634
  registers.each do |(k, v)|
@@ -640,19 +643,20 @@ module Aurora
640
643
 
641
644
  def print_registers(registers)
642
645
  result = []
643
- registers.each do |(k, v)|
646
+ registers.each do |(k, value)|
644
647
  # ignored
645
648
  next if REGISTER_NAMES.key?(k) && REGISTER_NAMES[k].nil?
649
+
646
650
  name = REGISTER_NAMES[k]
647
651
  value_proc = REGISTER_CONVERTERS.find { |(_, z)| z.include?(k) }&.first || ->(v) { v }
648
652
  format = REGISTER_FORMATS.find { |(_, z)| z.include?(k) }&.first || "%s"
649
653
  format = "%1$d (0x%1$04x)" unless name
650
654
  name ||= "???"
651
-
652
- value = value_proc.arity == 2 ? value_proc.call(registers, k) : value_proc.call(v)
655
+
656
+ value = value_proc.arity == 2 ? value_proc.call(registers, k) : value_proc.call(value)
653
657
  value = value.join(", ") if value.is_a?(Array)
654
- value = sprintf(format, value) if value
655
-
658
+ value = format(format, value) if value
659
+
656
660
  result << "#{name} (#{k}): #{value}"
657
661
  end
658
662
  result.join("\n")