m2x 1.0.0 → 2.0.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: 5ec355421314977e15e2c05ae0eb1efc9d0177d4
4
- data.tar.gz: ed401f222ce4c00a41e2d347a1fcafb268a2d433
3
+ metadata.gz: 084cf856cdc4b7844875f78adb56260dc52257a0
4
+ data.tar.gz: b9cc0d3d5185bc385d37121fa183248ceaef97f4
5
5
  SHA512:
6
- metadata.gz: f1e7b7bac788b62e4868e16073d048bb104e64984c1fbe08df3d1e47fccd2b01482a10f67b096b7dacfa9e37644a6031ec3d1750af88eda41e61d273d5289815
7
- data.tar.gz: cdde61bc4b9f577c5d9bbaf85f6ebfd079f158c3bbbc75e8caeb9305837d536d4e9ada1715100332d59dcafd87ca8e59c82f7cd90bebd20d7e3f40f1c521c658
6
+ metadata.gz: 33ee0afd354825adbe05a148c191776e07dd1ac3c3d41fb220d90fc1eee6f7d8040baa5f3cee0106fdb5961e977a149d5ae14600a8db5196552045cef03a898d
7
+ data.tar.gz: 1f12c23f3fe2aea2ccf4ccb93797c4be1a7b08b6fe336ba7a157b1c92a45d0db98d5007cd1ff3da17f527e10412388dffd54b6626048e421d0b9d99754c22fd1
data/README.md CHANGED
@@ -9,7 +9,7 @@ Getting Started
9
9
  ==========================
