nest_thermostat 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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