Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to Use Print Correctly #14

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
757a690
Separate main program from library calls
rbpasker Jul 15, 2013
60972e1
moved to python requests and collapsed POSTs
rbpasker Jul 15, 2013
0303ba9
Added requests as a requirement
rbpasker Jul 15, 2013
016b1d1
install_requires for git-based installs
rbpasker Jul 15, 2013
89d3713
adding setmode and show mode
abemassry Nov 1, 2013
ffa1830
added show current target temperature method
abemassry Dec 2, 2013
363371c
Update README.md
FiloSottile Mar 8, 2014
8d79b21
Create LICENSE.md
FiloSottile Mar 8, 2014
b598f1b
Update README.md
FiloSottile Mar 8, 2014
0f62fd9
Update setup.py
FiloSottile Mar 8, 2014
e357808
Merge PR smbaker/pynest#9 by @rbpasker
FiloSottile Mar 8, 2014
7c152bf
rename the module to nest_thermostat
FiloSottile Mar 8, 2014
6b86574
Merge PR smbaker/pynest#10 by @abemassry
FiloSottile Mar 8, 2014
d6c56a1
Add ability to toggle away status.
Mar 6, 2013
003be2b
update README help
FiloSottile Mar 9, 2014
2ca5624
Create .gitignore
FiloSottile Mar 9, 2014
9feb7c0
add encoding to setup.py
FiloSottile Mar 9, 2014
143ede7
add MANIFEST
FiloSottile Mar 9, 2014
513a225
advertise pip installation in README
FiloSottile Mar 9, 2014
7c3053d
changed message, add current set temp
abemassry Mar 9, 2014
b8e2fa8
changed message, add current set temp
abemassry Mar 9, 2014
98caaea
changed message, add current set temp
abemassry Mar 9, 2014
2c62462
Merge PR #1 by @abemassry - add curtarget
FiloSottile Mar 13, 2014
723f0bf
Updated to use the print function correctly
digilord Apr 14, 2014
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
*.py[cod]

# C extensions
*.so

# Packages
*.egg
*.egg-info
dist
build
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg
lib
lib64
__pycache__

# Installer logs
pip-log.txt

# Unit test / coverage reports
.coverage
.tox
nosetests.xml

# Translations
*.mo

# Mr Developer
.mr.developer.cfg
.project
.pydevproject

MANIFEST
1 change: 1 addition & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-nc-sa/3.0/88x31.png" /></a><br />This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/3.0/">Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License</a>.
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
include README.md
include LICENSE.md
61 changes: 40 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,47 @@
pynest -- a python interface for the Nest Thermostat
by Scott M Baker, [email protected], http://www.smbaker.com/
#nest_thermostat

Usage:
'nest.py help' will tell you what to do and how to do it
**a Python interface for the Nest Thermostat**

*fork of pynest by Scott M Baker, [email protected], http://www.smbaker.com/*

Example:
'nest.py --user [email protected] --password swordfish temp 73'
set the temperature to 73 degrees
##Installation
`[sudo] pip install nest_thermostat`

'nest.py --user [email protected] --password swordfish fan auto'
set the fan to automatic
##Usage

Installation:
'python ./setup.py install' will install nest.py to the right place,
usually your /usr/bin directory.
### Module

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)
You can import the module as `nest_thermostat`. Use the source, luke!

Acknowledgements:
Chris Burris's Siri Nest Proxy was very helpful to learn the nest's
authentication and some bits of the protocol.
Tips: you need to manually call `.login()` first, and `.get_status()` before `.show_*()`

### Command line
```
syntax: nest.py [options] command [command_args]
options:
--user <username> ... username on nest.com
--password <password> ... password on nest.com
--celsius ... use celsius (the default is farenheit)
--serial <number> ... optional, specify serial number of nest to use
--index <number> ... optional, 0-based index of nest
(use --serial or --index, but not both)

commands:
temp <temperature> ... set target temperature
fan [auto|on] ... set fan state
mode [cool|heat|range|off] ... set fan state
away ... toggle away
show ... show everything
curtemp ... print current temperature
curhumid ... print current humidity
curmode ... print current mode

examples:
nest.py --user [email protected] --password swordfish temp 73
nest.py --user [email protected] --password swordfish fan auto
```


---

*Chris Burris's Siri Nest Proxy was very helpful to learn the Nest's authentication and some bits of the protocol.*
213 changes: 45 additions & 168 deletions nest.py
Original file line number Diff line number Diff line change
@@ -1,145 +1,12 @@
#! /usr/bin/python

# nest.py -- a python interface to the Nest Thermostat
# by Scott M Baker, [email protected], http://www.smbaker.com/
#
# Usage:
# 'nest.py help' will tell you what to do and how to do it
#
# 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
"""
nest.py -- a python interface to the Nest Thermostat
"""

import sys
from optparse import OptionParser

try:
import json
except ImportError:
try:
import simplejson as json
except ImportError:
print "No json library available. I recommend installing either python-json"
print "or simpejson."
sys.exit(-1)

class Nest:
def __init__(self, username, password, serial=None, index=0, units="F"):
self.username = username
self.password = password
self.serial = serial
self.units = units
self.index = index