10
10
  1. Signup for an [M2X Account](https://m2x.att.com/signup).
11
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 [Data Source Blueprint](https://m2x.att.com/blueprints) and copy its _Feed ID_.
12
+ 2. Create your first [Device](https://m2x.att.com/devices) and copy its _Device ID_.
13
13
  3. Review the [M2X API Documentation](https://m2x.att.com/developer/documentation/overview).
14
14
 
15
15
  ## Installation
@@ -20,43 +20,46 @@ $ gem install m2x
20
20
 
21
21
  ## Usage
22
22
 
23
- In order to communicate with the M2X API, you need an instance of [M2X](lib/m2x.rb). You need to pass your API key in the constructor to access your data.
23
+ In order to communicate with the M2X API, you need an instance of [M2X::Client](lib/m2x/client.rb). You need to pass your API key in the constructor to access your data.
24
24
 
25
25
  ```ruby
26
- m2x = M2X.new(<YOUR-API-KEY>)
26
+ m2x = M2X::Client.new(<YOUR-API-KEY>)
27
27
  ```
28
28
 
29
29
  This provides an interface to your data on M2X
30
30
 
31
- - [Blueprints](lib/m2x/blueprints.rb)
31
+ - [Distribution](lib/m2x/distribution.rb)
32
32
  ```ruby
33
- blueprints_api = m2x.blueprints
34
- ```
33
+ distribution = m2x.distribution("<DISTRIBUTION-ID>")
35
34
 
36
- - [Batches](lib/m2x/batches.rb)
37
- ```ruby
38
- batches_api = m2x.batches
39
- ```
40
- - [Datasources](lib/m2x/datasources.rb)
41
- ```ruby
42
- datasources_api = m2x.datasources
35
+ distributions = m2x.distributions
43
36
  ```
44
37
 
45
- - [Feeds](lib/m2x/feeds.rb)
38
+ - [Device](lib/m2x/device.rb)
46
39
  ```ruby
47
- feeds_api = m2x.feeds
40
+ device = m2x.device("<DEVICE-ID>")
41
+
42
+ devices = m2x.devices
48
43
  ```
49
44
 
50
- - [Keys](lib/m2x/keys.rb)
45
+ - [Key](lib/m2x/key.rb)
51
46
  ```ruby
52
- keys_api = m2x.keys
47
+ key = m2x.key("<KEY-TOKEN>")
48
+
49
+ keys = m2x.keys
53
50
  ```
54
51
 
55
52
  Refer to the documentation on each class for further usage instructions.
56
53
 
57
54
  ## Example
58
55
 
59
- In order to run this example, you will need a `Feed ID` and `API Key`. If you don't have any, access your M2X account, create a new [Data Source Blueprint](https://m2x.att.com/blueprints), and copy the `Feed 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:
56
+ 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.
57
+
58
+ In order to execute this script run:
59
+
60
+ ```bash
61
+ API_KEY=<YOUR-API-KEY> DEVICE=<YOUR-DEVICE-ID> ./m2x-uptime.rb
62
+ ```
60
63
 
61
64
  ```ruby
62
65
  #! /usr/bin/env ruby
@@ -69,13 +72,17 @@ In order to run this example, you will need a `Feed ID` and `API Key`. If you do
69
72
  require "time"
70
73
  require "m2x"
71
74
 
72
- API_KEY = "<YOUR-FEED-API-KEY>"
73
- FEED = "<YOUR-FEED-ID>"
75
+ API_KEY = ENV.fetch("API_KEY")
76
+ DEVICE = ENV.fetch("DEVICE")
74
77
 
75
- m2x = M2X.new(API_KEY)
78
+ puts "M2X::Client/#{M2X::Client::VERSION} example"
76
79
 
77
80
  @run = true
78
- trap(:INT) { @run = false }
81
+
82
+ stop = Proc.new { @run = false }
83
+
84
+ trap(:INT, &stop)
85
+ trap(:TERM, &stop)
79
86
 
80
87
  # Match `uptime` load averages output for both Linux and OSX
81
88
  UPTIME_RE = /(\d+\.\d+),? (\d+\.\d+),? (\d+\.\d+)$/
@@ -84,10 +91,15 @@ def load_avg
84
91
  `uptime`.match(UPTIME_RE).captures
85
92
  end
86
93
 
94
+ m2x = M2X::Client.new(API_KEY)
95
+
96
+ # Get the device
97
+ device = m2x.device(DEVICE)
98
+
87
99
  # Create the streams if they don't exist
88
- m2x.feeds.update_stream(FEED, "load_1m")
89
- m2x.feeds.update_stream(FEED, "load_5m")
90
- m2x.feeds.update_stream(FEED, "load_15m")
100
+ device.create_stream("load_1m")
101
+ device.create_stream("load_5m")
102
+ device.create_stream("load_15m")
91
103
 
92
104
  while @run
93
105
  load_1m, load_5m, load_15m = load_avg
@@ -96,14 +108,14 @@ while @run
96
108
  now = Time.now.iso8601
97
109
 
98
110
  values = {
99
- load_1m: [ { value: load_1m, at: now } ],
100
- load_5m: [ { value: load_5m, at: now } ],
101
- load_15m: [ { value: load_15m, at: now } ]
111
+ load_1m: [ { value: load_1m, timestamp: now } ],
112
+ load_5m: [ { value: load_5m, timestamp: now } ],
113
+ load_15m: [ { value: load_15m, timestamp: now } ]
102
114
  }
103
115
 
104
- res = m2x.feeds.post_multiple(FEED, values)
116
+ res = device.post_updates(values: values)
105
117
 
106
- abort res.json["message"] unless res.code == 202
118
+ abort res.json["message"] unless res.success?
107
119
 
108
120
  sleep 1
109
121
  end
data/lib/m2x/client.rb CHANGED
@@ -2,94 +2,180 @@ require "net/http"
2
2
  require "json"
3
3
  require "openssl"
4
4
 
5
- class M2X
6
- class Client
7
- API_BASE = "http://api-m2x.att.com/v1".freeze
5
+ # Interface for connecting with M2X API service.
6
+ #
7
+ # This class provides convenience methods to access M2X most common resources.
8
+ # It can also be used to access any endpoint directly like this:
9
+ #
10
+ # m2x = M2X::Client.new("<YOUR-API-KEY>")
11
+ # m2x.get("/some_path")
12
+ #
13
+ class M2X::Client
14
+ DEFAULT_API_BASE = "https://api-m2x.att.com".freeze
15
+ DEFAULT_API_VERSION = "v2".freeze
16
+
17
+ CA_FILE = File.expand_path("../cacert.pem", __FILE__)
18
+
19
+ USER_AGENT = "M2X-Ruby/#{M2X::Client::VERSION} #{RUBY_ENGINE}/#{RUBY_VERSION} (#{RUBY_PLATFORM})".freeze
20
+
21
+ attr_accessor :api_key
22
+ attr_accessor :api_base
23
+ attr_accessor :api_version
24
+ attr_reader :last_response
25
+
26
+ def initialize(api_key=nil, api_base=nil)
27
+ @api_key = api_key
28
+ @api_base = api_base
29
+ @api_version = api_version
30
+ end
8
31
 
9
- CA_FILE = File.expand_path("../cacert.pem", __FILE__)
32
+ # Returns the status of the M2X system.
33
+ #
34
+ # The response to this endpoint is an object in which each of its attributes
35
+ # represents an M2X subsystem and its current status.
36
+ def status
37
+ get("/status")
38
+ end
10
39
 
11
- USER_AGENT = "M2X/#{::M2X::VERSION} (Ruby Net::HTTP)".freeze
40
+ # Obtain a Device from M2X
41
+ #
42
+ # This method instantiates an instance of Device and calls `Device#view`
43
+ # method, returning the device instance with all its attributes initialized
44
+ def device(id)
45
+ M2X::Client::Device.new(self, "id" => id).tap(&:view)
46
+ end
12
47
 
13
- def initialize(api_key=nil, api_base=nil)
14
- @api_base = api_base
15
- @api_key = api_key
16
- end
48
+ # Creates a new device on M2X with the specified parameters
49
+ def create_device(params)
50
+ M2X::Client::Device.create!(self, params)
51
+ end
17
52
 
18
- def request(verb, path, qs=nil, params=nil, headers=nil)
19
- url = URI.parse(File.join(api_base, path))
53
+ # Retrieve the list of devices accessible by the authenticated API key that
54
+ # meet the search criteria.
55
+ #
56
+ # See M2X::Client::Device.list for more details
57
+ def devices(params={})
58
+ M2X::Client::Device.list(self, params)
59
+ end
20
60
 
21
- url.query = URI.encode_www_form(qs) unless qs.nil? || qs.empty?
61
+ # Search the catalog of public Devices.
62
+ #
63
+ # This allows unauthenticated users to search Devices from other users that
64
+ # have been marked as public, allowing them to read public Device metadata,
65
+ # locations, streams list, and view each Devices' stream metadata and its
66
+ # values.
67
+ #
68
+ # See M2X::Client::Device.catalog for more details
69
+ def device_catalog(params={})
70
+ M2X::Client::Device.catalog(self, params)
71
+ end
22
72
 
23
- headers = default_headers.merge(headers || {})
73
+ # Obtain a Distribution from M2X
74
+ #
75
+ # This method instantiates an instance of Distribution and calls
76
+ # `Distribution#view` method, returning the device instance with all
77
+ # its attributes initialized
78
+ def distribution(id)
79
+ M2X::Client::Distribution.new(self, "id" => id).tap(&:view)
80
+ end
24
81
 
25
- body = if params
26
- headers["Content-Type"] ||= "application/x-www-form-urlencoded"
82
+ # Creates a new device distribution on M2X with the specified parameters
83
+ def create_distribution(params)
84
+ M2X::Client::Distribution.create!(self, params)
85
+ end
27
86
 
28
- case headers["Content-Type"]
29
- when "application/json" then JSON.dump(params)
30
- when "application/x-www-form-urlencoded" then URI.encode_www_form(params)
31
- else
32
- raise ArgumentError, "Unrecognized Content-Type `#{headers["Content-Type"]}`"
33
- end
34
- end
87
+ # Retrieve list of device distributions accessible by the authenticated
88
+ # API key.
89
+ #
90
+ # See M2X::Client::Distribution.list for more details
91
+ def distributions(params={})
92
+ M2X::Client::Distribution.list(self, params)
93
+ end
35
94
 
36
- options = {}
37
- options.merge!(use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_PEER, ca_file: CA_FILE) if url.scheme == "https"
95
+ # Obtain an API Key from M2X
96
+ #
97
+ # This method instantiates an instance of Key and calls
98
+ # `Key#view` method, returning the key instance with all
99
+ # its attributes initialized
100
+ def key(key)
101
+ M2X::Client::Key.new(self, "key" => key).tap(&:view)
102
+ end
38
103
 
39
- path = url.path
40
- path << "?#{url.query}" if url.query
104
+ # Create a new API Key
105
+ #
106
+ # Note that, according to the parameters sent, you can create a
107
+ # Master API Key or a Device/Stream API Key.
108
+ #
109
+ # See M2X::Client::Key.create! for more details
110
+ def create_key(params)
111
+ M2X::Client::Key.create!(self, params)
112
+ end
41
113
 
42
- res = Net::HTTP.start(url.host, url.port, options) do |http|
43
- http.send_request(verb.to_s.upcase, path, body, headers)
44
- end
114
+ # Retrieve list of keys associated with the user account.
115
+ #
116
+ # See M2X::Client::Key.list for more details
117
+ def keys
118
+ M2X::Client::Key.list(self)
119
+ end
45
120
 
46
- Response.new(res)
121
+ # Define methods for accessing M2X REST API
122
+ [:get, :post, :put, :delete, :head, :options, :patch].each do |verb|
123
+ define_method verb do |path, qs=nil, params=nil, headers=nil|
124
+ request(verb, path, qs, params, headers)
47
125
  end
126
+ end
48
127
 
49
- [:get, :post, :put, :delete, :head, :options, :patch].each do |verb|
50
- define_method verb do |path, qs=nil, params=nil, headers=nil|
51
- request(verb, path, qs, params, headers)
52
- end
53
- end
128
+ private
129
+ def request(verb, path, qs=nil, params=nil, headers=nil)
130
+ url = URI.parse(File.join(api_base, versioned(path)))
54
131
 
55
- class Response
56
- attr_reader :response
132
+ url.query = URI.encode_www_form(qs) unless qs.nil? || qs.empty?
57
133
 
58
- def initialize(response)
59
- @response = response
60
- end
134
+ headers = default_headers.merge(headers || {})
61
135
 
62
- def raw
63
- @response.body
64
- end
136
+ body = if params
137
+ headers["Content-Type"] ||= "application/x-www-form-urlencoded"
65
138
 
66
- def json
67
- raise "#{@response.content_type} is not application/json" unless @response.content_type == "application/json"
139
+ case headers["Content-Type"]
140
+ when "application/json" then JSON.dump(params)
141
+ when "application/x-www-form-urlencoded" then URI.encode_www_form(params)
142
+ else
143
+ raise ArgumentError, "Unrecognized Content-Type `#{headers["Content-Type"]}`"
144
+ end
145
+ end
68
146
 
69
- @json ||= ::JSON.parse(raw)
70
- end
147
+ options = {}
148
+ options.merge!(use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_PEER, ca_file: CA_FILE) if url.scheme == "https"
71
149
 
72
- def code
73
- @code ||= @response.code.to_i
74
- end
150
+ path = url.path
151
+ path << "?#{url.query}" if url.query
75
152
 
76
- def headers
77
- @headers ||= @response.to_hash
78
- end
153
+ res = Net::HTTP.start(url.host, url.port, options) do |http|
154
+ http.send_request(verb.to_s.upcase, path, body, headers)
79
155
  end
80
156
 
81
- private
157
+ @last_response = Response.new(res)
158
+ end
82
159
 
83
- def api_base
84
- @api_base ||= API_BASE
85
- end
160
+ def api_base
161
+ @api_base ||= DEFAULT_API_BASE
162
+ end
86
163
 
87
- def default_headers
88
- @headers ||= begin
89
- headers = { "User-Agent" => USER_AGENT }
90
- headers.merge!("X-M2X-KEY" => @api_key) if @api_key
91
- headers
92
- end
93
- end
164
+ def api_version
165
+ @api_version ||= DEFAULT_API_VERSION
166
+ end
167
+
168
+ def versioned(path)
169
+ versioned?(path) ? path : "/#{api_version}#{path}"
170
+ end
171
+
172
+ def versioned?(path)
173
+ path =~ /^\/v\d+\//
174
+ end
175
+
176
+ def default_headers
177
+ @headers ||= { "User-Agent" => USER_AGENT }.tap do |headers|
178
+ headers["X-M2X-KEY"] = @api_key if @api_key
179
+ end
94
180
  end
95
181
  end
data/lib/m2x/device.rb ADDED
@@ -0,0 +1,147 @@
1
+ # Wrapper for AT&T M2X Device API
2
+ # https://m2x.att.com/developer/documentation/v2/device
3
+ class M2X::Client::Device < M2X::Client::Resource
4
+
5
+ PATH = "/devices"
6
+
7
+ class << self
8
+ # Retrieve the list of devices accessible by the authenticated API key that
9
+ # meet the search criteria.
10
+ #
11
+ # https://m2x.att.com/developer/documentation/v2/device#List-Search-Devices
12
+ def list(client, params={})
13
+ res = client.get(PATH, params)
14
+
15
+ res.json["devices"].map{ |atts| new(client, atts) } if res.success?
16
+ end
17
+
18
+ # Search the catalog of public Devices.
19
+ #
20
+ # This allows unauthenticated users to search Devices from other users
21
+ # that have been marked as public, allowing them to read public Device
22
+ # metadata, locations, streams list, and view each Devices' stream metadata
23
+ # and its values.
24
+ #
25
+ # https://m2x.att.com/developer/documentation/v2/device#List-Search-Public-Devices-Catalog
26
+ def catalog(client, params={})
27
+ res = client.get("#{PATH}/catalog", params)
28
+
29
+ res.json["devices"].map{ |atts| new(client, atts) } if res.success?
30
+ end
31
+
32
+ # List Device Groups
33
+ # Retrieve the list of device groups for the authenticated user.
34
+ #
35
+ # https://m2x.att.com/developer/documentation/v2/device#List-Device-Groups
36
+ def groups(client)
37
+ client.get("#{PATH}/groups")
38
+ end
39
+
40
+ # Create a new device
41
+ #
42
+ # https://m2x.att.com/developer/documentation/v2/device#Create-Device
43
+ def create!(client, params)
44
+ res = client.post(PATH, nil, params, "Content-Type" => "application/json")
45
+
46
+ new(client, res.json) if res.success?
47
+ end
48
+ end
49
+
50
+ def path
51
+ @path ||= "#{ PATH }/#{ URI.encode(@attributes.fetch("id")) }"
52
+ end
53
+
54
+ # View Request Log
55
+ # Retrieve list of HTTP requests received lately by the specified device
56
+ # (up to 100 entries).
57
+ #
58
+ # https://m2x.att.com/developer/documentation/v2/device#View-Request-Log
59
+ def log
60
+ @client.get("#{path}/log")
61
+ end
62
+
63
+ # Get location details of an existing Device.
64
+ #
65
+ # Note that this method can return an empty value (response status
66
+ # of 204) if the device has no location defined.
67
+ #
68
+ # https://m2x.att.com/developer/documentation/v2/device#Read-Device-Location
69
+ def location
70
+ @client.get("#{path}/location")
71
+ end
72
+
73
+ # Update the current location of the specified device.
74
+ #
75
+ # https://m2x.att.com/developer/documentation/v2/device#Update-Device-Location
76
+ def update_location(params)
77
+ @client.put("#{path}/location", nil, params, "Content-Type" => "application/json")
78
+ end
79
+
80
+ # Post Device Updates (Multiple Values to Multiple Streams)
81
+ #
82
+ # This method allows posting multiple values to multiple streams
83
+ # belonging to a device and optionally, the device location.
84
+ #
85
+ # All the streams should be created before posting values using this method.
86
+ #
87
+ # The `values` parameter contains an object with one attribute per each stream to be updated.
88
+ # The value of each one of these attributes is an array of timestamped values.
89
+ #
90
+ # {
91
+ # temperature: [
92
+ # { "timestamp": <Time in ISO8601>, "value": x },
93
+ # { "timestamp": <Time in ISO8601>, "value": y },
94
+ # ],
95
+ # humidity: [
96
+ # { "timestamp": <Time in ISO8601>, "value": x },
97
+ # { "timestamp": <Time in ISO8601>, "value": y },
98
+ # ]
99
+ #
100
+ # }
101
+ #
102
+ # The optional location attribute can contain location information that will
103
+ # be used to update the current location of the specified device
104
+ #
105
+ # https://staging.m2x.sl.attcompute.com/developer/documentation/v2/device#Post-Device-Updates--Multiple-Values-to-Multiple-Streams-
106
+ def post_updates(params)
107
+ @client.post("#{path}/updates", nil, params, "Content-Type" => "application/json")
108
+ end
109
+
110
+ # Retrieve list of data streams associated with the device.
111
+ #
112
+ # https://m2x.att.com/developer/documentation/v2/device#List-Data-Streams
113
+ def streams
114
+ ::M2X::Client::Stream.list(@client, self)
115
+ end
116
+
117
+ # Get details of a specific data Stream associated with the device
118
+ #
119
+ # https://m2x.att.com/developer/documentation/v2/device#View-Data-Stream
120
+ def stream(name)
121
+ ::M2X::Client::Stream.fetch(@client, self, name)
122
+ end
123
+
124
+ # Update a data stream associated with the Device
125
+ # (if a stream with this name does not exist it gets created).
126
+ #
127
+ # https://m2x.att.com/developer/documentation/v2/device#Create-Update-Data-Stream
128
+ def update_stream(name, params={})
129
+ stream = ::M2X::Client::Stream.new(@client, self, "name" => name)
130
+
131
+ stream.update!(params)
132
+ end
133
+ alias_method :create_stream, :update_stream
134
+
135
+ # Returns a list of API keys associated with the device
136
+ def keys
137
+ ::M2X::Client::Key.list(@client, params.merge(device: self["id"]))
138
+ end
139
+
140
+ # Creates a new API key associated to the device
141
+ #
142
+ # If a parameter named `stream` is supplied with a stream name, it
143
+ # will create an API key associated with that stream only.
144
+ def create_key(params)
145
+ ::M2X::Client::Key.create!(@client, params.merge(device: self["id"]))
146
+ end
147
+ end
@@ -0,0 +1,53 @@
1
+ # Wrapper for AT&T M2X Distribution API
2
+ # https://m2x.att.com/developer/documentation/v2/distribution
3
+ class M2X::Client::Distribution < M2X::Client::Resource
4
+
5
+ PATH = "/distributions"
6
+
7
+ class << self
8
+ # Retrieve list of device distributions accessible by the authenticated
9
+ # API key.
10
+ #
11
+ # https://m2x.att.com/developer/documentation/v2/distribution#List-Distributions
12
+ def list(client, params={})
13
+ res = client.get(PATH, params)
14
+
15
+ res.json["distributions"].map{ |atts| new(client, atts) } if res.success?
16
+ end
17
+ alias_method :search, :list
18
+
19
+ # Create a new device distribution
20
+ #
21
+ # https://m2x.att.com/developer/documentation/v2/distribution#Create-Distribution
22
+ def create!(client, params)
23
+ res = client.post(PATH, nil, params, "Content-Type" => "application/json")
24
+
25
+ new(client, res.json) if res.success?
26
+ end
27
+ end
28
+
29
+ def path
30
+ @path ||= "#{ PATH }/#{ URI.encode(@attributes.fetch("id")) }"
31
+ end
32
+
33
+ # Retrieve list of devices added to the specified distribution.
34
+ #
35
+ # https://m2x.att.com/developer/documentation/v2/distribution#List-Devices-from-an-existing-Distribution
36
+ def devices(params={})
37
+ res = @client.get("#{path}/devices", params)
38
+
39
+ res.json["devices"].map{ |atts| ::M2X::Client::Device.new(@client, atts) } if res.success?
40
+ end
41
+
42
+ # Add a new device to an existing distribution
43
+ #
44
+ # Accepts a `serial` parameter, that must be a unique identifier
45
+ # within this distribution.
46
+ #
47
+ # https://m2x.att.com/developer/documentation/v2/distribution#Add-Device-to-an-existing-Distribution
48
+ def add_device(serial)
49
+ res = @client.post("#{path}/devices", nil, { serial: serial }, "Content-Type" => "application/json")
50
+
51
+ ::M2X::Client::Device.new(@client, res.json) if res.success?
52
+ end
53
+ end
data/lib/m2x/key.rb ADDED
@@ -0,0 +1,49 @@
1
+ # Wrapper for AT&T M2X Keys API
2
+ # https://m2x.att.com/developer/documentation/v2/keys
3
+ class M2X::Client::Key < M2X::Client::Resource
4
+
5
+ PATH = "/keys"
6
+
7
+ class << self
8
+ # Retrieve list of keys associated with the user account.
9
+ #
10
+ # https://m2x.att.com/developer/documentation/v2/keys#List-Keys
11
+ def list(client, params={})
12
+ res = client.get(PATH, params)
13
+
14
+ res.json["keys"].map{ |atts| new(client, atts) } if res.success?
15
+ end
16
+
17
+ # Create a new API Key
18
+ #
19
+ # Note that, according to the parameters sent, you can create a
20
+ # Master API Key or a Device/Stream API Key.
21
+ #
22
+ # https://m2x.att.com/developer/documentation/v2/keys#Create-Key
23
+ def create!(client, params={})
24
+ res = client.post(PATH, nil, params, "Content-Type" => "application/json")
25
+
26
+ new(client, res.json) if res.success?
27
+ end
28
+ end
29
+
30
+ def path
31
+ @path ||= "#{ PATH }/#{ URI.encode(@attributes.fetch("key")) }"
32
+ end
33
+
34
+ # Regenerate an API Key token
35
+ #
36
+ # Note that if you regenerate the key that you're using for
37
+ # authentication then you would need to change your scripts to
38
+ # start using the new key token for all subsequent requests.
39
+ #
40
+ # https://m2x.att.com/developer/documentation/v2/keys#Regenerate-Key
41
+ def regenerate
42
+ res = @client.post("#{path}/regenerate", nil, {})
43
+
44
+ if res.success?
45
+ @path = nil
46
+ @attributes = res.json
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,40 @@
1
+ require "forwardable"
2
+
3
+ # Wrapper for M2X::Client resources
4
+ class M2X::Client::Resource
5
+ extend Forwardable
6
+
7
+ attr_reader :attributes
8
+
9
+ def_delegator :@attributes, :[]
10
+
11
+ def initialize(client, attributes)
12
+ @client = client
13
+ @attributes = attributes
14
+ end
15
+
16
+ # Return the resource details
17
+ def view
18
+ res = @client.get(path)
19
+
20
+ @attributes = res.json if res.success?
21
+ end
22
+
23
+ # Update an existing resource details
24
+ def update!(params)
25
+ @client.put(path, nil, params, "Content-Type" => "application/json")
26
+ end
27
+
28
+ # Delete the resource
29
+ def delete!
30
+ @client.delete(path)
31
+ end
32
+
33
+ def inspect
34
+ "<#{self.class.name}: #{attributes.inspect}>"
35
+ end
36
+
37
+ def path
38
+ raise NotImplementedError
39
+ end
40
+ end