mqtt-homie 0.1.1 → 0.1.2

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: e325ebb1aedaf50aef04bd62e84b8cb2107561f87f8aa71a9f5f037cc4d5a006
4
- data.tar.gz: 4847fede7e1dcb105f4a869073c0a6a807cbcc0c6927059cf6465ed0f7794831
3
+ metadata.gz: ccd07988b5eafc7e3387a4a545d986dcea8f1d1355d9b6dd48bf4de2231eda61
4
+ data.tar.gz: 3889c445feaee69b229c8fe8c08d4c619cc0a83eb389f150aba2430c406bb39b
5
5
  SHA512:
6
- metadata.gz: 4b705eadfb0777b0f79f15a32965419bbfcfe2695dba3101c44a61680e38a9e58bbe634673f37f347213608099f7b13e8841e592135918899255c50bef4a0604
7
- data.tar.gz: dd9f77fc45d35d87a3d514cc18ecef672f84fb94b8a7b218e5f52dddbf2132be2f87028338cf26446bc0a45a44d6e924484cb540483bafa83c1181e2c1983859
6
+ metadata.gz: 2ed023aa563488d443537cb4ec9fd1656c8b91218bee305883489cb54ed380567c164e7731f3a1a4e7795c0dcb6e1aea6b0cb0b5f5926e8db90d23f47de60aa6
7
+ data.tar.gz: f5bb67c340d10e4413a68e4517383cbbad57b84f410adcd0b1e9f9d1b5be6000da0b73c1561d7e2ebe0fe820724dd88f499dc2739e28c39a5a52fd94fd6fde7f
data/.gitignore CHANGED
@@ -6,6 +6,8 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ /vendor/
10
+ /Gemfile.lock
9
11
 
10
12
  # rspec failure tracking
11
13
  .rspec_status
