nest_thermostat 0.0.1

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.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .env
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :rubygems
2
+
3
+ # Specify your gem's dependencies in nest_thermostat.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,32 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ nest_thermostat (0.0.1)
5
+ httparty (~> 0.8.3)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ awesome_print (1.0.2)
11
+ diff-lcs (1.1.3)
12
+ httparty (0.8.3)
13
+ multi_json (~> 1.0)
14
+ multi_xml
15
+ multi_json (1.3.6)
16
+ multi_xml (0.5.1)
17
+ rspec (2.10.0)
18
+ rspec-core (~> 2.10.0)
19
+ rspec-expectations (~> 2.10.0)
20
+ rspec-mocks (~> 2.10.0)
21
+ rspec-core (2.10.1)
22
+ rspec-expectations (2.10.0)
23
+ diff-lcs (~> 1.1.3)
24
+ rspec-mocks (2.10.1)
25
+
26
+ PLATFORMS
27
+ ruby
28
+
29
+ DEPENDENCIES
30
+ awesome_print
31
+ nest_thermostat!
32
+ rspec (~> 2.10)
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Eric Boehs
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # NestThermostat
2
+
3
+ This gem allows you to get and set the temperature of your Nest
4
+ thermostat. You can also get and set the away status and get the
5
+ current temperature and target temperature time.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'nest_thermostat'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install nest_thermostat
20
+
21
+ ## Usage
22
+ Get some useful info:
23
+ ```ruby
24
+ @nest = NestThermostat::Nest.new({email: ENV['NEST_EMAIL'], password: ENV['NEST_PASS']})
25
+ puts @nest.current_temperature # => 75.00
26
+ puts @nest.current_temp # => 75.00
27
+ puts @nest.temperature # => 73.00
28
+ puts @nest.temp # => 73.00
29
+ puts @nest.target_temperature_at # => 2012-06-05 14:28:48 +0000 # Ruby date object or false
30
+ puts @nest.target_temp_at # => 2012-06-05 14:28:48 +0000 # Ruby date object or false
31
+ puts @nest.away # => false
32
+ puts @nest.leaf # => true # May take a few seconds after a temp change
33
+ puts @nest.humidity # => 54 # Relative humidity in percent
34
+ ```
35
+
36
+ Change the temperature or away status:
37
+ ```ruby
38
+ puts @nest.temperature # => 73.0
39
+ puts @nest.temperature = 74.0
40
+ puts @nest.temperature # => 74.0
41
+
42
+ puts @nest.away # => false
43
+ puts @nest.away = true
44
+ puts @nest.away # => true
45
+ ```
46
+
47
+ Default temperatures are in fahrenheit but you can change to celsius or kelvin:
48
+ ```ruby
49
+ @nest = NestThermostat::Nest.new({..., temperature_scale: 'c'}) # Or C, Celsius or celsius
50
+ @nest.temperature_scale = 'k' # or K, Kelvin or kelvin
51
+ ```
52
+
53
+ And of course if you want to get LOTS of other goodies like (schedule and every diag piece of info you'd ever want):
54
+ ```ruby
55
+ p @nest.status
56
+
57
+ # -- OR --
58
+
59
+ require 'yaml'
60
+ yaml @nest.status
61
+
62
+ # -- OR my favorite --
63
+
64
+ require 'ap' # gem install awesome_print
65
+ ap @nest.status
66
+ ```
67
+ Feel free to implement anything you see useful and submit a pull
68
+ request. I'd love to see other information like scheduling or multiple
69
+ device/location support added.
70
+
71
+
72
+ ## Contributing
73
+
74
+ 1. Fork it
75
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
76
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
77
+ 4. Push to the branch (`git push origin my-new-feature`)
78
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,155 @@
1
+ require 'rubygems'
2
+ require 'httparty'
3
+ require 'json'
4
+ require 'uri'
5
+
6
+ module NestThermostat
7
+ class Nest
8
+ attr_accessor :email, :password, :login_url, :user_agent, :auth,
9
+ :temperature_scale, :login, :token, :user_id, :transport_url,
10
+ :transport_host, :structure_id, :device_id, :headers
11
+
12
+ def initialize(config = {})
13
+ raise 'Please specify your nest email' unless config[:email]
14
+ raise 'Please specify your nest password' unless config[:password]
15
+
16
+ # User specified information
17
+ self.email = config[:email]
18
+ self.password = config[:password]
19
+ self.temperature_scale = config[:temperature_scale] || config[:temp_scale] || 'f'
20
+ self.login_url = config[:login_url] || 'https://home.nest.com/user/login'
21
+ self.user_agent = config[:user_agent] ||'Nest/1.1.0.10 CFNetwork/548.0.4'
22
+
23
+ # Login and get token, user_id and URLs
24
+ login
25
+ self.token = login["access_token"]
26
+ self.user_id = login["userid"]
27
+ self.transport_url = login["urls"]["transport_url"]
28
+ self.transport_host = URI.parse(self.transport_url).host
29
+ self.headers = {
30
+ 'Host' => self.transport_host,
31
+ 'User-Agent' => self.user_agent,
32
+ 'Authorization' => 'Basic ' + self.token,
33
+ 'X-nl-user-id' => self.user_id,
34
+ 'X-nl-protocol-version' => '1',
35
+ 'Accept-Language' => 'en-us',
36
+ 'Connection' => 'keep-alive',
37
+ 'Accept' => '*/*'
38
+ }
39
+
40
+ # Set device and structure id
41
+ status
42
+ end
43
+
44
+ def status
45
+ request = HTTParty.get("#{self.transport_url}/v2/mobile/user.#{self.user_id}", headers: self.headers) rescue nil
46
+ result = JSON.parse(request.body) rescue nil
47
+
48
+ self.structure_id = result['user'][user_id]['structures'][0].split('.')[1]
49
+ self.device_id = result['structure'][structure_id]['devices'][0].split('.')[1]
50
+
51
+ result
52
+ end
53
+
54
+ def leaf
55
+ status["device"][self.device_id]["leaf"]
56
+ end
57
+
58
+ def humidity
59
+ status["device"][self.device_id]["current_humidity"]
60
+ end
61
+
62
+ def current_temperature
63
+ convert_temp_for_get(status["shared"][self.device_id]["current_temperature"])
64
+ end
65
+ alias_method :current_temp, :current_temperature
66
+
67
+ def temperature
68
+ convert_temp_for_get(status["shared"][self.device_id]["target_temperature"])
69
+ end
70
+ alias_method :temp, :temperature
71
+
72
+ def temperature=(degrees)
73
+ degrees = convert_temp_for_set(degrees)
74
+
75
+ request = HTTParty.post(
76
+ "#{self.transport_url}/v2/put/shared.#{self.device_id}",
77
+ body: %Q({"target_change_pending":true,"target_temperature":#{degrees}}),
78
+ headers: self.headers
79
+ ) rescue nil
80
+ end
81
+ alias_method :temp=, :temperature=
82
+
83
+ def target_temperature_at
84
+ epoch = status["device"][self.device_id]["time_to_target"]
85
+ epoch != 0 ? Time.at(epoch) : false
86
+ end
87
+ alias_method :target_temp_at, :target_temperature_at
88
+
89
+ def away
90
+ status["structure"][structure_id]["away"]
91
+ end
92
+
93
+ def away=(state)
94
+ request = HTTParty.post(
95
+ "#{self.transport_url}/v2/put/structure.#{self.structure_id}",
96
+ body: %Q({"away_timestamp":#{Time.now.to_i},"away":#{!!state},"away_setter":0}),
97
+ headers: self.headers
98
+ ) rescue nil
99
+ end
100
+
101
+ def temp_scale=(scale)
102
+ self.temperature_scale = scale
103
+ end
104
+
105
+ private
106
+ def login
107
+ login_request = HTTParty.post(
108
+ self.login_url,
109
+ body: { username: self.email, password: self.password },
110
+ headers: { 'User-Agent' => self.user_agent }
111
+ )
112
+
113
+ self.auth = JSON.parse(login_request.body) rescue nil
114
+ end
115
+
116
+ def convert_temp_for_get(degrees)
117
+ case self.temperature_scale
118
+ when /f|F|(F|f)ahrenheit/
119
+ c2f(degrees).round(3)
120
+ when /k|K|(K|k)elvin/
121
+ c2k(degrees).round(3)
122
+ else
123
+ degrees
124
+ end
125
+ end
126
+
127
+ def convert_temp_for_set(degrees)
128
+ case self.temperature_scale
129
+ when /f|F|(F|f)ahrenheit/
130
+ f2c(degrees).round(5)
131
+ when /k|K|(K|k)elvin/
132
+ k2c(degrees).round(5)
133
+ else
134
+ degrees
135
+ end
136
+ end
137
+
138
+ def k2c(degrees)
139
+ degrees.to_f - 273.15
140
+ end
141
+
142
+ def c2k(degrees)
143
+ degrees.to_f + 273.15
144
+ end
145
+
146
+ def c2f(degrees)
147
+ degrees.to_f * 9.0 / 5 + 32
148
+ end
149
+
150
+ def f2c(degrees)
151
+ (degrees.to_f - 32) * 5 / 9
152
+ end
153
+
154
+ end
155
+ end
@@ -0,0 +1,3 @@
1
+ module NestThermostat
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,2 @@
1
+ require "nest_thermostat/version"
2
+ require "nest_thermostat/nest"
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/nest_thermostat/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Eric Boehs"]
6
+ gem.email = ["ericboehs@gmail.com"]
7
+ gem.description = %q{Control your nest thermostat}
8
+ gem.summary = %q{View and set temperature and away status for your Nest}
9
+ gem.homepage = "http://github.com/ericboehs/nest-ruby"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "nest_thermostat"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = NestThermostat::VERSION
17
+ gem.add_dependency "httparty", "~> 0.8.3"
18
+
19
+ gem.add_development_dependency "rspec", "~> 2.10"
20
+ gem.add_development_dependency "awesome_print"
21
+ end
@@ -0,0 +1,74 @@
1
+ require 'nest_thermostat'
2
+
3
+ RSpec.configure do |c|
4
+ c.filter_run focus: true
5
+ c.run_all_when_everything_filtered = true
6
+ end
7
+
8
+ describe NestThermostat::Nest do
9
+ before(:all) do
10
+ @nest = NestThermostat::Nest.new({email: ENV['NEST_EMAIL'], password: ENV['NEST_PASS'], temperature_scale: 'F'})
11
+ end
12
+
13
+ it "logs in to home.nest.com" do
14
+ @nest.transport_url.should match /transport.nest.com/
15
+ end
16
+
17
+ it "gets the status" do
18
+ @nest.status['device'].first[1]['mac_address'].should match /(\d|[a-f]|[A-F])+/
19
+ end
20
+
21
+ it "gets the leaf status" do
22
+ @nest.leaf.should_not be_nil
23
+ end
24
+
25
+ it "gets away status" do
26
+ @nest.away.should_not be_nil
27
+ end
28
+
29
+ it "sets away status" do
30
+ @nest.away = true
31
+ @nest.away.should == true
32
+ @nest.away = false
33
+ @nest.away.should == false
34
+ end
35
+
36
+ it "gets the current temperature" do
37
+ @nest.current_temperature.should be_a_kind_of(Numeric)
38
+ @nest.current_temp.should be_a_kind_of(Numeric)
39
+ end
40
+
41
+ it "gets the relative humidity" do
42
+ @nest.humidity.should be_a_kind_of(Numeric)
43
+ end
44
+
45
+ it "gets the temperature" do
46
+ @nest.temperature.should be_a_kind_of(Numeric)
47
+ @nest.temp.should be_a_kind_of(Numeric)
48
+ end
49
+
50
+ it "sets the temperature" do
51
+ @nest.temp = '74'
52
+ @nest.temp.round.should eq(74)
53
+
54
+ @nest.temperature = '73'
55
+ @nest.temperature.round.should eq(73)
56
+ end
57
+
58
+ it "sets the temperature in celsius" do
59
+ @nest.temperature_scale = 'c'
60
+ @nest.temperature = '22'
61
+ @nest.temperature.should eq(22.0)
62
+ end
63
+
64
+ it "sets the temperature in kelvin" do
65
+ @nest.temp_scale = 'k'
66
+ @nest.temperature = '296'
67
+ @nest.temperature.should eq(296.0)
68
+ end
69
+
70
+ it "gets the target temperature time" do
71
+ @nest.target_temp_at.should_not be_nil # (DateObject or false)
72
+ @nest.target_temperature_at.should_not be_nil # (DateObject or false)
73
+ end
74
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nest_thermostat
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Eric Boehs
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: httparty
16
+ requirement: &16513040 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.8.3
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *16513040
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ requirement: &16511520 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: '2.10'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *16511520
36
+ - !ruby/object:Gem::Dependency
37
+ name: awesome_print
38
+ requirement: &16526700 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *16526700
47
+ description: Control your nest thermostat
48
+ email:
49
+ - ericboehs@gmail.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - .gitignore
55
+ - Gemfile
56
+ - Gemfile.lock
57
+ - LICENSE
58
+ - README.md
59
+ - Rakefile
60
+ - lib/nest_thermostat.rb
61
+ - lib/nest_thermostat/nest.rb
62
+ - lib/nest_thermostat/version.rb
63
+ - nest_thermostat.gemspec
64
+ - spec/nest_thermostat_spec.rb
65
+ homepage: http://github.com/ericboehs/nest-ruby
66
+ licenses: []
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 1.8.10
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: View and set temperature and away status for your Nest
89
+ test_files:
90
+ - spec/nest_thermostat_spec.rb