ecobee 0.1.6 → 0.2.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: 50df9ac248431f92cafec6438d42aa0bb04d964f
4
- data.tar.gz: 1928432f79c576e9d6f88a04a00a5a8a8ca1d511
3
+ metadata.gz: f15c138cad29178c3935acfdffc88446ca994d35
4
+ data.tar.gz: 58581cf67d84e8e0e43b83b2375069aa70d41a9b
5
5
  SHA512:
6
- metadata.gz: dd700da725bca1f2b2cd79e371cbc14e9b8a85b2852c2433852d473fc561ec39b67a6dc90d454ef8235fc55a5fdb1945044535a14257a4ce5a6cdd627a2f13bb
7
- data.tar.gz: d06a3c81087115ef8d741c749bcc99ea52efd0cc668c2543f10c4b524bfec85ac65c4dfb715a62b327136e4c536f834133207e120aee6246f24ba4cefac05a63
6
+ metadata.gz: 6cb824a3793ecd6582479f00c94fad5d3819d4a7da373abdadbed6fdf7bb108a9072e7091780fb6f42842d60c648e827750a53e4a77c9455d3b59bc09faf325d
7
+ data.tar.gz: 5f8afab66b9bb155caf5b6f4691a72a8ada13765cfe64d3f83555bfcd910473d6f9d51115d87e81fbb8804593f90ed17d5f01c5ef0ecc04cd06c2d994358e9ed
@@ -19,6 +19,8 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ["lib"]
21
21
 
22
+ spec.required_ruby_version = '>= 2.0.0'
23
+
22
24
  spec.add_development_dependency "bundler", "~> 1.12"
23
25
  spec.add_development_dependency "rake", "~> 10.0"
24
26
  spec.add_development_dependency "rspec", "~> 3.0"
@@ -4,7 +4,9 @@
4
4
  # to change the mode. -- @robzr
5
5
 
6
6
  require 'pp'
7
- require 'ecobee'
7
+
8
+ #require 'ecobee'
9
+ require_relative '../lib/ecobee.rb'
8
10
 
9
11
  @hvac_modes = Ecobee::HVAC_MODES + ['quit']
10
12
 
@@ -14,7 +16,7 @@ class TestFunctions
14
16
  end
15
17
 
16
18
  def print_summary
