ketra 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/README.md +4 -0
- data/ketra.gemspec +0 -2
- data/lib/ketra.rb +5 -88
- data/lib/ketra/client.rb +118 -0
- data/lib/ketra/commands.rb +23 -4
- data/lib/ketra/version.rb +1 -1
- metadata +3 -23
- data/lib/ketra/ketra_client.rb +0 -113
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 270326b96585a4978596304cafc2e0321b78af5a
|
4
|
+
data.tar.gz: 282ccceb5dc19ae5e41f1f5a7dd74c4c49e36ebd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fb0dfc716a86a1157503d2f71523039e4f42b0e478412070e62d5f6020377c5ac4192210a953973e02dda42e9a006fbb6f9b5820ee54f69c61555670e94e9f01
|
7
|
+
data.tar.gz: c9b0cdb0a791b89e1587a6971ef8e087080893be5f36d50405f09d166a997c617a689a7e112ba788600977886af335f3a418c39a4f58e97ce7fd60960e99b458
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Ketra
|
2
2
|
|
3
|
+
[](https://badge.fury.io/rb/ketra)
|
4
|
+
|
3
5
|
## Description
|
4
6
|
|
5
7
|
The Ketra gem provides a friendly Ruby interface to the Ketra API
|
@@ -12,6 +14,8 @@ Add this line to your application's Gemfile:
|
|
12
14
|
gem 'ketra'
|
13
15
|
```
|
14
16
|
|
17
|
+
NOTE: versions >= 0.3.0 is only supported for use with Ketra N4 Hubs with 1.15+ firmware
|
18
|
+
|
15
19
|
And then execute:
|
16
20
|
|
17
21
|
$ bundle
|
data/ketra.gemspec
CHANGED
@@ -28,9 +28,7 @@ Gem::Specification.new do |spec|
|
|
28
28
|
spec.require_paths = ["lib"]
|
29
29
|
|
30
30
|
spec.add_runtime_dependency 'oauth2', '~> 1.3', '>= 1.3.1'
|
31
|
-
spec.add_runtime_dependency 'rest-client', '~> 2.0', '>= 2.0.2'
|
32
31
|
spec.add_dependency 'json', '~> 2.1', '~> 2.1.0'
|
33
|
-
#spec.add_dependency "byebug", "~> 9.0.6"
|
34
32
|
|
35
33
|
spec.add_development_dependency 'bundler', '~> 1.10'
|
36
34
|
spec.add_development_dependency 'rake', '~> 10.0'
|
data/lib/ketra.rb
CHANGED
@@ -1,104 +1,21 @@
|
|
1
1
|
require 'oauth2'
|
2
|
-
require 'rest-client'
|
3
|
-
#require 'byebug'
|
4
2
|
|
5
3
|
require "ketra/version"
|
6
|
-
require "ketra/
|
4
|
+
require "ketra/client"
|
7
5
|
require "ketra/commands"
|
8
6
|
|
9
7
|
module Ketra
|
10
8
|
class Error < RuntimeError; end
|
11
9
|
|
12
10
|
class << self
|
13
|
-
attr_writer :callback_url
|
14
11
|
attr_accessor :hub_serial
|
12
|
+
attr_accessor :client_id
|
13
|
+
attr_accessor :client_secret
|
14
|
+
|
15
15
|
#TODO add permission_scopes
|
16
16
|
end
|
17
17
|
|
18
|
-
# Make Ketra.client_id and Ketra.client_secret global but also local to threads
|
19
|
-
|
20
|
-
def self.client_id
|
21
|
-
Thread.current[:ketra_client_id] || @client_id
|
22
|
-
end
|
23
|
-
|
24
|
-
def self.client_id=(id)
|
25
|
-
@client_id ||= id
|
26
|
-
Thread.current[:ketra_client_id] = id
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.client_secret
|
30
|
-
Thread.current[:client_secret] || @client_secret
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.client_secret=(secret)
|
34
|
-
@client_secret ||= secret
|
35
|
-
Thread.current[:ketra_client_secret] = secret
|
36
|
-
end
|
37
|
-
|
38
|
-
PRODUCTION_HOST = 'https://my.goketra.com'
|
39
|
-
|
40
|
-
# Set the environment, accepts :production (TODO add :sandbox environment).
|
41
|
-
# Defaults to :production
|
42
|
-
# will raise an exception when set to an unrecognized environment
|
43
|
-
def self.environment=(env)
|
44
|
-
unless [:production].include?(env)
|
45
|
-
raise(ArguementError, "environment must be set to :production")
|
46
|
-
end
|
47
|
-
@environment = env
|
48
|
-
@host = PRODUCTION_HOST
|
49
|
-
end
|
50
|
-
|
51
|
-
def self.environment
|
52
|
-
@environment || :production
|
53
|
-
end
|
54
|
-
|
55
|
-
def self.host
|
56
|
-
@host || PRODUCTION_HOST
|
57
|
-
end
|
58
|
-
|
59
|
-
# Set the authorization grant type
|
60
|
-
# accepts either :implicit or :password
|
61
|
-
# Defaults to :implicit
|
62
|
-
def self.authorization_grant=(grant_type)
|
63
|
-
unless [:code, :password].include?(grant_type)
|
64
|
-
raise(ArgumentError, "grant type must be set to either :code or :password")
|
65
|
-
end
|
66
|
-
@authorization_grant = grant_type
|
67
|
-
end
|
68
|
-
|
69
|
-
def self.authorization_grant
|
70
|
-
@authorization_grant || :code
|
71
|
-
end
|
72
|
-
|
73
|
-
def self.callback_url
|
74
|
-
@callback_url || 'urn:ietf:wg:oauth:2.0:oob'
|
75
|
-
end
|
76
|
-
|
77
|
-
def self.authorization_url
|
78
|
-
client.authorization_url
|
79
|
-
end
|
80
|
-
|
81
|
-
# Request Access Token
|
82
|
-
# credentials should be key/values based on grant type
|
83
|
-
# grant :code should include :authorization_code
|
84
|
-
# grant :password should include :username and :password
|
85
|
-
def self.authorize(credentials)
|
86
|
-
client.authorize(credentials)
|
87
|
-
end
|
88
|
-
|
89
|
-
def self.access_token
|
90
|
-
client.access_token.token if client.access_token
|
91
|
-
end
|
92
|
-
|
93
|
-
def self.access_token=(token)
|
94
|
-
client.access_token = token
|
95
|
-
end
|
96
|
-
|
97
18
|
def self.client
|
98
|
-
@client ||=
|
19
|
+
@client ||= Client.new client_id, client_secret, :hub_serial => hub_serial
|
99
20
|
end
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
21
|
end
|
data/lib/ketra/client.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'addressable'
|
2
|
+
require 'byebug'
|
3
|
+
|
4
|
+
module Ketra
|
5
|
+
class Client
|
6
|
+
PRODUCTION_HOST = 'https://my.goketra.com'
|
7
|
+
TEST_HOST = 'https://internal-my.goketra.com'
|
8
|
+
LOCAL_ENDPOINT_PREFIX = 'ketra.cgi/api/v1'
|
9
|
+
|
10
|
+
attr_accessor :options
|
11
|
+
attr_reader :id, :secret, :access_token
|
12
|
+
|
13
|
+
def initialize(id, secret, options = {}, &block)
|
14
|
+
opts = options.dup
|
15
|
+
@id = id
|
16
|
+
@secret = secret
|
17
|
+
@options = {:server => :production,
|
18
|
+
:authorization_mode => :password,
|
19
|
+
:redirect_uri => 'urn:ietf:wg:oauth:2.0:oob',
|
20
|
+
:hub_discovery_mode => :cloud,
|
21
|
+
:connection_build => block,
|
22
|
+
:api_mode => :local}.merge(opts)
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
# Authorization
|
27
|
+
|
28
|
+
def authorization_url
|
29
|
+
auth_client.auth_code.authorize_url(:redirect_uri => options[:redirect_uri])
|
30
|
+
end
|
31
|
+
|
32
|
+
def authorize(credentials)
|
33
|
+
case options[:authorization_mode]
|
34
|
+
when :token
|
35
|
+
@access_token = OAuth2::AccessToken.new(auth_client, credentials[:token])
|
36
|
+
when :code
|
37
|
+
@access_token = auth_client.auth_code.get_token(credentials[:authorization_code],
|
38
|
+
:redirect_uri => options[:redirect_uri])
|
39
|
+
else :password
|
40
|
+
@access_token = auth_client.password.get_token(credentials[:username],
|
41
|
+
credentials[:password])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# OAuth Client
|
46
|
+
|
47
|
+
def auth_client
|
48
|
+
@auth_client ||= OAuth2::Client.new(Ketra.client_id,
|
49
|
+
Ketra.client_secret,
|
50
|
+
:site => host,
|
51
|
+
:ssl => { :verify => false })
|
52
|
+
end
|
53
|
+
|
54
|
+
# Requests
|
55
|
+
|
56
|
+
def get(endpoint, params = {})
|
57
|
+
JSON.parse access_token.get(url(endpoint), :params => params).body
|
58
|
+
end
|
59
|
+
|
60
|
+
def post(endpoint, params = {})
|
61
|
+
internal_params = params.dup
|
62
|
+
resp = access_token.post url(endpoint),
|
63
|
+
:params => internal_params.delete(:query_params),
|
64
|
+
:body => JSON.generate(internal_params),
|
65
|
+
:headers => { 'Content-Type' => 'application/json' }
|
66
|
+
JSON.parse resp.body
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def host
|
72
|
+
case options[:server]
|
73
|
+
when :test
|
74
|
+
TEST_HOST
|
75
|
+
else
|
76
|
+
PRODUCTION_HOST
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def url(endpoint)
|
81
|
+
case options[:api_mode]
|
82
|
+
when :local
|
83
|
+
url = "#{local_url}/#{endpoint}"
|
84
|
+
else
|
85
|
+
url = "#{local_url}/#{endpoint}"
|
86
|
+
end
|
87
|
+
Addressable::URI.encode(url)
|
88
|
+
end
|
89
|
+
|
90
|
+
def local_url
|
91
|
+
"https://#{hub_ip}/#{LOCAL_ENDPOINT_PREFIX}"
|
92
|
+
end
|
93
|
+
|
94
|
+
def hub_ip
|
95
|
+
@hub_ip || discover_hub(options[:hub_serial])
|
96
|
+
end
|
97
|
+
|
98
|
+
def discover_hub(serial_number)
|
99
|
+
case options[:hub_discovery_mode]
|
100
|
+
when :cloud
|
101
|
+
cloud_discovery(serial_number)
|
102
|
+
else
|
103
|
+
cloud_discovery(serial_number)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def cloud_discovery(serial_number)
|
108
|
+
@hub_ip ||= perform_cloud_hub_discovery(serial_number)
|
109
|
+
end
|
110
|
+
|
111
|
+
def perform_cloud_hub_discovery(serial_number)
|
112
|
+
response = auth_client.request :get, "#{host}/api/n4/v1/query"
|
113
|
+
info = response.parsed["content"].detect { |h| h["serial_number"] == serial_number }
|
114
|
+
raise RuntimeError, "Could not discover hub with serial: #{serial_number}" if info.nil?
|
115
|
+
info["internal_ip"]
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
data/lib/ketra/commands.rb
CHANGED
@@ -1,9 +1,28 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
1
3
|
module Ketra
|
2
4
|
module Commands
|
3
|
-
def self.activate_button(
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
def self.activate_button(keypad, button, level=65535)
|
6
|
+
Ketra.client.post("Keypads/#{keypad}/Buttons/#{button}/Activate",
|
7
|
+
:Level => level)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.deactivate_button(keypad, button)
|
11
|
+
Ketra.client.post("Keypads/#{keypad}/Buttons/#{button}/Deactivate",
|
12
|
+
:Level => 0)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.push_button(keypad, button)
|
16
|
+
Ketra.client.post("Keypads/#{keypad}/Buttons/#{button}/PushButton",
|
17
|
+
:query_params => { :idempotency_key => SecureRandom.hex })
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.keypads
|
21
|
+
Ketra.client.get("Keypads")
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.groups
|
25
|
+
Ketra.client.get("Groups")
|
7
26
|
end
|
8
27
|
end
|
9
28
|
end
|
data/lib/ketra/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ketra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kenneth Priester
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-12-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: oauth2
|
@@ -30,26 +30,6 @@ dependencies:
|
|
30
30
|
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: 1.3.1
|
33
|
-
- !ruby/object:Gem::Dependency
|
34
|
-
name: rest-client
|
35
|
-
requirement: !ruby/object:Gem::Requirement
|
36
|
-
requirements:
|
37
|
-
- - "~>"
|
38
|
-
- !ruby/object:Gem::Version
|
39
|
-
version: '2.0'
|
40
|
-
- - ">="
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
version: 2.0.2
|
43
|
-
type: :runtime
|
44
|
-
prerelease: false
|
45
|
-
version_requirements: !ruby/object:Gem::Requirement
|
46
|
-
requirements:
|
47
|
-
- - "~>"
|
48
|
-
- !ruby/object:Gem::Version
|
49
|
-
version: '2.0'
|
50
|
-
- - ">="
|
51
|
-
- !ruby/object:Gem::Version
|
52
|
-
version: 2.0.2
|
53
33
|
- !ruby/object:Gem::Dependency
|
54
34
|
name: json
|
55
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -131,8 +111,8 @@ files:
|
|
131
111
|
- bin/setup
|
132
112
|
- ketra.gemspec
|
133
113
|
- lib/ketra.rb
|
114
|
+
- lib/ketra/client.rb
|
134
115
|
- lib/ketra/commands.rb
|
135
|
-
- lib/ketra/ketra_client.rb
|
136
116
|
- lib/ketra/version.rb
|
137
117
|
homepage: http://github.com/kennyjpowers/ketra
|
138
118
|
licenses:
|
data/lib/ketra/ketra_client.rb
DELETED
@@ -1,113 +0,0 @@
|
|
1
|
-
module Ketra
|
2
|
-
class KetraClient
|
3
|
-
LOCAL_ENDPOINT_PREFIX = 'ketra.cgi/api/v1'
|
4
|
-
attr_reader :access_token
|
5
|
-
|
6
|
-
def access_token=(token)
|
7
|
-
@access_token = OAuth2::AccessToken.new(auth_client, token)
|
8
|
-
end
|
9
|
-
|
10
|
-
# set the hub discovery mode, accepts: :cloud TODO implement :ssdp
|
11
|
-
|
12
|
-
def hub_discovery_mode=(mode)
|
13
|
-
unless [:cloud].include?(mode)
|
14
|
-
raise(ArgumentError, "hub discovery mode must be set to :cloud")
|
15
|
-
end
|
16
|
-
@hub_discovery_mode = mode
|
17
|
-
end
|
18
|
-
|
19
|
-
def hub_discovery_mode
|
20
|
-
@hub_discovery_mode || :cloud
|
21
|
-
end
|
22
|
-
|
23
|
-
# set the api mode, accepts: :local TODO implement :remote
|
24
|
-
# :local mode makes calls directly to the hub
|
25
|
-
def api_mode=(mode)
|
26
|
-
unless [:local].include?(mode)
|
27
|
-
raise(ArgumentError, "api mode must be set to :local")
|
28
|
-
end
|
29
|
-
@api_mode = mode
|
30
|
-
end
|
31
|
-
|
32
|
-
def api_mode
|
33
|
-
@api_mode || :local
|
34
|
-
end
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
# Authorization
|
40
|
-
|
41
|
-
def authorization_url
|
42
|
-
unless Ketra.authorization_grant == :code
|
43
|
-
raise(NotImplementedError, "authorization url is only for grant type :code")
|
44
|
-
end
|
45
|
-
client.auth_code.authorize_url(:redirect_uri => Ketra.callback_url)
|
46
|
-
end
|
47
|
-
|
48
|
-
def authorize(credentials)
|
49
|
-
case Ketra.authorization_grant
|
50
|
-
when :code
|
51
|
-
@access_token ||= auth_client.auth_code.get_token(credentials[:authorization_code], :redirect_uri => Ketra.callback_url)
|
52
|
-
when :password
|
53
|
-
@access_token ||= auth_client.password.get_token(credentials[:username], credentials[:password])
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def get(endpoint, url_params={})
|
58
|
-
case api_mode
|
59
|
-
when :local
|
60
|
-
RestClient::Request.execute(verify_ssl: false,
|
61
|
-
method: :get,
|
62
|
-
url: "#{local_url}/#{endpoint}",
|
63
|
-
user: '',
|
64
|
-
password: @access_token.token,
|
65
|
-
content_type: :json,
|
66
|
-
headers: {params: url_params})
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def post(endpoint, body_params={})
|
71
|
-
case api_mode
|
72
|
-
when :local
|
73
|
-
RestClient::Request.execute(verify_ssl: false,
|
74
|
-
method: :post,
|
75
|
-
url: "#{local_url}/#{endpoint}",
|
76
|
-
user: '',
|
77
|
-
password: @access_token.token,
|
78
|
-
content_type: :json,
|
79
|
-
payload: JSON.generate(body_params))
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
private
|
84
|
-
|
85
|
-
def hub_ip
|
86
|
-
@hub_ip || discover_hub(Ketra.hub_serial)
|
87
|
-
end
|
88
|
-
|
89
|
-
def local_url
|
90
|
-
"https://#{hub_ip}/#{LOCAL_ENDPOINT_PREFIX}"
|
91
|
-
end
|
92
|
-
|
93
|
-
|
94
|
-
def discover_hub(serial_number)
|
95
|
-
case hub_discovery_mode
|
96
|
-
when :cloud
|
97
|
-
response = RestClient.get "#{Ketra.host}/api/n4/v1/query"
|
98
|
-
object = JSON.parse(response)
|
99
|
-
hub_info = object["content"].select{ |h| h["serial_number"] == serial_number }.first
|
100
|
-
unless hub_info.nil?
|
101
|
-
@hub_ip = hub_info["internal_ip"]
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
def auth_client
|
107
|
-
@auth_client ||= OAuth2::Client.new(Ketra.client_id,
|
108
|
-
Ketra.client_secret,
|
109
|
-
:site => Ketra.host)
|
110
|
-
end
|
111
|
-
|
112
|
-
end
|
113
|
-
end
|