m2x-mqtt 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7b40f2dd197405129dea92eee3a9524a2ef941f0
4
+ data.tar.gz: 7c0504db6e1027b964e375338a62c77d20b4c5e1
5
+ SHA512:
6
+ metadata.gz: 695edb1116ab19e40677f7b5d93ea1c69196098738013e8959f5faaa56b247aa4c71794edbd0144583968840d450448c2c79b4f6cca7e92ef724bae27d6e1940
7
+ data.tar.gz: a8066d83bd256be686471e6ae476383fb1c1e28417706fcc66e9e895b00dfd797ce3e2609340e6aaac5a7fa93850009c91baa17e88353d285e5d1c619e2fda87
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 AT&T M2X
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,135 @@
1
+ # AT&T's M2X Ruby (MQTT) Client
2
+
3
+ [AT&T’s M2X](https://m2x.att.com/) is a cloud-based fully managed data storage service for network connected machine-to-machine (M2M) devices. From trucks and turbines to vending machines and freight containers, M2X enables the devices that power your business to connect and share valuable data.
4
+
5
+ This library aims to provide a simple wrapper to interact with the [AT&T M2X API](https://m2x.att.com/developer/documentation/overview) for [Ruby](https://www.ruby-lang.org/en/) using the [MQTT protocol](http://mqtt.org/). Refer to the [Glossary of Terms](https://m2x.att.com/developer/documentation/glossary) to understand the nomenclature used throughout this documentation.
6
+
7
+
8
+ Getting Started
9
+ ==========================
10
+ 1. Signup for an [M2X Account](https://m2x.att.com/signup).
11
+ 2. Obtain your _Master Key_ from the Master Keys tab of your [Account Settings](https://m2x.att.com/account) screen.
12
+ 2. Create your first [Device](https://m2x.att.com/devices) and copy its _Device ID_.
13
+ 3. Review the [M2X API Documentation](https://m2x.att.com/developer/documentation/overview).
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ $ gem install m2x-mqtt
19
+ ```
20
+ ## Usage
21
+
22
+ In order to communicate with the M2X API, you need an instance of [M2X::MQTT](lib/m2x/mqtt.rb). You need to pass your API key in the constructor to access your data.
23
+
24
+ ```ruby
25
+ m2x = M2X::MQTT.new(<YOUR-API-KEY>)
26
+ ```
27
+
28
+ This provides an interface to your data in M2X
29
+
30
+ - [Distribution](lib/m2x/mqtt/distribution.rb)
31
+ ```ruby
32
+ distribution = m2x.distribution("<DISTRIBUTION-ID>")
33
+ ```
34
+
35
+ - [Device](lib/m2x/mqtt/device.rb)
36
+ ```ruby
37
+ device = m2x.device("<DEVICE-ID>")
38
+ ```
39
+
40
+ - [Stream](lib/m2x/mqtt/stream.rb)
41
+ ```ruby
42
+ stream = m2x.stream("<DEVICE-ID>", "<STREAM-NAME>")
43
+
44
+ stream = m2x.device("<DEVICE-ID>").stream("<STREAM-NAME>")
45
+ ```
46
+
47
+ Refer to the documentation on each class for further usage instructions.
48
+
49
+ ## Example
50
+
51
+ In order to run this example, you will need a `Device ID` and `API Key`. If you don't have any, access your M2X account, create a new [Device](https://m2x.att.com/devices), and copy the `Device ID` and `API Key` values. The following script will send your CPU load average to three different streams named `load_1m`, `load_5m` and `load_15`. Check that there's no need to create a stream in order to write values into it.
52
+
53
+ In order to execute this script, run:
54
+
55
+ ```bash
56
+ API_KEY=<YOUR-API-KEY> DEVICE=<YOUR-DEVICE-ID> ./m2x-uptime.rb
57
+ ```
58
+
59
+ ```ruby
60
+ #! /usr/bin/env ruby
61
+
62
+ #
63
+ # https://github.com/attm2x/m2x-ruby-mqtt#example
64
+ # for instructions
65
+ #
66
+
67
+ require "time"
68
+ require "m2x/mqtt"
69
+
70
+ API_KEY = ENV.fetch("API_KEY")
71
+ DEVICE = ENV.fetch("DEVICE")
72
+
73
+ puts "M2X::MQTT/#{M2X::MQTT::VERSION} example"
74
+
75
+ @run = true
76
+
77
+ stop = Proc.new { @run = false }
78
+
79
+ trap(:INT, &stop)
80
+ trap(:TERM, &stop)
81
+
82
+ # Match `uptime` load averages output for both Linux and OSX
83
+ UPTIME_RE = /(\d+\.\d+),? (\d+\.\d+),? (\d+\.\d+)$/
84
+
85
+ def load_avg
86
+ `uptime`.match(UPTIME_RE).captures
87
+ end
88
+
89
+ m2x = M2X::MQTT.new(API_KEY)
90
+
91
+ # Get the device
92
+ device = m2x.device(DEVICE)
93
+
94
+ # Create the streams if they don't exist
95
+ device.stream("load_1m").update!
96
+ device.stream("load_5m").update!
97
+ device.stream("load_15m").update!
98
+
99
+ while @run
100
+ load_1m, load_5m, load_15m = load_avg
101
+
102
+ # Write the different values into AT&T M2X
103
+ now = Time.now.iso8601
104
+
105
+ values = {
106
+ load_1m: [ { value: load_1m, timestamp: now } ],
107
+ load_5m: [ { value: load_5m, timestamp: now } ],
108
+ load_15m: [ { value: load_15m, timestamp: now } ]
109
+ }
110
+
111
+ res = device.post_updates(values: values)
112
+
113
+ sleep 1
114
+ end
115
+
116
+ puts
117
+ ```
118
+
119
+ You can find this script in [`examples/m2x-uptime.rb`](examples/m2x-uptime.rb).
120
+
121
+ ## Versioning
122
+
123
+ This gem aims to adhere to [Semantic Versioning 2.0.0](http://semver.org/). As a summary, given a version number `MAJOR.MINOR.PATCH`:
124
+
125
+ 1. `MAJOR` will increment when backwards-incompatible changes are introduced to the client.
126
+ 2. `MINOR` will increment when backwards-compatible functionality is added.
127
+ 3. `PATCH` will increment with backwards-compatible bug fixes.
128
+
129
+ Additional labels for pre-release and build metadata are available as extensions to the `MAJOR.MINOR.PATCH` format.
130
+
131
+ **Note**: the client version does not necessarily reflect the version used in the AT&T M2X API.
132
+
133
+ ## License
134
+
135
+ This gem is provided under the MIT license. See [LICENSE](LICENSE) for applicable terms.
@@ -0,0 +1,47 @@
1
+ module M2X
2
+ class MQTT
3
+ require_relative "mqtt/version"
4
+ require_relative "mqtt/client"
5
+ require_relative "mqtt/resource"
6
+ require_relative "mqtt/device"
7
+ require_relative "mqtt/distribution"
8
+ require_relative "mqtt/stream"
9
+
10
+ attr_accessor :client
11
+
12
+ def initialize(api_key, options={})
13
+ @api_key = api_key
14
+ @options = options
15
+ end
16
+
17
+ def client
18
+ @client ||= M2X::MQTT::Client.new(@api_key, @options)
19
+ end
20
+
21
+ # Returns the status of the M2X system.
22
+ #
23
+ # The response to this endpoint is an object in which each of its attributes
24
+ # represents an M2X subsystem and its current status.
25
+ def status
26
+ client.subscribe
27
+ client.get("/status")
28
+ client.get_response
29
+ end
30
+
31
+ def device(id)
32
+ M2X::MQTT::Device.new(client, "id" => id)
33
+ end
34
+
35
+ def create_device(attributes)
36
+ M2X::MQTT::Device.create!(client, attributes)
37
+ end
38
+
39
+ def distribution(id)
40
+ M2X::MQTT::Distribution.new(client, "id" => id)
41
+ end
42
+
43
+ def stream(device_id, name)
44
+ M2X::MQTT::Stream.new(client, device(device_id), "name" => name)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,117 @@
1
+ require "mqtt"
2
+ require "json"
3
+ require "securerandom"
4
+
5
+ class M2X::MQTT::Client
6
+ DEFAULT_API_URL = "api-m2x.att.com".freeze
7
+ API_VERSION = "v2"
8
+
9
+ USER_AGENT = "M2X-Ruby/#{M2X::MQTT::VERSION} #{RUBY_ENGINE}/#{RUBY_VERSION} (#{RUBY_PLATFORM})".freeze
10
+
11
+ DEFAULTS = {
12
+ api_url: DEFAULT_API_URL,
13
+ use_ssl: false
14
+ }
15
+
16
+ def initialize(api_key, options={})
17
+ @api_key = api_key
18
+ @options = DEFAULTS.merge(options)
19
+ end
20
+
21
+ # Public: Subscribe the client to the responses topic.
22
+ #
23
+ # This is required in order to receive responses from the
24
+ # M2X API server. Note that #get_response already subscribes
25
+ # the client.
26
+ def subscribe
27
+ mqtt_client.subscribe(response_topic)
28
+ end
29
+
30
+ # Public: Send a payload to the M2X API server.
31
+ #
32
+ # payload - a Hash with the following keys:
33
+ # :id
34
+ # :method
35
+ # :resource
36
+ # :body
37
+ # See https://m2x.att.com/developer/documentation/v2/mqtt
38
+ def publish(payload)
39
+ mqtt_client.publish(request_topic, payload.to_json)
40
+ end
41
+
42
+ # Public: Retrieve a response from the M2X Server.
43
+ #
44
+ # Returns a Hash with the response from the MQTT Server in M2X.
45
+ # Optionally receives a block which will iterate through responses
46
+ # and yield each one.
47
+ def get_response
48
+ return JSON.parse(mqtt_client.get_packet(response_topic).payload) unless block_given?
49
+
50
+ mqtt_client.get_packet(response_topic) do |packet|
51
+ yield JSON.parse(packet.payload)
52
+ end
53
+ end
54
+
55
+ [:get, :post, :put, :delete, :head, :options, :patch].each do |verb|
56
+ define_method verb do |path, params=nil|
57
+ request(verb, path, params)
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def request(verb, path, params=nil)
64
+ path = versioned(path)
65
+ body = params || {}
66
+
67
+ payload = {
68
+ id: SecureRandom.hex,
69
+ agent: USER_AGENT,
70
+ method: verb.upcase,
71
+ resource: path,
72
+ body: body
73
+ }
74
+
75
+ publish(payload)
76
+
77
+ { id: payload[:id] }
78
+ end
79
+
80
+ def request_topic
81
+ @request_topic ||= "m2x/#{@api_key}/requests".freeze
82
+ end
83
+
84
+ def response_topic
85
+ @response_topic ||= "m2x/#{@api_key}/responses".freeze
86
+ end
87
+
88
+ def mqtt_client
89
+ @mqtt_client ||= ::MQTT::Client.new.tap do |client|
90
+ client.host = @options[:api_url]
91
+ client.username = @api_key
92
+
93
+ if @options[:use_ssl]
94
+ client.ssl = true
95
+ client.port = 8883
96
+ end
97
+ end
98
+
99
+ unless @mqtt_client.connected?
100
+ @mqtt_client.connect
101
+ end
102
+
103
+ @mqtt_client
104
+ end
105
+
106
+ def versioned(path)
107
+ versioned?(path) ? path : "/#{API_VERSION}#{path}"
108
+ end
109
+
110
+ def versioned?(path)
111
+ path =~ /^\/v\d+\//
112
+ end
113
+
114
+ at_exit do
115
+ @mqtt_client.disconnect if defined?(@mqtt_client)
116
+ end
117
+ end
@@ -0,0 +1,62 @@
1
+ # Wrapper for AT&T M2X Device API
2
+ # https://m2x.att.com/developer/documentation/v2/device
3
+ class M2X::MQTT::Device < M2X::MQTT::Resource
4
+
5
+ PATH = "/devices"
6
+
7
+ class << self
8
+ # Create a new device
9
+ #
10
+ # https://m2x.att.com/developer/documentation/v2/device#Create-Device
11
+ def create!(client, params)
12
+ client.post(PATH, params)
13
+
14
+ new(client, params)
15
+ end
16
+ end
17
+
18
+ def path
19
+ @path ||= "#{ PATH }/#{ URI.encode(@attributes.fetch("id")) }"
20
+ end
21
+
22
+ def stream(name)
23
+ M2X::MQTT::Stream.new(@client, self, "name" => name)
24
+ end
25
+
26
+ # Update the current location of the specified device.
27
+ #
28
+ # https://m2x.att.com/developer/documentation/v2/device#Update-Device-Location
29
+ def update_location(params)
30
+ @client.put("#{path}/location", params)
31
+ end
32
+
33
+ # Post Device Updates (Multiple Values to Multiple Streams)
34
+ #
35
+ # This method allows posting multiple values to multiple streams
36
+ # belonging to a device and optionally, the device location.
37
+ #
38
+ # All the streams should be created before posting values using this method.
39
+ #
40
+ # The `values` parameter contains an object with one attribute per each stream to be updated.
41
+ # The value of each one of these attributes is an array of timestamped values.
42
+ #
43
+ # {
44
+ # temperature: [
45
+ # { "timestamp": <Time in ISO8601>, "value": x },
46
+ # { "timestamp": <Time in ISO8601>, "value": y },
47
+ # ],
48
+ # humidity: [
49
+ # { "timestamp": <Time in ISO8601>, "value": x },
50
+ # { "timestamp": <Time in ISO8601>, "value": y },
51
+ # ]
52
+ #
53
+ # }
54
+ #
55
+ # The optional location attribute can contain location information that will
56
+ # be used to update the current location of the specified device
57
+ #
58
+ # https://staging.m2x.sl.attcompute.com/developer/documentation/v2/device#Post-Device-Updates--Multiple-Values-to-Multiple-Streams-
59
+ def post_updates(params)
60
+ @client.post("#{path}/updates", params)
61
+ end
62
+ end
@@ -0,0 +1,20 @@
1
+ # Wrapper for AT&T M2X Distribution API
2
+ # https://m2x.att.com/developer/documentation/v2/distribution
3
+ class M2X::MQTT::Distribution < M2X::MQTT::Resource
4
+
5
+ PATH = "/distributions"
6
+
7
+ def path
8
+ @path ||= "#{ PATH }/#{ URI.encode(@attributes.fetch("id")) }"
9
+ end
10
+
11
+ # Add a new device to an existing distribution
12
+ #
13
+ # Accepts a `serial` parameter, that must be a unique identifier
14
+ # within this distribution.
15
+ #
16
+ # https://m2x.att.com/developer/documentation/v2/distribution#Add-Device-to-an-existing-Distribution
17
+ def add_device(serial)
18
+ @client.post("#{path}/devices", serial: serial)
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ require "uri"
2
+ require "forwardable"
3
+
4
+ # Wrapper for M2X::Client resources
5
+ class M2X::MQTT::Resource
6
+ extend Forwardable
7
+
8
+ attr_reader :attributes
9
+
10
+ def_delegator :@attributes, :[]
11
+
12
+ def initialize(client, attributes)
13
+ @client = client
14
+ @attributes = attributes
15
+ end
16
+
17
+ def inspect
18
+ "<#{self.class.name}: #{attributes.inspect}>"
19
+ end
20
+
21
+ def path
22
+ raise NotImplementedError
23
+ end
24
+ end
@@ -0,0 +1,53 @@
1
+ # Wrapper for AT&T M2X Data Streams API
2
+ # https://m2x.att.com/developer/documentation/v2/device
3
+ class M2X::MQTT::Stream < M2X::MQTT::Resource
4
+
5
+ def initialize(client, device, attributes)
6
+ @client = client
7
+ @device = device
8
+ @attributes = attributes
9
+ end
10
+
11
+ def path
12
+ @path ||= "#{@device.path}/streams/#{ URI.encode(@attributes.fetch("name")) }"
13
+ end
14
+
15
+ # Update stream properties
16
+ # (if the stream does not exist it gets created).
17
+ #
18
+ # https://m2x.att.com/developer/documentation/v2/device#Create-Update-Data-Stream
19
+ def update!(params={})
20
+ @client.put(path, params)
21
+
22
+ @attributes.merge!(params)
23
+ end
24
+
25
+ # Update the current value of the stream. The timestamp
26
+ # is optional. If ommited, the current server time will be used
27
+ #
28
+ # https://m2x.att.com/developer/documentation/v2/device#Update-Data-Stream-Value
29
+ def update_value(value, timestamp=nil)
30
+ params = { value: value }
31
+
32
+ params[:at] = timestamp if timestamp
33
+
34
+ @client.put("#{path}/value", params)
35
+ end
36
+
37
+ # Post multiple values to the stream
38
+ #
39
+ # The `values` parameter is an array with the following format:
40
+ #
41
+ # [
42
+ # { "timestamp": <Time in ISO8601>, "value": x },
43
+ # { "timestamp": <Time in ISO8601>, "value": y },
44
+ # [ ... ]
45
+ # ]
46
+ #
47
+ # https://m2x.att.com/developer/documentation/v2/device#Post-Data-Stream-Values
48
+ def post_values(values)
49
+ params = { values: values }
50
+
51
+ @client.post("#{path}/values", params)
52
+ end
53
+ end
@@ -0,0 +1,5 @@
1
+ module M2X
2
+ class MQTT
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ require "./lib/m2x/mqtt/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "m2x-mqtt"
7
+ s.version = ::M2X::MQTT::VERSION
8
+ s.summary = "Ruby client for AT&T M2X (MQTT)"
9
+ s.description = "AT&T’s M2X is a cloud-based fully managed data storage service for network connected machine-to-machine (M2M) devices. From trucks and turbines to vending machines and freight containers, M2X enables the devices that power your business to connect and share valuable data."
10
+ s.authors = ["Leandro López", "Matías Flores", "Federico Saravia"]
11
+ s.email = ["inkel.ar@gmail.com", "flores.matias@gmail.com", "fedesaravia@gmail.com"]
12
+ s.homepage = "http://github.com/attm2x/m2x-ruby-mqtt"
13
+ s.licenses = ["MIT"]
14
+
15
+ s.files = Dir[
16
+ "LICENSE",
17
+ "README.md",
18
+ "lib/**/*.rb",
19
+ "*.gemspec"
20
+ ]
21
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: m2x-mqtt
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Leandro López
8
+ - Matías Flores
9
+ - Federico Saravia
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2015-03-16 00:00:00.000000000 Z
14
+ dependencies: []
15
+ description: AT&T’s M2X is a cloud-based fully managed data storage service for network
16
+ connected machine-to-machine (M2M) devices. From trucks and turbines to vending
17
+ machines and freight containers, M2X enables the devices that power your business
18
+ to connect and share valuable data.
19
+ email:
20
+ - inkel.ar@gmail.com
21
+ - flores.matias@gmail.com
22
+ - fedesaravia@gmail.com
23
+ executables: []
24
+ extensions: []
25
+ extra_rdoc_files: []
26
+ files:
27
+ - LICENSE
28
+ - README.md
29
+ - lib/m2x/mqtt.rb
30
+ - lib/m2x/mqtt/client.rb
31
+ - lib/m2x/mqtt/device.rb
32
+ - lib/m2x/mqtt/distribution.rb
33
+ - lib/m2x/mqtt/resource.rb
34
+ - lib/m2x/mqtt/stream.rb
35
+ - lib/m2x/mqtt/version.rb
36
+ - m2x-mqtt.gemspec
37
+ homepage: http://github.com/attm2x/m2x-ruby-mqtt
38
+ licenses:
39
+ - MIT
40
+ metadata: {}
41
+ post_install_message:
42
+ rdoc_options: []
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ requirements: []
56
+ rubyforge_project:
57
+ rubygems_version: 2.4.5
58
+ signing_key:
59
+ specification_version: 4
60
+ summary: Ruby client for AT&T M2X (MQTT)
61
+ test_files: []
62
+ has_rdoc: