m2x-mqtt 0.2.0 → 0.3.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
  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)