forked from smbaker/pynest
-
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make pynest installable via pip, split pynest.py into an main program and a library, and move from urllibX to requests
- Loading branch information
Showing
4 changed files
with
135 additions
and
119 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
#! /usr/bin/python | ||
|
||
# nest.py -- a python interface to the Nest Thermostat | ||
# by Scott M Baker, [email protected], http://www.smbaker.com/ | ||
# updated by Bob Pasker [email protected] http://pasker.net | ||
# | ||
# Licensing: | ||
# This is distributed unider the Creative Commons 3.0 Non-commecrial, | ||
# Attribution, Share-Alike license. You can use the code for noncommercial | ||
# purposes. You may NOT sell it. If you do use it, then you must make an | ||
# attribution to me (i.e. Include my name and thank me for the hours I spent | ||
# on this) | ||
# | ||
# Acknowledgements: | ||
# Chris Burris's Siri Nest Proxy was very helpful to learn the nest's | ||
# authentication and some bits of the protocol. | ||
|
||
import urllib | ||
import urllib2 | ||
import requests | ||
|
||
try: | ||
import json | ||
except ImportError: | ||
import simplejson as json | ||
|
||
class Nest: | ||
def __init__(self, username, password, serial=None, index=0, units="F", debug=False): | ||
self.username = username | ||
self.password = password | ||
self.serial = serial | ||
self.units = units | ||
self.index = index | ||
self.debug = debug | ||
|
||
def login(self): | ||
|
||
response = requests.post("https://home.nest.com/user/login", | ||
data = {"username":self.username, "password" : self.password}, | ||
headers = {"user-agent":"Nest/1.1.0.10 CFNetwork/548.0.4"}) | ||
|
||
response.raise_for_status() | ||
|
||
res = response.json() | ||
self.transport_url = res["urls"]["transport_url"] | ||
self.access_token = res["access_token"] | ||
self.userid = res["userid"] | ||
# print self.transport_url, self.access_token, self.userid | ||
|
||
def get_status(self): | ||
response = requests.get(self.transport_url + "/v2/mobile/user." + self.userid, | ||
headers={"user-agent":"Nest/1.1.0.10 CFNetwork/548.0.4", | ||
"Authorization":"Basic " + self.access_token, | ||
"X-nl-user-id": self.userid, | ||
"X-nl-protocol-version": "1"}) | ||
|
||
response.raise_for_status() | ||
res = response.json() | ||
|
||
self.structure_id = res["structure"].keys()[0] | ||
|
||
if (self.serial is None): | ||
self.device_id = res["structure"][self.structure_id]["devices"][self.index] | ||
self.serial = self.device_id.split(".")[1] | ||
|
||
self.status = res | ||
|
||
#print "res.keys", res.keys() | ||
#print "res[structure][structure_id].keys", res["structure"][self.structure_id].keys() | ||
#print "res[device].keys", res["device"].keys() | ||
#print "res[device][serial].keys", res["device"][self.serial].keys() | ||
#print "res[shared][serial].keys", res["shared"][self.serial].keys() | ||
|
||
def temp_in(self, temp): | ||
if (self.units == "F"): | ||
return (temp - 32.0) / 1.8 | ||
else: | ||
return temp | ||
|
||
def temp_out(self, temp): | ||
if (self.units == "F"): | ||
return temp*1.8 + 32.0 | ||
else: | ||
return temp | ||
|
||
def show_status(self): | ||
shared = self.status["shared"][self.serial] | ||
device = self.status["device"][self.serial] | ||
|
||
allvars = shared | ||
allvars.update(device) | ||
|
||
for k in sorted(allvars.keys()): | ||
print k + "."*(32-len(k)) + ":", allvars[k] | ||
|
||
def show_curtemp(self): | ||
temp = self.status["shared"][self.serial]["current_temperature"] | ||
temp = self.temp_out(temp) | ||
|
||
print "%0.1f" % temp | ||
|
||
def _set(self, data, which): | ||
if (self.debug): print json.dumps(data) | ||
url = "%s/v2/put/%s.%s" % (self.transport_url, which, self.serial) | ||
if (self.debug): print url | ||
response = requests.post(url, | ||
data = json.dumps(data), | ||
headers = {"user-agent":"Nest/1.1.0.10 CFNetwork/548.0.4", | ||
"Authorization":"Basic " + self.access_token, | ||
"X-nl-protocol-version": "1"}) | ||
|
||
if response.status_code > 200: | ||
if (self.debug): print response.content | ||
response.raise_for_status() | ||
return response | ||
|
||
def _set_shared(self, data): | ||
self._set(data, "shared") | ||
|
||
def _set_device(self, data): | ||
self._set(data, "device") | ||
|
||
def set_temperature(self, temp): | ||
return self._set_shared({ | ||
"target_change_pending": True, | ||
"target_temperature" : self.temp_in(temp) | ||
}) | ||
|
||
def set_fan(self, state): | ||
return self._set_device({ | ||
"fan_mode": str(state) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,4 +11,6 @@ | |
maintainer_email='[email protected]', | ||
url='https://github.com/FiloSottile/nest_thermostat/', | ||
scripts=['nest.py'], | ||
packages=['pynest'], | ||
install_requires = ['requests'] | ||
) |