-
-
Save tylerdave/409ffa08e1d47b1a1e23 to your computer and use it in GitHub Desktop.
{ | |
"metadata": { | |
"name": "Nest API Example" | |
}, | |
"nbformat": 3, | |
"nbformat_minor": 0, | |
"worksheets": [ | |
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": "You must have a Nest developer account client ID and client secret to proceed. If you don't already have a developer account, sign up here and create a new client:\n\nhttps://developer.nest.com/clients " | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": "Import the modules we'll use:" | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": "import hashlib\nimport json\nimport os\nimport requests", | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 1 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": "Enter your Nest developer account client's credentials here:" | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": "CLIENT_ID = 'CLIENT_ID_HERE'\nCLIENT_SECRET = 'CLIENT_SECRET_HERE'", | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 2 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": "Define URLs and data used:" | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": "AUTHORIZATION_URL = 'https://home.nest.com/login/oauth2?client_id={0}&state={1}'\nACCESS_TOKEN_URL = 'https://api.home.nest.com/oauth2/access_token'\nACCESS_TOKEN_POST_DATA = {\n 'code': '',\n 'client_id': CLIENT_ID,\n 'client_secret': CLIENT_SECRET,\n 'grant_type': 'authorization_code'\n }\nNEST_API_URL = 'https://developer-api.nest.com/devices.json?auth={0}'\nNEST_API_URL = 'https://developer-api.nest.com/?auth={0}'", | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 3 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": "Generate an authorization URL:" | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": "state = hashlib.md5(os.urandom(32)).hexdigest() # 'state' is just a random string of text\nprint AUTHORIZATION_URL.format(CLIENT_ID, state)", | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": "https://home.nest.com/login/oauth2?client_id=CLIENT_ID_HERE&state=8199d94c7c08de7791e3a67b8384c4b2\n" | |
} | |
], | |
"prompt_number": 4 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": "Visit the URL printed by the cell above, authorize the application to use your Nest account and enter the pincode in the cell below:" | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": "ACCESS_TOKEN_POST_DATA['code'] = 'PINCODE_HERE'", | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 5 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": "Request an access token:" | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": "token_response = requests.post(ACCESS_TOKEN_URL, data=ACCESS_TOKEN_POST_DATA)", | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 6 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": "Get the access token from the response. Raise an exception if there's an error:" | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": "try:\n token_response.raise_for_status() # Rasie and exception if the token request results in an error\n access_token = token_response.json()['access_token']\nexcept Exception as e:\n print token_response.content\n raise e", | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 7 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": "Read data from the Nest API:" | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": "nest_response = requests.get(NEST_API_URL.format(access_token))", | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 8 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": "Print the response nicely:" | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": "print json.dumps(nest_response.json(), sort_keys=True, indent=4)", | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": "{\n \"devices\": {\n \"thermostats\": {\n \"\": {\n \"ambient_temperature_c\": 21.5, \n \"ambient_temperature_f\": 72, \n \"away_temperature_high_c\": 29.0, \n \"away_temperature_high_f\": 85, \n \"away_temperature_low_c\": 15.5, \n \"away_temperature_low_f\": 60, \n \"can_cool\": true, \n \"can_heat\": true, \n \"device_id\": \"\", \n \"fan_timer_active\": false, \n \"has_fan\": true, \n \"has_leaf\": false, \n \"hvac_mode\": \"cool\", \n \"is_online\": true, \n \"is_using_emergency_heat\": false, \n \"last_connection\": \"2014-07-15T19:56:11.988Z\", \n \"locale\": \"en-US\", \n \"name\": \"Entryway (Home)\", \n \"name_long\": \"Entryway Thermostat (Home)\", \n \"software_version\": \"4.2.4\", \n \"structure_id\": \"\", \n \"target_temperature_c\": 21.5, \n \"target_temperature_f\": 71, \n \"target_temperature_high_c\": 20.5, \n \"target_temperature_high_f\": 69, \n \"target_temperature_low_c\": 19.0, \n \"target_temperature_low_f\": 67, \n \"temperature_scale\": \"F\"\n }\n }\n }, \n \"structures\": {\n \"\": {\n \"away\": \"home\", \n \"country_code\": \"US\", \n \"name\": \"Name\", \n \"structure_id\": \"\", \n \"thermostats\": [\n \"\"\n ]\n }\n }\n}\n" | |
} | |
], | |
"prompt_number": 9 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": "More details here: https://developer.nest.com/documentation/api-reference" | |
} | |
], | |
"metadata": {} | |
} | |
] | |
} |
Hi !
The last line - print json.dumps(nest_response.json() ..
I don't see a device key, only structures and metadata -- have I made a mistake while registering the product?
Would be really thankful.
This was really helpful, thanks!
I was trying to do this following https://developers.nest.com/documentation/cloud/rest-quick-guide which says to use the Authorization
header with your access_token
, and that was consistently failing with 401 Unauthorized. Using an auth
param instead seems to work, but I haven't seen documentation for it (that doesn't say much though, the documentation is pretty scattered).
Actually, I figured out why the authorization header wasn't working. Making requests to developer-api.nest.com ends up doing a redirect to a firebase hostname, and the requests library strips authorization headers when doing redirects. https://github.com/kennethreitz/requests/issues/2949 talks about this more, specifically about how it happens working with the Nest API.
Hi, if i want to set temperature?
regards
What programming language do I have to use in order to do this? I'm new to Nest development.
Thanks for the write up. This was exactly what I had been hunting for. One question, have you found a way to make the authorization_code be persistent? I can run the python code once per authorization_code. Second run I have get a new authorization code. This doesn't help with a cron'd script.