mqtt-homeassistant 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/mqtt/home_assistant/version.rb +7 -0
- data/lib/mqtt/home_assistant.rb +535 -0
- data/lib/mqtt-homeassistant.rb +3 -0
- metadata +145 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 63f377ed2f680df05fcdd443d7827be88ad49630b6a2e046a1291f3ccbe1fe41
|
4
|
+
data.tar.gz: 9f48fd3a21b57073ae31bc488c5f8fda3369a2e3d2ef37d41426e1865d1d307a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e378a1edd2a12093be108cb9b1685393422274fcc65b578dee2e73c0a429a06dc35f17889f113998ac03a3f4a936fb01028a07f201061dc5420b3557b204b0f2
|
7
|
+
data.tar.gz: 82f86cf62752b56a357844149c2b51952a9fa448783a29e2396053a77648d73acae97921db149a7745a423b97edbd606bd53185f8431b865026383d7cb7d2227
|
@@ -0,0 +1,535 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
|
5
|
+
module MQTT
|
6
|
+
module HomeAssistant
|
7
|
+
class << self
|
8
|
+
ENTITY_CATEGORIES = %i[config diagnostic system].freeze
|
9
|
+
DEVICE_CLASSES = {
|
10
|
+
binary_sensor: %i[
|
11
|
+
battery
|
12
|
+
battery_charging
|
13
|
+
cold
|
14
|
+
connectivity
|
15
|
+
door
|
16
|
+
garage_door
|
17
|
+
gas
|
18
|
+
heat
|
19
|
+
light
|
20
|
+
lock
|
21
|
+
moisture
|
22
|
+
motion
|
23
|
+
moving
|
24
|
+
occupancy
|
25
|
+
opening
|
26
|
+
plug
|
27
|
+
power
|
28
|
+
presence
|
29
|
+
problem
|
30
|
+
running
|
31
|
+
safety
|
32
|
+
smoke
|
33
|
+
sound
|
34
|
+
tamper
|
35
|
+
update
|
36
|
+
vibration
|
37
|
+
window
|
38
|
+
].freeze,
|
39
|
+
humidifier: %i[
|
40
|
+
humidifier
|
41
|
+
dehumidifier
|
42
|
+
].freeze,
|
43
|
+
sensor: %i[
|
44
|
+
aqi
|
45
|
+
battery
|
46
|
+
carbon_dioxide
|
47
|
+
carbon_monoxide
|
48
|
+
current
|
49
|
+
date
|
50
|
+
energy
|
51
|
+
gas
|
52
|
+
humidity
|
53
|
+
illuminance
|
54
|
+
monetary
|
55
|
+
nitrogen_dioxide
|
56
|
+
nitrogen_monoxide
|
57
|
+
nitrous_oxide
|
58
|
+
ozone
|
59
|
+
pm1
|
60
|
+
pm10
|
61
|
+
pm25
|
62
|
+
power_factor
|
63
|
+
power
|
64
|
+
pressure
|
65
|
+
signal_strength
|
66
|
+
sulphur_dioxide
|
67
|
+
temperature
|
68
|
+
timestamp
|
69
|
+
volatile_organic_compounds
|
70
|
+
voltage
|
71
|
+
].freeze
|
72
|
+
}.freeze
|
73
|
+
STATE_CLASSES = %i[measurement total total_increasing].freeze
|
74
|
+
ON_COMMAND_TYPES = %i[last first brightness].freeze
|
75
|
+
|
76
|
+
# @param property [MQTT::Homie::Property] A Homie property object of datatype :boolean
|
77
|
+
def publish_binary_sensor(
|
78
|
+
property,
|
79
|
+
device_class: nil,
|
80
|
+
expire_after: nil,
|
81
|
+
force_update: false,
|
82
|
+
off_delay: nil,
|
83
|
+
|
84
|
+
device: nil,
|
85
|
+
discovery_prefix: nil,
|
86
|
+
entity_category: nil,
|
87
|
+
icon: nil
|
88
|
+
)
|
89
|
+
raise ArgumentError, "Homie property must be a boolean" unless property.datatype == :boolean
|
90
|
+
if device_class && !DEVICE_CLASSES[:binary_sensor].include?(device_class)
|
91
|
+
raise ArgumentError, "Unrecognized device_class #{device_class.inspect}"
|
92
|
+
end
|
93
|
+
|
94
|
+
config = base_config(property.device,
|
95
|
+
property.full_name,
|
96
|
+
device_class: device_class,
|
97
|
+
device: device,
|
98
|
+
entity_category: entity_category,
|
99
|
+
icon: icon)
|
100
|
+
.merge({
|
101
|
+
payload_off: "false",
|
102
|
+
payload_on: "true",
|
103
|
+
unique_id: "#{property.device.id}_#{property.node.id}_#{property.id}",
|
104
|
+
state_topic: property.topic
|
105
|
+
})
|
106
|
+
config[:expire_after] = expire_after if expire_after
|
107
|
+
config[:force_update] = true if force_update
|
108
|
+
config[:off_delay] = off_delay if off_delay
|
109
|
+
|
110
|
+
publish(property.mqtt, "binary_sensor", config, discovery_prefix: discovery_prefix)
|
111
|
+
end
|
112
|
+
|
113
|
+
def publish_climate(
|
114
|
+
action_property: nil,
|
115
|
+
aux_property: nil,
|
116
|
+
away_mode_property: nil,
|
117
|
+
current_temperature_property: nil,
|
118
|
+
fan_mode_property: nil,
|
119
|
+
mode_property: nil,
|
120
|
+
hold_property: nil,
|
121
|
+
power_property: nil,
|
122
|
+
swing_mode_property: nil,
|
123
|
+
temperature_property: nil,
|
124
|
+
temperature_high_property: nil,
|
125
|
+
temperature_low_property: nil,
|
126
|
+
name: nil,
|
127
|
+
id: nil,
|
128
|
+
precision: nil,
|
129
|
+
temp_step: nil,
|
130
|
+
|
131
|
+
device: nil,
|
132
|
+
discovery_prefix: nil,
|
133
|
+
entity_category: nil,
|
134
|
+
icon: nil,
|
135
|
+
templates: {}
|
136
|
+
)
|
137
|
+
properties = {
|
138
|
+
action: action_property,
|
139
|
+
aux: aux_property,
|
140
|
+
away_mode: away_mode_property,
|
141
|
+
current_temperature: current_temperature_property,
|
142
|
+
fan_mode: fan_mode_property,
|
143
|
+
mode: mode_property,
|
144
|
+
hold: hold_property,
|
145
|
+
power: power_property,
|
146
|
+
swing_mode: swing_mode_property,
|
147
|
+
temperature: temperature_property,
|
148
|
+
temperature_high: temperature_high_property,
|
149
|
+
temperature_low: temperature_low_property
|
150
|
+
}.compact
|
151
|
+
raise ArgumentError, "At least one property must be specified" if properties.empty?
|
152
|
+
raise ArgumentError, "Power property must be a boolean" if power_property && power_property.datatype != :boolean
|
153
|
+
|
154
|
+
node = properties.first.last.node
|
155
|
+
|
156
|
+
config = base_config(node.device,
|
157
|
+
name || node.full_name,
|
158
|
+
device: device,
|
159
|
+
entity_category: entity_category,
|
160
|
+
icon: icon)
|
161
|
+
config[:unique_id] = "#{node.device.id}_#{id || node.id}"
|
162
|
+
properties.each do |prefix, property|
|
163
|
+
add_property(config, property, prefix, templates)
|
164
|
+
end
|
165
|
+
temp_properties = [
|
166
|
+
temperature_property,
|
167
|
+
temperature_high_property,
|
168
|
+
temperature_low_property
|
169
|
+
].compact
|
170
|
+
unless (temp_ranges = temp_properties.map(&:range).compact).empty?
|
171
|
+
config[:min_temp] = temp_ranges.map(&:begin).min
|
172
|
+
config[:max_temp] = temp_ranges.map(&:end).max
|
173
|
+
end
|
174
|
+
temperature_unit = temp_properties.map(&:unit).compact.first
|
175
|
+
config[:temperature_unit] = temperature_unit[-1] if temperature_unit
|
176
|
+
{
|
177
|
+
nil => mode_property,
|
178
|
+
:fan => fan_mode_property,
|
179
|
+
:hold => hold_property,
|
180
|
+
:swing => swing_mode_property
|
181
|
+
}.compact.each do |prefix, property|
|
182
|
+
valid_set = %w[auto off cool heat dry fan_only] if prefix.nil?
|
183
|
+
add_enum(config, property, prefix, valid_set)
|
184
|
+
end
|
185
|
+
config[:precision] = precision if precision
|
186
|
+
config[:temp_step] = temp_step if temp_step
|
187
|
+
if power_property
|
188
|
+
config[:payload_on] = "true"
|
189
|
+
config[:payload_off] = "false"
|
190
|
+
end
|
191
|
+
|
192
|
+
publish(node.mqtt, "climate", config, discovery_prefix: discovery_prefix)
|
193
|
+
end
|
194
|
+
|
195
|
+
def publish_fan(
|
196
|
+
property,
|
197
|
+
oscillation_property: nil,
|
198
|
+
percentage_property: nil,
|
199
|
+
preset_mode_property: nil,
|
200
|
+
|
201
|
+
device: nil,
|
202
|
+
discovery_prefix: nil,
|
203
|
+
entity_category: nil,
|
204
|
+
icon: nil
|
205
|
+
)
|
206
|
+
config = base_config(property.device,
|
207
|
+
name || property.node.full_name,
|
208
|
+
device: device,
|
209
|
+
device_class: device_class,
|
210
|
+
entity_category: entity_category,
|
211
|
+
icon: icon,
|
212
|
+
templates: {})
|
213
|
+
add_property(config, oscillation_property, :oscillation_property, templates)
|
214
|
+
add_property(config, percentage_property, :percentage, templates)
|
215
|
+
if percentage_property&.range
|
216
|
+
config[:speed_range_min] = percentage_property.range.begin
|
217
|
+
config[:speed_range_max] = percentage_property.range.end
|
218
|
+
end
|
219
|
+
add_property(config, preset_mode_property, :preset, templates)
|
220
|
+
add_enum(config, preset_mode_property, :preset)
|
221
|
+
|
222
|
+
publish(node.mqtt, "fan", config, discovery_prefix: discovery_prefix)
|
223
|
+
end
|
224
|
+
|
225
|
+
def publish_humidifier(
|
226
|
+
property,
|
227
|
+
device_class:,
|
228
|
+
target_property:,
|
229
|
+
mode_property: nil,
|
230
|
+
name: nil,
|
231
|
+
id: nil,
|
232
|
+
|
233
|
+
device: nil,
|
234
|
+
discovery_prefix: nil,
|
235
|
+
entity_category: nil,
|
236
|
+
icon: nil
|
237
|
+
)
|
238
|
+
raise ArgumentError, "Homie property must be a boolean" unless property.datatype == :boolean
|
239
|
+
|
240
|
+
unless DEVICE_CLASSES[:humidifier].include?(device_class)
|
241
|
+
raise ArgumentError, "Unrecognized device_class #{device_class.inspect}"
|
242
|
+
end
|
243
|
+
|
244
|
+
config = base_config(property.device,
|
245
|
+
name || property.node.full_name,
|
246
|
+
device: device,
|
247
|
+
device_class: device_class,
|
248
|
+
entity_category: entity_category,
|
249
|
+
icon: icon)
|
250
|
+
.merge({
|
251
|
+
command_topic: "#{property.topic}/set",
|
252
|
+
target_humidity_command_topic: "#{target_property.topic}/set",
|
253
|
+
payload_off: "false",
|
254
|
+
payload_on: "true",
|
255
|
+
unique_id: "#{property.device.id}_#{id || property.node.id}"
|
256
|
+
})
|
257
|
+
add_property(config, property)
|
258
|
+
add_property(config, target_property, :target_humidity)
|
259
|
+
if (range = target_property.range)
|
260
|
+
config[:min_humidity] = range.begin
|
261
|
+
config[:max_humidity] = range.end
|
262
|
+
end
|
263
|
+
add_property(config, mode_property, :mode)
|
264
|
+
add_enum(config, mode_property)
|
265
|
+
|
266
|
+
publish(property.mqtt, "humidifier", config, discovery_prefix: discovery_prefix)
|
267
|
+
end
|
268
|
+
|
269
|
+
# `default` schema only for now
|
270
|
+
def publish_light(
|
271
|
+
property = nil,
|
272
|
+
brightness_property: nil,
|
273
|
+
color_mode_property: nil,
|
274
|
+
color_temp_property: nil,
|
275
|
+
effect_property: nil,
|
276
|
+
hs_property: nil,
|
277
|
+
rgb_property: nil,
|
278
|
+
white_property: nil,
|
279
|
+
xy_property: nil,
|
280
|
+
on_command_type: nil,
|
281
|
+
|
282
|
+
device: nil,
|
283
|
+
discovery_prefix: nil,
|
284
|
+
entity_category: nil,
|
285
|
+
icon: nil,
|
286
|
+
templates: {}
|
287
|
+
)
|
288
|
+
if on_command_type && !ON_COMMAND_TYPES.include?(on_command_type)
|
289
|
+
raise ArgumentError, "Invalid on_command_type #{on_command_type.inspect}"
|
290
|
+
end
|
291
|
+
|
292
|
+
# automatically infer a brightness-only light and adjust config
|
293
|
+
if brightness_property && property.nil?
|
294
|
+
property = brightness_property
|
295
|
+
on_command_type = :brightness
|
296
|
+
end
|
297
|
+
|
298
|
+
config = base_config(property.device,
|
299
|
+
property.full_name,
|
300
|
+
device: device,
|
301
|
+
entity_category: entity_category,
|
302
|
+
icon: icon)
|
303
|
+
add_property(config, property)
|
304
|
+
case property.datatype
|
305
|
+
when :boolean
|
306
|
+
config[:payload_off] = "false"
|
307
|
+
config[:payload_on] = "true"
|
308
|
+
when :integer
|
309
|
+
config[:payload_off] = "0"
|
310
|
+
when :float
|
311
|
+
config[:payload_off] = "0.0"
|
312
|
+
end
|
313
|
+
add_property(config, brightness_property, :brightness, templates)
|
314
|
+
config[:brightness_scale] = brightness_property.range.end if brightness_property&.range
|
315
|
+
add_property(config, color_mode_property, :color_mode, templates)
|
316
|
+
add_property(config, color_temp_property, :color_temp, templates)
|
317
|
+
if color_temp_property&.range && color_temp_property.unit == "mired"
|
318
|
+
config[:min_mireds] = color_temp_property.range.begin
|
319
|
+
config[:max_mireds] = color_temp_property.range.end
|
320
|
+
end
|
321
|
+
add_property(config, effect_property, :effect, templates)
|
322
|
+
config[:effect_list] = effect_property.range if effect_property&.datatype == :enum
|
323
|
+
add_property(config, hs_property, :hs, templates)
|
324
|
+
add_property(config, rgb_property, :rgb, templates)
|
325
|
+
add_property(config, white_property, :white, templates)
|
326
|
+
config[:white_scale] = white_property.range.end if white_property&.range
|
327
|
+
add_property(config, xy_property, :xy, templates)
|
328
|
+
config[:on_command_type] = on_command_type if on_command_type
|
329
|
+
|
330
|
+
publish(property.mqtt, "light", config, discovery_prefix: discovery_prefix)
|
331
|
+
end
|
332
|
+
|
333
|
+
def publish_number(
|
334
|
+
property,
|
335
|
+
step: nil,
|
336
|
+
|
337
|
+
device: nil,
|
338
|
+
discovery_prefix: nil,
|
339
|
+
entity_category: nil,
|
340
|
+
icon: nil
|
341
|
+
)
|
342
|
+
raise ArgumentError, "Homie property must be an integer or a float" unless %i[integer
|
343
|
+
float].include?(property.datatype)
|
344
|
+
|
345
|
+
config = base_config(property.device,
|
346
|
+
property.full_name,
|
347
|
+
device: device,
|
348
|
+
entity_category: entity_category,
|
349
|
+
icon: icon)
|
350
|
+
config[:unique_id] = "#{property.device.id}_#{property.node.id}_#{property.id}"
|
351
|
+
add_property(config, property)
|
352
|
+
config[:unit_of_measurement] = property.unit if property.unit
|
353
|
+
if property.range
|
354
|
+
config[:min] = property.range.begin
|
355
|
+
config[:max] = property.range.end
|
356
|
+
end
|
357
|
+
config[:step] = step if step
|
358
|
+
|
359
|
+
publish(property.mqtt, "number", config, discovery_prefix: discovery_prefix)
|
360
|
+
end
|
361
|
+
|
362
|
+
def publish_scene(
|
363
|
+
property,
|
364
|
+
|
365
|
+
device: nil,
|
366
|
+
discovery_prefix: nil,
|
367
|
+
entity_category: nil,
|
368
|
+
icon: nil
|
369
|
+
)
|
370
|
+
unless property.datatype == :enum && property.range.length == 1
|
371
|
+
raise ArgumentError, "Homie property must be an enum with a single value"
|
372
|
+
end
|
373
|
+
|
374
|
+
config = base_config(property.device,
|
375
|
+
property.full_name,
|
376
|
+
device: device,
|
377
|
+
entity_category: entity_category,
|
378
|
+
icon: icon)
|
379
|
+
config[:unique_id] = "#{property.device.id}_#{property.node.id}_#{property.id}"
|
380
|
+
add_property(config, property)
|
381
|
+
config[:payload_on] = property.range.first
|
382
|
+
|
383
|
+
publish(property.mqtt, "scene", config, discovery_prefix: discovery_prefix)
|
384
|
+
end
|
385
|
+
|
386
|
+
def publish_select(
|
387
|
+
property,
|
388
|
+
|
389
|
+
device: nil,
|
390
|
+
discovery_prefix: nil,
|
391
|
+
entity_category: nil,
|
392
|
+
icon: nil
|
393
|
+
)
|
394
|
+
raise ArgumentError, "Homie property must be an enum" unless property.datatype == :enum
|
395
|
+
raise ArgumentError, "Homie property must be settable" unless property.settable?
|
396
|
+
|
397
|
+
config = base_config(property.device,
|
398
|
+
property.full_name,
|
399
|
+
device: device,
|
400
|
+
entity_category: entity_category,
|
401
|
+
icon: icon)
|
402
|
+
config[:unique_id] = "#{property.device.id}_#{property.node.id}_#{property.id}"
|
403
|
+
add_property(config, property)
|
404
|
+
config[:options] = property.range
|
405
|
+
|
406
|
+
publish(property.mqtt, "select", config, discovery_prefix: discovery_prefix)
|
407
|
+
end
|
408
|
+
|
409
|
+
# @param property [MQTT::Homie::Property] A Homie property object
|
410
|
+
def publish_sensor(
|
411
|
+
property,
|
412
|
+
device_class: nil,
|
413
|
+
expire_after: nil,
|
414
|
+
force_update: false,
|
415
|
+
state_class: nil,
|
416
|
+
|
417
|
+
device: nil,
|
418
|
+
discovery_prefix: nil,
|
419
|
+
entity_category: nil,
|
420
|
+
icon: nil
|
421
|
+
)
|
422
|
+
if device_class && !DEVICE_CLASSES[:sensor].include?(device_class)
|
423
|
+
raise ArgumentError, "Unrecognized device_class #{device_class.inspect}"
|
424
|
+
end
|
425
|
+
if state_class && !STATE_CLASSES.include?(state_class)
|
426
|
+
raise ArgumentError, "Unrecognized state_class #{state_class.inspect}"
|
427
|
+
end
|
428
|
+
|
429
|
+
config = base_config(property.device,
|
430
|
+
property.full_name,
|
431
|
+
device: device,
|
432
|
+
device_class: device_class,
|
433
|
+
entity_category: entity_category,
|
434
|
+
icon: icon)
|
435
|
+
.merge({
|
436
|
+
unique_id: "#{property.device.id}_#{property.node.id}_#{property.id}",
|
437
|
+
state_topic: property.topic
|
438
|
+
})
|
439
|
+
config[:state_class] = state_class if state_class
|
440
|
+
config[:expire_after] = expire_after if expire_after
|
441
|
+
config[:force_update] = true if force_update
|
442
|
+
config[:unit_of_measurement] = property.unit if property.unit
|
443
|
+
|
444
|
+
publish(property.mqtt, "sensor", config, discovery_prefix: discovery_prefix)
|
445
|
+
end
|
446
|
+
|
447
|
+
# @param property [MQTT::Homie::Property] A Homie property object of datatype :boolean
|
448
|
+
def publish_switch(property,
|
449
|
+
device_class: nil,
|
450
|
+
|
451
|
+
device: nil,
|
452
|
+
discovery_prefix: nil,
|
453
|
+
entity_category: nil,
|
454
|
+
icon: nil)
|
455
|
+
raise ArgumentError, "Homie property must be a boolean" unless property.datatype == :boolean
|
456
|
+
|
457
|
+
config = base_config(property.device,
|
458
|
+
property.full_name,
|
459
|
+
device: device,
|
460
|
+
device_class: device_class,
|
461
|
+
entity_category: entity_category,
|
462
|
+
icon: icon)
|
463
|
+
.merge({
|
464
|
+
unique_id: "#{property.device.id}_#{property.node.id}_#{property.id}",
|
465
|
+
payload_off: "false",
|
466
|
+
payload_on: "true"
|
467
|
+
})
|
468
|
+
add_property(config, property)
|
469
|
+
|
470
|
+
publish(property.mqtt, "switch", config, discovery_prefix: discovery_prefix)
|
471
|
+
end
|
472
|
+
|
473
|
+
private
|
474
|
+
|
475
|
+
def add_property(config, property, prefix = nil, templates = {})
|
476
|
+
return unless property
|
477
|
+
|
478
|
+
prefix = "#{prefix}_" if prefix
|
479
|
+
config[:"#{prefix}state_topic"] = property.topic if property.retained?
|
480
|
+
if property.settable?
|
481
|
+
config[:"#{prefix}command_topic"] = "#{property.topic}/set"
|
482
|
+
config[:"#{prefix}command_template"] = "{{ value | round(0) }}" if property.datatype == :integer
|
483
|
+
end
|
484
|
+
config.merge!(templates.slice(:"#{prefix}_template", :"#{prefix}_command_template"))
|
485
|
+
end
|
486
|
+
|
487
|
+
def add_enum(config, property, prefix = nil, valid_set = nil)
|
488
|
+
prefix = "#{prefix}_" if prefix
|
489
|
+
|
490
|
+
return unless property&.datatype == :enum
|
491
|
+
|
492
|
+
modes = property.range
|
493
|
+
modes &= valid_set if valid_set
|
494
|
+
config[:"#{prefix}modes"] = modes
|
495
|
+
end
|
496
|
+
|
497
|
+
def base_config(homie_device,
|
498
|
+
name,
|
499
|
+
device:,
|
500
|
+
entity_category:,
|
501
|
+
icon:,
|
502
|
+
device_class: nil)
|
503
|
+
if entity_category && !ENTITY_CATEGORIES.include?(entity_category)
|
504
|
+
raise ArgumentError, "Unrecognized entity_category #{entity_category.inspect}"
|
505
|
+
end
|
506
|
+
|
507
|
+
config = {
|
508
|
+
name: name,
|
509
|
+
availability_topic: "#{homie_device.topic}/$state",
|
510
|
+
payload_available: "ready",
|
511
|
+
payload_not_available: "lost",
|
512
|
+
qos: 1
|
513
|
+
}
|
514
|
+
config[:device_class] = device_class if device_class
|
515
|
+
config[:entity_category] = entity_category if entity_category
|
516
|
+
config[:icon] = icon if icon
|
517
|
+
|
518
|
+
device = device&.dup || {}
|
519
|
+
device[:name] ||= homie_device.name
|
520
|
+
device[:sw_version] ||= MQTT::Homie::Device::VERSION
|
521
|
+
device[:identifiers] ||= homie_device.id unless device[:connections]
|
522
|
+
config[:device] = device
|
523
|
+
|
524
|
+
config
|
525
|
+
end
|
526
|
+
|
527
|
+
def publish(mqtt, component, config, discovery_prefix:)
|
528
|
+
mqtt.publish("#{discovery_prefix || "homeassistant"}/#{component}/#{config[:unique_id]}/config",
|
529
|
+
config.to_json,
|
530
|
+
retain: true,
|
531
|
+
qos: 1)
|
532
|
+
end
|
533
|
+
end
|
534
|
+
end
|
535
|
+
end
|
metadata
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mqtt-homeassistant
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Cody Cutrer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-12-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: homie-mqtt
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: json
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: byebug
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '11.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '11.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '13.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '13.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.23'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.23'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop-performance
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.12'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.12'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubocop-rake
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.6'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.6'
|
111
|
+
description:
|
112
|
+
email: cody@cutrer.com'
|
113
|
+
executables: []
|
114
|
+
extensions: []
|
115
|
+
extra_rdoc_files: []
|
116
|
+
files:
|
117
|
+
- lib/mqtt-homeassistant.rb
|
118
|
+
- lib/mqtt/home_assistant.rb
|
119
|
+
- lib/mqtt/home_assistant/version.rb
|
120
|
+
homepage: https://github.com/ccutrer/ruby-mqtt-homeassistant
|
121
|
+
licenses:
|
122
|
+
- MIT
|
123
|
+
metadata:
|
124
|
+
rubygems_mfa_required: 'true'
|
125
|
+
post_install_message:
|
126
|
+
rdoc_options: []
|
127
|
+
require_paths:
|
128
|
+
- lib
|
129
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '2.5'
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
requirements: []
|
140
|
+
rubygems_version: 3.1.2
|
141
|
+
signing_key:
|
142
|
+
specification_version: 4
|
143
|
+
summary: Library for publishing device auto-discovery configuration for Home Assistant
|
144
|
+
via MQTT.
|
145
|
+
test_files: []
|