Navigation

IoT Temperature Tracker

This tutorial demonstrates how to use MongoDB Stitch to integrate IoT devices with your applications. It covers the following:

  • Using Electric Imp to read the indoor temperature and send it to Stitch.
  • Using Dark Sky to add general weather data to the indoor readings.
  • Protecting data stored in Atlas with access rules.
  • Integrating with Twilio to send temperature readings over text messages.

Note

This tutorial can still be followed without an impExplorer kit by simulating the hardware with scripts included in the example repository in the IoTTemperatureTracking directory.

Prerequisites

This tutorial uses the Electric Imp impExplorer™ Developer Kit. The device will read temperature and send it to the Stitch backend. Before setting up, make an account for Electric Imp’s IDE and download the Electric Imp app (on an iOS or Android phone). Your Electric Imp account will link to your device and contains an online editor for the device code.

If you do not have an Electric Imp device, you can emulate one. To do so, you will need to have Node version 6.0.0+ to run the application. See the Node.js docs for installation instructions.

Setting Up the Electric Imp Device

To start, unpack the impExplorer. It should include a board, a card (a WiFi IoT module), and a USB power cord. Start by inserting the card into the board and powering it on by attaching the provided cable and then plugging it into a USB port on a computer or a USB wall adapter.

After powering on the board, use the Electric Imp app to blink up the board. This connects the board to the internet and assigns it to your account so that you can deploy code to it. If the board times out and the LED stops flashing, restart and try again.

For more information or troubleshooting, see the impExplorer Getting Started Guide.

Deploying the Code

Now that the device is blinked up, build out the code to work with the device. Electric Imp breaks down the code into two components:

  • Device Code reads inputs from the sensors on the impExplorer
  • Agent Code ensures that the device communicates reliably and securely with the internet

Both the device and agent code used in this tutorial can be found in the GitHub example repository in the IoTTemperatureTracking directory. After downloading the code, sign into the Electric Imp IDE.

For more information see the tour of the Imp IDE.

To load the code onto the device do the following:

1
2

Add code, build, and run

The Imp IDE has a split window, with a space for the Agent code on the left and Device code on the right and Development Device Logs below. To add code onto the device do the following:

  1. Copy-paste the code from the file temp.device.nut to the Device pane (on the right)
  2. Copy-paste the code from the file temp.agent.nut to the Agent IDE (on the left)
  3. Click Build and Run to deploy your code to the device and agent.

Connecting the Device to Stitch

Now the device periodically measures temperature but currently does not persist it anywhere. MongoDB Stitch can quickly provide a backend to store the temperature readings.

1

Log into Atlas.

To use MongoDB Stitch, you must be logged into MongoDB Atlas. If you do not have an Atlas account, follow the instructions in the Atlas documentation to create an account.

2

Create an Atlas cluster.

If you do not already have an Atlas cluster for use with MongoDB Stitch, create a cluster.

Important

You must deploy the Atlas cluster with MongoDB version 3.4 or greater.

Atlas provides a Free Tier M0 replica set as well as paid M10+ clusters. Free Tier deployments have restrictions as compared to paid M10+ deployments but will work for the purposes of this tutorial. For complete documentation on these restrictions, see Atlas M0 (Free Tier), M2, and M5 Limitations.

3

Add a MongoDB Stitch application.

  1. In Atlas, click Stitch Apps in the left-hand navigation.
  2. Click the Create New Application button.
  3. Under Application Name, enter a name for your application. The name can only contain ASCII letters, numbers, underscores, and hyphens.
  4. Under Link To Cluster, select the MongoDB Atlas cluster that you’d like to use for your application.
  5. Click Create.

After you click Create, a new Stitch application will be created for you. The application will include a MongoDB service named mongodb-atlas that is linked to your cluster. This process may take several minutes.

Once your application has been created, you will be automatically redirected to the Stitch application console.

With Stitch, data is protected by default. The next steps walk through the following:

  1. Creating an API Key the device can use to authenticate to your Stitch Application
  2. Putting Rules in place so clients can read/write data properly
  3. Creating a function for the device to execute to write data

Setting up Authentication

Enable API key authentication in Stitch:

  1. Navigate to the Stitch console.
  2. Select Users from the left-side navigation.
  3. Under Providers, find API Keys and click Edit.
  4. Enable API Key authentication and create an API key with any name.
  5. Click Copy to copy the key. Stitch only allows you to view a key once. If you lose this key you must generate a new one.

Update the Imp Agent Code

Update the agent code with the API key and App ID so it can authenticate.

  • Navigate back to the Electric Imp IDE. Under the Agent code, replace <STITCH API KEY> with the copied API key.
  • Replace <STITCH APP ID> with the Stitch App ID. This can be found in the Stitch console under Clients.
  • Click Build and Run to update the device. A device restart may be required to fully refresh the code.

