waterfurnace_aurora 0.6.4 → 0.7.3

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: aa7915f9b848e8cea608787f628b077e7fc2d5904044581758099db9a3b26742
4
- data.tar.gz: ecf97a652368c8ed73d6bffdea6d1961e1cbb85c0587e50ba5211735368fb7b3
3
+ metadata.gz: 022f7ed4808f1276a58c999584d2b4bd38dc756e85e018e41cb5e9c5a5535bcf
4
+ data.tar.gz: c428e4f7ef1c9bb3fb1a64d65be9ca76043305d250eaf434e453c0729bf3189e
5
5
  SHA512:
6
- metadata.gz: a8b861192fcb395fbec9643840b9b91aaa3d42193d55efda03812d10114a3f4e076afc2eb79a6294bc89a0e340bd5c14f3f2e2fca25e6d1eefa32c9bff359a20
7
- data.tar.gz: a35c95acd756183eb2bd2af220e65a182a2206b054453fb49c0e550d512831328d74f72df8e46aec118824efd581fd26e04374b67dbc7898b07f9a964d1123d8
6
+ metadata.gz: 6732c28063980999e4b5feffd59eaee3829ca5785d53028b0c659567dc35aae4c32ddcb7770b5e4a094b1f5d5219ae6d04659920c631cea881bd077977f7a63a
7
+ data.tar.gz: 2c866d3d0c628a6a4f814f1a1fd78d4cbe62140787a43585e56cb8d749b3f6421dde793839d67d83bba268037a6493578b47eae23c669ad72296eabf5a584226
data/exe/aurora_mock CHANGED
@@ -38,7 +38,7 @@ r = slave1.holding_registers = slave2.holding_registers = slave255.holding_regis
38
38
  registers = YAML.safe_load(File.read(ARGV[2]))
39
39
  registers.each { |(k, v)| r[k] = v }
40
40
 
