homie-mqtt 1.4.2 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
- - ">="
|