A week or so ago we had a Nest Thermostat installed.
It’s quite clever – learning when you are in, out and awake, and estimating a heating profile for those times. It needed some tweaking, sure, but it did a very good job overall.
I then realised – what use is a smart device, which has an API, if you’re not looking at the data?
Right – what do we need?
- A way to talk to the API
- A way to parse that data
- A way to log that Data
I’m not going through the API documentation and cadging something together to talk to the API – sod that, someone’s already done it. It might not give me all the data I need in easy chunks, but most of the hard work is done.
These requirements can be solved by:
- nest_thermostat python module
- Some bash bashing
- rrdtool
so nest_thermostat, once installed with pip install nest_thermostat
can be used with the following 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
Now the first four we don’t need to do anything with, as we only want to read data, not start writing a copy of the nest website where we can start setting temperatures and things.
curmode
is useless to me as my nest is only configured to heat, not to cool, as I’m in the UK and we don’t typically have Air Conditioning window boxes, much less a fully installed system.
Initially, I set up a small script to look at curtemp
, log it to rrdtool
and let my current monitoring graphing scripts graph it along with temp measured by my currentcost. This was fine until I hit the API limit of the Nest API, and the query returned HTTP 429: Too Many Requests
. Oops. This gave me a reading of Zero and resulted in lots of vertical lines on the graph.
Secondarily, I set up a script to look at curtemp
, and if that resulted in a successful retrieval, log it to rrdtool
. This was much better, and gave me much more consistent rrdtool entries.
#!/bin/bash
#get the current temperature from nest_thermostat
var=$(/usr/local/bin/nest.py --user <username> --password <password> --celsius curtemp)
#check to see if the value is a valid set of numbers only - weeding out the HTTP429 errors
if [[ $var = *[[:digit:]]* ]]; then
#push it into rrdtool
rrdtool update /mnt/bigdisk/cc/nesttemp.rrd N:$var
fi
Next, I had the itch for more data. current temperature wasn’t enough – wouldn’t it be nice to see when the wife turned the thermostat up? And When/How long the heating had been on?
Looking at the source for nest_thermostat, I was going to have to modify that pretty heavily to give me some extra commands to use – this might have resulted in too many API requests again though, making 3 calls to the API for the 3 peices of data I needed. A much better idea was to use the show command, and parse that for the data I wanted.
But what was it I wanted? I needed to know which variables represented heating on/off and the temperature the thermostat was set to.
I pushed $ nest.py --user <username> --password <password> --celsius show >> heating.txt
when the heating was on (I manually set the target temp to 24C to get it to come on) and pushed it to notheating2.txt
when it was off.
I then ran a diff on the files:
$ diff heating.txt notheating2.txt -y --suppress-common-lines
hvac_heater_state...............: True | hvac_heater_state...............: False
target_temperature..............: 24 | target_temperature..............: 20
Right, some awful (and I mean awful) hacking with pipes and sed
and I had my three pieces of data:
- Current Temperature (
|grep target_temperature|grep -v target_temperature_ | sed 's/.*://' | sed -r 's/^.{1}//'| sed 's/[[:blank:]]//g'
) - Target Temperature (
|grep current_temperature| sed 's/.*\(.....\)/\1/'| sed 's/[[:blank:]]//g'
) - Heating True/False (
|grep hvac_heater_state|sed 's/.*://' | sed -r 's/^.{1}//' | sed 's/[[:blank:]]//g'
)
(the last sed
commands in each are to deal with an issue I encountered this morning where extra white space was screwing up the data going in to rrdtool
– hacky, but it works. I’d be glad to hear of any improvements though!)
So, we need to run the script like this – send the full output from nest_thermostat
into a bash variable, do the tasks above on it to get the individual pieces of data, and then if they are valid values (using the same check as before) then we’ll let them through to rrdtool
to update the nesttemp.rrd
.
I’ve set a thing in there to make the heating
variable numeric, so it appears nicely on the graphs with the rest of the figures.
#!/bin/bash
var=$(/usr/local/bin/nest.py --user --password --celsius show)
targ_temp=$(echo "$var" |grep target_temperature|grep -v target_temperature_ |sed 's/.*://' | sed -r 's/^.{1}//'|sed 's/[[:blank:]]//g' );
cur_temp=$(echo "$var" |grep current_temperature| sed 's/.*\(.....\)/\1/'|sed 's/[[:blank:]]//g');
heating=$(echo "$var" |grep hvac_heater_state|sed 's/.*://' | sed -r 's/^.{1}//' |sed 's/[[:blank:]]//g');
if [[ "$heating" == True ]]; then
heating='10'
else
heating='0'
fi
if [[ $cur_temp = *[[:digit:]]* ]]; then
rrdtool update /mnt/bigdisk/cc/nesttemp.rrd N:$cur_temp:$targ_temp:$heating;
fi
This results in some nice little graphs like this: