homie-mqtt 1.4.2 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/homie-mqtt.rb +1 -14
- data/lib/mqtt/homie/base.rb +8 -7
- data/lib/mqtt/homie/device.rb +37 -19
- data/lib/mqtt/homie/node.rb +22 -5
- data/lib/mqtt/homie/property.rb +122 -70
- data/lib/mqtt/homie/version.rb +1 -1
- data/lib/mqtt/homie.rb +16 -0
- metadata +68 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac2d4aeded4ffe715b8de38705b648c3aa2c80d378f57435f7e5bd854f8eac22
|
4
|
+
data.tar.gz: d4503b114004ebed3cd4987ecc1466ff0c3e6637d474477fb8f9e43eaf4e91b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 02f74510916e8fb1d0ef8d40b3aea41320e9e12973175fb41b004598ab84038f16df3b171bf0c88e22e8fa894096871de17add5ca5aa37194bbda27e1cadecae
|
7
|
+
data.tar.gz: ffe27a55cf9e3e561a9469b17931b989e589a319b3e9e1aa976641640510bcbabe7f71988688922bd7ce77077f79f50ccf85f742a08d34bd73667bfc93eca5fc
|
data/lib/homie-mqtt.rb
CHANGED
@@ -1,16 +1,3 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
module Homie
|
5
|
-
class << self
|
6
|
-
def escape_id(id)
|
7
|
-
id.downcase.gsub(/[^a-z0-9\-]/, '-').sub(/^[^a-z0-9]+/, '')
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
require 'mqtt/homie/base'
|
14
|
-
require 'mqtt/homie/device'
|
15
|
-
require 'mqtt/homie/node'
|
16
|
-
require 'mqtt/homie/property'
|
3
|
+
require "mqtt/homie"
|
data/lib/mqtt/homie/base.rb
CHANGED
@@ -9,18 +9,19 @@ module MQTT
|
|
9
9
|
|
10
10
|
def initialize(id, name)
|
11
11
|
raise ArgumentError, "Invalid Homie ID '#{id}'" unless id.is_a?(String) && id =~ Regexp.new("^#{REGEX}$")
|
12
|
+
|
12
13
|
@id = id
|
13
14
|
@name = name
|
14
15
|
end
|
15
16
|
|
16
17
|
def name=(value)
|
17
|
-
if name
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
18
|
+
return if name == value
|
19
|
+
|
20
|
+
name = value
|
21
|
+
return unless @published
|
22
|
+
|
23
|
+
device.init do
|
24
|
+
mqtt.publish("#{topic}/$name", name, retain: true, qos: 1)
|
24
25
|
end
|
25
26
|
end
|
26
27
|
end
|
data/lib/mqtt/homie/device.rb
CHANGED
@@ -1,28 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "mqtt"
|
4
|
+
require "ruby2_keywords"
|
4
5
|
|
5
6
|
module MQTT
|
6
7
|
module Homie
|
7
8
|
class Device < Base
|
9
|
+
# the Homie spec version
|
10
|
+
VERSION = "4.0.0"
|
11
|
+
|
8
12
|
attr_reader :root_topic, :state, :mqtt
|
13
|
+
attr_accessor :logger, :out_of_band_topic_proc
|
9
14
|
|
10
15
|
def initialize(id, name, root_topic: nil, mqtt: nil, clear_topics: true, &block)
|
11
16
|
super(id, name)
|
12
|
-
@root_topic =
|
17
|
+
@root_topic = root_topic || "homie"
|
13
18
|
@state = :init
|
14
19
|
@nodes = {}
|
15
20
|
@published = false
|
16
|
-
@
|
21
|
+
@out_of_band_topic_proc = block
|
17
22
|
mqtt = MQTT::Client.new(mqtt) if mqtt.is_a?(String)
|
18
23
|
@mqtt = mqtt || MQTT::Client.new
|
19
24
|
@mqtt.set_will("#{topic}/$state", "lost", retain: true, qos: 1)
|
20
25
|
|
21
26
|
@mqtt.on_reconnect do
|
22
27
|
each do |node|
|
23
|
-
node.each
|
24
|
-
property.subscribe
|
25
|
-
end
|
28
|
+
node.each(&:subscribe)
|
26
29
|
end
|
27
30
|
mqtt.publish("#{topic}/$state", :init, retain: true, qos: 1)
|
28
31
|
mqtt.publish("#{topic}/$state", state, retain: true, qos: 1) unless state == :init
|
@@ -32,6 +35,10 @@ module MQTT
|
|
32
35
|
self.clear_topics if clear_topics
|
33
36
|
end
|
34
37
|
|
38
|
+
def inspect
|
39
|
+
"#<MQTT::Homie::Device #{topic} name=#{name.inspect}, $state=#{state.inspect}>"
|
40
|
+
end
|
41
|
+
|
35
42
|
def device
|
36
43
|
self
|
37
44
|
end
|
@@ -40,11 +47,11 @@ module MQTT
|
|
40
47
|
"#{root_topic}/#{id}"
|
41
48
|
end
|
42
49
|
|
43
|
-
def node(id, *args
|
50
|
+
ruby2_keywords def node(id, *args)
|
44
51
|
raise ArgumentError, "Node '#{id}' already exists" if @nodes.key?(id)
|
45
52
|
|
46
53
|
init do |prior_state|
|
47
|
-
node = Node.new(self, id, *args
|
54
|
+
node = Node.new(self, id, *args)
|
48
55
|
|
49
56
|
@nodes[id] = node
|
50
57
|
yield node if block_given?
|
@@ -58,10 +65,11 @@ module MQTT
|
|
58
65
|
|
59
66
|
def remove_node(id)
|
60
67
|
return false unless (node = @nodes[id])
|
68
|
+
|
61
69
|
init do
|
62
70
|
node.unpublish
|
63
71
|
@nodes.delete(id)
|
64
|
-
mqtt.publish("#{topic}/$nodes", @nodes.keys.join(","), retain: true, qos: 1) if
|
72
|
+
mqtt.publish("#{topic}/$nodes", @nodes.keys.join(","), retain: true, qos: 1) if published?
|
65
73
|
end
|
66
74
|
true
|
67
75
|
end
|
@@ -74,11 +82,19 @@ module MQTT
|
|
74
82
|
@nodes.each_value(&block)
|
75
83
|
end
|
76
84
|
|
85
|
+
def count
|
86
|
+
@nodes.count
|
87
|
+
end
|
88
|
+
|
89
|
+
def published?
|
90
|
+
@published
|
91
|
+
end
|
92
|
+
|
77
93
|
def publish
|
78
|
-
return if
|
94
|
+
return if published?
|
79
95
|
|
80
96
|
mqtt.batch_publish do
|
81
|
-
mqtt.publish("#{topic}/$homie",
|
97
|
+
mqtt.publish("#{topic}/$homie", VERSION, retain: true, qos: 1)
|
82
98
|
mqtt.publish("#{topic}/$name", name, retain: true, qos: 1)
|
83
99
|
mqtt.publish("#{topic}/$state", @state.to_s, retain: true, qos: 1)
|
84
100
|
|
@@ -87,12 +103,13 @@ module MQTT
|
|
87
103
|
Thread.current.report_on_exception = false
|
88
104
|
|
89
105
|
mqtt.get do |packet|
|
106
|
+
logger&.debug("received packet at #{packet.topic} with payload #{packet.payload.inspect}")
|
90
107
|
match = packet.topic.match(topic_regex)
|
91
108
|
node = @nodes[match[:node]] if match
|
92
109
|
property = node[match[:property]] if node
|
93
110
|
|
94
111
|
unless property&.settable?
|
95
|
-
@
|
112
|
+
@out_of_band_topic_proc&.call(packet.topic, packet.payload)
|
96
113
|
next
|
97
114
|
end
|
98
115
|
|
@@ -102,6 +119,9 @@ module MQTT
|
|
102
119
|
|
103
120
|
mqtt.publish("#{topic}/$nodes", @nodes.keys.join(","), retain: true, qos: 1)
|
104
121
|
@nodes.each_value(&:publish)
|
122
|
+
|
123
|
+
yield if block_given?
|
124
|
+
|
105
125
|
mqtt.publish("#{topic}/$state", (@state = :ready).to_s, retain: true, qos: 1)
|
106
126
|
end
|
107
127
|
|
@@ -122,26 +142,24 @@ module MQTT
|
|
122
142
|
end
|
123
143
|
|
124
144
|
def init
|
125
|
-
if state == :init
|
126
|
-
return yield state
|
127
|
-
end
|
145
|
+
return yield state if state == :init
|
128
146
|
|
129
147
|
prior_state = state
|
130
|
-
mqtt.publish("#{topic}/$state", (state = :init).to_s, retain: true, qos: 1)
|
148
|
+
mqtt.publish("#{topic}/$state", (@state = :init).to_s, retain: true, qos: 1)
|
131
149
|
result = nil
|
132
150
|
mqtt.batch_publish do
|
133
151
|
result = yield prior_state
|
134
152
|
end
|
135
|
-
mqtt.publish("#{topic}/$state", (state = :ready).to_s, retain: true, qos: 1)
|
153
|
+
mqtt.publish("#{topic}/$state", (@state = :ready).to_s, retain: true, qos: 1)
|
136
154
|
result
|
137
155
|
end
|
138
156
|
|
139
157
|
def clear_topics
|
140
|
-
raise ArgumentError, "cannot clear topics once published" if
|
158
|
+
raise ArgumentError, "cannot clear topics once published" if published?
|
141
159
|
|
142
160
|
@mqtt.subscribe("#{topic}/#")
|
143
161
|
@mqtt.unsubscribe("#{topic}/#", wait_for_ack: true)
|
144
|
-
|
162
|
+
until @mqtt.queue_empty?
|
145
163
|
packet = @mqtt.get
|
146
164
|
@mqtt.publish(packet.topic, retain: true, qos: 0)
|
147
165
|
end
|
data/lib/mqtt/homie/node.rb
CHANGED
@@ -13,14 +13,25 @@ module MQTT
|
|
13
13
|
@published = false
|
14
14
|
end
|
15
15
|
|
16
|
+
def inspect
|
17
|
+
"#<MQTT::Homie::Node #{topic} name=#{full_name.inspect}, type=#{type.inspect}>"
|
18
|
+
end
|
19
|
+
|
20
|
+
def full_name
|
21
|
+
return name if device.count == 1
|
22
|
+
|
23
|
+
"#{device.name} #{name}"
|
24
|
+
end
|
25
|
+
|
16
26
|
def topic
|
17
27
|
"#{device.topic}/#{id}"
|
18
28
|
end
|
19
29
|
|
20
|
-
def property(*args,
|
30
|
+
ruby2_keywords def property(*args, &block)
|
21
31
|
device.init do |prior_state|
|
22
|
-
property = Property.new(self, *args,
|
32
|
+
property = Property.new(self, *args, &block)
|
23
33
|
raise ArgumentError, "Property '#{property.id}' already exists on '#{id}'" if @properties.key?(property.id)
|
34
|
+
|
24
35
|
@properties[property.id] = property
|
25
36
|
property.publish if prior_state == :ready
|
26
37
|
property
|
@@ -29,10 +40,11 @@ module MQTT
|
|
29
40
|
|
30
41
|
def remove_property(id)
|
31
42
|
return false unless (property = @properties[id])
|
43
|
+
|
32
44
|
init do
|
33
45
|
property.unpublish
|
34
46
|
@properties.delete(id)
|
35
|
-
mqtt.publish("#{topic}/$properties", @properties.keys.join(","), retain: true, qos: 1) if
|
47
|
+
mqtt.publish("#{topic}/$properties", @properties.keys.join(","), retain: true, qos: 1) if published?
|
36
48
|
end
|
37
49
|
true
|
38
50
|
end
|
@@ -58,9 +70,13 @@ module MQTT
|
|
58
70
|
end
|
59
71
|
end
|
60
72
|
|
73
|
+
def published?
|
74
|
+
@published
|
75
|
+
end
|
76
|
+
|
61
77
|
def publish
|
62
78
|
mqtt.batch_publish do
|
63
|
-
unless
|
79
|
+
unless published?
|
64
80
|
mqtt.publish("#{topic}/$name", name, retain: true, qos: 1)
|
65
81
|
mqtt.publish("#{topic}/$type", @type.to_s, retain: true, qos: 1)
|
66
82
|
@published = true
|
@@ -72,7 +88,8 @@ module MQTT
|
|
72
88
|
end
|
73
89
|
|
74
90
|
def unpublish
|
75
|
-
return unless
|
91
|
+
return unless published?
|
92
|
+
|
76
93
|
@published = false
|
77
94
|
|
78
95
|
mqtt.publish("#{topic}/$name", retain: true, qos: 0)
|
data/lib/mqtt/homie/property.rb
CHANGED
@@ -5,33 +5,61 @@ module MQTT
|
|
5
5
|
class Property < Base
|
6
6
|
attr_reader :node, :datatype, :format, :unit, :value
|
7
7
|
|
8
|
-
def initialize(node,
|
9
|
-
|
8
|
+
def initialize(node,
|
9
|
+
id,
|
10
|
+
name,
|
11
|
+
datatype,
|
12
|
+
value = nil,
|
13
|
+
format: nil,
|
14
|
+
retained: true,
|
15
|
+
unit: nil,
|
16
|
+
non_standard_value_check: nil,
|
17
|
+
&block)
|
18
|
+
raise ArgumentError, "Invalid Homie datatype" unless %i[string
|
19
|
+
integer
|
20
|
+
float
|
21
|
+
boolean
|
22
|
+
enum
|
23
|
+
color
|
24
|
+
datetime
|
25
|
+
duration].include?(datatype)
|
10
26
|
raise ArgumentError, "retained must be boolean" unless [true, false].include?(retained)
|
11
|
-
format = format.join(",") if format.is_a?(Array) && datatype == :enum
|
12
|
-
if %i{integer float}.include?(datatype) && format.is_a?(Range)
|
13
|
-
raise ArgumentError "only inclusive ranges are supported" if format.exclude_end?
|
14
|
-
format = "#{format.begin}:#{format.end}"
|
15
|
-
end
|
16
|
-
raise ArgumentError, "format must be nil or a string" unless format.nil? || format.is_a?(String)
|
17
27
|
raise ArgumentError, "unit must be nil or a string" unless unit.nil? || unit.is_a?(String)
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
raise ArgumentError, "an initial value cannot be provided for a non-retained property" if !value.nil? && !retained
|
28
|
+
if !value.nil? && !retained
|
29
|
+
raise ArgumentError, "an initial value cannot be provided for a non-retained property"
|
30
|
+
end
|
22
31
|
|
23
32
|
super(id, name)
|
24
33
|
|
25
34
|
@node = node
|
26
35
|
@datatype = datatype
|
27
|
-
|
36
|
+
self.format = format
|
28
37
|
@retained = retained
|
29
38
|
@unit = unit
|
30
39
|
@value = value
|
31
40
|
@published = false
|
41
|
+
@non_standard_value_check = non_standard_value_check
|
32
42
|
@block = block
|
33
43
|
end
|
34
44
|
|
45
|
+
def inspect
|
46
|
+
result = +"#<MQTT::Homie::Property #{topic} name=#{full_name.inspect}, datatype=#{datatype.inspect}"
|
47
|
+
result << ", format=#{format.inspect}" if format
|
48
|
+
result << ", unit=#{unit.inspect}" if unit
|
49
|
+
result << ", settable=true" if settable?
|
50
|
+
result << if retained?
|
51
|
+
", value=#{value.inspect}"
|
52
|
+
else
|
53
|
+
", retained=false"
|
54
|
+
end
|
55
|
+
result << ">"
|
56
|
+
result.freeze
|
57
|
+
end
|
58
|
+
|
59
|
+
def full_name
|
60
|
+
"#{node.full_name} #{name}"
|
61
|
+
end
|
62
|
+
|
35
63
|
def device
|
36
64
|
node.device
|
37
65
|
end
|
@@ -49,89 +77,110 @@ module MQTT
|
|
49
77
|
end
|
50
78
|
|
51
79
|
def value=(value)
|
52
|
-
if @value
|
53
|
-
|
54
|
-
|
55
|
-
|
80
|
+
return if @value == value
|
81
|
+
|
82
|
+
@value = value if retained?
|
83
|
+
publish_value if published?
|
56
84
|
end
|
57
85
|
|
58
86
|
def unit=(unit)
|
59
|
-
if unit
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
87
|
+
return if unit == @unit
|
88
|
+
|
89
|
+
@unit = unit
|
90
|
+
return unless published?
|
91
|
+
|
92
|
+
device.init do
|
93
|
+
mqtt.publish("#{topic}/$unit", unit.to_s, retain: true, qos: 1)
|
66
94
|
end
|
67
95
|
end
|
68
96
|
|
69
97
|
def format=(format)
|
70
|
-
if format
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
end
|
98
|
+
return if format == @format
|
99
|
+
|
100
|
+
format = format.join(",") if format.is_a?(Array) && datatype == :enum
|
101
|
+
if %i[integer float].include?(datatype) && format.is_a?(Range)
|
102
|
+
raise ArgumentError, "only inclusive ranges are supported" if format.last.is_a?(Float) && format.exclude_end?
|
103
|
+
|
104
|
+
last = format.end
|
105
|
+
last -= 1 if format.exclude_end?
|
106
|
+
|
107
|
+
format = "#{format.begin}:#{last}"
|
108
|
+
end
|
109
|
+
raise ArgumentError, "format must be nil or a string" unless format.nil? || format.is_a?(String)
|
110
|
+
raise ArgumentError, "format is required for enums" if datatype == :enum && format.nil?
|
111
|
+
raise ArgumentError, "format is required for colors" if datatype == :color && format.nil?
|
112
|
+
if datatype == :color && !%w[rgb hsv].include?(format.to_s)
|
113
|
+
raise ArgumentError, "format must be either rgb or hsv for colors"
|
114
|
+
end
|
115
|
+
|
116
|
+
@format = format
|
117
|
+
return unless published?
|
118
|
+
|
119
|
+
device.init do
|
120
|
+
mqtt.publish("#{topic}/$format", format.to_s, retain: true, qos: 1)
|
77
121
|
end
|
78
122
|
end
|
79
123
|
|
80
124
|
def range
|
125
|
+
return nil unless format
|
126
|
+
|
81
127
|
case datatype
|
82
|
-
when :enum
|
83
|
-
when :integer
|
84
|
-
when :float
|
128
|
+
when :enum then format.split(",")
|
129
|
+
when :integer then Range.new(*format.split(":").map(&:to_i))
|
130
|
+
when :float then Range.new(*format.split(":").map(&:to_f))
|
85
131
|
else; raise MethodNotImplemented
|
86
132
|
end
|
87
133
|
end
|
88
134
|
|
89
135
|
def set(value)
|
136
|
+
casted_value = case datatype
|
137
|
+
when :boolean
|
138
|
+
%w[true false].include?(value) ? value == "true" : nil
|
139
|
+
when :integer
|
140
|
+
/^-?\d+$/.match?(value) && value.to_i
|
141
|
+
when :float
|
142
|
+
/^-?(?:\d+|\d+\.|\.\d+|\d+\.\d+)(?:[eE]-?\d+)?$/.match?(value) && value.to_f
|
143
|
+
when :enum
|
144
|
+
value
|
145
|
+
when :color
|
146
|
+
/^\d{1,3},\d{1,3},\d{1,3}$/.match?(value) && value = value.split(",").map(&:to_i)
|
147
|
+
when :datetime
|
148
|
+
begin
|
149
|
+
value = Time.parse(value)
|
150
|
+
rescue ArgumentError
|
151
|
+
nil
|
152
|
+
end
|
153
|
+
when :duration
|
154
|
+
begin
|
155
|
+
value = ActiveSupport::Duration.parse(value)
|
156
|
+
rescue ActiveSupport::Duration::ISO8601Parser::ParsingError
|
157
|
+
nil
|
158
|
+
end
|
159
|
+
end
|
90
160
|
case datatype
|
91
|
-
when :
|
92
|
-
|
93
|
-
value = value == 'true'
|
94
|
-
when :integer
|
95
|
-
return unless value =~ /^-?\d+$/
|
96
|
-
value = value.to_i
|
97
|
-
return unless range.include?(value) if format
|
98
|
-
when :float
|
99
|
-
return unless value =~ /^-?(?:\d+|\d+\.|\.\d+|\d+\.\d+)(?:[eE]-?\d+)?$/
|
100
|
-
value = value.to_f
|
101
|
-
return unless range.include?(value) if format
|
102
|
-
when :enum
|
103
|
-
return unless range.include?(value)
|
161
|
+
when :integer, :float, :enum
|
162
|
+
casted_value = nil if format && !range.include?(casted_value)
|
104
163
|
when :color
|
105
|
-
|
106
|
-
|
107
|
-
if format == 'rgb'
|
108
|
-
return if value.max > 255
|
109
|
-
elsif format == 'hsv'
|
110
|
-
return if value.first > 360 || value[1..2].max > 100
|
111
|
-
end
|
112
|
-
when :datetime
|
113
|
-
begin
|
114
|
-
value = Time.parse(value)
|
115
|
-
rescue ArgumentError
|
116
|
-
return
|
117
|
-
end
|
118
|
-
when :duration
|
119
|
-
begin
|
120
|
-
value = ActiveSupport::Duration.parse(value)
|
121
|
-
rescue ActiveSupport::Duration::ISO8601Parser::ParsingError
|
122
|
-
return
|
123
|
-
end
|
164
|
+
casted_value = nil if (format == "rgb" && value.max > 255) ||
|
165
|
+
(format == "hsb" && (value.first > 360 || value[1..2].max > 100))
|
124
166
|
end
|
125
167
|
|
126
|
-
|
168
|
+
casted_value = @non_standard_value_check&.call(value) if casted_value.nil?
|
169
|
+
return if casted_value.nil?
|
170
|
+
|
171
|
+
@block.arity == 2 ? @block.call(casted_value, self) : @block.call(casted_value)
|
127
172
|
end
|
128
173
|
|
129
174
|
def mqtt
|
130
175
|
node.mqtt
|
131
176
|
end
|
132
177
|
|
178
|
+
def published?
|
179
|
+
@published
|
180
|
+
end
|
181
|
+
|
133
182
|
def publish
|
134
|
-
return if
|
183
|
+
return if published?
|
135
184
|
|
136
185
|
mqtt.batch_publish do
|
137
186
|
mqtt.publish("#{topic}/$name", name, retain: true, qos: 1)
|
@@ -152,7 +201,8 @@ module MQTT
|
|
152
201
|
end
|
153
202
|
|
154
203
|
def unpublish
|
155
|
-
return unless
|
204
|
+
return unless published?
|
205
|
+
|
156
206
|
@published = false
|
157
207
|
|
158
208
|
mqtt.publish("#{topic}/$name", retain: true, qos: 0)
|
@@ -170,8 +220,10 @@ module MQTT
|
|
170
220
|
def publish_value
|
171
221
|
serialized = value
|
172
222
|
serialized = serialized&.iso8601 if %i[datetime duration].include?(datatype)
|
223
|
+
serialized = serialized.to_s
|
173
224
|
|
174
|
-
|
225
|
+
node.device.logger&.debug("publishing #{serialized.inspect} to #{topic}")
|
226
|
+
mqtt.publish(topic, serialized, retain: retained?, qos: 1)
|
175
227
|
end
|
176
228
|
end
|
177
229
|
end
|
data/lib/mqtt/homie/version.rb
CHANGED
data/lib/mqtt/homie.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MQTT
|
4
|
+
module Homie
|
5
|
+
class << self
|
6
|
+
def escape_id(id)
|
7
|
+
id.downcase.gsub(/[^a-z0-9\-]/, "-").sub(/^[^a-z0-9]+/, "")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
require "mqtt/homie/base"
|
14
|
+
require "mqtt/homie/device"
|
15
|
+
require "mqtt/homie/node"
|
16
|
+
require "mqtt/homie/property"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: homie-mqtt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cody Cutrer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mqtt-ccutrer
|
@@ -17,6 +17,9 @@ dependencies:
|
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.0'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.0.1
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -24,6 +27,23 @@ dependencies:
|
|
24
27
|
- - "~>"
|
25
28
|
- !ruby/object:Gem::Version
|
26
29
|
version: '1.0'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.0.1
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: ruby2_keywords
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 0.0.5
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 0.0.5
|
27
47
|
- !ruby/object:Gem::Dependency
|
28
48
|
name: byebug
|
29
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +72,48 @@ dependencies:
|
|
52
72
|
- - "~>"
|
53
73
|
- !ruby/object:Gem::Version
|
54
74
|
version: '13.0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: rubocop
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '1.23'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '1.23'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: rubocop-performance
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '1.12'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '1.12'
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: rubocop-rake
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0.6'
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - "~>"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0.6'
|
55
117
|
description:
|
56
118
|
email: cody@cutrer.com'
|
57
119
|
executables: []
|
@@ -59,6 +121,7 @@ extensions: []
|
|
59
121
|
extra_rdoc_files: []
|
60
122
|
files:
|
61
123
|
- lib/homie-mqtt.rb
|
124
|
+
- lib/mqtt/homie.rb
|
62
125
|
- lib/mqtt/homie/base.rb
|
63
126
|
- lib/mqtt/homie/device.rb
|
64
127
|
- lib/mqtt/homie/node.rb
|
@@ -67,7 +130,8 @@ files:
|
|
67
130
|
homepage: https://github.com/ccutrer/homie-mqtt
|
68
131
|
licenses:
|
69
132
|
- MIT
|
70
|
-
metadata:
|
133
|
+
metadata:
|
134
|
+
rubygems_mfa_required: 'true'
|
71
135
|
post_install_message:
|
72
136
|
rdoc_options: []
|
73
137
|
require_paths:
|
@@ -76,7 +140,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
76
140
|
requirements:
|
77
141
|
- - ">="
|
78
142
|
- !ruby/object:Gem::Version
|
79
|
-
version: '
|
143
|
+
version: '2.5'
|
80
144
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
145
|
requirements:
|
82
146
|
- - ">="
|