waterfurnace_aurora 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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")