ketra 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 +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
|
+
[![Gem Version](https://badge.fury.io/rb/ketra.png)](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
|