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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: df54d2ae01eb1d1972e4d0f5fb40d05286969feff5ad83547476be6d11db05e2
4
- data.tar.gz: 719a2c270af518fd2ee7d7da4941a211da1f4af90d1e5f0daae2a0c50fd1616f
3
+ metadata.gz: ac2d4aeded4ffe715b8de38705b648c3aa2c80d378f57435f7e5bd854f8eac22
4
+ data.tar.gz: d4503b114004ebed3cd4987ecc1466ff0c3e6637d474477fb8f9e43eaf4e91b0
5
5
  SHA512:
6
- metadata.gz: 19fdcadf299dbe73d3bafca37e32d65b27edb006569ae80f27ecae036e6da17370c9e1b0af405f0517fd6649f5cc0c5bcb75912f00ec2560971d17385502408f
7
- data.tar.gz: b92d4b4cb05cc96b1a4b0d7e0254476f05db8be89f48d969277bbb09ae56cfcc7e597f5f9ccede42f5279d034bda7a85fe36ad1d652155cf3e38aac961c02667
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
- 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'
3
+ require "mqtt/homie"
@@ -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 != value
18
- name = value
19
- if @published
20
- device.init do
21
- mqtt.publish("#{topic}/$name", name, retain: true, qos: 1)
22
- end
23
- end
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
@@ -1,28 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'mqtt'
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 = @root_topic || "homie"
17
+ @root_topic = root_topic || "homie"
13
18
  @state = :init
14
19
  @nodes = {}
15
20
  @published = false
16
- @block = block
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 do |property|
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, **kwargs)
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, **kwargs)
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 @published
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 @published
94
+ return if published?
79
95
 
80
96
  mqtt.batch_publish do
81
- mqtt.publish("#{topic}/$homie", "4.0.0", retain: true, qos: 1)
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
- @block&.call(packet.topic, packet.payload)
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 @published
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
- while !@mqtt.queue_empty?
162
+ until @mqtt.queue_empty?
145
163
  packet = @mqtt.get
146
164
  @mqtt.publish(packet.topic, retain: true, qos: 0)
147
165
  end
@@ -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, **kwargs, &block)
30
+ ruby2_keywords def property(*args, &block)
21
31
  device.init do |prior_state|
22
- property = Property.new(self, *args, **kwargs, &block)
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 @published
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 @published
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 @published
91
+ return unless published?
92
+
76
93
  @published = false
77
94
 
78
95
  mqtt.publish("#{topic}/$name", retain: true, qos: 0)
@@ -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, id, name, datatype, value = nil, format: nil, retained: true, unit: nil, &block)
9
- raise ArgumentError, "Invalid Homie datatype" unless %i[string integer float boolean enum color datetime duration].include?(datatype)
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
- raise ArgumentError, "format is required for enums" if datatype == :enum && format.nil?
19
- raise ArgumentError, "format is required for colors" if datatype == :color && format.nil?
20
- raise ArgumentError, "format must be either rgb or hsv for colors" if datatype == :color && !%w{rgb hsv}.include?(format.to_s)
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
- @format = format
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 != value
53
- @value = value if retained?
54
- publish_value if @published
55
- end
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 != @unit
60
- @unit = unit
61
- if @published
62
- device.init do
63
- mqtt.publish("#{topic}/$unit", unit.to_s, retain: true, qos: 1)
64
- end
65
- end
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 != @format
71
- @format = format
72
- if @published
73
- device.init do
74
- mqtt.publish("#{topic}/$format", format.to_s, retain: true, qos: 1)
75
- end
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; format.split(',')
83
- when :integer; Range.new(*format.split(':').map(&:to_i))
84
- when :float; Range.new(*format.split(':').map(&:to_f))
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 :boolean
92
- return unless %w{true false}.include?(value)
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
- return unless value =~ /^\d{1,3},\d{1,3},\d{1,3}$/
106
- value = value.split(',').map(&:to_i)
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
- @block.arity == 2 ? @block.call(value, self) : @block.call(value)
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 @published
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 @published
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
- mqtt.publish(topic, serialized.to_s, retain: retained?, qos: 1)
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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module MQTT
4
4
  module Homie
5
- VERSION = '1.4.2'
5
+ VERSION = "1.6.0"
6
6
  end
7
7
  end
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.2
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-08-26 00:00:00.000000000 Z
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: '0'
143
+ version: '2.5'
80
144
  required_rubygems_version: !ruby/object:Gem::Requirement
81
145
  requirements:
82
146
  - - ">="