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 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