Getting Data From DarkSky with a Webhook

Table of contents

  1. Getting Started
  2. Setting up a webhook - Getting the Weather
  3. Requesting Weather Information

In this tutorial, we’re going to setup a webhook called forecast that will get information from DarkSky - an online platform that specializes in weather forecasting and visualization.

When we’re finished, we’ll have set up a webhook that will ask for one bit of information - the latitude and longitude for the place you want weather info on - and it sends back four things:

  1. a descriptive label for the current weather in that location (e.g. cloudy, rain, etc.)
  2. the temperature
  3. the probability of rain
  4. the intensity of rain (millimeters per hour)

We’ll connect this into our code, have it look up weather information for Pittsburgh (lat: 40.4406, lon: -79.9959), and collect the response!

Getting Started

To get started you’ll need to register for a DarkSky account.

  1. Visit https://darksky.net/dev/register and follow the instructions to sign up
  2. You’ll need to confirm your account by email
  3. Once you’ve signed up, visit your account page and you’ll see a long alphanumeric string marked “Your Secret Key”. This is a unique ID that identifies your account when you make calls to the DarkSky API and it’s required that you include it in your calls.

  4. You’ll also see a sample call that looks like https://api.darksky.net/forecast/1234566/37.8267,-122.4233 This is the URL we’ll use as part of our Webhook to request information. You’ll see it contains a) your secret or API key, and b) the latitude and longitude of the location you want to get weather predictions about. If you visit the link you’ll see a big detailed response like:
{"latitude":37.8267,"longitude":-122.4233,"timezone":"America/Los_Angeles","currently":{"time":1549234644,"summary":"Drizzle","icon":"rain","nearestStormDistance":0,"precipIntensity":0.0084,"precipIntensityError":0.002,"precipProbability":0.98,"precipType":"rain","temperature":52.61,"apparentTemperature":52.61,"dewPoint":45.63,"humidity":0.77,"pressure":1006.09,"windSpeed":11.45,"windGust":19.7,"windBearing":236,"cloudCover":0.6,"uvIndex":1,"visibility":10,"ozone":314.41},"minutely":{"summary":"Light rain stopping in 25 min.","icon":"rain","data":[{"time":1549234620,"precipIntensity":0.008,"precipIntensityError":0.002,"precipProbability":0.98,"precipType":"rain"},{"time":1549234680,"precipIntensity":0.009,"precipIntensityError":0.002,"precipProbability":0.98,"precipType":"rain"},{"time":1549234740,"precipIntensity":0.01,"precipIntensityError":0.002,"precipProbability":0.99,"precipType":"rain"},{"time":1549234800,"precipIntensity":0.01,"precipIntensityError":0.002,"precipProbability":0.99,"precipType":"rain"},{"time":1549234860,"precipIntensity":0.01,"precipIntensityError":0.002,"precipProbability":0.98,"precipType":"rain"},{"time":1549234920,"precipIntensity":0.009,"precipIntensityError":0.003,"precipProbability":0.97,"precipType":"rain"},{"time":1549234980,"precipIntensity":0.008,"precipIntensityError":0.003,"precipProbability":0.93,"precipType":"rain"},{"time":1549235040,"precipIntensity":0.007,"precipIntensityError":0.003,"precipProbability":0.88,"precipType":"rain"},{"time":1549235100,"precipIntensity":0.007,"precipIntensityError":0.003,"precipProbability":0.83,"precipType":"rain"},{"time":1549235160,"precipIntensity":0.006,"precipIntensityError":0.003,"precipProbability":0.76,"precipType":"rain"},{"time":1549235220,"precipIntensity":0.006,"precipIntensityError":0.003,"precipProbability":0.74,"precipType":"rain"},{"time":1549235280,"precipIntensity":0.006,"precipIntensityError":0.004,"precipProbability":0.72,"precipType":"rain"},{"time":1549235340,"precipIntensity":0.007,"precipIntensityError":0.004,"precipProbability":0.7,"precipType":"rain"},{"time":1549235400,"precipIntensity":0.007,"precipIntensityError":0.004,"precipProbability":0.7,"precipType":"rain"}, ... 

This is known as a JSON (or javascript object notation) formatted response. It’s a common format for sharing raw data through API or web service calls. Particle webhooks require the web resource you want information from to respond with a JSON reply. If it doesn’t send information in this way - it might not work with a webhook.

You’ll also notice the volume of information this web response contains. It’s a lot. More information than our particle device can handle; and this explains why we can’t just have our Particle microcontroller directly request the information.

Using a service like JSONPrettyPrint, you can reformat the response into something more organized and readable. I recommend doing this as you experiment with webhooks. After doing this, the data will look more like this:

{
  "latitude": 37.8267,
  "longitude": -122.4233,
  "timezone": "America\/Los_Angeles",
  "currently": {
    "time": 1549234644,
    "summary": "Drizzle",
    "icon": "rain",
    "nearestStormDistance": 0,
    "precipIntensity": 0.0084,
    "precipIntensityError": 0.002,
    "precipProbability": 0.98,
    "precipType": "rain",
    "temperature": 52.61,
    "apparentTemperature": 52.61,
    "dewPoint": 45.63,
    "humidity": 0.77,
    "pressure": 1006.09,
    "windSpeed": 11.45,
    "windGust": 19.7,
    "windBearing": 236,
    "cloudCover": 0.6,
    "uvIndex": 1,
    "visibility": 10,
    "ozone": 314.41
  },
  "minutely": {
    "summary": "Light rain stopping in 25 min.",
    "icon": "rain",
    "data": [
      {

Great. Now you can see exactly what it contains. A lot. For this scenario, however, I really only care about the current weather. And I can see that this is contained in a object called currently. currently has a lot of child elements including summary (which is Drizzle) and humidity which is 0.77. We can use this nested structure to specify what information you want to include in your webhook response and filter it down. This is done with a simple templating language

For example, if I only only want the current temperature I could access this by using `` or the wind speed by using . We’ll get back to this later.

For now you’re set up, your API key is working and you have a URL that you can use to request information as part of your webhook. Now, let’s create the webhook.

Setting up a webhook - Getting the Weather

Go to the Particle Console and sign in. On the left hand side there’s a small icon bar, you’ll find an option for ‘Integrations’.

Click it and choose the option to add a new integration. You’ll get four options like this. Choose the webhook.

You’ll then be asked to add the info for your webhook.

Add the following:

  • Event Name: forecast
  • URL: https://api.forecast.io/forecast/YOUR_API_KEY/?exclude=minutely,hourly,daily,flags,alerts
  • Request Type: GET
  • Request Format: Query Parameters
  • Device: Any

Select the Advanced Options:

  • Under Response Template, add the following:

{{#currently}}{{icon}}~{{temperature}}~{{precipProbability}}~{{precipIntensity}}{{/currently}}

This is your response template. It will filter out the current temperature, precipitation and icon. Each will be separated by a ~

Then create the WebHook!

Requesting Weather Information

We’re going to add two pieces of code to help get data on the weather in Pittsburgh Copy and paste the following into the end of your code file

void getData()
{
	// Publish an event to trigger the webhook
  Particle.publish("forecast", "40.4406,-79.9959", PRIVATE);
}

// This function will handle data received back from the webhook
void handleForecastReceived(const char *event, const char *data) {
  // Handle the integration response

  String receivedStr =  String( data );
  int loc1 = 0;
  int loc2 = 0;
  int loc3 = 0;
  int loc4 = 0;

  loc1 = receivedStr.indexOf("~");

  weatherIcon = receivedStr.substring(0,loc1);

  loc2 = receivedStr.indexOf("~",loc1+1);
  temperature = (double) String(receivedStr.substring(loc1+1,loc2)).toFloat();

  loc3 = receivedStr.indexOf("~",loc2+1);
  precipProbability = (double) String(receivedStr.substring(loc2+1,loc3)).toFloat();

  loc4 = receivedStr.indexOf("~",loc3+1);
  precipIntensity = (double) String(receivedStr.indexOf(loc3+1)).toFloat();

}

The following codde will break up the string based on the position of the ~ and extract the bits of information we care about. Finally it converts the right information to numbers where appropriate.

Making progress.

Now you also need to tell your Particle to listen for the response to the webhook. To do this, add this line of code to the end of your setup()

Particle.subscribe("hook-response/forecast", handleForecastReceived, MY_DEVICES);

This registers for the webhook response and maps it into the function we just added…

Now one last thing, we need to publish the event and trigger the webhook. Let’s do this when the device first starts. To do this, add the following line right before the end of the setup()’s last curly bracket.

	getData();
}

You know the drill. Save your code. Flash your code. Fingers crossed. It’ll appear on your Particle! To know if it worked, open up the console (http://console.particle.io) and you should see something like this when the device restarts

Nice work!


Table of contents