17
- http_response = @client.get(
19
+ response = @client.get(
18
20
  'thermostat',
19
21
  {
20
22
  'selection' => {
@@ -25,7 +27,6 @@ class TestFunctions
25
27
  }
26
28
  }
27
29
  )
28
- response = JSON.parse(http_response.body)
29
30
 
30
31
  puts "Found %d thermostats." % response['thermostatList'].length
31
32
 
@@ -42,7 +43,7 @@ class TestFunctions
42
43
  end
43
44
 
44
45
  def update_mode(mode)
45
- http_response = @client.post(
46
+ @client.post(
46
47
  'thermostat',
47
48
  body: {
48
49
  'selection' => {
@@ -56,18 +57,16 @@ class TestFunctions
56
57
  }
57
58
  }
58
59
  )
59
- response = JSON.parse(http_response.body)
60
60
  end
61
61
  end
62
62
 
63
63
  token = Ecobee::Token.new(
64
64
  app_key: ENV['ECOBEE_APP_KEY'],
65
- app_name: 'set_mode',
66
- scope: :smartWrite,
67
- token_file: '~/.ecobee_token'
65
+ app_name: 'ecobee-gem'
68
66
  )
69
67
 
70
- puts token.pin_message if token.pin token.wait
68
+ puts token.pin_message if token.pin
69
+ token.wait
71
70
  test_functions = TestFunctions.new(
72
71
  Ecobee::Client.new(token: token)
73
72
  )
@@ -3,14 +3,11 @@
3
3
  # Refreshes token; displays details on saved token. -- @robzr
4
4
 
5
5
  require 'pp'
6
- require 'ecobee'
7
- require_relative '/Users/robzr/GitHub/ecobee/lib/ecobee/token.rb'
8
- require_relative '/Users/robzr/GitHub/ecobee/lib/ecobee/register.rb'
6
+ require_relative '../lib/ecobee.rb'
9
7
 
10
8
  token = Ecobee::Token.new(
11
- app_key: ENV['ECOBEE_API_KEY'],
12
- app_name: 'ecobee-gem',
13
- token_file: '~/.ecobee_token'
9
+ app_key: ENV['ECOBEE_APP_KEY'],
10
+ app_name: 'ecobee-gem'
14
11
  )
15
12
 
16
13
  puts token.pin_message if token.pin
@@ -18,6 +15,6 @@ token.wait
18
15
 
19
16
  puts "Access Token: #{token.access_token}"
20
17
  puts "Refresh Token: #{token.refresh_token}"
21
- puts "Expires At: #{token.expires_at}"
18
+ puts "Expires At: #{token.access_expires_at}"
22
19
  puts "Scope: #{token.scope}"
23
20
  puts "Type: #{token.type}"
@@ -2,31 +2,33 @@ require 'pp'
2
2
  require 'json'
3
3
  require 'net/http'
4
4
 
5
- require "ecobee/client"
6
- require "ecobee/register"
7
- require "ecobee/token"
8
- require "ecobee/version"
5
+ require 'ecobee/client'
6
+ require 'ecobee/register'
7
+ require 'ecobee/token'
8
+ require 'ecobee/version'
9
+ #require_relative 'ecobee/client'
10
+ #require_relative 'ecobee/register'
11
+ #require_relative 'ecobee/token'
12
+ #require_relative 'ecobee/version'
9
13
 
10
14
  module Ecobee
11
15
  API_HOST = 'api.ecobee.com'
12
16
  API_PORT = 443
13
17
  CONTENT_TYPE = ['application/json', { 'charset' => 'UTF-8' }]
14
-
18
+ DEFAULT_FILES = [
19
+ '~/Library/Mobile Documents/com~apple~CloudDocs/.ecobee_token',
20
+ '~/.ecobee_token'
21
+ ]
15
22
  HVAC_MODES = ['auto', 'auxHeatOnly', 'cool', 'heat', 'off']
16
-
17
- REFRESH_INTERVAL_PAD = 60
23
+ REFRESH_INTERVAL_PAD = 120
18
24
  REFRESH_TOKEN_CHECK = 10
19
-
20
- SCOPES = [:smartRead, :smartWrite]
21
-
25
+ SCOPES = [:smartWrite, :smartRead]
22
26
  URL_BASE= "https://#{API_HOST}:#{API_PORT}"
23
-
24
27
  URL_API = "#{URL_BASE}/1/"
25
28
  URL_GET_PIN = URL_BASE +
26
29
  '/authorize?response_type=ecobeePin&client_id=%s&scope=%s'
27
30
  URL_TOKEN = "#{URL_BASE}/token"
28
31
 
29
-
30
32
  def self.Model(model)
31
33
  { 'idtSmart' => 'ecobee Smart',
32
34
  'idtEms' => 'ecobee Smart EMS',
@@ -14,7 +14,10 @@ module Ecobee
14
14
  request = Net::HTTP::Get.new(URI(URI.escape(new_uri)))
15
15
  request['Content-Type'] = *CONTENT_TYPE
16
16
  request['Authorization'] = @token.authorization
17
- http.request(request)
17
+ http_response = http.request request
18
+ validate_status JSON.parse(http_response.body)
19
+ rescue JSON::ParserError => msg
20
+ raise ClientError.new("JSON::ParserError => #{msg}")
18
21
  end
19
22
 
20
23
  def post(arg, options: {}, body: nil)
@@ -24,7 +27,25 @@ module Ecobee
24
27
  request.body = JSON.generate(body) if body
25
28
  request['Content-Type'] = *CONTENT_TYPE
26
29
  request['Authorization'] = @token.authorization
27
- http.request(request)
30
+ http_response = http.request request
31
+ validate_status JSON.parse http_response.body
32
+ rescue JSON::ParserError => msg
33
+ raise ClientError.new("JSON::ParserError => #{msg}")
34
+ end
35
+
36
+ def validate_status(response)
37
+ if !response.key? 'status'
38
+ raise ClientError.new('Missing Status')
39
+ elsif !response['status'].key? 'code'
40
+ raise ClientError.new('Missing Status Code')
41
+ elsif response['status']['code'] != 0
42
+ raise ClientError.new(
43
+ "GET Error: #{response['status']['code']} " +
44
+ "Message: #{response['status']['message']}"
45
+ )
46
+ else
47
+ response
48
+ end
28
49
  end
29
50
 
30
51
  private
@@ -40,4 +61,6 @@ module Ecobee
40
61
 
41
62
  end
42
63
 
64
+ class ClientError < StandardError ; end
65
+
43
66
  end
@@ -44,6 +44,7 @@ module Ecobee
44
44
  rescue Exception => msg
45
45
  raise Ecobee::TokenError.new("Unknown Error: #{msg}")
46
46
  end
47
+
47
48
  end
48
49
 
49
50
  end
@@ -2,8 +2,8 @@ module Ecobee
2
2
  require 'date'
3
3
 
4
4
  class Token
5
- attr_reader :access_token,
6
- :expires_at,
5
+ attr_reader :access_expires_at,
6
+ :access_token,
7
7
  :pin,
8
8
  :pin_message,
9
9
  :refresh_token,
@@ -13,22 +13,28 @@ module Ecobee
13
13
  :type
14
14
 
15
15
  def initialize(
16
- app_key: nil,
16
+ access_expires_at: nil,
17
+ access_token: nil,
18
+ app_key: nil,
17
19
  app_name: nil,
18
20
  code: nil,
19
21
  refresh_token: nil,
20
22
  scope: SCOPES[0],
21
- token_file: nil
23
+ token_file: DEFAULT_FILES
22
24
  )
25
+ @access_expires_at = access_expires_at
26
+ @access_token = access_token
23
27
  @app_key = app_key
24
28
  @app_name = app_name
25
29
  @code = code
26
- @access_token, @code_expires_at, @expires_at, @pin, @type = nil
27
30
  @refresh_token = refresh_token
28
31
  @scope = scope
29
- @status = :authorization_pending
30
- @token_file = File.expand_path(token_file)
31
- parse_token_file unless @refresh_token
32
+ @token_file = expand_files token_file
33
+
34
+ @code_expires_at, @pin, @type = nil
35
+ parse_token_file
36
+ @status = @refresh_token ? :ready : :authorization_pending
37
+
32
38
  if @refresh_token
33
39
  refresh
34
40
  else
@@ -39,7 +45,7 @@ module Ecobee
39
45
  end
40
46
 
41
47
  def access_token
42
- refresh if Time.now + REFRESH_INTERVAL_PAD > @expires_at
48
+ refresh
43
49
  @access_token
44
50
  end
45
51
 
@@ -61,6 +67,7 @@ module Ecobee
61
67
  end
62
68
 
63
69
  def refresh
70
+ return if Time.now.to_i + REFRESH_INTERVAL_PAD < @access_expires_at
64
71
  response = Net::HTTP.post_form(
65
72
  URI(URL_TOKEN),
66
73
  'grant_type' => 'refresh_token',
@@ -69,14 +76,14 @@ module Ecobee
69
76
  )
70
77
  result = JSON.parse(response.body)
71
78
  if result.key? 'error'
72
- # pp result
79
+ pp result
73
80
  raise Ecobee::TokenError.new(
74
81
  "Result Error: (%s) %s" % [result['error'],
75
82
  result['error_description']]
76
83
  )
77
84
  else
78
85
  @access_token = result['access_token']
79
- @expires_at = Time.now + result['expires_in']
86
+ @access_expires_at = Time.now.to_i + result['expires_in']
80
87
  @refresh_token = result['refresh_token']
81
88
  @pin, @code, @code_expires_at = nil
82
89
  @scope = result['scope']
@@ -120,7 +127,7 @@ module Ecobee
120
127
  @status = :ready
121
128
  @access_token = result['access_token']
122
129
  @type = result['token_type']
123
- @expires_at = Time.now + result['expires_in']
130
+ @access_expires_at = Time.now.to_i + result['expires_in']
124
131
  @refresh_token = result['refresh_token']
125
132
  @scope = result['scope']
126
133
  @pin, @code, @code_expires_at = nil
@@ -134,6 +141,14 @@ module Ecobee
134
141
  raise Ecobee::TokenError.new("Unknown Error: #{msg}")
135
142
  end
136
143
 
144
+ def expand_files(token_file)
145
+ if token_file.is_a? Array
146
+ token_file.map { |tf| File.expand_path tf }
147
+ else
148
+ expand_files [token_file]
149
+ end
150
+ end
151
+
137
152
  def launch_monitor_thread
138
153
  Thread.new {
139
154
  loop do
@@ -145,34 +160,41 @@ module Ecobee
145
160
  end
146
161
 
147
162
  def parse_token_file
148
- #puts "Before Parse: app_key:#{@app_key} refresh_token:#{@refresh_token} pin:#{pin}"
149
- return unless (config = read_token_file).is_a? Hash
150
- section = (@app_name && config.key?(@app_name)) ? @app_name : @app_key
151
- if config.key?(section)
152
- @app_key ||= if config[section].key?('app_key')
153
- config[section]['app_key']
154
- else
155
- @app_name
156
- end
157
- if config[section].key?('refresh_token')
158
- @refresh_token ||= config[section]['refresh_token']
159
- elsif config[section].key?('pin')
160
- @pin ||= config[section]['pin']
161
- @code ||= config[section]['code']
162
- @code_expires_at ||= config[section]['code_expires_at'].to_i
163
- end
163
+ return unless (all_config = read_token_file).is_a? Hash
164
+ section = (@app_name && all_config.key?(@app_name)) ? @app_name : @app_key
165
+ return unless all_config.key?(section)
166
+ config = all_config[section]
167
+ @app_key ||= config.key?('app_key') ? config['app_key'] : @app_name
168
+ if config.key?('refresh_token')
169
+ @access_expires_at ||= config['access_expires_at'].to_i
170
+ @access_token ||= config['access_token']
171
+ @refresh_token ||= config['refresh_token']
172
+ @scope ||= config['scope']
173
+ @type ||= config['token_type']
174
+ elsif config.key?('pin')
175
+ @code ||= config['code']
176
+ @code_expires_at ||= config['code_expires_at'].to_i
177
+ @pin ||= config['pin']
164
178
  end
165
- #puts "After Parse: app_key:#{@app_key} refresh_token:#{@refresh_token} pin:#{pin}"
166
179
  end
167
180
 
168
- def read_token_file
181
+ def read_json_file(file)
169
182
  JSON.parse(
170
- File.open(@token_file, 'r').read(16 * 1024)
183
+ File.open(file, 'r').read(16 * 1024)
171
184
  )
185
+ rescue JSON::ParserError => msg
186
+ raise Ecobee::TokenError.new("Result parsing: #{msg}")
172
187
  rescue Errno::ENOENT
173
188
  {}
174
189
  end
175
190
 
191
+ def read_token_file
192
+ @token_file.each do |tf|
193
+ result = read_json_file(tf)
194
+ return result if result.length > 0
195
+ end
196
+ end
197
+
176
198
  def register
177
199
  result = Register.new(app_key: @app_key, scope: @scope)
178
200
  @pin = result.pin
@@ -184,7 +206,12 @@ module Ecobee
184
206
  end
185
207
 
186
208
  def write_token_file
187
- return unless @token_file
209
+ @token_file.each do |file|
210
+ return if write_json_file file
211
+ end
212
+ end
213
+
214
+ def write_json_file(file)
188
215
  if config = read_token_file
189
216
  config.delete(@app_name)
190
217
  config.delete(@app_key)
@@ -193,15 +220,22 @@ module Ecobee
193
220
  config[section] = {}
194
221
  config[section]['app_key'] = @app_key if @app_key && section != @app_key
195
222
  if @refresh_token
223
+ config[section]['access_token'] = @access_token
224
+ config[section]['access_expires_at'] = @access_expires_at
196
225
  config[section]['refresh_token'] = @refresh_token
226
+ config[section]['token_type'] = @type
227
+ config[section]['scope'] = @scope
197
228
  elsif @pin
198
229
  config[section]['pin'] = @pin
199
230
  config[section]['code'] = @code
200
231
  config[section]['code_expires_at'] = @code_expires_at
201
232
  end
202
- File.open(@token_file, 'w') do |tf|
233
+ File.open(file, 'w') do |tf|
203
234
  tf.puts JSON.pretty_generate(config)
204
235
  end
236
+ true
237
+ rescue Errno::ENOENT
238
+ nil
205
239
  end
206
240
 
207
241
  end
@@ -1,3 +1,3 @@
1
1
  module Ecobee
2
- VERSION = "0.1.6"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ecobee
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob Zwissler
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-08-06 00:00:00.000000000 Z
11
+ date: 2016-08-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -70,7 +70,6 @@ files:
70
70
  - bin/console
71
71
  - bin/setup
72
72
  - ecobee.gemspec
73
- - examples/bitbar_plugin.rb
74
73
  - examples/set_mode.rb
75
74
  - examples/test_token.rb
76
75
  - lib/ecobee.rb
@@ -90,7 +89,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
90
89
  requirements:
91
90
  - - ">="
92
91
  - !ruby/object:Gem::Version
93
- version: '0'
92
+ version: 2.0.0
94
93
  required_rubygems_version: !ruby/object:Gem::Requirement
95
94
  requirements:
96
95
  - - ">="
@@ -1,252 +0,0 @@
1
- #!/usr/bin/env ruby
2
- #
3
- # Allows for display and control of your Ecobee in the Mac OS X
4
- # menubar, using BitBar (http://getbitbar.com). -- @robzr
5
- #
6
- # <bitbar.title>EcobeeStat</bitbar.title>
7
- # <bitbar.version>v1.0</bitbar.version>
8
- # <bitbar.author>Rob Zwissler</bitbar.author>
9
- # <bitbar.author.github>robzr</bitbar.author.github>
10
- # <bitbar.desc>Ecobee Thermostat Control</bitbar.desc>
11
- # <bitbar.image>http://github.com/robzr/ecobee</bitbar.image>
12
- # <bitbar.dependencies>ruby</bitbar.dependencies>
13
- # <bitbar.abouturl>http://github.com/robzr/ecobee</bitbar.abouturl>
14
-
15
- require 'pp'
16
- require 'ecobee'
17
- #require_relative '/Users/robzr/GitHub/ecobee/lib/ecobee.rb'
18
- #require_relative '/Users/robzr/GitHub/ecobee/lib/ecobee/client.rb'
19
- #require_relative '/Users/robzr/GitHub/ecobee/lib/ecobee/token.rb'
20
- #require_relative '/Users/robzr/GitHub/ecobee/lib/ecobee/register.rb'
21
-
22
- API_KEY = 'u2Krw0OumeliB0OnwiaogySvgExhy2K4'
23
- HVAC_MODES = ['auto', 'auxHeatOnly', 'cool', 'heat', 'off', 'quit']
24
- DEG = '°'
25
-
26
- module Ecobee
27
- class ResponseError < StandardError ; end
28
-
29
- class BitBar
30
- def initialize(client)
31
- @client = client
32
- end
33
-
34
- def get_thermostat(args = {})
35
- index = args.delete(:index) || 0
36
- http_response = @client.get('thermostat',
37
- Ecobee::Selection(args))
38
- response = JSON.parse(http_response.body)
39
- get_thermostat_list_index(index: index,
40
- response: validate_status(response))
41
- rescue JSON::ParserError => msg
42
- raise ResponseError.new("JSON::ParserError => #{msg}")
43
- end
44
-
45
- def get_thermostat_list_index(index: 0, response: nil)
46
- if !response.key? 'thermostatList'
47
- raise ResponseError.new('Missing thermostatList')
48
- elsif index >= response['thermostatList'].length
49
- raise ResponseError.new(
50
- "Missing thermostatList Index #{index} (Max Found: " +
51
- "#{response['thermostatList'].length - 1})"
52
- )
53
- else
54
- response['thermostatList'][index]
55
- end
56
- end
57
-
58
- def validate_status(response)
59
- if !response.key? 'status'
60
- raise ResponseError.new('Missing Status')
61
- elsif !response['status'].key? 'code'
62
- raise ResponseError.new('Missing Status Code')
63
- elsif response['status']['code'] != 0
64
- raise ResponseError.new(
65
- "GET Error: #{response['status']['code']} " +
66
- "Message: #{response['status']['message']}"
67
- )
68
- else
69
- response
70
- end
71
- end
72
-
73
- # puts "Heat: #{info['runtime']['desiredHeat'] / 10}#{DEG} | color=red"
74
-
75
- def set_hold(cool_hold: nil, heat_hold: nil)
76
- functions = [{
77
- 'type' => 'setHold',
78
- 'params' => {
79
- 'holdType' => 'nextTransition',
80
- }
81
- }]
82
- functions[0]['params']['coolHoldTemp'] = cool_hold
83
- functions[0]['params']['heatHoldTemp'] = heat_hold
84
- http_response = @client.post(
85
- 'thermostat',
86
- body: {
87
- 'selection' => {
88
- 'selectionType' => 'registered',
89
- 'selectionMatch' => '',
90
- },
91
- 'functions' => functions
92
- }
93
- )
94
- response = JSON.parse(http_response.body)
95
- end
96
-
97
- def update_mode(mode)
98
- http_response = @client.post(
99
- 'thermostat',
100
- body: {
101
- 'selection' => {
102
- 'selectionType' => 'registered',
103
- 'selectionMatch' => '',
104
- },
105
- 'thermostat' => {
106
- 'settings' => {
107
- 'hvacMode' => mode
108
- }
109
- }
110
- }
111
- )
112
- response = JSON.parse(http_response.body)
113
- end
114
- end
115
- end
116
-
117
- def header(info)
118
- puts "#{info['runtime']['actualTemperature'] / 10.0}#{DEG}"
119
- puts '---'
120
- end
121
-
122
- def cool_menu(info)
123
- present_mode = info['settings']['hvacMode']
124
- return unless ['auto', 'cool'].include? present_mode
125
- puts "Cool: #{info['runtime']['desiredCool'] / 10}#{DEG} | color=blue"
126
- cool_low = info['settings']['coolRangeLow'] / 10
127
- cool_high = info['settings']['coolRangeHigh'] / 10
128
- (cool_low..cool_high).reverse_each do |temp|
129
- flag, color = ''
130
- flag = ' :arrow_left:' if temp == info['runtime']['actualTemperature'] / 10
131
- color = ' color=blue' if temp == info['runtime']['desiredCool'] / 10
132
- puts("--#{temp}#{DEG}#{flag}|#{color} bash=\"#{$0}\" " +
133
- "param1=\"set_cool=#{temp}\" refresh=true terminal=false")
134
- end
135
- end
136
-
137
- def heat_menu(info)
138
- present_mode = info['settings']['hvacMode']
139
- return unless ['auto', 'auxHeatOnly', 'heat'].include? present_mode
140
- puts "Heat: #{info['runtime']['desiredHeat'] / 10}#{DEG} | color=red"
141
- heat_low = info['settings']['heatRangeLow'] / 10
142
- heat_high = info['settings']['heatRangeHigh'] / 10
143
- (heat_low..heat_high).reverse_each do |temp|
144
- flag, color = ''
145
- flag = ' :arrow_left:' if temp == info['runtime']['actualTemperature'] / 10
146
- color = ' color=red' if temp == info['runtime']['desiredHeat'] / 10
147
- puts("--#{temp}#{DEG}#{flag}|#{color} bash=\"#{$0}\" " +
148
- "param1=\"set_heat=#{temp}\" refresh=true terminal=false")
149
- end
150
- end
151
-
152
- def mode_menu(info)
153
- puts "Mode: #{info['settings']['hvacMode']}"
154
- Ecobee::HVAC_MODES.reject { |mode| mode == info['settings']['hvacMode'] }
155
- .each do |mode|
156
- puts("--#{mode} | bash=\"#{$0}\" param1=\"set_mode=#{mode}\" " +
157
- "refresh=true terminal=false")
158
- end
159
- end
160
-
161
- def separator
162
- puts '---'
163
- end
164
-
165
- def stat_info(info)
166
- puts info['name']
167
- info['remoteSensors'].each do |sensor|
168
- temp = sensor['capability'].select do |cap|
169
- cap['type'] == 'temperature'
170
- end
171
- temp = temp[0]['value'].to_i / 10.0
172
- puts "--#{sensor['name']}: #{temp}#{DEG}"
173
- end
174
- puts "#{info['brand']} #{Ecobee::Model(info['modelNumber'])}"
175
- puts "Status: #{info['equipmentStatus']}"
176
- end
177
-
178
- def website
179
- puts 'Ecobee Web Portal|href="https://www.ecobee.com/consumerportal/index.html"'
180
- end
181
-
182
- token = Ecobee::Token.new(
183
- app_key: API_KEY, app_name: API_KEY,
184
- scope: :smartWrite,
185
- token_file: '~/.ecobee_token'
186
- )
187
- if token.pin
188
- puts "Ecobee | color=red"
189
- puts "---"
190
- puts "Registration Needed | color=red"
191
- puts "---"
192
- puts 'Login to Ecobee | href=\'https://www.ecobee.com/consumerportal/index.html\''
193
- puts 'Select \'My Apps\' from the drop-down menu'
194
- puts 'Press the \'Add Application\' button'
195
- puts "Enter authorization code: #{token.pin}"
196
- exit
197
- end
198
-
199
- ecobar = Ecobee::BitBar.new Ecobee::Client.new(token: token)
200
-
201
- case arg = ARGV.shift
202
- when /^dump/
203
- pp ecobar.get_thermostat(
204
- :includeRuntime => true,
205
- :includeExtendedRuntime => true,
206
- :includeElectricity => true,
207
- :includeSettings => true,
208
- :includeLocation => true,
209
- :includeProgram => true,
210
- :includeEvents => true,
211
- :includeDevice => true,
212
- :includeTechnician => true,
213
- :includeUtility => true,
214
- :includeAlerts => true,
215
- :includeWeather => true,
216
- :includeOemConfig => true,
217
- :includeEquipmentStatus => true,
218
- :includeNotificationSettings => true,
219
- :includeVersion => true,
220
- :includeSensors => true
221
- )
222
- when /^set_mode=/
223
- mode = arg.sub(/^.*=/, '')
224
- ecobar.update_mode mode
225
- when /^set_cool=/
226
- info = ecobar.get_thermostat(includeRuntime: true,
227
- includeSettings: true)
228
- cool_hold = arg.sub(/^.*=/, '').to_i * 10
229
- heat_hold = info['runtime']['desiredHeat']
230
-
231
- ecobar.set_hold(cool_hold: cool_hold, heat_hold: heat_hold)
232
- when /^set_heat=/
233
- info = ecobar.get_thermostat(includeRuntime: true,
234
- includeSettings: true)
235
- cool_hold = info['runtime']['desiredCool']
236
- heat_hold = arg.sub(/^.*=/, '').to_i * 10
237
-
238
- ecobar.set_hold(cool_hold: cool_hold, heat_hold: heat_hold)
239
- else
240
- info = ecobar.get_thermostat(includeRuntime: true,
241
- includeSettings: true,
242
- includeEquipmentStatus: true,
243
- includeSensors: true)
244
- header info
245
- cool_menu info
246
- heat_menu info
247
- separator
248
- stat_info info
249
- mode_menu info
250
- separator
251
- website
252
- end