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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 95b00ea816d131398c046ead4a0195e55befd07a
4
- data.tar.gz: 43b3ce8604a0a3b0c58c07f415bd516e9fe63328
3
+ metadata.gz: 270326b96585a4978596304cafc2e0321b78af5a
4
+ data.tar.gz: 282ccceb5dc19ae5e41f1f5a7dd74c4c49e36ebd
5
5
  SHA512:
6
- metadata.gz: 5176169e0039713e7ef100a0aadceb3b35d627f66c4a1febd58f7b59f4645e9d7c3ef33ae480975ef685e3f02d49ee53102748c01f314ce1c5396cbf6c1fc55f
7
- data.tar.gz: 37871765f712c252c80d9fedb40192db0f94212fa5c5795d1e25cd58ecd9c838170a2550eeebafa9a609baa0999782e25fade900c6496bbebb93dd4553c92830
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
@@ -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'
@@ -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/ketra_client"
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 ||= KetraClient.new
19
+ @client ||= Client.new client_id, client_secret, :hub_serial => hub_serial
99
20
  end
100
-
101
-
102
-
103
-
104
21
  end
@@ -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
@@ -1,9 +1,28 @@
1
+ require 'securerandom'
2
+
1
3
  module Ketra
2
4
  module Commands
3
- def self.activate_button(keypad_name, button_name, level=65535)
4
- endpoint = "activateButton?keypadName=#{keypad_name}&buttonName=#{button_name}"
5
- body_params = { "Level": level }
6
- Ketra.client.post(endpoint, body_params)
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
@@ -1,3 +1,3 @@
1
1
  module Ketra
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
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.2.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-05-02 00:00:00.000000000 Z
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:
@@ -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