adafruit-io 2.0.0.beta.2 → 2.0.0.beta.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +8 -8
- data/adafruit-io.gemspec +1 -0
- data/lib/adafruit/io.rb +1 -0
- data/lib/adafruit/io/client.rb +22 -3
- data/lib/adafruit/io/mqtt.rb +199 -0
- data/lib/adafruit/io/version.rb +1 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 82354463cf584413ee421f62dc087fa182b191a3
|
4
|
+
data.tar.gz: 7569063a8a78d7c97189a66bf89894f8c0f089dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d3dd1a6feec6e1804a08c0b5a805fb2053d35a4854acd354e018dc5f2815cb57454c7fb433eaf01be3ce1578f4e65a60b5b531aec8bcc69b6811d327c466fc23
|
7
|
+
data.tar.gz: 69e5cdb283b4d8d615fc3c575d0df498f82ecd04c1933b90f3d507a1cdd4c6983fcef7506040d226f60d788f3c2f10195351ce77ab31a877c678a838ab6e0db3
|
data/README.md
CHANGED
@@ -25,14 +25,14 @@ It is our goal to eventually support all API V2 methods, but that will happen in
|
|
25
25
|
- [x] Feeds `2.0.0.beta.1`
|
26
26
|
- [x] Data `2.0.0.beta.1`
|
27
27
|
- [x] Groups `2.0.0.beta.1`
|
28
|
-
-
|
29
|
-
-
|
30
|
-
-
|
31
|
-
-
|
32
|
-
- Permissions
|
33
|
-
- Sessions
|
34
|
-
- Tokens
|
35
|
-
- Triggers
|
28
|
+
- [x] MQTT `2.0.0.beta.3`
|
29
|
+
- [] Activities
|
30
|
+
- [] Blocks
|
31
|
+
- [] Dashboards
|
32
|
+
- [] Permissions
|
33
|
+
- [] Sessions
|
34
|
+
- [] Tokens
|
35
|
+
- [] Triggers
|
36
36
|
|
37
37
|
## Installation
|
38
38
|
|
data/adafruit-io.gemspec
CHANGED
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_dependency "faraday", "~> 0.8"
|
24
24
|
spec.add_dependency "faraday_middleware", "~> 0.9"
|
25
25
|
spec.add_dependency "activesupport", "~> 4.2"
|
26
|
+
spec.add_dependency "mqtt", "~> 0.4"
|
26
27
|
|
27
28
|
spec.add_development_dependency "bundler", "~> 1.5"
|
28
29
|
spec.add_development_dependency "rake", "~> 10.4"
|
data/lib/adafruit/io.rb
CHANGED
data/lib/adafruit/io/client.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'json'
|
2
|
-
require 'uri'
|
3
2
|
|
4
3
|
require 'faraday'
|
5
4
|
require 'faraday_middleware'
|
@@ -71,10 +70,30 @@ module Adafruit
|
|
71
70
|
end
|
72
71
|
|
73
72
|
def api_url(username, *args)
|
74
|
-
|
73
|
+
safe_path_join *['api', 'v2', username].concat(args)
|
74
|
+
end
|
75
|
+
|
76
|
+
# safely build URL paths from segments
|
77
|
+
def safe_path_join(*paths)
|
78
|
+
paths = paths.compact.reject(&:empty?)
|
79
|
+
last = paths.length - 1
|
80
|
+
paths.each_with_index.map { |path, index|
|
81
|
+
safe_path_expand(path, index, last)
|
82
|
+
}.join
|
83
|
+
end
|
84
|
+
|
85
|
+
def safe_path_expand(path, current, last)
|
86
|
+
if path[0] === '/' && current != 0
|
87
|
+
path = path[1..-1]
|
88
|
+
end
|
89
|
+
|
90
|
+
unless path[-1] === '/' || current == last
|
91
|
+
path = [path, '/']
|
92
|
+
end
|
75
93
|
|
76
|
-
|
94
|
+
path
|
77
95
|
end
|
96
|
+
|
78
97
|
end
|
79
98
|
end
|
80
99
|
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
require 'mqtt'
|
2
|
+
|
3
|
+
#
|
4
|
+
# Adafruit::IO::MQTT provides a simple Adafruit IO aware wrapper around the
|
5
|
+
# Ruby MQTT library at https://github.com/njh/ruby-mqtt.
|
6
|
+
#
|
7
|
+
# Our primary goal is to provide basic MQTT access to feeds.
|
8
|
+
#
|
9
|
+
# For example, publishing to a feed is as simple as:
|
10
|
+
#
|
11
|
+
# mqtt = Adafruit::IO::MQTT.new user, key
|
12
|
+
# mqtt.publish('feed-key', 1)
|
13
|
+
#
|
14
|
+
# And subscribing to a feed is just as easy:
|
15
|
+
#
|
16
|
+
# mqtt = Adafruit::IO::MQTT.new user, key
|
17
|
+
# mqtt.subscribe('feed-key')
|
18
|
+
# mqtt.get do |topic, value|
|
19
|
+
# puts "GOT VALUE FROM #{topic}: #{value}"
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# If you need to access different MQTT endpoints or data formats (JSON, CSV)
|
23
|
+
# you can use the MQTT library directly:
|
24
|
+
#
|
25
|
+
# mqtt = Adafruit::IO::MQTT.new user, key
|
26
|
+
# mqtt.client.get("#{user}/groups/group-key/json") do |topic, message|
|
27
|
+
# payload = JSON.parse(message)
|
28
|
+
# # etc...
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# Documentation for Ruby MQTT is available at http://www.rubydoc.info/gems/mqtt/MQTT/Client
|
32
|
+
#
|
33
|
+
module Adafruit
|
34
|
+
module IO
|
35
|
+
class MQTT
|
36
|
+
|
37
|
+
# provide access to the raw MQTT library client
|
38
|
+
attr_reader :client
|
39
|
+
|
40
|
+
def initialize(username, key, opts={})
|
41
|
+
@options = {
|
42
|
+
uri: 'io.adafruit.com',
|
43
|
+
protocol: 'mqtts',
|
44
|
+
port: 8883,
|
45
|
+
username: username,
|
46
|
+
key: key
|
47
|
+
}.merge(opts)
|
48
|
+
|
49
|
+
@connect_uri = "%{protocol}://%{username}:%{key}@%{uri}" % @options
|
50
|
+
|
51
|
+
connect
|
52
|
+
end
|
53
|
+
|
54
|
+
def connect
|
55
|
+
if @client.nil? || !@client.connected?
|
56
|
+
@client = ::MQTT::Client.connect @connect_uri, @options[:port], ack_timeout: 10
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def disconnect
|
61
|
+
if @client && @client.connected?
|
62
|
+
@client.disconnect
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Publish value to feed with given key
|
67
|
+
def publish(key, value, location={})
|
68
|
+
raise 'client is not connected' unless @client.connected?
|
69
|
+
|
70
|
+
topic = key_to_feed_topic(key)
|
71
|
+
location = indifferent_keys(location)
|
72
|
+
payload = payload_from_value_with_location(value, location)
|
73
|
+
|
74
|
+
@client.publish(topic, payload)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Publish to multiple feeds within a group.
|
78
|
+
#
|
79
|
+
# - `key` is a group key
|
80
|
+
# - `values` is a hash where keys are feed keys and values are the
|
81
|
+
# published value.
|
82
|
+
# - `location` is the optional { :lat, :lon, :ele } hash specifying the
|
83
|
+
# location data for this publish event.
|
84
|
+
#
|
85
|
+
def publish_group(key, values, location={})
|
86
|
+
raise 'client is not connected' unless @client.connected?
|
87
|
+
raise 'values must be a hash' unless values.is_a?(Hash)
|
88
|
+
|
89
|
+
topic = key_to_group_topic(key, false)
|
90
|
+
location = indifferent_keys(location)
|
91
|
+
payload = payload_from_values_with_location(values, location)
|
92
|
+
|
93
|
+
@client.publish(topic, payload)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Subscribe to the feed with the given key. Use .get to retrieve messages
|
97
|
+
# from subscribed feeds.
|
98
|
+
def subscribe(key)
|
99
|
+
raise 'client is not connected' unless @client.connected?
|
100
|
+
|
101
|
+
topic = key_to_feed_topic(key)
|
102
|
+
@client.subscribe(topic)
|
103
|
+
end
|
104
|
+
|
105
|
+
def unsubscribe(key)
|
106
|
+
raise 'client is not connected' unless @client.connected?
|
107
|
+
|
108
|
+
topic = key_to_feed_topic(key)
|
109
|
+
@client.unsubscribe(topic)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Subscribe to a group with the given key.
|
113
|
+
#
|
114
|
+
# NOTE: Unlike feed subscriptions, group subscriptions return a JSON
|
115
|
+
# representation of the group record with a 'feeds' property containing a
|
116
|
+
# JSON object whose keys are feed keys and whose values are the last
|
117
|
+
# value received for that feed.
|
118
|
+
def subscribe_group(key)
|
119
|
+
raise 'client is not connected' unless @client.connected?
|
120
|
+
|
121
|
+
topic = key_to_group_topic(key)
|
122
|
+
@client.subscribe(topic)
|
123
|
+
end
|
124
|
+
|
125
|
+
# Retrieve the last value received from the MQTT connection for any
|
126
|
+
# subscribed feeds or groups. This is a blocking method, which means it
|
127
|
+
# won't return until a message is retrieved.
|
128
|
+
#
|
129
|
+
# Returns [topic, message] or yields it into the given block.
|
130
|
+
#
|
131
|
+
# With no block:
|
132
|
+
#
|
133
|
+
# mqtt_client.subscribe('feed-key')
|
134
|
+
# loop do
|
135
|
+
# topic, message = mqtt_client.get
|
136
|
+
# # do something
|
137
|
+
# end
|
138
|
+
#
|
139
|
+
# With a block:
|
140
|
+
#
|
141
|
+
# mqtt_client.subscribe('feed-key')
|
142
|
+
# mqtt_client.get do |topic, message|
|
143
|
+
# # do something
|
144
|
+
# end
|
145
|
+
#
|
146
|
+
# NOTE: if a feed already has a value, subscribing and calling get will
|
147
|
+
# immediately return the most recent value for the subscription,
|
148
|
+
# regardless of when it was received by IO.
|
149
|
+
def get(&block)
|
150
|
+
@client.get(&block)
|
151
|
+
end
|
152
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
def key_to_feed_topic(key)
|
156
|
+
"%s/f/%s" % [@options[:username], key]
|
157
|
+
end
|
158
|
+
|
159
|
+
def key_to_group_topic(key, json=true)
|
160
|
+
"%s/g/%s%s" % [@options[:username], key, (json ? '/json' : '')]
|
161
|
+
end
|
162
|
+
|
163
|
+
def payload_from_value_with_location(value, location)
|
164
|
+
payload = { value: value.to_s }
|
165
|
+
|
166
|
+
if location.has_key?('lat') && location.has_key?['lon']
|
167
|
+
%w(lat lon ele).each do |f|
|
168
|
+
payload[f] = location[f]
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
JSON.generate payload
|
173
|
+
end
|
174
|
+
|
175
|
+
def payload_from_values_with_location(values, location)
|
176
|
+
payload = { feeds: values }
|
177
|
+
|
178
|
+
if location.has_key?('lat') && location.has_key?['lon']
|
179
|
+
payload[:location] = {}
|
180
|
+
|
181
|
+
%w(lat lon ele).each do |f|
|
182
|
+
payload[:location][f] = location[f]
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
JSON.generate payload
|
187
|
+
end
|
188
|
+
|
189
|
+
def indifferent_keys(hash)
|
190
|
+
hash.keys.inject({}) {|new_hash, key|
|
191
|
+
new_hash[key.to_s] = hash[key]
|
192
|
+
new_hash[key.to_sym] = hash[key]
|
193
|
+
|
194
|
+
new_hash
|
195
|
+
}
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
data/lib/adafruit/io/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: adafruit-io
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0.beta.
|
4
|
+
version: 2.0.0.beta.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Cooper
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-04-
|
12
|
+
date: 2017-04-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: faraday
|
@@ -53,6 +53,20 @@ dependencies:
|
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: '4.2'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: mqtt
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0.4'
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0.4'
|
56
70
|
- !ruby/object:Gem::Dependency
|
57
71
|
name: bundler
|
58
72
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,6 +114,7 @@ files:
|
|
100
114
|
- lib/adafruit/io/client/groups.rb
|
101
115
|
- lib/adafruit/io/client/tokens.rb
|
102
116
|
- lib/adafruit/io/configurable.rb
|
117
|
+
- lib/adafruit/io/mqtt.rb
|
103
118
|
- lib/adafruit/io/request_handler.rb
|
104
119
|
- lib/adafruit/io/version.rb
|
105
120
|
homepage: https://github.com/adafruit/io-client-ruby
|