m2x-mqtt 0.2.0 → 0.3.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/m2x/mqtt.rb +2 -0
- data/lib/m2x/mqtt/client.rb +32 -6
- data/lib/m2x/mqtt/client/packet_router.rb +27 -0
- data/lib/m2x/mqtt/command.rb +31 -0
- data/lib/m2x/mqtt/device.rb +21 -0
- data/lib/m2x/mqtt/resource.rb +15 -0
- data/lib/m2x/mqtt/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e5c6b14401ae444dfd7369aa051367c84e99469
|
4
|
+
data.tar.gz: 349ab423f5899f54af40b9c4dae57b40de04f1d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b844080a95c6a2b88d41270225ece40aa5c1cfbda94fc7832a2bf3bbe66c24d5dff27c27ecaa50836e9077056c2a6fde0407f83722d914a7f788ce8afc31e25
|
7
|
+
data.tar.gz: 5d1dc996ff2e34369fde6cd4ac1413a98bd36acecbd8e5d6c7cf1ec5b625b2d9d8d17ac4f8ca4d12288ef04bfd11bd7a5f233d942910d2f9d06b9e1d8a196348
|
data/lib/m2x/mqtt.rb
CHANGED
@@ -2,10 +2,12 @@ module M2X
|
|
2
2
|
class MQTT
|
3
3
|
require_relative "mqtt/version"
|
4
4
|
require_relative "mqtt/client"
|
5
|
+
require_relative "mqtt/client/packet_router"
|
5
6
|
require_relative "mqtt/resource"
|
6
7
|
require_relative "mqtt/device"
|
7
8
|
require_relative "mqtt/distribution"
|
8
9
|
require_relative "mqtt/stream"
|
10
|
+
require_relative "mqtt/command"
|
9
11
|
|
10
12
|
attr_accessor :client
|
11
13
|
|
data/lib/m2x/mqtt/client.rb
CHANGED
@@ -16,15 +16,18 @@ class M2X::MQTT::Client
|
|
16
16
|
def initialize(api_key, options={})
|
17
17
|
@api_key = api_key
|
18
18
|
@options = DEFAULTS.merge(options)
|
19
|
+
|
20
|
+
@packet_router = PacketRouter.new
|
19
21
|
end
|
20
22
|
|
21
23
|
# Public: Subscribe the client to the responses topic.
|
22
24
|
#
|
23
|
-
# This is required in order to receive responses
|
24
|
-
# M2X API server. Note that #get_response already
|
25
|
-
# the client.
|
25
|
+
# This is required in order to receive responses or commands
|
26
|
+
# from the M2X API server. Note that #get_response already
|
27
|
+
# subscribes the client.
|
26
28
|
def subscribe
|
27
29
|
mqtt_client.subscribe(response_topic)
|
30
|
+
mqtt_client.subscribe(command_topic)
|
28
31
|
end
|
29
32
|
|
30
33
|
# Public: Send a payload to the M2X API server.
|
@@ -45,10 +48,27 @@ class M2X::MQTT::Client
|
|
45
48
|
# Optionally receives a block which will iterate through responses
|
46
49
|
# and yield each one.
|
47
50
|
def get_response
|
48
|
-
|
51
|
+
mqtt_client.subscribe(response_topic)
|
49
52
|
|
50
|
-
|
51
|
-
|
53
|
+
return packet_router.json_fetch(mqtt_client, response_topic) unless block_given?
|
54
|
+
|
55
|
+
loop do
|
56
|
+
yield packet_router.json_fetch(mqtt_client, response_topic)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Public: Retrieve a command from the M2X Server.
|
61
|
+
#
|
62
|
+
# Returns a Hash with the command from the MQTT Server in M2X.
|
63
|
+
# Optionally receives a block which will iterate through commands
|
64
|
+
# and yield each one.
|
65
|
+
def get_command
|
66
|
+
mqtt_client.subscribe(command_topic)
|
67
|
+
|
68
|
+
return M2X::MQTT::Command.new(self, packet_router.json_fetch(mqtt_client, command_topic)) unless block_given?
|
69
|
+
|
70
|
+
loop do
|
71
|
+
yield M2X::MQTT::Command.new(self, packet_router.json_fetch(mqtt_client, command_topic))
|
52
72
|
end
|
53
73
|
end
|
54
74
|
|
@@ -60,6 +80,8 @@ class M2X::MQTT::Client
|
|
60
80
|
|
61
81
|
private
|
62
82
|
|
83
|
+
attr_reader :packet_router
|
84
|
+
|
63
85
|
def request(verb, path, params=nil)
|
64
86
|
path = versioned(path)
|
65
87
|
body = params || {}
|
@@ -85,6 +107,10 @@ class M2X::MQTT::Client
|
|
85
107
|
@response_topic ||= "m2x/#{@api_key}/responses".freeze
|
86
108
|
end
|
87
109
|
|
110
|
+
def command_topic
|
111
|
+
@command_topic ||= "m2x/#{@api_key}/commands".freeze
|
112
|
+
end
|
113
|
+
|
88
114
|
def mqtt_client
|
89
115
|
@mqtt_client ||= ::MQTT::Client.new.tap do |client|
|
90
116
|
client.host = @options[:api_url]
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "json"
|
2
|
+
require "thread"
|
3
|
+
|
4
|
+
class M2X::MQTT::Client::PacketRouter
|
5
|
+
def initialize
|
6
|
+
@lock = Mutex.new
|
7
|
+
@queues = Hash.new { |hash, key| hash[key] = [] }
|
8
|
+
end
|
9
|
+
|
10
|
+
def fetch(mqtt_client, topic)
|
11
|
+
@lock.synchronize do
|
12
|
+
packet = @queues[topic].shift
|
13
|
+
return packet if packet
|
14
|
+
|
15
|
+
loop do
|
16
|
+
packet = mqtt_client.get_packet
|
17
|
+
return packet if topic == packet.topic
|
18
|
+
|
19
|
+
@queues[packet.topic] << packet
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def json_fetch(mqtt_client, topic)
|
25
|
+
JSON.parse(fetch(mqtt_client, topic).payload)
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "uri"
|
2
|
+
|
3
|
+
# Wrapper for AT&T M2X Commands API
|
4
|
+
# https://m2x.att.com/developer/documentation/v2/device
|
5
|
+
class M2X::MQTT::Command < M2X::MQTT::Resource
|
6
|
+
|
7
|
+
def initialize(client, attributes)
|
8
|
+
@client = client
|
9
|
+
@attributes = attributes
|
10
|
+
end
|
11
|
+
|
12
|
+
def path
|
13
|
+
@path ||= URI.parse(@attributes.fetch("url")).path
|
14
|
+
end
|
15
|
+
|
16
|
+
# Mark the command as processed, with optional response data.
|
17
|
+
# Check the API response after calling to verify success (no status conflict).
|
18
|
+
#
|
19
|
+
# https://m2x.att.com/developer/documentation/v2/commands#Device-Marks-a-Command-as-Processed
|
20
|
+
def process!(response_data={})
|
21
|
+
@client.post("#{path}/process", response_data)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Mark the command as rejected, with optional response data.
|
25
|
+
# Check the API response after calling to verify success (no status conflict).
|
26
|
+
#
|
27
|
+
# https://m2x.att.com/developer/documentation/v2/commands#Device-Marks-a-Command-as-Rejected
|
28
|
+
def reject!(response_data={})
|
29
|
+
@client.post("#{path}/reject", response_data)
|
30
|
+
end
|
31
|
+
end
|
data/lib/m2x/mqtt/device.rb
CHANGED
@@ -23,6 +23,27 @@ class M2X::MQTT::Device < M2X::MQTT::Resource
|
|
23
23
|
M2X::MQTT::Stream.new(@client, self, "name" => name)
|
24
24
|
end
|
25
25
|
|
26
|
+
# Return a list of recently received commands.
|
27
|
+
#
|
28
|
+
# Most commonly, this method can be used to fetch unacknowledged
|
29
|
+
# commands by filtering by delivery status, using the parameters:
|
30
|
+
#
|
31
|
+
# { status: "sent" }
|
32
|
+
#
|
33
|
+
# MQTT clients that are subscribed to command delivery notifications
|
34
|
+
# should still use this method periodically to check for unacknowledged
|
35
|
+
# commands that were missed while offline or during a network partition.
|
36
|
+
#
|
37
|
+
# https://m2x.att.com/developer/documentation/v2/commands#Device-List-of-Received-Commands
|
38
|
+
def commands(params={})
|
39
|
+
@client.get("#{path}/commands", params)
|
40
|
+
|
41
|
+
res = @client.get_response
|
42
|
+
commands = res["body"]["commands"] if res["status"] < 300
|
43
|
+
|
44
|
+
commands.map { |data| M2X::MQTT::Command.new(@client, data) } if commands
|
45
|
+
end
|
46
|
+
|
26
47
|
# Update the current location of the specified device.
|
27
48
|
#
|
28
49
|
# https://m2x.att.com/developer/documentation/v2/device#Update-Device-Location
|
data/lib/m2x/mqtt/resource.rb
CHANGED
@@ -21,4 +21,19 @@ class M2X::MQTT::Resource
|
|
21
21
|
def path
|
22
22
|
raise NotImplementedError
|
23
23
|
end
|
24
|
+
|
25
|
+
# Return the resource details
|
26
|
+
def view
|
27
|
+
@client.get(path)
|
28
|
+
|
29
|
+
res = @client.get_response
|
30
|
+
|
31
|
+
@attributes = res["body"] if res["status"] < 300 && res["body"]
|
32
|
+
end
|
33
|
+
|
34
|
+
# Refresh the resource details and return self
|
35
|
+
def refresh
|
36
|
+
view
|
37
|
+
self
|
38
|
+
end
|
24
39
|
end
|
data/lib/m2x/mqtt/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: m2x-mqtt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Leandro López
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2015-
|
13
|
+
date: 2015-11-13 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: mqtt
|
@@ -42,6 +42,8 @@ files:
|
|
42
42
|
- README.md
|
43
43
|
- lib/m2x/mqtt.rb
|
44
44
|
- lib/m2x/mqtt/client.rb
|
45
|
+
- lib/m2x/mqtt/client/packet_router.rb
|
46
|
+
- lib/m2x/mqtt/command.rb
|
45
47
|
- lib/m2x/mqtt/device.rb
|
46
48
|
- lib/m2x/mqtt/distribution.rb
|
47
49
|
- lib/m2x/mqtt/resource.rb
|
@@ -68,7 +70,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
68
70
|
version: '0'
|
69
71
|
requirements: []
|
70
72
|
rubyforge_project:
|
71
|
-
rubygems_version: 2.4.5
|
73
|
+
rubygems_version: 2.4.5
|
72
74
|
signing_key:
|
73
75
|
specification_version: 4
|
74
76
|
summary: Ruby client for AT&T M2X (MQTT)
|