Navigation

Temperature Tracker (IoT Integration)

Overview

What We’ll Build

In this tutorial, we’ll collect indoor temperature readings from an IoT device and store each reading in MongoDB alongside outdoor temperature data from the same time. Once everything is set up, we’ll use Twilio to query the data via SMS.

We’ll use Stitch to do the following:

  • Store indoor temperature readings from an Electric Imp device in MongoDB.
  • Collect outdoor temperature data from the Dark Sky API using the HTTP Service.
  • Respond to text message queries with the temperature readings from a specified time using the Twilio Service.

Prerequisites

You must have the following before beginning this tutorial:

Procedure

A. Create and Configure a MongoDB Stitch App

1

Create a Stitch Application

We need to create a Stitch app so that we can store and query the temperature readings in MongoDB.

To create a new Stitch application:

  1. Log in to MongoDB Atlas.
  2. Click Stitch Apps in the left-hand navigation of the MongoDB Atlas console.
  3. Click Create New Application.
  4. Give the application a name (e.g. IoT-Tutorial) and click Create.
  5. Wait for your application to initialize. Upon creation of your app, you will be redirected to the Stitch UI.
2

Create an API Authentication Key

Stitch requires all clients to authenticate before it will allow them to access your application. For this tutorial we’ll use API Key Authentication, a common method for authenticating physical devices.

To create a new API Authentication Key from the Stitch UI:

  1. Select Users from the left-side navigation.
  2. Under Providers, find API Keys and click Edit.
  3. Enable API Key authentication and create an API key with any name.
  4. Click Copy to copy the key.

Important

Stitch only allows you to view a key once. If you lose this key you must generate a new one.

3

Configure a MongoDB Collection

Stitch only allows you to work with MongoDB collections for which you have configured data access rules. We need to configure a collection to store the temperature readings from the impExplorer.

To add the MongoDB collection from the Stitch UI:

  1. Click Rules under Atlas Cluster in the left-hand navigation.

  2. Click + Add Collection.

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

    Property Value
    Database Name Imp
    Collection Name TempData
    Select a Template No Template
  4. Click + Add Collection.

After you’ve added the Imp.TempData collection, Stitch will present you with the Permissions configuration screen for the collection. Since we selected No Template, the default role has no read or write permissions. We need to enable these permissions so that we can query and insert into the collection.

To enable read and write permissions:

  1. Check the Read and Write boxes for the default role.
  2. Click Save.
4

Create a Function to Store Device Data

Now that we’ve set up authentication and configured our MongoDB collection, all that’s left is to write a Stitch function that actually inserts data into MongoDB. The function should accept a temperature reading data object from the device and store the data in the MongoDB collection we just configured.

To create the function in the Stitch UI:

  1. Click Functions in the left-hand navigation.

  2. Click New Function.

  3. Enter the following configuration values on the function’s Settings page:

    Property Value
    Name logTemperatureReading
    Private Leave unselected.
    Can Evaluate Leave blank.
  4. Navigate to the function’s Function Editor tab.

  5. Replace the default function code with the following:

    exports = function(impData) {
      // Prepare the temperature reading data
      const now = new Date();
      const temperatureData = {
        indoorTemp: impData.temp * 9 / 5 + 32, // Convert to Fahrenheit
        indoorHumidity: impData.humid,
        timestamp: now.getTime(),
        date: now
      };
    
      // Insert the temperature data into MongoDB
      const mongodb = context.services.get("mongodb-atlas");
      const TempData = mongodb.db("Imp").collection("TempData");
    
      return TempData.insertOne(temperatureData);
    };
    
  6. Click the save icon Save button in the top left corner of the function editor.

B. Set Up the Electric Imp Device

We’ve created a Stitch app for the device to communicate with. Now we need to set up the impExplorer and deploy custom code to the device and the Electric Imp server.

Simulate the Electric Imp Device

If you don’t have access to an impExplorer device, you can simulate one using the no_hardware.js script in the IoTTemperatureTracking directory.

To use the script:

  1. Open no_hardware.js and replace <your-app-id> with the App ID of the Stitch app we created earlier. You can find the App ID on the Clients page of the Stitch UI.

  2. Save the file and run the following code in the IoTTemperatureTracking directory:

    npm install
    node no_hardware.js
    

The script will begin uploading simulated temperature readings to Stitch every two minutes by calling the logTemperatureReading function directly. Once the script is running, you can skip to C. Record Outdoor Temperature Data.

