Configuring Arduino

Arduino Uno R3 is connected to DHT 22, which is a humidity and temperature sensor. It uses XBee series 2 for sending the sensor data to the IoT gateway through the ZigBee protocol. When powered by an external LiPo or solar cell, this becomes a deployable sensor node with self-contained power and a communication radio capable of sending data to the centralized IoT gateway. Refer to the following schematic for wiring up the sensor and radio to Arduino Uno R3.
Arduino_DHT22_XBee_bb
The sketch below is used to get the humidity and temperature from the sensor. Note that we are not using a special library to communicate to the gateway. The data written to the serial port is available to the gateway. XBee radio is a drop-in replacement for serial port communication. Neither the sensor node nor the gateway realize that they are separated over a ZigBee wireless link. Upload the sketch to Arduino.
#include 
#define dht_dpin 2
dht DHT;
void setup(){
  Serial.begin(9600);
}
void loop(){
  DHT.read11(dht_dpin);
 Serial.print(DHT.humidity);
    Serial.print(",");
    Serial.print(DHT.temperature); 
    Serial.print("\n");
  delay(800);
}

Configuring Raspberry Pi 2

After building the sensor node, let’s wire up the gateway. We will connect XBee Series 2 to Raspberry Pi 2 as shown in the below diagram. Install a terminal client, such Minicom, to ensure that Arduino and Raspberry Pi are connected over the serial port. If your XBee configuration is correct, you should see a CSV string emitted by Arduino in the terminal client. Refer to this tutorial for configuring XBee with  Raspberry Pi.
RPi_XBee_bb
In the above configuration, it is clear that Raspberry Pi 2 uses ZigBee for inbound communication and Wi-Fi for outbound communication. It receives the data in CSV and may transform that into JSON to store in a document store database. As a typical field gateway, it is performing protocol transformation and also data transformation.
Now that we are done with the hardware and network configuration, let’s install the required software. We will set up and configure an open source RESTful API backend called DreamFactory for ingestion and storage of data. To visualize the data stream in real-time, we will configure Freeboard, an open source dashboard framework.

Overview of DreamFactory Services Platform

DreamFactory is an open source REST API backend. It acts as a universal data access layer for connecting to a variety of data sources including relational databases, NoSQL databases, object storage and file systems. The key advantage of using DreamFactory is that it exposes consistent, simple REST endpoints for any data source. Developers dealing with disparate data sources — such as Amazon S3, MySQL, MongoDB and local file systems — can use a unified API. For data sources that are not supported out of the box, DreamFactory lets developers register custom REST endpoints. This makes it possible to consolidate the data access API with DreamFactory . We will use this software to interact with the local datastore as well as the cloud database.
Since Raspberry Pi 2 is not the most appropriate device to store data long term, we will periodically upload the data to Amazon DynamoDB. This data may be an input for Amazon RedShift or Elastic MapReduce for further processing and analysis. The below diagram explains the role of DreamFactory in aggregating and ingesting the data stream.
DSP_Architecture
The source code of DreamFactory is available on GitHub. Since it is a typical LAMP application, the software can be installed on any Linux distribution capable of running Apache, PHP and MySQL. Raspberry Pi runs a customized version of Debian that can run most of the mainstream Linux packages. There are many tutorials on setting up Apache and PHP on Raspberry Pi to run a local web server. Apart from that, it is also possible to run the latest version of MySQL, which completes the LAMP stack.
Developers can clone the dsp-core GitHub repo and follow the instructions to configure the stack.
Installing phpMyAdmin is highly recommended for the initial configuration of the database. Create a database called WeatherStation and run the following SQL script to create a table in local MySQL.
CREATE TABLE IF NOT EXISTS `Weather` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `RoomID` int(11) NOT NULL,
  `DeviceID` int(11) NOT NULL,
  `SensorID` int(11) NOT NULL,
  `SensorType` varchar(20) DEFAULT NULL,
  `SensorValue` float NOT NULL,
  `SensorUnit` varchar(11) NOT NULL,
  `Date` date DEFAULT NULL,
  `Time` time DEFAULT NULL,
  PRIMARY KEY (`ID`)
) 
Open a browser on your PC or Mac to access the DreamFactory stack installed in Raspberry Pi. Register with the local DreamFactory stack, click on the Services tab in DreamFactory, and log in with the MySQL credentials to create the REST API for the data source. We can create REST API endpoints for both MySQL and Amazon DynamoDB. The following screenshot shows the service endpoint for local MySQL.
DSP_Services
Swagger, the popular REST API tool, is tightly integrated with DreamFactory, making it easy to test the API before invoking it from the clients. You can click on API Docs to access the Swagger playground. Clicking on the service we created in the last section shows us all the methods exposed by the REST API. The screenshot below confirms that DreamFactory is able to access the datasource.
DSP_Swagger

Ingesting the Sensor Data

