Home Home Control: Nest Thermostat API
Post
Cancel
Preview Image

Home Control: Nest Thermostat API

To get connected into the Google Nest API is rather complicated and costs $5 ($10 in my case since I did it against the wrong email the first time!). It utilises the Device Access Program from Google, and the Smart Device Management (SDM) API.

Register for Device Access program

  • Register with Google for device access. This includes a one-off payment of US$5
    • Device Access Console
    • NOTE: If you have more than one Google email address, make sure you select the right one or you will have to pay again for the correct email address (bitter experience!)
  • Once registered there will be a projects screen with the option to create a project

Create GCP project, Enable SDM API and Get OAuth 2.0 Client ID

  • Access to the SDM API is provided through the Google Cloud Platform (GCP). To enable the API and authorise a Google account with a supported Nest device, you need a GCP project
  • On the Device Access home page, select Go To Console button top right, and this brings up the projects page [or might allow direct access to Projects page, sometimes wanted paying again… avoid!]
    • Select Documentation top right -> Guides top left -> 1. Get Started and scroll down to Set up Google Cloud Platform section [link]
    • Click the Enable the API and get an OAuth 2.0 Client ID button, Create Project
      • Project name: Nest API Project
      • Product name: NestDeviceAccess
      • Where are you calling from: Web Server
      • Authorized redirect URIs: https://www.google.com
      • Click Create, brings up a page with client configuration
        • Download JSON
        • Client ID: 803912481486-gcdoopdmarudrmacgvh65pl689mlj15j.apps.googleusercontent.com
        • Client Secret: GOCSPX–c-l3e5DYxEDGJ9LXPyB9-wYddj0

Create Device Access Project, get Project ID

  • Return to the Device Access Console projects page
  • Create project: Nest Thermostat Project
    • OAuth Client ID: from above
    • Enable Events allows faster thermostat state updates
    • Click Create Project button and a Project ID is created. Take note of it
      • f93794af-4ffb-49fb-8a27-ad8b929c27a0

Authorise an Account

  • Link the Account using the Partner Connections Manager (PCM). This uses a web browser to generate an authorisation code for Nest devices. Either use the Device Access page (preferred) or, replace the projectId and clientId in the following URL and paste into a browser (ensure no space or carriage returns)
    1
    2
    3
    4
    5
    6
    7
    
    https://nestservices.google.com/partnerconnections/><projectId>/auth?
    redirect_uri=https://www.google.com&
    access_type=offline&
    prompt=consent&
    client_id=<strong><clientId></strong>&
    response_type=code&
    scope=https://www.googleapis.com/auth/sdm.service
    
  • Enable all permissions, and click Next
  • Select relevant Google account when prompted
  • At the warning “Google hasn’t verified this app”, select Advanced, click on link “Go to NestDeviceAccess (unsafe)”
  • At the “NestDeviceAccess wants access to your Google Account”, select Continue
  • This will redirect to Google.com with the authorisation code between the “…code=” and the “&scope…” part of the URL:
  • 4/0AX4XfWgkBHmydbmXSUYcn2m8BBGVvEo9TIq2vCEHXQiZ_czoidtC_eVY3xWBuBCPeJV_mA

Get Access and Refresh Tokens

Using the Device Access page again, enter the ClientID, clientSecret and authorisationCode to create a curl command to paste into Terminal:

1
curl -L -X POST 'https://www.googleapis.com/oauth2/v4/token?client_id=<strong>clientId</strong>&client_secret=<strong>clientSecret</strong>&code=<strong>authorizationCode</strong>&grant_type=authorization_code&redirect_uri=https://www.google.com'

returns:

1
2
3
4
5
{ "access_token": "accessToken",
  "expires_in": 3599,
  "refresh_token": "refreshToken",
  "scope": "https://www.googleapis.com/auth/sdm.service",
  "token_type": "Bearer" }

Node-RED Flow

Could not get OpenHAB plugin for Nest to work so setup a flow in Node-RED instead. which are then used to get the Nest state every 5 minutes.

This first function uses the credentials and refreshToken above to get new accessToken every hour (refer to return message above expires_in: 3599 seconds) which is saved in a flow variable:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let clientId = '803912481486-gcdoopdmarudrmacgvh65pl689mlj15j.apps.googleusercontent.com';
let clientSecret = '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';
let refreshToken = '1//03wEYMPOJQzPmCgYIARAAGAMSNwF-L9IrhU4P98YREGQfmpfTm2jb57ud-FOh6ESLJNpmWuWuIjSmYbgKMl5LFqlN7o1sjgjiVSk';

msg.url = "https://www.googleapis.com/oauth2/v4/token";
msg.method = "POST";
msg.payload = {
  "client_id": clientId,
  "client_secret": clientSecret,
  "refresh_token": refreshToken,
  "grant_type": 'refresh_token'
};

var d = new Date();
node.status({fill:'blue',shape:'dot',text:'Last update ' + ('0'+d.getHours()).slice(-2) + ':' + ('0'+d.getMinutes()).slice(-2)});
    
return msg;

The second function, called every 5 minutes, requests the device data which is then used to populate the OpenHAB items:

1
2
3
4
5
6
7
8
let projectId = 'f93794af-4ffb-49fb-8a27-ad8b929c27a0';
msg.url = "https://smartdevicemanagement.googleapis.com/v1/enterprises/" + projectId + "/devices"
msg.method = "GET";
msg.headers = {
    'Authorization': 'Bearer ' + flow.get("access_token"),
    'Content-Type': 'application/json'
};
return msg;

NOTE: Had to enable the Smart Device Management API for the testing via Terminal to work. Received messages then okay: https://console.developers.google.com/apis/api/smartdevicemanagement.googleapis.com/overview?project=803912481486 [these digits are first part of OAuth ID]

HabPanel Widget

The widget is similar in function to the other temperature widgets.

Uses the Nest_Connection item state to show either the orange (online) or grey (offline) thermometer. When online it also shows the current temperature associated with Nest_AmbientTemp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div class="rounded-box">
  <table style="width: 100%; text-align: center">
    <tr><td style="padding-top: 0.1vw">
      <div ng-if="itemValue('Nest_Connection') == 'Online'">
        <img ng-src="/static/images/thermometer-online.svg" style="height: 3vw" />
      </div>
      <div ng-if="itemValue('Nest_Connection') != 'Online'">
        <img ng-src="/static/images/thermometer-offline.svg" style="height: 3vw" />
      </div>
    </td></tr>
    <tr><td style="font-size: 0.9vw;">Hall (Nest)</td></tr>
    <tr><td class="hilite" style="font-size: 1.2vw;">
      <div ng-if="itemValue('Nest_Connection') == 'Online'">
        {{'%.1f' | sprintf:itemValue('Nest_AmbientTemp')}} °C
      </div>
    </td></tr>
  </table>
</div>

Resources

This post is licensed under CC BY 4.0 by the author.
Recently Updated
Trending Tags
Contents
Trending Tags