Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

.NET Works with Nest - Guide to calling Nest API from C#

5.00/5 (3 votes)
14 Sep 2014CPOL3 min read 39.9K   477  
How to call Nest API from .NET using FirebaseSharp

Introduction

This article demonstrates how to call Nest API from .NET using FirebaseSharp, an unofficial open source Firebase .NET client.

To follow along and test drive Nest API you do not need to own a Nest device, a simulator is available.

Background

Nest API enables developers to integrate with their Nest Learning Thermostatâ„¢ and Nest Protect: Smoke + Carbon Monoxideâ„¢.

But although the API comes in different flavours (Firebase, REST and REST Streaming), currently you're a bit left in the cold when trying to consume the API's real time features from .NET:

  • the official Firebase client libraries currently target Web (JavaScript client), iOS and Android
  • the alternative REST Streaming is based on EventSource, another option that doesn't come out of the .NET box
  • and finally the REST option is not intended for real-time updates, with Nest placing limits on the number of calls you can make in a specific time period (so forget about polling for updates)

Looking for a solution I stumbled upon FirebaseSharp, which enables you to call Nest API using the Firebase protocol and get all the real time goodness.

Read below to discover what happened next.

Using the code

You can download the completed project.

Get access to Nest API

To get access to Nest API, you have to register your client.

Complete this easy no-hassle step at https://developer.nest.com/

  1. Sign in
    • Sign up
  2. Clients (available when signed in)
    • Register new client
      • OAuth Redirect URI
      • Permissions
        • Choose Thermostat > read permission at the minimum, to successfully run this demo

Well done, you now have a client ID and secret which are required for OAuth in the next step.

Get access to Nest device data

To get access to Nest device data, Nest explains why and how they use OAuth.

So let's translate this to .NET

First update the App.config with your client OAuth settings, copy them from your Nest client settings:

XML
<add key="client-id" value="<client-id>" />
<add key="client-secret" value ="<client-secret>" />

To request access, we simply browse to the authorization URL, which uses your client ID to identify the application requesting access:

C#
var authorizationUrl = string.Format("https://home.nest.com/login/oauth2?client_id={0}&state={1}",
    ConfigurationManager.AppSettings["client-id"], "dummy-random-value-for-anti-csfr");

using (var process = Process.Start(authorizationUrl))
{
    Console.WriteLine("Awaiting response, please accept on the Works with Nest page to continue");
}

If the user accepts, Nest redirects to the OAuth redirect URI you configured.

To keep this demo simple and self contained in the console application, we self-host ASP .NET Web API, to handle the repsonse:

C#
using (WebApp.Start<Startup>(url: "http://localhost:9000/"))
{
    // snip
}

So, first the state argument is validated, this should match the anti-cross-site forgery request token we sent to ensure the integrity of the communication.
Then the received authorization code is used to request an access token.
Again to keep it simple, the resulting access code response is cast to dynamic, so we can access the token property without having to properly deserialize to a strongly typed object.

C#
/// <summary>
/// Called by Nest when user grants access
/// </summary>
/// <param name="state">Anti-cross-site forgery request token</param>
/// <param name="code">Code to request access token</param>
/// <returns>Access code</returns>
public HttpResponseMessage Get(string state, string code)
{
     if (!string.Equals("dummy-random-value-for-anti-csfr", state))
         throw new HttpResponseException(HttpStatusCode.BadRequest);

     var accessToken = GetAccessToken(code);
     Program.SubscribeToNestDeviceDataUpdates(accessToken);

     var response = new HttpResponseMessage(HttpStatusCode.OK) 
     {
         Content = new StringContent("Well done, you now have an access token which allows you to call Nest API on behalf of the user.") 
     };
     response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html");

     return response;
}

private async Task<string> GetAccessToken(string authorizationCode)
{
    var url = string.Format("https://api.home.nest.com/oauth2/access_token?code={0}&client_id={1}&client_secret={2}&grant_type=authorization_code",
                authorizationCode, ConfigurationManager.AppSettings["client-id"], ConfigurationManager.AppSettings["client-secret"]);

    using (var httpClient = new HttpClient())
    {
        using (var response = httpClient.PostAsync(url, content: null).Result)
        {
            var accessToken = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result);

            return (accessToken as dynamic).access_token;
        }
    }
}

Well done, you now have an access token which allows you to call Nest API on behalf of the user.

Simulate Nest device

To simulate a Nest device, you have to use the Nest Developer Chrome Extension.

If you have any trouble with this, follow the easy steps at https://developer.nest.com/documentation/chrome-extension, in a nutshell:

  1. Launch Google Chrome
  2. Install the Nest Developer Chrome Extension
  3. Browse to https://home.nest.com
  4. Open the Developer tools
  5. Open the Nest tab
  6. Add a thermostat

Well done, you now have a virtual device which can simulate real time events which we'll consume in the next step.

Consume real-time updates

Get FirebaseSharp through nuget, to install through the Nuget Package Manager Console:

Install-Package FirebaseSharp

Once the access token is in, we initialize a Firebase client, that points to Nest API using the access token we retrieved. In this case we listen to the devices, but go ahead and consult the Nest API reference to find out your options on how granular you want to be.

Change the current temperature in the Nest Developer Chrome Extension and witness the real-time updates :)

C#
var firebaseClient = new Firebase("https://developer-api.nest.com", _accessToken);
var response = firebaseClient.GetStreaming("devices",
        changed: (s, e) => {
            if (e.Path.Contains("ambient_temperature_f"))
                Console.WriteLine("Current temperature has been updated to: {0}.", e.Data);
        });

Well done, you have a working solution!

Points of Interest

Official support for C# by Firebase might come, mentioned in a blog post by the author of FirebaseSharp, read it here http://www.roberthorvick.com/2014/03/26/firebase-net-client-library/.

History

  1. Added link to download the completed project.
  2. Removed duplicate attachment

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)