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.

Getting Started with Electric Imp

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.

Setting up the Imp

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. The name can only contain ASCII letters, numbers, underscores, and hyphens.
  3. Select your Atlas cluster.
  4. Click Create.

Upon creation of your app, you will be redirected to the MongoDB Stitch console. Your app is created with a MongoDB service named mongodb-atlas.

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. Click Authentication in the lefthand 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.

  • Click mongodb-atlas in the lefthand navigation.
  • Under Rules, click New. Enter Imp for the database and TempData for the collection and click Create.
  • Click the created collection
    • Click the Filter tab and delete the existing Filter.
    • Under Field Rules, select Top-Level Document.
    • Set the write rule to {}.
    • Delete the read rule entirely, leaving an empty box.

This enables the device (and only the device) to write data and prevents all reads to the data by devices. For more information see MongoDB Rules.

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
      var now = new Date();
    
      //Define Services and point to the correct Atlas collection
      var mongodb = context.services.get("mongodb-atlas");
      var TempData = mongodb.db("Imp").collection("TempData");
    
      var status =
        {
          "Timestamp": now.getTime(),
          "Date": now,
          "indoorTemp": data.temp*9/5+32,
          "indoorHumidity": data.humid
        };
    
      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, it can be simulated with the script no_hardware.js included in the example repository. To run it, navigate to the IoTTemperatureTracking directory in a terminal window and run:

npm install
node no_hardware.js

This script calls the Imp_Write function with random temperature values every two minutes.

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.

DeviceLocation Enter the longitude/latitude of where your device is located in the form. E.g. "40.757,-73.987"
DarkSkyKey Enter the secret key from Dark Sky.

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
      var now = new Date();
    
      //Define Services and point to the correct Atlas collection
      var darksky = context.services.get("darksky");
      var mongodb = context.services.get("mongodb-atlas");
      var TempData = mongodb.db("Imp").collection("TempData");
    
      //Code for Dark Sky
      var response = darksky.get({ "url":
        "https://api.darksky.net/forecast/" +
        context.values.get("DarkSkyKey") +
        '/' +
        context.values.get("DeviceLocation")
      });
    
      var darkskyJSON = EJSON.parse(response.body.text());
    
      var status =
        {
          "Timestamp": now.getTime(),
          "Date": now,
          "indoorTemp": data.temp*9/5+32,
          "indoorHumidity": data.humid,
          "outdoorTemp": darkskyJSON.currently.temperature,
          "outdoorHumidity": darkskyJSON.currently.humidity
        };
    
      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 MongoDB 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){
      //Parse the date
      var userDate = new Date(message.Body.substring(5,message.Body.length));
    
      //Define Services and Collections
      var mongodb = context.services.get("mongodb-atlas");
      var TempData = mongodb.db("Imp").collection("TempData");
      var twilio = context.services.get("my-twilio-service");
      var responseMessage = "No weather data found";
    
      if(message.Body.toLowerCase() === "temp" || message.Body.toLowerCase() === "temp now"){
        var data = TempData.find().sort({"Timestamp" : -1}).limit(1).toArray();
        if (data.length === 1){
          responseMessage = "As of " + data[0].Date + " the indoor temperature was " + data[0].indoorTemp + "°F and the outdoor temperature was " + data[0].outdoorTemp + "°F.";
        }
      }else if(!isNaN(userDate.valueOf())){
        var data = TempData.find({"Timestamp" : {"$lte" : userDate.getTime()/1000}}).sort({"Timestamp" : -1}).limit(1).toArray();
        if (date.length === 1){
          responseMessage = "As of " + data[0].Date + " the indoor temperature was " + data[0].indoorTemp + "°F and the outdoor temperature was " + data[0].outdoorTemp + "°F.";
        }
      }else{
        responseMessage = "Invalid Request: Try \"Temp Now\" or \"Temp [Date]\"";
      }
    
      //Send the response
      return twilio.send({
        from : context.values.get("TwilioPhone"),
        to : message.From,
        body : responseMessage
      });
    };
    
  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.