1

Set Up the Electric Imp Device

Follow the Electric Imp impExplorer Quick Start Guide to set up your device and project.

2

Add and Deploy Custom Code

The Electric Imp code is divided into device code and agent code:

Device Code
This code runs directly on the impExplorer device. It takes periodic temperature readings and sends each reading to the Electric Imp servers for further processing.
Agent Code
This code runs on the Electric Imp servers. It receives readings sent by the device and passes them as the argument to the logTemperatureReading function we just created.

Note

The device and agent code for this tutorial are both available in the IoTTemperatureTracking directory of the stitch-examples repository.

To build and deploy the Electric Imp code:

  1. Navigate to the Code Editor in the Electric Imp IDE .

  2. In the Device Code panel, paste the code from the temp.device.nut file.

  3. In the Agent Code panel, paste the code from the temp.agent.nut file.
    Replace <STITCH APP ID> in this code with the App ID of the Stitch app we created earlier. You can find the App ID on the Clients page of the Stitch UI.
  4. Click Build and Run.

Once the code is deployed, the device will begin sending temperature readings to the Electric Imp servers every two minutes. The Agent Code passes these readings to the logTemperatureReading function where they are inserted into MongoDB.

C. Record Outdoor Temperature Data

Our function is now recording the impExplorer temperature readings in MongoDB. We can go further by including outdoor temperature data from Dark Sky alongside each device reading.

1

Get a Dark Sky API Key

To access the Dark Sky API, we need to have an API key.

To get a Dark Sky API Key:

  1. Create a Dark Sky developer account for free on the Dark Sky developer site.
  2. Once you’ve registered, find your Dark Sky Secret Key on your account page.
2

Save the API Key in Stitch

To use the API Key in Stitch, we’ll save it as a value so that we can safely reference it.

To save the API Key from the Stitch UI:

  1. Click Values in the left-hand navigation.
  2. Click Create New Value.
  3. Paste the API Key into the value editor. We want to save the key as a string, so make sure to enclose the key in quotes.
  4. Enter DarkSkyKey as the New Value Name.
  5. Click Save.
3

Specify the Device Data Coordinates

We need to request the temperature for a specific latitude/longitude from Dark Sky. If you are using an impExplorer device, you should request data from roughly the same coordinates as the device’s location. If you are simulating the device readings, you can specify any location.

Find the coordinates you wish to use, then save them as a new value named DeviceLocation using the following form:

"40.7573,-73.9879"
4

Create a Dark Sky HTTP Service

Now that we have an API key, we can create an HTTP Service to connect the Stitch app with Dark Sky.

To create the HTTP Service in the Stitch UI:

  1. Click Services in the left-hand navigation.
  2. Click Add a Service.
  3. Enter DarkSky as the Service Name.
  4. Click Add Service.
5

Configure the Dark Sky HTTP Service

Before we can use the Dark Sky HTTP Service, we need to define a rule for the GET action.

To create the rule:

  1. Navigate to the Rules tab of the HTTP Service.

  2. Click New Rule.

  3. Enter canGetTemperatureData as the Rule Name.

  4. Click Add Rule.

  5. Enable the Get toggle for the rule.

  6. Enter the following When expression to prevent requests that are not to Dark Sky:

    {
      "%%args.url.host": "api.darksky.net"
    }
    
  7. Click Save.

6

Update Stitch Function Code

Now that we’ve fully configured the HTTP Service, we can update our function code to store Dark Sky temperature data alongside each device temperature reading.

Open the logTemperatureReading function and update the code to match the following:

logTemperatureReading
async function getDarkSkyData() {
  // Get the current temperature from Dark Sky
  const DarkSky = context.services.get("DarkSky");
  const darkSkyKey = context.values.get("DarkSkyKey");
  const deviceLocation = context.values.get("DeviceLocation");
  const url = `https://api.darksky.net/forecast/${darkSkyKey}/${deviceLocation}`;

  const darkSkyResponse = await DarkSky.get({ url });
  return EJSON.parse(darkSkyResponse.body.text())
}

exports = async function(impData) {
  const darkSkyData = await getDarkSkyData();

  // Prepare the temperature reading data
  const now = new Date();
  const temperatureData = {
    indoorTemp: impData.temp * 9 / 5 + 32, // Convert to Fahrenheit
    indoorHumidity: impData.humid,
    outdoorTemp: darkSkyData.currently.temperature,
    outdoorHumidity: darkSkyData.currently.humidity,
    timestamp: now.getTime(),
    date: now
  };

  // Insert the temperature data into MongoDB
  const mongodb = context.services.get("mongodb-atlas");
  const TempData = mongodb.db("Imp").collection("TempData");

  return TempData.insertOne(temperatureData);
};

