Analyzing Home Heating and Cooling Data Using Nest: Data Collection

By Jason Thompson, co-founder, 33 Sticks
 
As home automation becomes more of a consumer reality, the data available to home owners to monitor, analyze, and optimize the home will become increasingly valuable. In this multi-part series, we will be examining home automation analytics, specifically focusing on data acquired through home heating and cooling automation using the Nest Thermostat. This three part series will address data collection, data visualization, and analysis, insights, & optimization.
 
In part one of this series, we will examine the data that is available from the Nest and how to collect and store that data for future use.
 
Before we can determine what data we want to collect, we must first understand what data is available. The following data elements can be accessed from your Nest Thermostat:
 

  • Current and Target Temperatures & Humidity
  • Time to Target Temperature
  • Nest

  • Target Temperature Mode, Fan Mode
  • AC, Heat, and Fan Status; On/Off
  • Manual and Automatic Away Mode
  • Location Information
  • Network Information
  • Currently Active Schedule (by Day)
  • Next Scheduled Event
  • Last 10 Days Energy Report

 
Step 1 – Build a Database
The first step is to determine what data elements you are interested in capturing and then build a corresponding database table that will store the information.
 
We decided to capture the following elements: Location, Outside Temperature, Away Status, Current Temperature, Current Humidity, Temperature Mode, Target Temperature, Time to Target Temperature, Heat Status, and AC Status. In addition to the data retrieved from the Nest, we are also capturing a date and timestamp that aligns with the date and time the script retrieves the data from the Nest.
 
Once we had determined the data we wanted to capture, it was easy to create a simple table within mySQL to hold the data. We created a database tabled named ‘nest’ that has the following structure:
 
Nest Database Table
 
Step 2 – Capture Nest Data Into Database
In order to query your Nest data and insert the data into your newly created database table, you must create a script that has two parts to it. The first part authenticates to your Nest and retrieves the requested data that is returned in JSON format. Our base script is making use of a NEST API that was developed using PHP. The API is available on GetHub.
 
The second part of the script parses the JSON data and inserts it into the database table we created in Step 1.
 
Rather than just dump all the code out into this blog post, we have created a template file that can be downloaded and modified as needed. The file is well documented and allows you to create a database connection, create a Nest object, query Nest, and insert values into a database table.
 

 
Step 3 – Automate Date Capture
Once you have coded your script and everything is working as expected, the next step is to automate the execution of your script to run on an ongoing basis to continuously capture and log data from your Nest.
 
We chose to execute our script every 5 minutes, at this point that number is completely arbitrary, you could choose Raspberry Pito run it every minute or every 30 minutes. We will have a better idea on a proper interval once we have had a chance to spend some quality time analyzing the data we are currently capturing.
 
To automate the execution of our script, we are making use of a cron job.
 
As we have a Raspberry Pi laying around, we thought it would make the perfect server to manage our Nest data capture script.
 
Once you have decided where you want to run your script from, if you are comfortable with it, it is pretty easy to create a new cron job directly from the command line by creating a new crontab file for your user. This is done by accessing the command line. Type the following into the command line:
 
crontab -e
 
Determine how often you want to run your script and add a new entry to your crontab file. As mentioned, we are running our script every 5 minutes, so our entry looks like:
 
*/5 * * * * /home/nest/nest.php
 
If you are hosting your script using a service like GoDaddy, while you will have less control over what you can do with your cron job, they make very nice UI tools that make creating a new cron job super simple. Here is a link to the GoDaddy help file on setting up new cron jobs.
 
* * * * *
 
Visually, our three step data collection process looks like the following:
Nest Data Collection Flow
 
And that is it, once you have completed those 3 steps, you will be capturing data from your Nest Thermostat.
 
In the next part of this series, we will be covering techniques to visualize your Nest data. Following that, we will go in-depth on analyzing the Nest data and illustrating how the insights gleaned from that analysis can be put into use to lower overall energy consumption.
 
Note, this project is very much a work-in-process, if you have any suggestions on how we can optimize this process, from the database setup to the execution of the script, please add your suggestions below.
 
We hope you enjoy this series and if you have any questions, please don’t hesitate to contact us.
 
 

Join the Conversation