Now your device can authenticate to Stitch. The next step is to create rules and a Stitch function the device can call.

Creating Rules

In Stitch, even when authenticated, all access to data and services is off by default. To enable access to data and services, it is necessary to define appropriate rules.

The device needs access to store temperature data to the collection Imp.TempData. To enable this, do the following:

  • Click mongodb-atlas in the left-hand navigation.
  1. Click the + Add Collection button.

  2. In the Add New Collection dialog, provide the following values:

    Property Value
    Database Name Imp
    Collection Name TempData
    Select a Template No Template
  3. Click the Add Collection button.

  4. In the list of Collections, select TempData under Imp, and then check the Write All checkbox. Note that when you select Write All, the Read All checkbox is also selected automatically.

  5. Click Save.

Creating a Stitch Function for Writing Data

Now that Stitch has an authenticated device associated with it, define the function that the device calls to record temperature readings to the database.

  • In the Stitch console, click Functions on the lefthand navigation.

  • Click New Function.

  • Enter the following properties for the function:

    Property Value
    Name Imp_Write
    Private Leave unselected. If selected, the function is inaccessible by a client and is only accessible in other Stitch definitions, such as webhooks and other functions.
    Can Evaluate Leave as {}. The Can Evaluate condition determines whether the function can be run. An empty document {} always evaluates to true, indicating that the function can always be run.
  • Under Function Editor add the following code:

    exports = function(data) {
      //Get the current time
      const now = new Date();
    
      //Define Services and point to the correct Atlas collection
      const mongodb = context.services.get("mongodb-atlas");
      const TempData = mongodb.db("Imp").collection("TempData");
    
      // Prepare the status document
      const indoorTemp = data.temp * 9 / 5 + 32;
      const indoorHumidity = data.humid;
      const status = {
        indoorTemp,
        indoorHumidity,
        Timestamp: now.getTime(),
        Date: now
      };
    
      return TempData.insertOne(status);
    };
    
  • Click the save button on the upper lefthand corner.

Testing and Simulating the Device

The device should now call the Imp_Write function every two minutes. To see the stored temperature readings, connect to your Atlas cluster with a MongoDB shell and run:

use Imp;
db.TempData.find()

The resulting documents should resemble the following:

{ "_id" : ObjectId("5a1c5287b8b99840c65e7f5a"), "Timestamp" : NumberLong("1511805575238"), "Date" : ISODate("2017-11-27T17:59:35.238Z"), "indoorTemp" : 80.79278, "indoorHumidity" : 28.5889 }

If you do not have a device, you can still test your Stitch app. We have created a script that simulates a weather device by sending random temperature and humidity data every two minutes. The script no_hardware.js is included in the root folder of the example repository.

To use this script, open the file and replace <your-app-id> with the app id for your Stitch app. Then, to run it, navigate to the IoTTemperatureTracking directory in a terminal window and run the following commands:

npm install
node no_hardware.js

Building out the Backend

Now that a simple backend is set up, the scope of the app can be expanded. This section covers how to integrate with Dark Sky to incorporate public weather data and with Twilio to enable searching the collected data via text message.

Additional weather data with Dark Sky

Dark Sky offers a public API serving realtime weather data. Using this service enables the application to pair real time weather data with the indoor temperature and humidity readings from the device.

Sign in to your Dark Sky account or register. Copy down your Dark Sky secret key.

Creating an HTTP Service

Next, create an HTTP service to make requests to the Dark Sky API:

  1. In the Stitch console, click Services then click Add Service.
  2. Select HTTP.
  3. Name the service darksky and click Add Service.
  4. Under Rules click New, enter a name, and click Add Rule.
  5. Select the newly created rule, and toggle Get.
  6. Set When to {}.

Updating Imp_Write

In the Stitch console, go to Values found on the lefthand menu and create the following values.

Value Name Description Example
DeviceLocation The longitude/latitude of where your device is located in the form. "40.757,-73.987"
DarkSkyKey The secret key from Dark Sky. "3c9f57aab7a98be4fe12b670333b513e"

Update the Imp_Write function to pull in data from the darksky service.

  1. In the Stitch console, click Functions and edit the Imp_Write function.

  2. Under Function Editor change the code to the following:

    exports = function(data) {
      //Get the current time
      const now = new Date();
    
      // Parse the function argument
      const indoorTemp = data.temp * 9 / 5 + 32;
      const indoorHumidity = data.humid;
    
      //Define Services and point to the correct Atlas collection
      const darksky = context.services.get("darksky");
      const mongodb = context.services.get("mongodb-atlas");
      const TempData = mongodb.db("Imp").collection("TempData");
    
      //Code for Dark Sky
      const darkSkyKey = context.values.get("DarkSkyKey");
      const deviceLocation = context.values.get("DeviceLocation");
      const url = `https://api.darksky.net/forecast/${darkSkyKey}/$      {deviceLocation}`;
    
      return darksky.get({ url }).then(response => {
        const darkskyJSON = EJSON.parse(response.body.text());
    
        const status = {
          indoorTemp,
          indoorHumidity,
          outdoorTemp: darkskyJSON.currently.temperature,
          outdoorHumidity: darkskyJSON.currently.humidity,
          Timestamp: now.getTime(),
          Date: now
        };
        return TempData.insertOne(status);
      });
    };
    
  3. Click Save.