D. Add Text Message Querying

We’re now storing both indoor and outdoor temperature data in MongoDB. We could connect to the database directly to query the data, but it might be more useful to get the information via text message. To enable that, we’ll use a Twilio Service webhook to query and return the data.

1

Get Your Twilio Credentials

To connect to Twilio, we’ll need to have an Account SID and Auth Token for a Twilio account.

To find your account credentials:

  1. Log in to Twilio. If you don’t have a Twilio account, you can create one for free.
  2. Navigate to your Twilio console.
  3. Find the Account SID and Auth Token values on the right side of the dashboard.
2

Create a Twilio Service

Now that we have Twilio credentials, we can create a Twilio service to handle text message requests.

To set up the service in the Stitch UI:

  1. Click Services in the left-hand navigation.
  2. Click Add a Service.
  3. Select the Twilio service.
  4. Enter TwilioSMS as the Service Name.
  5. Enter the Account SID and Auth Token values you got from the Twilio dashboard.
  6. Click Add Service
3

Create a Twilio Webhook

We need a way to accept and handle incoming text message requests that users send to our phone number. To enable this, Twilio lets us specify a webhook URL to which it will send the data for all incoming messages.

The Twilio Service in Stitch lets us create webhook URLs that pass any data they receive to a function. We can return the results of the function back to Twilio to send a response message to the user.

To create a webhook:

  1. Navigate to the Incoming Webhooks tab of the TwilioSMS service.
  2. Click Add Incoming Webhook.
  3. Enter handleTemperatureRequest as the Webhook Name.
  4. Enable the Respond With Result toggle.
  5. Click Save.

You should now see the Function Editor for the webhook. Paste the following webhook function into the editor and click the save icon Save icon:

exports = async function(message) {
  // Parse the text message body
  const requestBody = message.Body.toLowerCase().trim();
  const isRequestForCurrentTemperature = requestBody === "now";
  const requestedDate = isRequestForCurrentTemperature
    ? Date.now()
    : Date.parse(requestBody);
  if (!requestedDate) {
    return `Invalid Request: Send "now" for the current temperature, or send a specific date.`;
  }

  // Fetch the data for the requested date
  const TemperatureData = context.services
    .get("mongodb-atlas")
    .db("Imp")
    .collection("TempData");
  const latestTemperatureData = await TemperatureData
    .find({ timestamp: { $lte: requestedDate / 1000 } })
    .sort({ timestamp: -1 })
    .limit(1)
    .next();
  if (typeof latestTemperatureData == 'undefined') {
    return `No temperature data found for ${requestBody}`;
  }

  const { date, indoorTemp, outdoorTemp } = latestTemperatureData;

  // Send the temperature data back to the user
  return `On ${date}, ` +
         `the indoor temperature was ${indoorTemp}°F ` +
         `and the outdoor temperature was ${outdoorTemp}°F.`
};
4

Configure Twilio to Call the Webhook

Note

We need to have an SMS-enabled Twilio phone number in order to send temperature data back to users that request it. For information on acquiring a Twilio phone number, see the Twilio docs.

Now that we’ve created our webhook, all that’s left to do is provide the webhook URL to Twilio. Whenever Twilio receives a text message, it sends a POST request that includes the sender’s phone number and the message body to the webhook URL.

To add the webhook to Twilio:

  1. Find and copy the Webhook URL from the Stitch UI. You can find the webhook URL on the Settings tab of the handleTemperatureRequest webhook in the Stitch UI.
  1. From the Twilio Console, navigate to the Phone Numbers page using the left-hand navigation.
  2. Click the phone number that you want to receive and send text messages.
  3. Under Messaging, set Configure With to Webhooks, TwiML Bins, Functions, Studio, or Proxy.
  4. Set A Message Comes In to Webhook and paste the webhook URL as the value.
  5. Click Save.
5

Request the Temperature with SMS

Great job! We’re all set up to query our stored temperature data via text message. Test it out by sending a specific date/time or the word “now” to your Twilio phone number. You should receive a message with the most recent indoor and outdoor temperature readings relative to your requested time.