16 Comments

  1. What’s the use case and point of this? I would like to see how I can do this for google or adobe site catalyst. Is this actionable?

    1. The use case is to better understand home energy usage and how analyzing the data made available through the thermostat as well as weather and energy usage data provided by the power company can be used to optimize home heating & cooling efficiency and reduce energy usage.

  2. Nice work! This is something I’ve wanted to do for quite some time but just haven’t gotten around to it, thanks for the doing the heavy lifting.
     
    A couple of comments:
     
    1. Your code only supports pulling data for 1 Nest, for someone like myself with multiple Nests the serial number needs to be passed to the getDeviceInfo() function. I hacked the code up to hard code my serials and make multiple API calls per serial number.
     
    2. When Nest is in Away mode the target temperature is returned as an array with the away target and non-away target. I had to modify the code to check if an array is being returned and pull the value out of the array rather than a single value.
     
    Otherwise, good stuff. I’ll be doing some more data analysis as well!

    1. Preston,

      Thank you so much for the feedback, much appreciated. My hope is that people will take this idea and really start to build upon it. I’m very interested in your experience and what you uncover with your analysis.

  3. Something is not right in AutoAway from the nest.class.php (at least if the temp is in F). The database puts out “Array” instead of temp in the version above, something is wrong with the “range” array. I wish I knew how to fix it but can’t at this time.

      1. Thanks for spending the time putting together this little program in the first place. Much appreciated! Other than that one little glitch, seems to be working great for me (only one Nest in the house so far). It would not work in my free hosted site, but now I have migrated it to my paid site it works well other than that “Array” problem with the “range.” 🙂

  4. Oh, forgot to mention “Time to Temp” displays a 10 digit number… such as “1394057907” or “1394058163” (at a half hour interval) I’m not sure how to translate that.

    1. It’s a Unix timestamp giving you the ‘exact’ time that Nest thinks it’ll reach the target temp. Depending on how you’re processing the data there would be different ways of converting this into a human readable format.

  5. It’s not elegant, but I got something working by placing the following code (changes commented below) into the nest.class.php somewhere near line 142 of your code:

    public function getDeviceInfo($serial_number=null) {
    $this->getStatus();
    $serial_number = $this->getDefaultSerial($serial_number);
    list(, $structure) = explode(‘.’, $this->last_status->link->{$serial_number}->structure);
    $manual_away = $this->last_status->structure->{$structure}->away;
    $mode = strtolower($this->last_status->device->{$serial_number}->current_schedule_mode);
    $target_mode = $this->last_status->shared->{$serial_number}->target_temperature_type;
    if ($manual_away || $mode == ‘away’ || $this->last_status->shared->{$serial_number}->auto_away > 0) {
    $mode = $mode . ‘,away’;
    $target_mode = ‘range’;

    // $target_temperatures = array($this->temperatureInUserScale((float) $this->last_status->device->{$serial_number}->away_temperature_low), $this->temperatureInUserScale((float) $this->last_status->device->{$serial_number}->away_temperature_high));

    //Hard Code start
    if ($mode == ‘heat,away’) {$target_temperatures=’50’;
    }
    if ($mode == ‘cool,away’) {$target_temperatures=’84’;
    }
    if ($mode == ‘range,away’) {$target_temperatures=’70’;
    }

    //Hard Code end

    } else if ($mode == ‘range’) {
    $target_mode = ‘range’;

    1. I wouldn’t edit the class file for this. You can makes changes in the nest.php file to get the actual values instead of hardcoding them. The ‘range’ option presents an interesting situation because it should actually have two target temperatures (one for heating, one for cooling).

      In my situation I don’t use range. However, this code in nest.php before the $query should work.

      //If away, read temperature array.
      if (is_array($infos->target->temperature)) {
      if (strpos($infos->current_state->mode,’heat’) !== false) {
      $targettemp = $infos->target->temperature[0];
      } elseif(strpos($infos->current_state->mode,’ac’) !== false) {
      $targettemp = $infos->target->temperature[1];
      } elseif(strpos($infos->current_state->mode,’range’) !== false) {
      $targettemp = $infos->target->temperature[0].’ , ‘.$infos->target->temperature[1];
      }
      } else {
      $targettemp = $infos->target->temperature;
      }

      Then in the $query line change $infos->target->temperature to $targettemp.

      If you’re running heat, $targettemp will report the lower Away value. If you’re running ac, it’ll report the higher Away value. If you’re running in range, it should report as “Lower_Value, Higher_Value”. (This could be a problem if you’re trying to make graphs.)

      1. Matt
        I had to do the hard coding I did above, because when I put it in Range mode, I didn’t get anything for output. So I believe the Class file had to be changed. It seems you did not experience the same thing. I wonder why.

  6. Appreciate the work you’ve done here. I took this and started converting the data into graphs. (http://imgur.com/7BgFugP) I hope to have my code up on GitHub soon in case anyone else wants to take a look at it.

    1. Matt,
      I love what you did on your site. I’d love to do the same, but lack any kind of knowledge to do that. I have my MySQL database populated (since March 3) but currently import to Excel to look at the charting. Can you teach me, an extreme novice, how to get from where I am to what you have? I haven’t seen it on GetHub; and frankly most of what’s there is a bit over my head.

Leave a comment

Your email address will not be published. Required fields are marked *