homie-mqtt 1.5.0 → 1.6.0

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: 8552d2aca44043208c3b3cd06fff9d5376515103d7de423926713441acecd6e0
4
- data.tar.gz: a27b5fe2fe50e2975708c308ed9a0f9b5b7d2469667741fe092210adcda8582a
3
+ metadata.gz: ac2d4aeded4ffe715b8de38705b648c3aa2c80d378f57435f7e5bd854f8eac22
4
+ data.tar.gz: d4503b114004ebed3cd4987ecc1466ff0c3e6637d474477fb8f9e43eaf4e91b0
5
5
  SHA512:
6
- metadata.gz: b10c773d61781b4fb2e5595056e1b5e41373ec579bcf0a152f0c5dc763c3973ad09914964caaaf9c619b079e6cf15f4dc923122caf214f571741b8b6934a8317
7
- data.tar.gz: dd8069070124dea54d81f3fc0095b9cce1d28d77ed655d7162182c0a11cdfecbb93cc40c97ea3778b3ebd35508cf960fdfcdd2594cac87f3621fdf11e64845c0
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"
@@ -69,7 +69,7 @@ module MQTT
69
69
  init do
70
70
  node.unpublish
71
71
  @nodes.delete(id)
72
- 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?
73
73
  end
74
74
  true
75
75
  end
@@ -86,8 +86,12 @@ module MQTT
86
86
  @nodes.count
87
87
  end
88
88
 
89
+ def published?
90
+ @published
91
+ end
92
+
89
93
  def publish
90
- return if @published
94
+ return if published?
91
95
 
92
96
  mqtt.batch_publish do
93
97
  mqtt.publish("#{topic}/$homie", VERSION, retain: true, qos: 1)
@@ -141,17 +145,17 @@ module MQTT
141
145
  return yield state if state == :init
142
146
 
143
147
  prior_state = state
144
- mqtt.publish("#{topic}/$state", (self.state = :init).to_s, retain: true, qos: 1)
148
+ mqtt.publish("#{topic}/$state", (@state = :init).to_s, retain: true, qos: 1)
145
149
  result = nil
146
150
  mqtt.batch_publish do
147
151
  result = yield prior_state
148
152
  end
149
- mqtt.publish("#{topic}/$state", (self.state = :ready).to_s, retain: true, qos: 1)
153
+ mqtt.publish("#{topic}/$state", (@state = :ready).to_s, retain: true, qos: 1)
150
154
  result
151
155
  end
152
156
 
153
157
  def clear_topics
154
- raise ArgumentError, "cannot clear topics once published" if @published
158
+ raise ArgumentError, "cannot clear topics once published" if published?
155
159
 
156
160
  @mqtt.subscribe("#{topic}/#")
157
161
  @mqtt.unsubscribe("#{topic}/#", wait_for_ack: true)
@@ -44,7 +44,7 @@ module MQTT
44
44
  init do
45
45
  property.unpublish
46
46
  @properties.delete(id)
47
- 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?
48
48
  end
49
49
  true
50
50
  end
@@ -70,9 +70,13 @@ module MQTT
70
70
  end
71
71
  end
72
72
 
73
+ def published?
74
+ @published
75
+ end
76
+
73
77
  def publish
74
78
  mqtt.batch_publish do
75
- unless @published
79
+ unless published?
76
80
  mqtt.publish("#{topic}/$name", name, retain: true, qos: 1)
77
81
  mqtt.publish("#{topic}/$type", @type.to_s, retain: true, qos: 1)
78
82
  @published = true
@@ -84,7 +88,7 @@ module MQTT
84
88
  end
85
89
 
86
90
  def unpublish
87
- return unless @published
91
+ return unless published?
88
92
 
89
93
  @published = false
90
94
 
@@ -5,24 +5,26 @@ 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
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
10
25
  duration].include?(datatype)
11
26
  raise ArgumentError, "retained must be boolean" unless [true, false].include?(retained)
12
-
13
- format = format.join(",") if format.is_a?(Array) && datatype == :enum
14
- if %i[integer float].include?(datatype) && format.is_a?(Range)
15
- raise ArgumentError "only inclusive ranges are supported" if format.exclude_end?
16
-
17
- format = "#{format.begin}:#{format.end}"
18
- end
19
- raise ArgumentError, "format must be nil or a string" unless format.nil? || format.is_a?(String)
20
27
  raise ArgumentError, "unit must be nil or a string" unless unit.nil? || unit.is_a?(String)