def loads(self, res):
if hasattr(json, "loads"):
res = json.loads(res)
else:
res = json.read(res)
return res

def login(self):
data = urllib.urlencode({"username": self.username, "password": self.password})

req = urllib2.Request("https://home.nest.com/user/login",
data,
{"user-agent":"Nest/1.1.0.10 CFNetwork/548.0.4"})

res = urllib2.urlopen(req).read()

res = self.loads(res)

self.transport_url = res["urls"]["transport_url"]
self.access_token = res["access_token"]
self.userid = res["userid"]

def get_status(self):
req = urllib2.Request(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"})

res = urllib2.urlopen(req).read()

res = self.loads(res)

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_temperature(self, temp):
temp = self.temp_in(temp)

data = '{"target_change_pending":true,"target_temperature":' + '%0.1f' % temp + '}'
req = urllib2.Request(self.transport_url + "/v2/put/shared." + self.serial,
data,
{"user-agent":"Nest/1.1.0.10 CFNetwork/548.0.4",
"Authorization":"Basic " + self.access_token,
"X-nl-protocol-version": "1"})

res = urllib2.urlopen(req).read()

print res

def set_fan(self, state):
data = '{"fan_mode":"' + str(state) + '"}'
req = urllib2.Request(self.transport_url + "/v2/put/device." + self.serial,
data,
{"user-agent":"Nest/1.1.0.10 CFNetwork/548.0.4",
"Authorization":"Basic " + self.access_token,
"X-nl-protocol-version": "1"})

res = urllib2.urlopen(req).read()

print res
from nest_thermostat import Nest

def create_parser():
parser = OptionParser(usage="nest [options] command [command_options] [command_args]",
Expand All @@ -165,25 +32,29 @@ def create_parser():
return parser

def help():
print "syntax: nest [options] command [command_args]"
print "options:"
print " --user <username> ... username on nest.com"
print " --password <password> ... password on nest.com"
print " --celsius ... use celsius (the default is farenheit)"
print " --serial <number> ... optional, specify serial number of nest to use"
print " --index <number> ... optional, 0-based index of nest"
print " (use --serial or --index, but not both)"
print
print "commands: temp, fan, show, curtemp, curhumid"
print " temp <temperature> ... set target temperature"
print " fan [auto|on] ... set fan state"
print " show ... show everything"
print " curtemp ... print current temperature"
print " curhumid ... print current humidity"
print
print "examples:"
print " nest.py --user [email protected] --password swordfish temp 73"
print " nest.py --user [email protected] --password swordfish fan auto"
print( "syntax: nest.py [options] command [command_args]")
print( "options:")
print( " --user <username> ... username on nest.com")
print( " --password <password> ... password on nest.com")
print( " --celsius ... use celsius (the default is farenheit)")
print( " --serial <number> ... optional, specify serial number of nest to use")
print( " --index <number> ... optional, 0-based index of nest")
print( " (use --serial or --index, but not both)")
print()
print( "commands:")
print( " temp <temperature> ... set target temperature")
print( " fan [auto|on] ... set fan state")
print( " mode [cool|heat|range|off] ... set mode state")
print( " away ... toggle away")
print( " show ... show everything")
print( " curtemp ... print current temperature")
print( " curhumid ... print current humidity")
print( " curmode ... print current mode")
print( " curtarget ... print current target temp")
print()
print( "examples:")
print( " nest.py --user [email protected] --password swordfish temp 73")
print( " nest.py --user [email protected] --password swordfish fan auto")

def main():
parser = create_parser()
Expand All @@ -194,7 +65,7 @@ def main():
sys.exit(-1)

if (not opts.user) or (not opts.password):
print "how about specifying a --user and --password option next time?"
print( "how about specifying a --user and --password option next time?")
sys.exit(-1)

if opts.celsius:
Expand All @@ -210,28 +81,34 @@ def main():

if (cmd == "temp"):
if len(args)<2:
print "please specify a temperature"
print( "please specify a temperature")
sys.exit(-1)
n.set_temperature(int(args[1]))
elif (cmd == "fan"):
if len(args)<2:
print "please specify a fan state of 'on' or 'auto'"
print( "please specify a fan state of 'on' or 'auto'")
sys.exit(-1)
n.set_fan(args[1])
elif (cmd == "mode"):
if len(args)<2:
print( "valid modes are cool, heat, range, and off")
sys.exit(-1)
n.set_mode(args[1])
elif (cmd == "away"):
n.toggle_away()
elif (cmd == "show"):
n.show_status()
elif (cmd == "curtemp"):
n.show_curtemp()
elif (cmd == "curmode"):
n.show_curmode()
elif (cmd == "curtarget"):
n.show_target()
elif (cmd == "curhumid"):
print n.status["device"][n.serial]["current_humidity"]
print( n.status["device"][n.serial]["current_humidity"])
else:
print "misunderstood command:", cmd
print "do 'nest.py help' for help"
print( "misunderstood command: %s" % cmd)
print( "do 'nest.py help' for help")

if __name__=="__main__":
main()





Loading