41
- server1.request_callback = lambda { |uid, func, req|
41
+ server1.request_callback = lambda do |uid, func, req|
42
42
  if func == 68
43
43
  puts "===== no idea to #{uid}: #{req.inspect}"
44
44
  elsif func == 67
@@ -54,9 +54,9 @@ server1.request_callback = lambda { |uid, func, req|
54
54
  else
55
55
  puts "**** new func #{func}"
56
56
  end
57
- }
57
+ end
58
58
 
59
- server1.response_callback = lambda { |uid, func, res, req|
59
+ server1.response_callback = lambda do |uid, func, res, req|
60
60
  if func == 3 && res.is_a?(Array) && req
61
61
  unless req[:quant] == res.length
62
62
  puts "wrong number of results"
@@ -88,7 +88,7 @@ server1.response_callback = lambda { |uid, func, res, req|
88
88
  else
89
89
  puts "**** new func #{func}"
90
90
  end
91
- }
91
+ end
92
92
 
93
93
  server2.start
94
94
  server1.send(:serve, server1.instance_variable_get(:@sp))
data/exe/aurora_monitor CHANGED
@@ -79,7 +79,7 @@ diff_and_print = lambda do |registers|
79
79
  last_registers = new_registers
80
80
  end
81
81
 
82
- server.request_callback = lambda { |uid, func, req|
82
+ server.request_callback = lambda do |uid, func, req|
83
83
  if func == 6
84
84
  puts "#{Time.now} ===== write register to #{uid}:"
85
85
  registers = { req[:addr] => req[:val] }
@@ -104,9 +104,9 @@ server.request_callback = lambda { |uid, func, req|
104
104
  else
105
105
  puts "#{Time.now} **** new func #{func}"
106
106
  end
107
- }
107
+ end
108
108
 
109
- server.response_callback = lambda { |uid, func, res, req|
109
+ server.response_callback = lambda do |uid, func, res, req|
110
110
  if func == 3 && res.is_a?(Array) && req
111
111
  unless req[:quant] == res.length
112
112
  puts "wrong number of results"
@@ -138,7 +138,7 @@ server.response_callback = lambda { |uid, func, res, req|
138
138
  else
139
139
  puts "#{Time.now} **** new func #{func}"
140
140
  end
141
- }
141
+ end
142
142
 
143
143
  server.send(:serve, server.instance_variable_get(:@sp))
144
144
  loop { nil }
@@ -3,6 +3,7 @@
3
3
 
4
4
  require "aurora"
5
5
  require "homie-mqtt"
6
+ require "mqtt/home_assistant"
6
7
  require "ccutrer-serialport"
7
8
  require "uri"
8
9
  require "optparse"
@@ -79,7 +80,7 @@ class MQTTBridge
79
80
  end
80
81
  end
81
82
  end
82
- rescue StandardError => e
83
+ rescue => e
83
84
  warn "failed processing message: #{e}\n#{e.backtrace}"
84
85
  end
85
86
 
@@ -123,153 +124,363 @@ class MQTTBridge
123
124
  end
124
125
 
125
126
  def publish_basic_attributes
126
- @homie_abc = @homie.node("abc", "Aurora Basic Control", "ABC") do |node|
127
+ @homie.home_assistant_device = {
128
+ manufacturer: "WaterFurnace",
129
+ sw_version: Aurora::VERSION,
130
+ model: @abc.model
131
+ }
132
+
133
+ @homie_abc = @homie.node("abc", "Heat Pump", "ABC") do |node|
127
134
  allowed_modes = %w[lockout standby blower heating cooling eh1 eh2 emergency waiting]
128
135
  allowed_modes << "dehumidify" if @abc.compressor.is_a?(Aurora::Compressor::VSDrive)
129
- node.property("current-mode", "Current Heating/Cooling Mode", :enum, @abc.current_mode,
130
- format: allowed_modes)
131
- node.property("entering-air-temperature", "Entering Air Temperature", :float, @abc.entering_air_temperature,
132
- unit: "ºF")
133
- node.property("entering-water-temperature", "Entering Water Temperature", :float,
134
- @abc.entering_water_temperature, unit: "ºF")
135
- node.property("leaving-air-temperature", "Leaving Air Temperature", :float, @abc.leaving_air_temperature,
136
- unit: "ºF")
137
- node.property("leaving-water-temperature", "Leaving Water Temperature", :float, @abc.leaving_water_temperature,
138
- unit: "ºF")
136
+ node.property("current-mode",
137
+ "Current Heating/Cooling Mode",
138
+ :enum,
139
+ @abc.current_mode,
140
+ format: allowed_modes,
141
+ hass: { sensor: { state_class: :measurement } })
142
+ node.property("entering-air-temperature",
143
+ "Entering Air Temperature",
144
+ :float,
145
+ @abc.entering_air_temperature,
146
+ unit: "°F",
147
+ hass: { sensor: { device_class: :temperature,
148
+ state_class: :measurement,
149
+ entity_category: :diagnostic } })
150
+ node.property("entering-water-temperature",
151
+ "Entering Water Temperature",
152
+ :float,
153
+ @abc.entering_water_temperature,
154
+ unit: "°F",
155
+ hass: { sensor: { device_class: :temperature,
156
+ state_class: :measurement,
157
+ entity_category: :diagnostic } })
158
+ node.property("leaving-air-temperature",
159
+ "Leaving Air Temperature",
160
+ :float,
161
+ @abc.leaving_air_temperature,
162
+ unit: "°F",
163
+ hass: { sensor: { device_class: :temperature,
164
+ state_class: :measurement,
165
+ entity_category: :diagnostic } })
166
+ node.property("leaving-water-temperature",
167
+ "Leaving Water Temperature",
168
+ :float,
169
+ @abc.leaving_water_temperature,
170
+ unit: "°F",
171
+ hass: { sensor: { device_class: :temperature,
172
+ state_class: :measurement,
173
+ entity_category: :diagnostic } })
139
174
  unless @abc.outdoor_temperature.zero? # TODO: figure out the config if this actually exists
140
- node.property("outdoor-temperature", "Outdoor Temperature", :float, @abc.outdoor_temperature, unit: "ºF")
175
+ node.property("outdoor-temperature",
176
+ "Outdoor Temperature",
177
+ :float,
178
+ @abc.outdoor_temperature,
179
+ unit: "°F",
180
+ hass: { sensor: { device_class: :temperature,
181
+ state_class: :measurement } })
141
182
  end
142
183
 
143
- node.property("fp1", "FP1 Sensor", :float, @abc.fp1, unit: "ºF")
144
- node.property("fp2", "FP2 Sensor", :float, @abc.fp2, unit: "ºF")
184
+ node.property("fp1",
185
+ "FP1 Sensor",
186
+ :float,
187
+ @abc.fp1,
188
+ unit: "°F",
189
+ hass: { sensor: { device_class: :temperature,
190
+ state_class: :measurement,
191
+ entity_category: :diagnostic } })
192
+ node.property("fp2",
193
+ "FP2 Sensor",
194
+ :float,
195
+ @abc.fp2,
196
+ unit: "°F",
197
+ hass: { sensor: { device_class: :temperature,
198
+ state_class: :measurement,
199
+ entity_category: :diagnostic } })
145
200
  %i[aux_heat total].each do |component|
146
201
  component = "#{component}_watts"
147
- node.property(component.tr("_", "-"), component.tr("_", " ").titleize, :integer,
148
- @abc.public_send(component), unit: "W")
202
+ node.property(component.tr("_", "-"),
203
+ component.sub("_watts", " Power Usage").tr("_", " ").titleize,
204
+ :integer,
205
+ @abc.public_send(component),
206
+ unit: "W",
207
+ hass: { sensor: { device_class: :power,
208
+ state_class: :measurement } })
149
209
  end
150
210
  end
151
211
 
152
212
  @compressor = @homie.node("compressor", "Compressor", @abc.compressor.type) do |node|
153
- node.property("speed", "Current compressor speed", :integer, @abc.compressor.speed,
154
- format: @abc.compressor.speed_range)
155
- node.property("watts", "Energy Usage", :integer, @abc.compressor.watts, unit: "W") if @abc.energy_monitoring?
213
+ node.property("speed",
214
+ "Current Speed",
215
+ :integer,
216
+ @abc.compressor.speed,
217
+ format: @abc.compressor.speed_range,
218
+ hass: { sensor: { state_class: :measurement } })
219
+ if @abc.energy_monitoring?
220
+ node.property("watts",
221
+ "Power Usage",
222
+ :integer,
223
+ @abc.compressor.watts,
224
+ unit: "W",
225
+ hass: { sensor: { device_class: :power,
226
+ state_class: :measurement } })
227
+ end
156
228
 
157
229
  next unless @abc.compressor.is_a?(Aurora::Compressor::VSDrive)
158
230
 
159
- node.property("ambient-temperature", "Compressor ambient temperature", :float,
160
- @abc.compressor.ambient_temperature, unit: "ºF")
231
+ node.property("ambient-temperature",
232
+ "Ambient Temperature",
233
+ :float,
234
+ @abc.compressor.ambient_temperature,
235
+ unit: "°F",
236
+ hass: { sensor: { device_class: :temperature,
237
+ state_class: :measurement,
238
+ entity_category: :diagnostic } })
161
239
 
162
240
  next unless @abc.iz2?
163
241
 
164
- node.property("iz2-desired-speed", "IZ2 Desired Speed", :integer, @abc.compressor.iz2_desired_speed,
165
- format: 0..12)
242
+ node.property("iz2-desired-speed",
243
+ "IZ2 Desired Speed",
244
+ :integer,
245
+ @abc.compressor.iz2_desired_speed,
246
+ format: 0..12,
247
+ hass: { sensor: { state_class: :measurement,
248
+ entity_category: :diagnostic } })
166
249
  end
167
250
 
168
251
  @blower = @homie.node("blower", "Blower", @abc.blower.type) do |node|
169
- node.property("running", "Blower is running", :boolean, @abc.blower.running?)
252
+ node.property("running",
253
+ "Running",
254
+ :boolean,
255
+ @abc.blower.running?,
256
+ hass: { binary_sensor: { device_class: :running } })
170
257
  if @abc.blower.respond_to?(:speed)
171
- node.property("speed", "Current blower speed", :integer, @abc.blower.speed, format: @abc.blower.speed_range)
258
+ node.property("speed",
259
+ "Current Speed",
260
+ :integer,
261
+ @abc.blower.speed,
262
+ format: @abc.blower.speed_range,
263
+ hass: { sensor: { state_class: :measurement } })
264
+ end
265
+ if @abc.energy_monitoring?
266
+ node.property("watts",
267
+ "Power Usage",
268
+ :integer,
269
+ @abc.blower.watts,
270
+ unit: "W",
271
+ hass: { sensor: { device_class: :power,
272
+ state_class: :measurement } })
172
273
  end
173
- node.property("watts", "Energy Usage", :integer, @abc.blower.watts, unit: "W") if @abc.energy_monitoring?
174
274
 
175
275
  next unless @abc.blower.is_a?(Aurora::Blower::ECM)
176
276
 
177
277
  presets = %w[blower-only aux-heat]
178
278
  presets.concat %w[low-compressor high-compressor] unless @abc.iz2?
179
279
  presets.each do |setting|
180
- field = "#{setting.tr('-', '_')}_speed"
181
- node.property("#{setting}-speed", "#{setting.tr('-', ' ').titleize} Preset Speed", :integer,
182
- @abc.blower.public_send(field), format: 1..12) do |value, property|
280
+ field = "#{setting.tr("-", "_")}_speed"
281
+ node.property("#{setting}-speed",
282
+ "#{setting.tr("-", " ").titleize} Preset Speed",
283
+ :integer,
284
+ @abc.blower.public_send(field),
285
+ format: 1..12,
286
+ hass: { number: { entity_category: :config } }) do |value, property|
183
287
  @mutex.synchronize { property.value = @abc.blower.public_send("#{field}=", value) }
184
288
  end
185
289
  end
186
290
 
187
291
  next unless @abc.iz2?
188
292
 
189
- node.property("iz2-desired-speed", "IZ2 Desired Speed", :integer, @abc.blower.iz2_desired_speed,
190
- format: 0..100, unit: "%")
293
+ node.property("iz2-desired-speed",
294
+ "IZ2 Desired Speed",
295
+ :integer,
296
+ @abc.blower.iz2_desired_speed,
297
+ format: 0..100,
298
+ unit: "%",
299
+ hass: { sensor: { state_class: :measurement,
300
+ entity_category: :diagnostic } })
191
301
  end
192
302
 
193
303
  @pump = @homie.node("pump", "Loop Pump", @abc.pump.type) do |node|
194
- node.property("waterflow", "Waterflow", :float, @abc.pump.waterflow, unit: "gpm")
195
- node.property("watts", "Energy Usage", :integer, @abc.pump.watts, unit: "W") if @abc.energy_monitoring?
304
+ node.property("waterflow",
305
+ "Waterflow",
306
+ :float,
307
+ @abc.pump.waterflow,
308
+ unit: "gpm",
309
+ hass: { sensor: { state_class: :measurement,
310
+ entity_category: :diagnostic } })
311
+ if @abc.energy_monitoring?
312
+ node.property("watts",
313
+ "Power Usage",
314
+ :integer,
315
+ @abc.pump.watts,
316
+ unit: "W",
317
+ hass: { sensor: { device_class: :power,
318
+ state_class: :measurement } })
319
+ end
196
320
 
197
321
  next unless @abc.pump.is_a?(Aurora::Pump::VSPump)
198
322
 
199
- node.property("running", "Pump is running", :boolean, @abc.pump.running)
200
- node.property("speed", "Speed", :integer, @abc.pump.speed, format: 0..100, unit: "%") do |value, property|
323
+ node.property("running",
324
+ "Running",
325
+ :boolean,
326
+ @abc.pump.running,
327
+ hass: { binary_sensor: { device_class: :running } })
328
+ node.property("speed",
329
+ "Speed",
330
+ :integer,
331
+ @abc.pump.speed,
332
+ format: 0..100,
333
+ unit: "%",
334
+ hass: { number: { entity_category: :diagnostic } }) do |value, property|
201
335
  @mutex.synchronize { property.value = @abc.pump.speed = value }
202
336
  end
203
- node.property("manual-control", "If manual control is enabled", :boolean,
204
- @abc.pump.manual_control?) do |value, property|
337
+ node.property("manual-control",
338
+ "Manual Control",
339
+ :boolean,
340
+ @abc.pump.manual_control?,
341
+ hass: { switch: { entity_category: :diagnostic } }) do |value, property|
205
342
  @mutex.synchronize { property.value = @abc.pump.manual_control = value }
206
343
  end
207
- node.property("minimum-speed", "Speed pump runs at compressor speed 0", :integer, @abc.pump.minimum_speed,
208
- format: 0..100, unit: "%") do |value, property|
344
+ node.property("minimum-speed",
345
+ "Actual Minimum Speed",
346
+ :integer,
347
+ @abc.pump.minimum_speed,
348
+ format: 0..100,
349
+ unit: "%",
350
+ hass: { number: { entity_category: :config } }) do |value, property|
209
351
  @mutex.synchronize { property.value = @abc.pump.minimum_speed = value }
210
352
  end
211
- node.property("maximum-speed", "Speed pump runs at compressor speed 12", :integer, @abc.pump.minimum_speed,
212
- format: 0..100, unit: "%") do |value, property|
353
+ node.property("maximum-speed",
354
+ "Actual Maximum Speed",
355
+ :integer,
356
+ @abc.pump.minimum_speed,
357
+ format: 0..100,
358
+ unit: "%",
359
+ hass: { number: { entity_category: :config } }) do |value, property|
213
360
  @mutex.synchronize { property.value = @abc.pump.maximum_speed = value }
214
361
  end
215
362
  end
216
363
 
217
364
  if @abc.dhw
218
365
  @dhw = @homie.node("dhw", "Domestic Hot Water Generator", "DHW") do |node|
219
- node.property("enabled", "Enabled", :boolean, @abc.dhw.enabled) do |value, property|
366
+ node.property("enabled",
367
+ "Enabled",
368
+ :boolean,
369
+ @abc.dhw.enabled,
370
+ hass: { switch: { icon: "mdi:water-boiler" } }) do |value, property|
220
371
  @mutex.synchronize { property.value = @abc.dhw.enabled = value }
221
372
  end
222
- node.property("running", "DHW Pump is running", :boolean, @abc.dhw.running?)
223
- node.property("water-temperature", "Water Temperature", :float,
224
- @abc.dhw.water_temperature, unit: "ºF")
225
- node.property("set-point", "Set Point", :float, @abc.dhw.set_point, format: 100..140,
226
- unit: "ºF") do |value, property|
373
+ node.property("running",
374
+ "Pump Running",
375
+ :boolean,
376
+ @abc.dhw.running?,
377
+ hass: { binary_sensor: { device_class: :running } })
378
+ node.property("water-temperature",
379
+ "Water Temperature",
380
+ :float,
381
+ @abc.dhw.water_temperature,
382
+ unit: "°F",
383
+ hass: { sensor: { device_class: :temperature,
384
+ state_class: :measurement } })
385
+ node.property("set-point",
386
+ "Set Point",
387
+ :float,
388
+ @abc.dhw.set_point,
389
+ format: 100..140,
390
+ unit: "°F",
391
+ hass: :number) do |value, property|
227
392
  @mutex.synchronize { property.value = @abc.dhw.set_point = value }
228
393
  end
229
394
  end
230
395
  end
231
396
 
232
397
  @humidistat = @homie.node("humidistat", "Humidistat", "Humidistat") do |node|
233
- node.property("relative-humidity", "Relative Humidity", :integer, @abc.humidistat.relative_humidity,
234
- unit: "%", format: 0..100)
398
+ node.property("relative-humidity",
399
+ "Relative Humidity",
400
+ :integer,
401
+ @abc.humidistat.relative_humidity,
402
+ unit: "%",
403
+ format: 0..100,
404
+ hass: { sensor: { device_class: :humidity,
405
+ state_class: :measurement } })
235
406
  if @abc.humidistat.humidifier?
236
- node.property("humidifier-running", "Humidifier is running", :boolean, @abc.humidistat.humidifier_running?)
237
- node.property("humidifier-mode", "Humidifier Mode", :enum, @abc.humidistat.humidifier_mode,
407
+ node.property("humidifier-running",
408
+ "Humidifier Running",
409
+ :boolean,
410
+ @abc.humidistat.humidifier_running?)
411
+ node.property("humidifier-mode",
412
+ "Humidifier Mode",
413
+ :enum,
414
+ @abc.humidistat.humidifier_mode,
238
415
  format: %i[auto manual]) do |value, property|
239
416
  @mutex.synchronize { property.value = @abc.humidistat.humidifier_mode = value.to_sym }
240
417
  end
241
- node.property("humidification-target", "Humidification target relative humidity", :integer,
242
- @abc.humidistat.humidification_target, unit: "%", format: 15..50) do |value, property|
418
+ node.property("humidification-target",
419
+ "Humidification Target Relative Humidity",
420
+ :integer,
421
+ @abc.humidistat.humidification_target,
422
+ unit: "%",
423
+ format: 15..50) do |value, property|
243
424
  @mutex.synchronize { property.value = @abc.humidistat.humidification_target = value }
244
425
  end
426
+ node.hass_humidifier("humidifier-running",
427
+ target_property: "humidification-target",
428
+ mode_property: "humidifier-mode",
429
+ id: "humidifier",
430
+ name: "Humidifier",
431
+ device_class: :humidifier)
245
432
  end
246
433
 
247
434
  # VSDrive can perform active dehumidification, even without a dedicated dehumidifier
248
- if @abc.humidistat.dehumidifier? || @abc.compressor.is_a?(Aurora::Compressor::VSDrive)
249
- node.property("dehumidifier-mode", "Dehumidifier Mode", :enum, @abc.humidistat.dehumidifier_mode,
435
+ if @abc.humidistat.dehumidifier? ||
436
+ @abc.compressor.is_a?(Aurora::Compressor::VSDrive)
437
+ node.property("dehumidifier-running",
438
+ "Dehumidifier Running",
439
+ :boolean,
440
+ @abc.humidistat.dehumidifier_running?)
441
+ node.property("dehumidifier-mode",
442
+ "Dehumidifier Mode",
443
+ :enum,
444
+ @abc.humidistat.dehumidifier_mode,
250
445
  format: %i[auto manual]) do |value, property|
251
446
  @mutex.synchronize { property.value = @abc.humidistat.dehumidifier_mode = value.to_sym }
252
447
  end
253
- node.property("dehumidification-target", "Dehumidification target relative humidity", :integer,
254
- @abc.humidistat.dehumidification_target, unit: "%", format: 35..65) do |value, property|
448
+ node.property("dehumidification-target",
449
+ "Dehumidification Target Relative Humidity",
450
+ :integer,
451
+ @abc.humidistat.dehumidification_target,
452
+ unit: "%",
453
+ format: 35..65) do |value, property|
255
454
  @mutex.synchronize { property.value = @abc.humidistat.dehumidification_target = value }
256
455
  end
456
+ node.hass_humidifier("dehumidifier-running",
457
+ target_property: "dehumidification-target",
458
+ mode_property: "dehumidifier-mode",
459
+ id: "dehumidifier",
460
+ name: "Dehumidifier",
461
+ device_class: :dehumidifier)
257
462
  end
258
-
259
- next unless @abc.humidistat.dehumidifier?
260
-
261
- node.property("dehumidifier-running", "Dehumidifier is running", :boolean, @abc.humidistat.dehumidifier_running?)
262
463
  end
263
464
 
264
465
  @faults = @homie.node("faults", "Fault History", "ABC") do |node|
265
- node.property("clear-history", "Reset fault counts", :enum, retained: false, format: "clear") do |_|
466
+ node.property("clear-history",
467
+ "Reset Fault Counts",
468
+ :enum,
469
+ retained: false,
470
+ format: "clear",
471
+ hass: :scene) do |_|
266
472
  @mutex.synchronize { @abc.clear_fault_history }
267
473
  end
268
474
  @abc.faults.each_with_index do |count, i|
269
475
  next if count == 0xffff
270
476
 
271
477
  name = Aurora::FAULTS[i + 1]
272
- node.property("e#{i + 1}", name || "E#{i + 1}", :integer, count)
478
+ node.property("e#{i + 1}",
479
+ name || "E#{i + 1}",
480
+ :integer,
481
+ count,
482
+ hass: { sensor: { state_class: :total_increasing,
483
+ entity_category: :diagnostic } })
273
484
  end
274
485
  end
275
486
 
@@ -278,39 +489,108 @@ class MQTTBridge
278
489
  @homie.node("zone#{i + 1}", "Zone #{i + 1}", type) do |node|
279
490
  allowed_modes = %w[off auto cool heat]
280
491
  allowed_modes << "eheat" if i.zero?
281
- node.property("target-mode", "Target Heating/Cooling Mode", :enum, zone.target_mode,
492
+ node.property("target-mode",
493
+ "Target Heating/Cooling Mode",
494
+ :enum,
495
+ zone.target_mode,
282
496
  format: allowed_modes) do |value, property|
283
497
  @mutex.synchronize { property.value = zone.target_mode = value.to_sym }
284
498
  end
285
- node.property("current-mode", "Current Heating/Cooling Mode Requested", :enum, zone.current_mode,
499
+ node.property("current-mode",
500
+ "Current Heating/Cooling Mode Requested",
501
+ :enum,
502
+ zone.current_mode,
286
503
  format: %w[standby h1 h2 h3 c1 c2])
287
- node.property("target-fan-mode", "Target Fan Mode", :enum, zone.target_fan_mode,
504
+ node.property("target-fan-mode",
505
+ "Target Fan Mode",
506
+ :enum,
507
+ zone.target_fan_mode,
288
508
  format: %w[auto continuous intermittent]) do |value, property|
289
509
  @mutex.synchronize { property.value = zone.target_fan_mode = value.to_sym }
290
510
  end
291
- node.property("fan-intermittent-on", "Fan Intermittent Mode On Duration", :enum, zone.fan_intermittent_on,
292
- unit: "M", format: %w[0 5 10 15 20]) do |value, property|
511
+ node.property("fan-intermittent-on",
512
+ "Fan Intermittent Mode On Duration",
513
+ :enum,
514
+ zone.fan_intermittent_on,
515
+ unit: "M",
516
+ format: %w[0 5 10 15 20],
517
+ hass: { select: { entity_category: :config } }) do |value, property|
293
518
  @mutex.synchronize { property.value = zone.fan_intermittent_on = value.to_i }
294
519
  end
295
- node.property("fan-intermittent-off", "Fan Intermittent Mode Off Duration", :enum, zone.fan_intermittent_on,
296
- unit: "M", format: %w[0 5 10 15 20 25 30 35 40]) do |value, property|
520
+ node.property("fan-intermittent-off",
521
+ "Fan Intermittent Mode Off Duration",
522
+ :enum,
523
+ zone.fan_intermittent_on,
524
+ unit: "M",
525
+ format: %w[0 5 10 15 20 25 30 35 40],
526
+ hass: { select: { entity_category: :config } }) do |value, property|
297
527
  @mutex.synchronize { property.value = zone.fan_intermittent_on = value.to_i }
298
528
  end
299
- node.property("current-fan-mode", "Current Fan Status", :boolean, zone.current_fan_mode)
529
+ node.property("current-fan-mode",
530
+ "Current Fan Status",
531
+ :boolean,
532
+ zone.current_fan_mode,
533
+ hass: { binary_sensor: { device_class: :running } })
300
534
  if zone.is_a?(Aurora::IZ2Zone)
301
- node.property("priority", "Zone Priority", :enum, zone.priority, format: %w[economy comfort])
302
- node.property("size", "Size", :enum, zone.size, format: %w[0 25 45 70])
303
- node.property("normalized-size", "Normalized Size", :integer, zone.normalized_size, unit: "%", format: 0..100)
535
+ node.property("priority",
536
+ "Zone Priority",
537
+ :enum,
538
+ zone.priority,
539
+ format: %w[economy comfort],
540
+ hass: { sensor: { state_class: :measurement,
541
+ entity_category: :diagnostic } })
542
+ node.property("size",
543
+ "Size",
544
+ :enum,
545
+ zone.size,
546
+ format: %w[0 25 45 70],
547
+ hass: { sensor: { state_class: :measurement,
548
+ entity_category: :diagnostic } })
549
+ node.property("normalized-size",
550
+ "Normalized Size",
551
+ :integer,
552
+ zone.normalized_size,
553
+ unit: "%",
554
+ format: 0..100,
555
+ hass: { sensor: { state_class: :measurement,
556
+ entity_category: :diagnostic } })
304
557
  end
305
- node.property("ambient-temperature", "Ambient Temperature", :float, zone.ambient_temperature, unit: "ºF")
306
- node.property("heating-target-temperature", "Heating Target Temperature", :integer,
307
- zone.heating_target_temperature, unit: "ºF", format: 40..90) do |value, property|
558
+ node.property("ambient-temperature",
559
+ "Ambient Temperature",
560
+ :float,
561
+ zone.ambient_temperature,
562
+ unit: "°F")
563
+ node.property("heating-target-temperature",
564
+ "Heating Target Temperature",
565
+ :integer,
566
+ zone.heating_target_temperature,
567
+ unit: "°F",
568
+ format: 40..90) do |value, property|
308
569
  @mutex.synchronize { property.value = zone.heating_target_temperature = value }
309
570
  end
310
- node.property("cooling-target-temperature", "Cooling Target Temperature", :integer,
311
- zone.cooling_target_temperature, unit: "ºF", format: 54..99) do |value, property|
571
+ node.property("cooling-target-temperature",
572
+ "Cooling Target Temperature", :integer,
573
+ zone.cooling_target_temperature,
574
+ unit: "°F",
575
+ format: 54..99) do |value, property|
312
576
  @mutex.synchronize { property.value = zone.cooling_target_temperature = value }
313
577
  end
578
+ node.hass_climate(action_property: "current-mode",
579
+ current_temperature_property: "ambient-temperature",
580
+ fan_mode_property: "target-mode",
581
+ temperature_high_property: "cooling-target-temperature",
582
+ temperature_low_property: "heating-target-temperature",
583
+ templates: {
584
+ action_template: <<~JINJA
585
+ {% if value.startswith('h') %}
586
+ heating
587
+ {% elif value.startswith('c') %}
588
+ cooling
589
+ {% elif value == 'standby' %}
590
+ idle
591
+ {% endif %}
592
+ JINJA
593
+ })
314
594
  end
315
595
  end
316
596
 
@@ -328,7 +608,7 @@ logger.level = log_level
328
608
  abc.modbus_slave.logger = logger
329
609
 
330
610
  device = "aurora-#{abc.serial_number}"
331
- homie = MQTT::Homie::Device.new(device, "Aurora MQTT Bridge", mqtt: mqtt_uri)
611
+ homie = MQTT::Homie::Device.new(device, "WaterFurnace", mqtt: mqtt_uri)
332
612
  homie.logger = logger
333
613
 
334
614
  MQTTBridge.new(abc, homie)
@@ -43,6 +43,7 @@ module Aurora
43
43
  end
44
44
 
45
45
  attr_reader :modbus_slave,
46
+ :model,
46
47
  :serial_number,
47
48
  :zones,
48
49
  :compressor,
@@ -66,9 +67,10 @@ module Aurora
66
67
  @modbus_slave = self.class.open_modbus_slave(uri)
67
68
  @modbus_slave.read_retry_timeout = 15
68
69
  @modbus_slave.read_retries = 2
69
- raw_registers = @modbus_slave.holding_registers[33, 88..91, 105...110, 404, 412..413, 1103, 1114]
70
+ raw_registers = @modbus_slave.holding_registers[33, 88...110, 404, 412..413, 1103, 1114]
70
71
  registers = Aurora.transform_registers(raw_registers.dup)
71
72
  @program = registers[88]
73
+ @model = registers[92]
72
74
  @serial_number = registers[105]
73
75
  @energy_monitor = raw_registers[412]
74
76
 
@@ -92,14 +94,14 @@ module Aurora
92
94
  when 3 then Blower::FiveSpeed.new(self, registers[404])
93
95
  else; Blower::PSC.new(self, registers[404])
94
96
  end
95
- @pump = if (3..5).include?(raw_registers[413])
97
+ @pump = if (3..5).cover?(raw_registers[413])
96
98
  Pump::VSPump.new(self,
97
99
  registers[413])
98
100
  else
99
101
  Pump::GenericPump.new(self,
100
102
  registers[413])
101
103
  end
102
- @dhw = DHW.new(self) if (-999..999).include?(registers[1114])
104
+ @dhw = DHW.new(self) if (-999..999).cover?(registers[1114])
103
105
  @humidistat = Humidistat.new(self,
104
106
  @abc_dipswitches[:accessory_relay] == :humidifier,
105
107
  @axb_dipswitches[:accessory_relay2] == :dehumidifier)
@@ -171,7 +173,7 @@ module Aurora
171
173
  @fp2 = registers[20]
172
174
  @locked_out = registers[25] & 0x8000
173
175
  @error = registers[25] & 0x7fff
174
- @derated = (41..46).include?(@error)
176
+ @derated = (41..46).cover?(@error)
175
177
  @safe_mode = [47, 48, 49, 72, 74].include?(@error)
176
178
  @aux_heat_watts = registers[1151]
177
179
  @total_watts = registers[1153]
@@ -212,7 +214,7 @@ module Aurora
212
214
  end
213
215
 
214
216
  def line_voltage=(value)
215
- raise ArgumentError unless (90..635).include?(value)
217
+ raise ArgumentError unless (90..635).cover?(value)
216
218
 
217
219
  @modbus_slave.holding_registers[112] = value
218
220
  end
@@ -227,13 +229,13 @@ module Aurora
227
229
  pump_speed: :with_compressor,
228
230
  aux_heat: false)
229
231
  raise ArgumentError, "mode must be :off, :heating, or :cooling" unless %i[off heating cooling].include?(mode)
230
- raise ArgumentError, "compressor speed must be between 0 and 12" unless (0..12).include?(compressor_speed)
232
+ raise ArgumentError, "compressor speed must be between 0 and 12" unless (0..12).cover?(compressor_speed)
231
233
 
232
- unless blower_speed == :with_compressor || (0..12).include?(blower_speed)
234
+ unless blower_speed == :with_compressor || (0..12).cover?(blower_speed)
233
235
  raise ArgumentError,
234
236
  "blower speed must be :with_compressor or between 0 and 12"
235
237
  end
236
- unless pump_speed == :with_compressor || (0..100).include?(pump_speed)
238
+ unless pump_speed == :with_compressor || (0..100).cover?(pump_speed)
237
239
  raise ArgumentError,
238
240
  "pump speed must be :with_compressor or between 0 and 100"
239
241
  end
@@ -273,7 +275,7 @@ module Aurora
273
275
  def inspect
274
276
  "#<Aurora::ABCClient #{(instance_variables - [:@modbus_slave]).map do |iv|
275
277
  "#{iv}=#{instance_variable_get(iv).inspect}"
276
- end.join(', ')}>"
278
+ end.join(", ")}>"
277
279
  end
278
280
  end
279
281
  end
data/lib/aurora/blower.rb CHANGED
@@ -6,7 +6,7 @@ module Aurora
6
6
  module Blower
7
7
  class PSC < Component
8
8
  attr_reader :type, :watts, :running
9
- alias running? running
9
+ alias_method :running?, :running
10
10
 
11
11
  def initialize(abc, type)
12
12
  super(abc)
@@ -9,7 +9,7 @@ module Aurora
9
9
  def inspect
10
10
  "#<Aurora::#{self.class.name} #{(instance_variables - [:@abc]).map do |iv|
11
11
  "#{iv}=#{instance_variable_get(iv).inspect}"
12
- end.join(', ')}>"
12
+ end.join(", ")}>"
13
13
  end
14
14
 
15
15
  private
@@ -13,7 +13,7 @@ module Aurora
13
13
  end
14
14
 
15
15
  def type
16
- "#{@stages == 2 ? 'Dual' : 'Single'} Stage Compressor"
16
+ "#{@stages == 2 ? "Dual" : "Single"} Stage Compressor"
17
17
  end
18
18
 
19
19
  def speed_range
data/lib/aurora/dhw.rb CHANGED
@@ -5,7 +5,7 @@ require "aurora/component"
5
5
  module Aurora
6
6
  class DHW < Component
7
7
  attr_reader :enabled, :running, :set_point, :water_temperature
8
- alias running? running
8
+ alias_method :running?, :running
9
9
 
10
10
  def registers_to_read
11
11
  [400..401, 1114]
@@ -23,7 +23,7 @@ module Aurora
23
23
  end
24
24
 
25
25
  def set_point=(value) # rubocop:disable Naming/AccessorMethodName
26
- raise ArgumentError unless (100..140).include?(value)
26
+ raise ArgumentError unless (100..140).cover?(value)
27
27
 
28
28
  raw_value = (value * 10).to_i
29
29
  holding_registers[401] = raw_value
@@ -5,10 +5,9 @@ require "aurora/component"
5
5
  module Aurora
6
6
  class Humidistat < Component
7
7
  attr_reader :humidifier_running, :humidifier_mode, :humidification_target,
8
- :dehumidifier_running, :dehumidifier_mode, :dehumidification_target,
8
+ :dehumidifier_mode, :dehumidification_target,
9
9
  :relative_humidity
10
- alias humidifier_running? humidifier_running
11
- alias dehumidifer_running? dehumidifier_running
10
+ alias_method :humidifier_running?, :humidifier_running
12
11
 
13
12
  def initialize(abc, has_humidifier, has_dehumidifier)
14
13
  super(abc)
@@ -24,6 +23,11 @@ module Aurora
24
23
  @dehumidifier
25
24
  end
26
25
 
26
+ def dehumidifier_running
27
+ dehumidifier? ? @dehumidifier_running : abc.current_mode == :dehumidify
28
+ end
29
+ alias_method :dehumidifier_running?, :dehumidifier_running
30
+
27
31
  def registers_to_read
28
32
  result = [741]
29
33
  if humidifier? || dehumidifier? || abc.compressor.is_a?(Compressor::VSDrive)
@@ -82,8 +86,8 @@ module Aurora
82
86
  end
83
87
 
84
88
  def set_humidistat_targets(humidification_target, dehumidification_target)
85
- raise ArgumentError unless (15..50).include?(humidification_target)
86
- raise ArgumentError unless (35..65).include?(dehumidification_target)
89
+ raise ArgumentError unless (15..50).cover?(humidification_target)
90
+ raise ArgumentError unless (35..65).cover?(dehumidification_target)
87
91
 
88
92
  holding_registers[abc.iz2? ? 21_115 : 12_310] = (humidification_target << 8) + dehumidification_target
89
93
  @humidification_target = humidification_target
@@ -15,18 +15,18 @@ module Aurora
15
15
  end
16
16
 
17
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
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
21
  [base1..(base1 + 1), base2..(base2 + 2), base3]
22
22
  end
23
23
 
24
24
  def refresh(registers)
25
- @ambient_temperature = registers[31_007 + (zone_number - 1) * 3]
25
+ @ambient_temperature = registers[31_007 + ((zone_number - 1) * 3)]
26
26
 
27
- config1 = registers[31_008 + (zone_number - 1) * 3]
28
- config2 = registers[31_009 + (zone_number - 1) * 3]
29
- config3 = registers[31_200 + (zone_number - 1) * 3]
27
+ config1 = registers[31_008 + ((zone_number - 1) * 3)]
28
+ config2 = registers[31_009 + ((zone_number - 1) * 3)]
29
+ config3 = registers[31_200 + ((zone_number - 1) * 3)]
30
30
 
31
31
  @target_fan_mode = config1[:fan]
32
32
  @fan_intermittent_on = config1[:on_time]
@@ -45,28 +45,28 @@ module Aurora
45
45
  def target_mode=(value)
46
46
  return unless (raw_value = Aurora::HEATING_MODE.invert[value])
47
47
 
48
- holding_registers[21_202 + (zone_number - 1) * 9] = raw_value
48
+ holding_registers[21_202 + ((zone_number - 1) * 9)] = raw_value
49
49
  @target_mode = value
50
50
  end
51
51
 
52
52
  def target_fan_mode=(value)
53
53
  return unless (raw_value = Aurora::FAN_MODE.invert[value])
54
54
 
55
- holding_registers[21_205 + (zone_number - 1) * 9] = raw_value
55
+ holding_registers[21_205 + ((zone_number - 1) * 9)] = raw_value
56
56
  @target_fan_mode = value
57
57
  end
58
58
 
59
59
  def fan_intermittent_on=(value)
60
60
  return unless value >= 0 && value <= 25 && (value % 5).zero?
61
61
 
62
- holding_registers[21_206 + (zone_number - 1) * 9] = value
62
+ holding_registers[21_206 + ((zone_number - 1) * 9)] = value
63
63
  @fan_intermittent_on = value
64
64
  end
65
65
 
66
66
  def fan_intermittent_off=(value)
67
67
  return unless value >= 0 && value <= 40 && (value % 5).zero?
68
68
 
69
- holding_registers[21_207 + (zone_number - 1) * 9] = value
69
+ holding_registers[21_207 + ((zone_number - 1) * 9)] = value
70
70
  @fan_intermittent_off = value
71
71
  end
72
72
 
@@ -74,7 +74,7 @@ module Aurora
74
74
  return unless value >= 40 && value <= 90
75
75
 
76
76
  raw_value = (value * 10).to_i
77
- holding_registers[21_203 + (zone_number - 1) * 9] = raw_value
77
+ holding_registers[21_203 + ((zone_number - 1) * 9)] = raw_value
78
78
  @heating_target_temperature = value
79
79
  end
80
80
 
@@ -82,7 +82,7 @@ module Aurora
82
82
  return unless value >= 54 && value <= 99
83
83
 
84
84
  raw_value = (value * 10).to_i
85
- holding_registers[21_204 + (zone_number - 1) * 9] = raw_value
85
+ holding_registers[21_204 + ((zone_number - 1) * 9)] = raw_value
86
86
  @cooling_target_temperature = value
87
87
  end
88
88
  end
@@ -44,6 +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
+ alias_method :[]=, :write_holding_register
48
48
  end
49
49
  end
@@ -4,14 +4,14 @@ module Aurora
4
4
  module ModBus
5
5
  module Slave
6
6
  def read_multiple_holding_registers(*ranges)
7
- values = if ranges.any? { |r| r.is_a?(Range) }
7
+ values = if ranges.any?(Range)
8
8
  addrs_and_lengths = ranges.map do |r|
9
9
  r = Array(r)
10
10
  [r.first, r.last - r.first + 1]
11
11
  end.flatten
12
- query("A#{addrs_and_lengths.pack('n*')}").unpack("n*")
12
+ query("A#{addrs_and_lengths.pack("n*")}").unpack("n*")
13
13
  else
14
- query("B#{ranges.pack('n*')}").unpack("n*")
14
+ query("B#{ranges.pack("n*")}").unpack("n*")
15
15
  end
16
16
  ranges.map { |r| Array(r) }.flatten.zip(values).to_h
17
17
  end
data/lib/aurora/pump.rb CHANGED
@@ -6,7 +6,7 @@ module Aurora
6
6
  module Pump
7
7
  class GenericPump < Component
8
8
  attr_reader :type, :watts, :waterflow, :running
9
- alias running? running
9
+ alias_method :running?, :running
10
10
 
11
11
  def initialize(abc, type)
12
12
  super(abc)
@@ -28,7 +28,7 @@ module Aurora
28
28
 
29
29
  class VSPump < GenericPump
30
30
  attr_reader :speed, :minimum_speed, :maximum_speed, :manual_control
31
- alias manual_control? manual_control
31
+ alias_method :manual_control?, :manual_control
32
32
 
33
33
  def registers_to_read
34
34
  super + [321..325]
@@ -108,7 +108,7 @@ module Aurora
108
108
  48 => "EEV OD Comm Error", # Com with EEV is interupted EEV has gone independent mode
109
109
  49 => "Cabinet Temperature Sensor", # Ambient Temperature (Tamb) is <-76 or > 212 F and out of range or invalid
110
110
  51 => "Discharge Temp Sensor", # Discharge Sensor (Sd) is > 280 F or invalid (-76 to 392 F)
111
- 52 => "Suction Presure Sensor", # Suction Pressure (P0) is invalid (0 to 232 psi)
111
+ 52 => "Suction Pressure Sensor", # Suction Pressure (P0) is invalid (0 to 232 psi)
112
112
  53 => "Condensing Pressure Sensor", # Low condensing pressure (PD) or invalid (0 to 870 psi) Retry 10x.
113
113
  54 => "Low Supply Voltage", # Supply Voltage is <180 V (190V to reset) or powered off/on too quickly (<30 sec.).
114
114
  55 => "Out of Envelope", # Comp Operating out of envelope (P0) more than 90 sec. Retry 10x.
@@ -550,7 +550,7 @@ module Aurora
550
550
  REGISTER_FORMATS = {
551
551
  "%ds" => [1, 6, 9, 15, 84, 85, 110],
552
552
  "%dV" => [16, 112, 3331, 3424, 3523],
553
- "%0.1fºF" => [19, 20, 401, 501, 502, 567, 740, 745, 746, 747, 900, 903,
553
+ "%0.1f°F" => [19, 20, 401, 501, 502, 567, 740, 745, 746, 747, 900, 903,
554
554
  1109, 1110, 1111, 1112, 1113, 1114, 1124, 1125, 1134, 1135, 1136,
555
555
  3325, 3326, 3327, 3330, 3522, 3903, 3905, 3906,
556
556
  12_619, 12_620,
@@ -587,9 +587,9 @@ module Aurora
587
587
 
588
588
  def zone_registers
589
589
  (1..6).map do |i|
590
- base1 = 21_202 + (i - 1) * 9
591
- base2 = 31_007 + (i - 1) * 3
592
- base3 = 31_200 + (i - 1) * 3
590
+ base1 = 21_202 + ((i - 1) * 9)
591
+ base2 = 31_007 + ((i - 1) * 3)
592
+ base3 = 31_200 + ((i - 1) * 3)
593
593
  {
594
594
  base1 => "Zone #{i} Heating Mode (write)",
595
595
  (base1 + 1) => "Zone #{i} Heating Setpoint (write)",
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Aurora
4
- VERSION = "0.6.4"
4
+ VERSION = "0.7.3"
5
5
  end
data/lib/aurora.rb CHANGED
@@ -7,6 +7,7 @@ require "aurora/mock_abc"
7
7
  require "aurora/modbus/server"
8
8
  require "aurora/modbus/slave"
9
9
  require "aurora/registers"
10
+ require "aurora/version"
10
11
 
11
12
  # extend ModBus for WaterFurnace's custom functions
12
13
  ModBus::RTUServer.include(Aurora::ModBus::Server)
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.6.4
4
+ version: 0.7.3
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-09-08 00:00:00.000000000 Z
11
+ date: 2021-12-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ccutrer-serialport
@@ -25,25 +25,25 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.0.0
27
27
  - !ruby/object:Gem::Dependency
28
- name: homie-mqtt
28
+ name: mqtt-homeassistant
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.4'
33
+ version: '0.1'
34
34
  - - ">="
35
35
  - !ruby/object:Gem::Version
36
- version: 1.4.5
36
+ version: 0.1.2
37
37
  type: :runtime
38
38
  prerelease: false
39
39
  version_requirements: !ruby/object:Gem::Requirement
40
40
  requirements:
41
41
  - - "~>"
42
42
  - !ruby/object:Gem::Version
43
- version: '1.4'
43
+ version: '0.1'
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: 1.4.5
46
+ version: 0.1.2
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: net-telnet-rfc2217
49
49
  requirement: !ruby/object:Gem::Requirement
@@ -98,28 +98,56 @@ dependencies:
98
98
  requirements:
99
99
  - - "~>"
100
100
  - !ruby/object:Gem::Version
101
- version: '9.0'
101
+ version: '11.0'
102
102
  type: :development
103
103
  prerelease: false
104
104
  version_requirements: !ruby/object:Gem::Requirement
105
105
  requirements:
106
106
  - - "~>"
107
107
  - !ruby/object:Gem::Version
108
- version: '9.0'
108
+ version: '11.0'
109
109
  - !ruby/object:Gem::Dependency
110
110
  name: rubocop
111
111
  requirement: !ruby/object:Gem::Requirement
112
112
  requirements:
113
113
  - - "~>"
114
114
  - !ruby/object:Gem::Version
115
- version: '1.19'
115
+ version: '1.23'
116
116
  type: :development
117
117
  prerelease: false
118
118
  version_requirements: !ruby/object:Gem::Requirement
119
119
  requirements:
120
120
  - - "~>"
121
121
  - !ruby/object:Gem::Version
122
- version: '1.19'
122
+ version: '1.23'
123
+ - !ruby/object:Gem::Dependency
124
+ name: rubocop-performance
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: '1.12'
130
+ type: :development
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - "~>"
135
+ - !ruby/object:Gem::Version
136
+ version: '1.12'
137
+ - !ruby/object:Gem::Dependency
138
+ name: rubocop-rake
139
+ requirement: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - "~>"
142
+ - !ruby/object:Gem::Version
143
+ version: '0.6'
144
+ type: :development
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - "~>"
149
+ - !ruby/object:Gem::Version
150
+ version: '0.6'
123
151
  description:
124
152
  email: cody@cutrer.com'
125
153
  executables:
@@ -157,7 +185,8 @@ files:
157
185
  homepage: https://github.com/ccutrer/waterfurnace_aurora
158
186
  licenses:
159
187
  - MIT
160
- metadata: {}
188
+ metadata:
189
+ rubygems_mfa_required: 'true'
161
190
  post_install_message:
162
191
  rdoc_options: []
163
192
  require_paths: