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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6473976f9a8f12fcb6c6e8e08884a31b6e7865e0
4
- data.tar.gz: 3e4b2ad0d14a5e5a5324da70bc54f22c145a80d5
3
+ metadata.gz: 4e5c6b14401ae444dfd7369aa051367c84e99469
4
+ data.tar.gz: 349ab423f5899f54af40b9c4dae57b40de04f1d5
5
5
  SHA512:
6
- metadata.gz: bdef4c3d3d59b5b1b2a7efd4aa0aeb8d4e229528327cf92280dc978426709ecc2abe0275ee948ed6cfd6ee21a7be1626a0979197132174e655db9ffbb7ad9eba
7
- data.tar.gz: 462e780b49e185af8109e646712ebebb497ffdb8148f06d45b934efe55d4c631bb583405e1a38bbe71b81c0b5027fc233b05b9a2e9ffd2b08788d5357101c608
6
+ metadata.gz: 3b844080a95c6a2b88d41270225ece40aa5c1cfbda94fc7832a2bf3bbe66c24d5dff27c27ecaa50836e9077056c2a6fde0407f83722d914a7f788ce8afc31e25
7
+ data.tar.gz: 5d1dc996ff2e34369fde6cd4ac1413a98bd36acecbd8e5d6c7cf1ec5b625b2d9d8d17ac4f8ca4d12288ef04bfd11bd7a5f233d942910d2f9d06b9e1d8a196348
@@ -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
 
@@ -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 from the
24
- # M2X API server. Note that #get_response already subscribes
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
- return JSON.parse(mqtt_client.get_packet(response_topic).payload) unless block_given?
51
+ mqtt_client.subscribe(response_topic)
49
52
 
50
- mqtt_client.get_packet(response_topic) do |packet|
51
- yield JSON.parse(packet.payload)
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
@@ -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
@@ -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
@@ -1,5 +1,5 @@
1
1
  module M2X
2
2
  class MQTT
3
- VERSION = "0.2.0"
3
+ VERSION = "0.3.0"
4
4
  end
5
5
  end
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.2.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-08-28 00:00:00.000000000 Z
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.1
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)