Now that the data tier and the API tier are in place, let’s go ahead and populate the local database with the sensor data. As discussed earlier, XBee is treated as a serial port to send and receive data using the standard UART clients. This means we can use any library capable of dealing with the serial port to talk to XBee.
Since we are going to use Python code for ingestion and storage, go ahead and install PySerial library. The following code snippet acquires the sensor data and stores in the local datastore. It uses DreamFactory’s REST API as the data access layer.
The code is self-explanatory. It starts by getting an authentication token from DreamFactory, which will be used in subsequent operations.It then opens the serial port and splits the CSV into temperature and humidity values. For each data point, the code invokes the REST API endpoint to perform a POST operation that results in storing the data.
import json
import unirest
import binascii
import os
import serial
import time
data=""
# Get authenticated and grab the session id
response = unirest.post("http://DreamFactory_URL/rest/user/session", headers = {"X-DreamFactory-Application-Name": "WeatherStation"}, params=json.dumps({ "email": "janakiramm@gmail.com", "password": "Password@123"}))
session_id=json.loads(response.raw_body)["session_id"]

print "Successfully authenticated with DreamFactory:" + session_id

while 1:
  try:    
    ser = serial.Serial('/dev/ttyAMA0', 9600) # Replace the port number to match your Raspberry Pi
    if ser.inWaiting():
      data=ser.readline().split(',')
  except Exception, e:
    print "Error ", e
    continue
  if len(data)==4 and len(data[0]) >= 5 and len(data[1]) >= 5: # Skip missing entries from serial port
     for sensorid in range(2):
          Rec={}
          Rec["RoomID"] = "1"
          Rec["DeviceID"] = "1"
          Rec["SensorID"] = sensorid
          Rec["SensorValue"] = data[sensorid].rstrip()

          if (sensorid==0):
               Rec["SensorType"] = "Humidity"
               Rec["SensorUnit"] = "Percentage"
          if (sensorid==1):
               Rec["SensorType"] = "Temperature"
               Rec["SensorUnit"] = "Celsius"

          Rec["Date"] = time.strftime("%d/%m/%Y")
          Rec["Time"] = time.strftime("%H:%M:%S")

          print Rec["SensorID"]
          print Rec["SensorType"]
          print Rec["SensorValue"]

          Weather={}
          Weather["record"]=Rec
          # Ingest data from sensor
          response = unirest.post("http://DreamFactory_URL/rest/WeatherStation/Weather", headers = {"X-DreamFactory-Application-Name": "WeatherStation", "X-DreamFactory-Session-Token": session_id}, params=json.dumps(Weather), auth = (), callback = None)
          print "Added sensor data as of " + time.strftime("%H:%M:%S")

Visualizing the Data Stream With Freeboard

Freeboard is an open source visualization and dashboard tool. Though there is a commercial hosted edition, the source code is available on GitHub. The best thing about freeboard is that it can be run entirely from a local hard drive. One word of caution about freeboard is that it is completely stateless. There is no database or persistence available within the tool. This is left for the developers to implement. But it does support importing and exporting dashboards, giving us an option to save the configuration. You can install this like any other web application on Apache.
Freeboard can be integrated with any REST endpoint that emits valid JSON output. This fits well within DreamFactory’s model of API implementation. Go back to Swagger and query the Weather table for temperature while sorting on the timestamp and limiting the number of records to one. This gives us the latest value of temperature streamed by Arduino.
DSP_Swagger_Query
Just grab the URL from the Swagger console and paste it in the URL field of data sources section in Freeboard.
http://DreamFactory_URL/rest/WeatherStation/Weather?filter=SensorType%3D%22Humidity%22&limit=1&order=Time%20DESC
To make Freeboard seamlessly work with DreamFactory, you need to add two headers called ‘X-DreamFactory-Session-Token’ and ‘X-DreamFactory-Application-Name.’ The following Python code snippet gives us an authentication token of DreamFactory.
Use this for the X-DreamFactory-Session-Token and the DreamFactory service name as the application name. The datasources section should update the timestamp indicating that the DreamFactory REST API call was successful.
import json
import unirest
response = unirest.post("http://DreamFactory_URL/rest/user/session", headers = {"X-DreamFactory-Application-Name": "WeatherStation"}, params=json.dumps({ "email": "user@example.com", "password": "bitnami"}))
session_id=json.loads(response.raw_body)["session_id"]
print "X-DreamFactory-Application-Name : WeatherStation" 
print "X-DreamFactory-Session-Token : " + session_id
DSP_Freeboard_Auth
You can now add individual panes to show the temperature and humidity. Your dashboard should resemble the following screenshot.
DSP_Freeboard
To make it easy for you to implement the dashboard, I have exported a working freeboard configuration that you can download and import. Simply replace the URL and the HTTP headers to configure for your DreamFactory implementation.

Summary

The objective of this tutorial was to introduce the end-to-end scenario of configuring sensor nodes, gateways, data ingestion, data aggregation and visualization. Though the scope was limited to querying the local database, you can easily extend it to support a cloud database like Amazon DynamoDB.
Feature image: “OF4” by Karen is licensed under CC BY 2.0.