Now when the device calls Imp_Write the local temperature data is stored with data retrieved from the Dark Sky API.

Searching your data with Twilio

Since Atlas is storing the data it is possible to connect to the database and query it directly. However, Twilio can enable retrieving data through text messages.

If you do not have a Twilio account and an SMS-enabled phone number you can register for one.

Add a Twilio service in MongoDB Stitch

  1. In the Stitch console, click on Services
  2. Click Twilio, assign the service the name my-twilio-service, and then add your SID and Token.
  3. Once your Twilio service is configured, setup a rule that enables Stitch to send text messages. To do this:
    1. Click into the Rules tab of your Twilio service.
    2. Click New Rule, enter a name, and click Add Rule.
    3. Click the newly created rule and toggle send to enable it.

Create a Webhook

In the Stitch console, go to Values found on the lefthand menu and create the following values.

TwilioPhone Your Twilio number in the form "+15558675309"

Set up an incoming webhook that parses incoming text messages from Twilio, searches the database, and responds with weather information for a specific time.

  1. In the newly created Twilio service, under Incoming Webhooks click + Add Incoming Webhook.

  2. Give the webhook a name and enable Respond with Result.

  3. Under Function Editor enter the following code:

    exports = function(message) {
      //Define Services and Collections
      const mongodb = context.services.get("mongodb-atlas");
      const TempData = mongodb.db("Imp").collection("TempData");
      const twilio = context.services.get("my-twilio-service");
    
      // Parse the message
      const userDate = new Date(message.Body.substring(5, message.Body.length));
      const isValidUserDate = !isNaN(userDate.valueOf());
      const isTemp =
        message.Body.toLowerCase() === "temp" ||
        message.Body.toLowerCase() === "temp now";
      const isValidRequest = isValidUserDate || isTemp;
    
      const responseBodyPromise = new Promise(resolve => {
        if (!isValidRequest) {
          resolve(`Invalid Request: Try "Temp Now" or "Temp [Date]"`);
        } else {
          const query = isValidUserDate ? { Timestamp: { $lte: userDate.getTime() / 1000 } } : {};
          TempData
            .find(query)
            .sort({ Timestamp: -1 })
            .limit(1)
            .toArray() // Returns a promise
            .then(data => {
              if (data.length) {
                const { date, indoorTemp, outdoorTemp } = data[0];
                resolve(
                  `On ${date}, the indoor temperature was ${indoorTemp}°F and the outdoor temperature was ${outdoorTemp}°F.`
                );
              } else {
                resolve("No weather data found");
              }
            });
        }
      });
    
      responseBodyPromise.then(responseBody => {
        twilio.send({
          from: context.values.get("TwilioPhone"),
          to: message.From,
          body: responseBody
        });
      });
    };
    
  4. Click Save. Under Settings copy the Webhook URL.

Now that the webhook is set up on Stitch, add the webhook URL to Twilio so it gets called for incoming text messages.

  1. Go to your Twilio Console and navigate to Phone Numbers using the lefthand navigation.
  2. Click the number you want to receive and send text messages for this demo.
  3. Under Messaging make sure that Configure With is set to “Webhooks, …” and that when A Message Comes In is configured to execute your Twilio webhook by selecting Webhook and pasting your webhook URL.
  4. Save any changes.

Test out the texting service

Test out the weather app by sending text messages to your Twilio phone number:

  • Sending Temp or Temp Now responds with the current temperature readings.
  • Sending Temp <time> where <time> has the form YYYY-MM-DDThh:mm responds with the most recent temperature before the given time.

Examples

Message Example Response
Temp As of Mon, 27 Nov 2017 21:25:17 UTC the indoor temperature was 69.8°F and the outdoor temperature was 49.18°F
Temp 2017-11-27T21:20 As of Mon, 27 Nov 2017 21:08:23 UTC the indoor temperature was 69.7°F and the outdoor temperature was 48.95°F

Summary

Both MongoDB Stitch and Electric Imp make it easy to get IoT projects off the ground. This tutorial covered building an app to record indoor temperature using the Electric Imp and outdoor temperature with Dark Sky. Integrating Twilio made it possible to offer this data as a texting service.