21
- raise ArgumentError, "format is required for enums" if datatype == :enum && format.nil?
22
- raise ArgumentError, "format is required for colors" if datatype == :color && format.nil?
23
- if datatype == :color && !%w[rgb hsv].include?(format.to_s)
24
- raise ArgumentError, "format must be either rgb or hsv for colors"
25
- end
26
28
  if !value.nil? && !retained
27
29
  raise ArgumentError, "an initial value cannot be provided for a non-retained property"
28
30
  end
@@ -31,11 +33,12 @@ module MQTT
31
33
 
32
34
  @node = node
33
35
  @datatype = datatype
34
- @format = format
36
+ self.format = format
35
37
  @retained = retained
36
38
  @unit = unit
37
39
  @value = value
38
40
  @published = false
41
+ @non_standard_value_check = non_standard_value_check
39
42
  @block = block
40
43
  end
41
44
 
@@ -77,14 +80,14 @@ module MQTT
77
80
  return if @value == value
78
81
 
79
82
  @value = value if retained?
80
- publish_value if @published
83
+ publish_value if published?
81
84
  end
82
85
 
83
86
  def unit=(unit)
84
87
  return if unit == @unit
85
88
 
86
89
  @unit = unit
87
- return unless @published
90
+ return unless published?
88
91
 
89
92
  device.init do
90
93
  mqtt.publish("#{topic}/$unit", unit.to_s, retain: true, qos: 1)
@@ -94,8 +97,24 @@ module MQTT
94
97
  def format=(format)
95
98
  return if format == @format
96
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
+
97
116
  @format = format
98
- return unless @published
117
+ return unless published?
99
118
 
100
119
  device.init do
101
120
  mqtt.publish("#{topic}/$format", format.to_s, retain: true, qos: 1)
@@ -114,56 +133,54 @@ module MQTT
114
133
  end
115
134
 
116
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
117
160
  case datatype
118
- when :boolean
119
- return unless %w[true false].include?(value)
120
-
121
- value = value == "true"
122
- when :integer
123
- return unless /^-?\d+$/.match?(value)
124
-
125
- value = value.to_i
126
- return if format && !range.include?(value)
127
- when :float
128
- return unless /^-?(?:\d+|\d+\.|\.\d+|\d+\.\d+)(?:[eE]-?\d+)?$/.match?(value)
129
-
130
- value = value.to_f
131
- return if format && !range.include?(value)
132
- when :enum
133
- return unless range.include?(value)
161
+ when :integer, :float, :enum
162
+ casted_value = nil if format && !range.include?(casted_value)
134
163
  when :color
135
- return unless /^\d{1,3},\d{1,3},\d{1,3}$/.match?(value)
136
-
137
- value = value.split(",").map(&:to_i)
138
- case format
139
- when "rgb"
140
- return if value.max > 255
141
- when "hsv"
142
- return if value.first > 360 || value[1..2].max > 100
143
- end
144
- when :datetime
145
- begin
146
- value = Time.parse(value)
147
- rescue ArgumentError
148
- return
149
- end
150
- when :duration
151
- begin
152
- value = ActiveSupport::Duration.parse(value)
153
- rescue ActiveSupport::Duration::ISO8601Parser::ParsingError
154
- return
155
- end
164
+ casted_value = nil if (format == "rgb" && value.max > 255) ||
165
+ (format == "hsb" && (value.first > 360 || value[1..2].max > 100))
156
166
  end
157
167
 
158
- @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)
159
172
  end
160
173
 
161
174
  def mqtt
162
175
  node.mqtt
163
176
  end
164
177
 
178
+ def published?
179
+ @published
180
+ end
181
+
165
182
  def publish
166
- return if @published
183
+ return if published?
167
184
 
168
185
  mqtt.batch_publish do
169
186
  mqtt.publish("#{topic}/$name", name, retain: true, qos: 1)
@@ -184,7 +201,7 @@ module MQTT
184
201
  end
185
202
 
186
203
  def unpublish
187
- return unless @published
204
+ return unless published?
188
205
 
189
206
  @published = false
190
207
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module MQTT
4
4
  module Homie
5
- VERSION = "1.5.0"
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.5.0
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-12-08 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
@@ -121,6 +121,7 @@ extensions: []
121
121
  extra_rdoc_files: []
122
122
  files:
123
123
  - lib/homie-mqtt.rb
124
+ - lib/mqtt/homie.rb
124
125
  - lib/mqtt/homie/base.rb
125
126
  - lib/mqtt/homie/device.rb
126
127
  - lib/mqtt/homie/node.rb