data/README.md CHANGED
@@ -1,66 +1,68 @@
1
- # MQTT::Homie
2
-
3
- A ruby interface for creating a device conforming to the MQTT [Homie] convention.
4
- This gem builds upon the [ruby-mqtt] ruby gem.
5
-
6
- The [Homie] convention defines a standardized way of how IoT devices and services announce themselves and their data to a MQTT broker.
7
-
8
- ## Installation
9
-
10
- Add this line to your application's Gemfile:
11
-
12
- ```ruby
13
- gem 'mqtt-homie'
14
- ```
15
-
16
- And then execute:
17
-
18
- $ bundle
19
-
20
- Or install it yourself as:
21
-
22
- $ gem install mqtt-homie
23
-
24
- ## Quick Start
25
-
26
- ~~~ ruby
27
- require 'rubygems'
28
- require 'mqtt/homie'
29
-
30
- # Set up a device, with a node and properties
31
- device = MQTT::Homie.device_builder(id: 'device', name: 'Device')
32
- .node(id: "gate", name: "Front gate", type: "Gate")
33
- .property(id: "state", name: "Gate state", enum: [:open, :closed, :opening, :closing], value: :closed)
34
- .property(id: "position", name: "Gate position", datatype: :integer, unit: "%", value: 0)
35
- .property(id: "command", name: "Send gate command", settable: true, enum: [:open, :close]).build
36
-
37
- # Create a client and connect to a MQTT broker
38
- client = MQTT::Homie::Client.new(device: device, host: 'localhost')
39
- client.connect
40
-
41
- # access nodes and properties of the device
42
- node = device.node('gate')
43
- state = node.property('state')
44
- state.value = :open # publishes new state to MQTT
45
-
46
- # listen for changes to properties via the Observer interface
47
- node.property('command').add_observer(self)
48
- ~~~
49
-
50
- ## Overview
51
-
52
- TODO
53
-
54
- ## License
55
-
56
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
57
-
58
- ## Code of Conduct
59
-
60
- Everyone interacting in the Mqtt::Homie project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/mqtt-homie/blob/master/CODE_OF_CONDUCT.md).
61
-
62
-
63
-
64
- [Homie]: https://homieiot.github.io/
65
- [MQTT]: http://www.mqtt.org/
1
+ [![Build Status](https://travis-ci.com/sobakasu/mqtt-homie.svg?branch=develop)](https://travis-ci.com/sobakasu/mqtt-homie)
2
+
3
+ # MQTT::Homie
4
+
5
+ A ruby interface for creating a device conforming to the MQTT [Homie] convention.
6
+ This gem builds upon the [ruby-mqtt] ruby gem.
7
+
8
+ The [Homie] convention defines a standardized way of how IoT devices and services announce themselves and their data to a MQTT broker.
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ ```ruby
15
+ gem 'mqtt-homie'
16
+ ```
17
+
18
+ And then execute:
19
+
20
+ $ bundle
21
+
22
+ Or install it yourself as:
23
+
24
+ $ gem install mqtt-homie
25
+
26
+ ## Quick Start
27
+
28
+ ~~~ ruby
29
+ require 'rubygems'
30
+ require 'mqtt/homie'
31
+
32
+ # Set up a device, with a node and properties
33
+ device = MQTT::Homie.device_builder(id: 'device', name: 'Device')
34
+ .node(id: "gate", name: "Front gate", type: "Gate")
35
+ .property(id: "state", name: "Gate state", enum: [:open, :closed, :opening, :closing], value: :closed)
36
+ .property(id: "position", name: "Gate position", datatype: :integer, unit: "%", value: 0)
37
+ .property(id: "command", name: "Send gate command", settable: true, enum: [:open, :close]).build
38
+
39
+ # Create a client and connect to a MQTT broker
40
+ client = MQTT::Homie::Client.new(device: device, host: 'localhost')
41
+ client.connect
42
+
43
+ # access nodes and properties of the device
44
+ node = device.node('gate')
45
+ state = node.property('state')
46
+ state.value = :open # publishes new state to MQTT
47
+
48
+ # listen for changes to properties via the Observer interface
49
+ node.property('command').add_observer(self)
50
+ ~~~
51
+
52
+ ## Overview
53
+
54
+ TODO
55
+
56
+ ## License
57
+
58
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
59
+
60
+ ## Code of Conduct
61
+
62
+ Everyone interacting in the Mqtt::Homie project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/mqtt-homie/blob/master/CODE_OF_CONDUCT.md).
63
+
64
+
65
+
66
+ [Homie]: https://homieiot.github.io/
67
+ [MQTT]: http://www.mqtt.org/
66
68
  [ruby-mqtt]: https://github.com/njh/ruby-mqtt
@@ -1,173 +1,173 @@
1
- module MQTT
2
- module Homie
3
- # https://homieiot.github.io/specification/
4
-
5
- class Client
6
- DEFAULT_ROOT_TOPIC = "homie"
7
-
8
- attr_accessor :host, :root_topic
9
- attr_reader :device
10
-
11
- def initialize(options = {})
12
- @device = options[:device]
13
- @host = options[:host]
14
- @root_topic = options[:root_topic] || DEFAULT_ROOT_TOPIC
15
-
16
- raise "device required" unless @device
17
-
18
- # next version of homie doesn't use stats or firmware details
19
- @use_stats = true
20
- if options[:develop]
21
- @device.use_stats = false
22
- @device.use_fw = false
23
- @use_stats = false
24
- end
25
-
26
- # observe all node properties so we can publish values when they change
27
- @device.nodes.each do |node|
28
- node.properties.each do |property|
29
- property.add_observer(self)
30
- end
31
- end
32
- end
33
-
34
- def connect
35
- return if connected?
36
-
37
- @device.state = :init
38
- @client = create_mqtt_client
39
- @client.connect
40
-
41
- publish(@device, topic)
42
- publish_statistics if @use_stats
43
-
44
- @threads = []
45
-
46
- # run a thread to publish statistics
47
- @threads << Thread.new { run_statistics } if @use_stats
48
-
49
- # run a thread to listen for settings
50
- @threads << Thread.new { run_set_listener }
51
-
52
- @device.state = :ready
53
- publish_state
54
- end
55
-
56
- def disconnect
57
- @device.state = :disconnected
58
- publish_state
59
-
60
- @client.disconnect
61
- @client = nil
62
-
63
- @threads.each { |i| i[:done] = true }
64
- @threads = []
65
- end
66
-
67
- def topic
68
- @root_topic + "/" + @device.id
69
- end
70
-
71
- def connected?
72
- @device.state == :ready
73
- end
74
-
75
- def update(time, object)
76
- if object.kind_of?(MQTT::Homie::Property)
77
- publish_property_value(object)
78
- end
79
- end
80
-
81
- private
82
-
83
- def create_mqtt_client
84
- client = ::MQTT::Client.new
85
- client.host = @host
86
- client.will_topic = topic + "/$state"
87
- client.will_payload = :lost
88
- client.will_retain = true
89
- client
90
- end
91
-
92
- def run_set_listener
93
- # subscribe to 'set' topics for all settable properties
94
- @device.nodes.each do |node|
95
- node.properties.each do |property|
96
- if property.settable?
97
- set_topic = topic + "/" + node.topic + "/" + property.topic + "/set"
98
- debug("subscribe #{set_topic}")
99
- @client.subscribe(set_topic) if @client
100
- end
101
- end
102
- end
103
-
104
- if @client
105
- @client.get do |topic, message|
106
- debug("received message: #{topic}, message: #{message}")
107
- property = find_property_by_set_topic(topic)
108
- property.value = message if property
109
- break if Thread.current[:done]
110
- end
111
- end
112
- debug("set listener thread exiting")
113
- end
114
-
115
- def run_statistics
116
- while !Thread.current[:done]
117
- publish_statistics
118
-
119
- # halve interval, if we miss a notification then we will be marked as offline
120
- sleep @device.stats.interval / 2
121
- end
122
- debug("statistics thread exiting")
123
- end
124
-
125
- def find_property_by_set_topic(set_topic)
126
- @device.nodes.each do |node|
127
- node.properties.each do |property|
128
- return property if set_topic == topic + "/" + node.topic + "/" + property.topic + "/set"
129
- end
130
- end
131
- nil
132
- end
133
-
134
- def publish_statistics
135
- publish(@device.stats, topic + "/$stats")
136
- end
137
-
138
- def publish_property_value(property)
139
- node = @device.nodes.find { |i| i.properties.include?(property) }
140
- data = {
141
- property.id => property.value,
142
- }
143
- publish(data, topic + "/" + node.topic)
144
- end
145
-
146
- def publish_state
147
- data = {
148
- "$state" => @device.state,
149
- }
150
- publish(data, topic)
151
- end
152
-
153
- def publish(object, prefix = nil)
154
- data = {}
155
- if object.respond_to?(:homie_attributes)
156
- data = object.homie_attributes
157
- else
158
- data = object
159
- end
160
-
161
- data.each do |k, v|
162
- topic = prefix + "/" + k
163
- debug("mqtt publish #{topic} -> #{v}")
164
- @client.publish(topic, v, true)
165
- end
166
- end
167
-
168
- def debug(message)
169
- MQTT::Homie.debug(message)
170
- end
171
- end
172
- end
173
- end
1
+ module MQTT
2
+ module Homie
3
+ # https://homieiot.github.io/specification/
4
+
5
+ class Client
6
+ DEFAULT_ROOT_TOPIC = "homie"
7
+
8
+ attr_accessor :host, :root_topic
9
+ attr_reader :device
10
+
11
+ def initialize(options = {})
12
+ @device = options[:device]
13
+ @host = options[:host]
14
+ @root_topic = options[:root_topic] || DEFAULT_ROOT_TOPIC
15
+
16
+ raise "device required" unless @device
17
+
18
+ # next version of homie doesn't use stats or firmware details
19
+ @use_stats = true
20
+ if options[:develop]
21
+ @device.use_stats = false
22
+ @device.use_fw = false
23
+ @use_stats = false
24
+ end
25
+
26
+ # observe all node properties so we can publish values when they change
27
+ @device.nodes.each do |node|
28
+ node.properties.each do |property|
29
+ property.add_observer(self)
30
+ end
31
+ end
32
+ end
33
+
34
+ def connect
35
+ return if connected?
36
+
37
+ @device.state = :init
38
+ @client = create_mqtt_client
39
+ @client.connect
40
+
41
+ publish(@device, topic)
42
+ publish_statistics if @use_stats
43
+
44
+ @threads = []
45
+
46
+ # run a thread to publish statistics
47
+ @threads << Thread.new { run_statistics } if @use_stats
48
+
49
+ # run a thread to listen for settings
50
+ @threads << Thread.new { run_set_listener }
51
+
52
+ @device.state = :ready
53
+ publish_state
54
+ end
55
+
56
+ def disconnect
57
+ @device.state = :disconnected
58
+ publish_state
59
+
60
+ @client.disconnect
61
+ @client = nil
62
+
63
+ @threads.each { |i| i[:done] = true }
64
+ @threads = []
65
+ end
66
+
67
+ def topic
68
+ @root_topic + "/" + @device.id
69
+ end
70
+
71
+ def connected?
72
+ @device.state == :ready
73
+ end
74
+
75
+ def update(time, object)
76
+ if object.kind_of?(MQTT::Homie::Property)
77
+ publish_property_value(object)
78
+ end
79
+ end
80
+
81
+ private
82
+
83
+ def create_mqtt_client
84
+ client = ::MQTT::Client.new
85
+ client.host = @host
86
+ client.will_topic = topic + "/$state"
87
+ client.will_payload = :lost
88
+ client.will_retain = true
89
+ client
90
+ end
91
+
92
+ def run_set_listener
93
+ # subscribe to 'set' topics for all settable properties
94
+ @device.nodes.each do |node|
95
+ node.properties.each do |property|
96
+ if property.settable?
97
+ set_topic = topic + "/" + node.topic + "/" + property.topic + "/set"
98
+ debug("subscribe #{set_topic}")
99
+ @client.subscribe(set_topic) if @client
100
+ end
101
+ end
102
+ end
103
+
104
+ if @client
105
+ @client.get do |topic, message|
106
+ debug("received message: #{topic}, message: #{message}")
107
+ property = find_property_by_set_topic(topic)
108
+ property.value = message if property
109
+ break if Thread.current[:done]
110
+ end
111
+ end
112
+ debug("set listener thread exiting")
113
+ end
114
+
115
+ def run_statistics
116
+ while !Thread.current[:done]
117
+ publish_statistics
118
+
119
+ # halve interval, if we miss a notification then we will be marked as offline
120
+ sleep @device.stats.interval / 2
121
+ end
122
+ debug("statistics thread exiting")
123
+ end
124
+
125
+ def find_property_by_set_topic(set_topic)
126
+ @device.nodes.each do |node|
127
+ node.properties.each do |property|
128
+ return property if set_topic == topic + "/" + node.topic + "/" + property.topic + "/set"
129
+ end
130
+ end
131
+ nil
132
+ end
133
+
134
+ def publish_statistics
135
+ publish(@device.stats, topic + "/$stats")
136
+ end
137
+
138
+ def publish_property_value(property)
139
+ node = @device.nodes.find { |i| i.properties.include?(property) }
140
+ data = {
141
+ property.id => property.value,
142
+ }
143
+ publish(data, topic + "/" + node.topic)
144
+ end
145
+
146
+ def publish_state
147
+ data = {
148
+ "$state" => @device.state,
149
+ }
150
+ publish(data, topic)
151
+ end
152
+
153
+ def publish(object, prefix = nil)
154
+ data = {}
155
+ if object.respond_to?(:homie_attributes)
156
+ data = object.homie_attributes
157
+ else
158
+ data = object
159
+ end
160
+
161
+ data.each do |k, v|
162
+ topic = prefix + "/" + k
163
+ debug("mqtt publish #{topic} -> #{v}")
164
+ @client.publish(topic, v, true)
165
+ end
166
+ end
167
+
168
+ def debug(message)
169
+ MQTT::Homie.debug(message)
170
+ end
171
+ end
172
+ end
173
+ end