Adding Webhooks

While controlling devices from a mobile app is useful, there are cases in which you want to control devices without involving users. For example, you may want to turn on or off a device based on an event from another device.

There will be some logic or rules to determine the reaction. MODE lets you implement this logic on a server on the internet and have the server called every time there is an interesting event. These webhooks are provided by Smart Modules you add to your MODE project. (Smart Modules are pluggable features you can add to your project. More on this later.)

Your servers are called for events triggered in any homes in your project. They are intended for you to provide common functionality to your users. You can also use webhooks to aggregate project-wide information to generate statistics or analytics.

Sample Server Quick Start Guide

Before diving into the details of setting up webhooks, let’s spin up a sample server on Heroku that will be receiving the webhook calls. Heroku is a cloud service for running your web service. We will be using this example.

Here we assume you have already configured your MODE project to work with devices and apps. If you have not set up a project before, please read Creating a MODE Project first.

Deploy Sample Code to Heroku

To run the sample code on Heroku, create a Heroku account or sign in to Heroku. Then click the following Deploy to Heroku button:

Deploy to Heroku

You will land on Heroku’s app deployment screen that looks like the following:

Screenshot - Heroku deployment

Pick a unique App Name for your Heroku app. Then under the Config Variables section, replace (YOUR_APP_NAME) in the EVENT_URL field with the app name you just chose. If your app name is my-webhooks-handler, EVENT_URL will be https://my-webhooks-handler.herokuapp.com/evt.

Before clicking the Deploy for Free button, open the MODE Developer Console in another browser window and set up a Webhooks Smart Module.

Set up a Webhooks Smart Module on MODE

On the Developer Console, go to the Smart Modules section of your project. Smart Modules are pluggable modules that you can add to your project for extra features.

Click the +NEW button at the top of SMART MODULE LIST. You will see the following screen which lists the types of Smart Modules you can use for your project. More types of Smart Modules will become available over time, but for the purpose of this tutorial, you are using the Webhooks module.

Screenshot - Smart Modules Catalog

Click the ADD button on the Webhooks module. You will see the following form:

Screenshot - Creating Smart Module

Fill in the items to configure your Smart Module. Specify a module ID and enter a short description. In the Event Webhook section, for URL enter the same URL you used for EVENT_URL in the previous step. For Key, simply click the GENERATE button to create one for you. Once you are done, click SAVE.

Now you can see your new Smart Module in SMART MODULE LIST. Click the entry and you can see its settings and activity logs.

Launch the Webhooks Handler

Back to the Heroku’s app deployment screen. Note the event webhook key you generated earlier on the MODE console. Copy-and-paste that into the EVENT_KEY field under the Config Variables section.

Click the Deploy for Free button. If the deployment is successful, click the View button to open the app you just deployed in your browser. You will see the text No device event.

Test the Webhook

Now go to the MODE console and launch a device simulator. Make sure the device already belongs to a home. Then simply trigger an event on the simulator. Then check the browser window with the Heroku app loaded. You should see an event JSON string like the following:

{"homeId":173,"timestamp":"2016-01-04T23:26:09.521Z","eventType":"abc","eventData":{},"originDeviceId":260}

You can trigger events from the device simulator with different event types and event data. Whenever you trigger an event, you will see a new JSON string with a new timestamp. If you do not see any JSON strings on the browser, make sure the Heroku app’s config variables (EVENT_URL and EVENT_KEY) are correctly set.

Reacting to Events and Commands

As you can see in the example above, webhooks can be configured to be called when events are triggered by devices.

An event webhook URL is called whenever an event happens. For example:

https://www.example.com/event_webhook

MODE will make a POST request to the specified URL with information about the event in the request body. The content is in JSON format, so Content-Type will be application/json. Also, the webhook POST request comes with an X-Mode-Signature HTTP header. The webhooks handler should check that the signature and the content match. We will explain this later.

Here is an example of a webhook POST request:

POST /event_webhook HTTP/1.0
Content-Type: application/json
X-Mode-Signature: d3b07384d113edec49eaa6238ad5ff00

{
    "eventType":"abc",
    "eventData":{"key":"value"},
    "homeId":3,
    "timestamp":"2015-06-07T08:37:37.997281148Z",
    "originDeviceId":3
}

The data the webhooks handler receives are in the format of an event data object. In addition to eventType and eventData, MODE cloud adds information about where the request was coming from and when.

When setting up your Smart Module earlier, you probalby noticed that you can also specify a Command Webhook. This webhook is called whenever you make a PUT request to the MODE cloud at the following API endpoint:

https://api.tinkermode.com/homes/HOME_ID/smartModules/MODULE_ID/command

Where HOME_ID specifies the home associated with this request and MODULE_ID is the ID of your webhooks module. The body of the request must a JSON object that contains an action field and a parameters field (similar to a device command object).

Webhook Signature Verification

Anyone can call your webhook URL and post a request. To verify that the request is coming from MODE, your webhooks handler should check the ‘X-Mode-Signature’ header in the request. The signature is calculated by applying the SHA-256 hash algorithm on the webhook URL and the request body.

What You Need for Generating the Signature

Let’s say the URL of the webhook is as follows:

https://www.example.com/command_webhook

And the following is the JSON string in the request body:

{"homeId":4567,"timestamp":"2015-06-02T23:07:48.513902477Z","eventType":"counter","eventData":{"cnt":120},"originDeviceId":1234}

On the Developer Console, you can find the secret key associated with the webhook. Let’s say the key is:

6idnnaidkdkdr5zq1838jGV

Generating and Matching the Signatures

First you have to create an HMAC using the webhook key. After that, concatenate the webhook URL and the body, calculate the SHA-256 digest, and encode the results using HEX encoding.

Here is a sample code for NodeJS, using the crypto module:

crypto = require("crypto");

var webhook_url = 'https://www.example.com/command_webhook';
var webhook_key = '6idnnaidkdkdr5zq1838jGV';
var body = '{"homeId":4567,"timestamp":"2015-06-02T23:07:48.513902477Z","eventType":"counter","eventData":{"cnt":120},"originDeviceId":1234}';

var hmac = crypto.createHmac('sha256', webhook_key);
hmac.update(webhook_url + body);
var generated_signature = hmac.digest('hex');

Your handler needs to compare the generated signature with the string coming from the X-Mode-Signature header string. If it doesn’t match the string, the handler should reject the request.

Advanced Use of Webhooks Smart Module

Subscribing to Specific Events

You can configure a Smart Module to listen to only a subset of events. This is done by specifying the list of event types the Smart Module subscribes to in its settings.

By default, a Smart Module subscribes to all events (*). If you are only interested in motion-detected and home-status events, you can specify the Subscribed Events field as follows:

motion-detected
home-status

Multiple Smart Modules

You can set up multiple Smart Modules for a single project. Each event is delivered to all the Smart Modules that subscribe to that type of events.

For example, you can have a Smart Module for debugging in addition to a Smart Module that handles the business logic.

Conclusion

Webhooks provide a flexible and powerful way to augment the functionalities of your IoT system. You can host your webhooks handlers on dedicated servers that you operate. But it is also possible to implement them on other cloud services, as seen in our Heroku example above. Also check out this how-to guide for instructions on running a webhooks handler on scriptr.io, a cloud-based scripting engine.