Filter results by

Monitor Fire and Temperature Using SAMI, Open-Source IoT Hardware and Android

Note: This tutorial has been updated for ARTIK Cloud. Read it here.

In this article we will build a remote monitoring system using SAMI, off-the-shelf sensors, Arduino UNO, Raspberry Pi, and an Android application. Using our Android app, we can remotely monitor data from temperature and flame sensors that are connected to SAMI via the IoT development platform. Note that if you attended our SAMI Developer Meet-up, you will recognize this IoT setup from the live demo I presented with Dr. Luc Julia.

This is the first in a series of articles exploring the DIY smart home with SAMI. Read the second tutorial, An IoT Remote Control. For a basic IoT implementation, see our tutorial Your first IoT device and the previous blog Make an IoT Weather Station with SAMI. However, this article can be read independently. You will learn how to do three things:

  • Combine data from multiple sensors on Arduino UNO to send to Raspberry Pi.
  • Set up a WebSocket connection on Raspbery Pi to send data to SAMI cloud.
  • Build an Android application to monitor new sensor data via SAMI in real-time.

SAMI creates an open ecosystem

In a system like this, SAMI acts as back-end storage for IoT devices. Meanwhile, application developers use SAMI APIs to develop mobile/web applications for these IoT devices.

Device developers do not need to build their own apps. Instead, application developers can learn the device Manifests and build applications for the devices that interest them. Each of the players in the ecosystem can focus on what they do best, instead of building a complicated end-to-end system.

Architecture

The diagram below shows the high-level architecture:

Architecture

We use the following hardware components:

  • Raspberry Pi with a network connection
  • Arduino UNO with a breadboard
  • DHT11 temperature sensor
  • IR flame sensor
  • USB and power cables, plus wiring for the breadboard
  • Android phone

We will write the following software:

  • A Sketch program running on the Arduino
  • A Node.js script running on the Raspberry Pi
  • An Android application running on the Android phone

You can check out the code of the above software on GitHub.

Demo video

Build the sensor monitor system

Step 1: Connect a device in the SAMI User Portal

I have published a device type “SAMI Example IoT DIY Sensor” with multiple fields (temperature and flame detection) as below. Any SAMI developer can now use this device type as part of an IoT setup. device type fields

  1. First, sign into the SAMI User Portal. If you don’t have a Samsung account, you can create one at this step.
  2. On the dashboard, click to connect a new device. Choose the pre-defined device type “SAMI Example IoT DIY Sensor”.
  3. Name this device using your name (e.g., “Yujing IoT Sensor”).
  4. Click “Connect Device…”. You’re taken back to the dashboard.
  5. Click the Settings icon of the device you just added. In the pop-up, click “GENERATE DEVICE TOKEN…”.
  6. Copy the device ID and device token on this screen. You will use these in the code. device info screen

Step 2: Set up the Arduino

Now let’s wire the sensors to the Arduino.

Arduino and sensors

The two sensors are wired as follows:

Fritzing

Next, upload the Sketch program (read_temperature_flame_sensors.ino) to the Arduino UNO using the Arduino IDE. This code reads the data from the temperature sensor and IR flame sensor, and then sends them to the serial port every 5 seconds (you can change this parameter in the code later, since SAMI has rate limits for the number of messages per day). Below is a data sample:

1 84,1002,1

The first value is the temperature (in Fahrenheit) from DHT11; the second value is the analog reading ([0~1023]) from the flame sensor; and the third value is the digital reading ([0,1]) from the flame sensor. For the digital readings, “0” means that a fire is detected and “1” means no fire.

Here is the straightforward code:

 1 #include <DHT.h>
 2 
 3 // Delay between reads
 4 const int delayBetweenReads = 5000;//5s
 5 
 6 // For temperature sensor
 7 const int DHTPIN = 2;
 8 const int DHTTYPE = DHT11;
 9 DHT dht(DHTPIN, DHTTYPE);
10 
11 // For flame detector senso
12 const int flameDigitalPinIn = 3; 
13 
14 void setup() {
15   // initialize serial communication @ 9600 baud:
16   Serial.begin(9600);
17   dht.begin();
18   pinMode(flameDigitalPinIn, INPUT);
19 }
20 
21 void loop() {
22   // Read data from temperature sensor
23   float temp = dht.readTemperature(true);
24   if (isnan(temp)) {
25     temp = -1;// error
26   } 
27   
28   // read the sensor on analog A0:
29   int flameAnalogReading = analogRead(A0);
30   
31   // HIGH(1) means no fire is detected
32   // LOW (0) means fire is detected
33   int flameDigitalReading = digitalRead(flameDigitalPinIn);
34   
35   // Compose data and send to Serial
36   // Data format: "temperature,flameAnalogReading,flameDigitalReading
37   // Data example: "84,1001,1"
38   Serial.print(String((int)temp));
39   Serial.print(",");
40   Serial.print(String(flameAnalogReading));
41   Serial.print(",");
42   Serial.println(String(flameDigitalReading));
43 
44   delay(delayBetweenReads);
45 }

Step 3: Set up the Raspberry Pi

Connect your Raspberry Pi to a monitor, mouse and keyboard. Ensure that an Ethernet or WiFi® connection is working, and make sure the OS is up-to-date:

$ sudo apt-get update
$ sudo apt-get upgrade

If not already installed, install Node.js for ARM, then add the packages ‘serialport’ and ‘ws’ via npm:

$ npm install serialport
$ npm install ws

Now connect the serial port from the Arduino to the USB on the Raspberry Pi.

Connect Arduino and Raspberry Pi

Finally, download the Node.js code (send_data_to_sami.js) to the Raspberry Pi. Replace the placeholders in the code with the device token and device ID you collected from the User Portal.

1 var webSocketUrl = "wss://api.samsungsami.io/v1.1/websocket?ack=true";
2 var device_id = "<YOUR DEVICE ID>";
3 var device_token = "<YOUR DEVICE TOKEN>";

The Node.js code snippet below establishes a bi-directional WebSocket connection between the Raspberry Pi and SAMI:

 1 /**
 2  * Create a /websocket bi-directional connection 
 3  */
 4 function start() {
 5     //Create the websocket connection
 6     isWebSocketReady = false;
 7     ws = new WebSocket(webSocketUrl);
 8     ws.on('open', function() {
 9         console.log("Websocket connection is open ....");
10         register();
11     });
12     ws.on('message', function(data, flags) {
13         console.log("Received message: " + data + '\n');
14     });
15     ws.on('close', function() {
16         console.log("Websocket connection is closed ....");
17     });
18 }
19 
20 /**
21  * Sends a register message to the websocket and starts the message flooder
22  */
23 function register(){
24     console.log("Registering device on the websocket connection");
25     try{
26         var registerMessage = '{"type":"register", "sdid":"'+device_id+'", "Authorization":"bearer '+device_token+'", "cid":"'+getTimeMillis()+'"}';
27         console.log('Sending register message ' + registerMessage + '\n');
28         ws.send(registerMessage, {mask: true});
29         isWebSocketReady = true;
30     }
31     catch (e) {
32         console.error('Failed to register messages. Error in registering message: ' + e.toString());
33     }   
34 }

Each time, the Raspberry Pi reads three data points from the serial port, and then composes and sends one message to SAMI via WebSocket as illustrated below:

 1 start(); // create websocket connection
 2 
 3 sp.on("open", function () {
 4     sp.on('data', function(data) {
 5             if (!isWebSocketReady){
 6                 console.log("Websocket is not ready. Skip sending data to SAMI (data:" + data +")");
 7                 return;
 8             }
 9             console.log("Serial port received data:" + data);
10             var parsedStrs = data.split(",");
11             var temperature = parseInt(parsedStrs[0]);
12             var flameAnalogValue = parseInt(parsedStrs[1]);
13             var flameDigitalValue = parseInt(parsedStrs[2]);
14 
15             // flameDigitalValue = 1 ==> no fire is detected
16             // flameDigitalValue = 0 ==> fire is detected
17             var onFire = false;
18             if (flameDigitalValue == 0) {
19                onFire = true;
20             }
21             sendData(temperature, flameAnalogValue, onFire);
22     });
23 });

Here is how each message is composed and sent to SAMI over WebSocket:

 1 /**
 2  * Send one message to SAMI
 3  */
 4 function sendData(temperature, flameAnalogReading, onFire){
 5     try{
 6         ts = ', "ts": '+getTimeMillis();
 7         var data = {
 8               "temp": temperature,
 9               "flameAnalogReading": flameAnalogReading,
10               "onFire": onFire
11               };
12         var payload = '{"sdid":"'+device_id+'"'+ts+', "data": '+JSON.stringify(data)+', "cid":"'+getTimeMillis()+'"}';
13         console.log('Sending payload ' + payload);
14         ws.send(payload, {mask: true});
15     } catch (e) {
16         console.error('Error in sending a message: ' + e.toString());
17     }   
18 }

Step 4: Fire it up and view the data!

Let’s start the Node.js program on the Raspberry Pi from the terminal:

$ node send_data_to_sami.js

In the terminal, you should see the payload of the message sent to SAMI and the corresponding response from SAMI as follows:

Serial port received data:84,1003,1
Sending payload {"sdid":"45176de99e424d98b1a3c42558bfccf4", "ts": 1438722871167, "data": {"temp":84,"flameAnalogReading":1003,"onFire":false}, "cid":"1438722871167"}
Received message: {"data":{"mid":"77b89ba8d8fb41a296403044698de3ac","cid":"1438722871167"}}

Log into the SAMI User Portal once again.

View your device data as it’s generated by clicking the device name in the device box. This takes you to Data Visualization. From there, click the “+/- CHARTS” button and check “temp” and “onFire” to visualize a chart for each field. (Read this post for more information on Data Visualization.)

SAMI data visualization

Step 5: Build the Android monitoring app

The sensor data is now being sent to SAMI. Now we can build an Android app to read the data from SAMI in real-time. It’s important to note that any developer can build such a mobile app, since the “SAMI Example IoT DIY Sensor” with the appropriate fields has already been published in the Developer Portal. Again, thanks to the openness of the SAMI ecosystem, any developer can build an application for any published devices.

Below is a screenshot of our app. The status and time continually refreshes as new data comes in. The Android app uses a read-only WebSocket API /live to listen in real-time for each message sent to SAMI by the Raspberry Pi. This type of WebSocket is primarily used by applications with monitoring functionalities.

monitor sensor data on Android

Check out the Android code on GitHub. Follow the instructions there to build the Android application. Please do remember to replace the placeholders in SAMISession.java with the device token and device ID you collected from the User Portal.

Below is the read-only WebSocket URL:

String liveUrl = "wss://api.samsungsami.io/v1.1/live?sdid=<YOUR DEVICE ID>&Authorization=bearer+<YOUR DEVICE TOKEN>";

The following snippet shows the WebSocket event handler:

 1 public void connectLiveWebsocket() {
 2     if (mLive == null) {
 3         mLive = new Websocket();
 4     }
 5 
 6     if(!mLive.isConnected() && !mLive.isConnecting()) {
 7         String liveUrl = getLiveUrl();
 8         if (liveUrl == null || liveUrl.length() <= 0) {
 9             Log.w(TAG, "Cannot to connect to live websocket with empty URL");
10             return;
11         }
12         mLive.connect(liveUrl, new WebsocketEvents() {
13             @Override
14             public void onOpen(ServerHandshake handshakedata) {
15                 final Intent intent = new Intent(WEBSOCKET_LIVE_ONOPEN);
16                 LocalBroadcastManager.getInstance(ourContext).sendBroadcast(intent);
17             }
18 
19             @Override
20             public void onMessage(String message) {
21                try {
22                     JSONObject json = new JSONObject(message);
23                     JSONObject dataNode = json.optJSONObject("data");
24                     JSONObject errorNode = json.optJSONObject("error");
25                     if (dataNode != null) {
26                         final Intent intent = new Intent(WEBSOCKET_LIVE_ONMSG);
27                         intent.putExtra(SDID, json.optString("sdid"));
28                         intent.putExtra(DEVICE_DATA, dataNode.toString());
29                         intent.putExtra(TIMESTEP,json.optString("ts"));
30                         LocalBroadcastManager.getInstance(ourContext).sendBroadcast(intent);
31                         Log.d(TAG, "data: " + dataNode.toString());
32                     } else if(errorNode != null) {
33                         Log.w(TAG, "error on Message: " + errorNode.toString());
34                     }
35                 } catch (JSONException e) {
36                     // This message doesn't contain data node, might be a ping.
37                 }
38             }
39 
40             @Override
41             public void onClose(int code, String reason, boolean remote) {
42                 final Intent intent = new Intent(WEBSOCKET_LIVE_ONCLOSE);
43                 intent.putExtra("error", "mLive is closed. code: " + code + "; reason: " + reason);
44                 LocalBroadcastManager.getInstance(ourContext).sendBroadcast(intent);
45             }
46 
47             @Override
48             public void onError(Exception ex) {
49                 final Intent intent = new Intent(WEBSOCKET_LIVE_ONERROR);
50                 intent.putExtra("error", "mLive error: " + ex.getMessage());
51                 LocalBroadcastManager.getInstance(ourContext).sendBroadcast(intent);
52             }
53         });
54     }
55 }

Once SAMI receives a message from the Raspberry Pi, it notifies the Android app about this message via the read-only WebSocket. This notification invokes the callback method onMessage. The callback eventually triggers the new data to show up on the UI.

Where to go from here?

For a home monitoring system, you may want to monitor locks on your doors, the moisture level in your garden, lights in your rooms, and the earth’s movements under your house (we live in California), etc. For the sake of fun, think of using different IoT open-source development modules (e.g., various Arduino boards, Raspbery Pi, ARTIK, Galileo) or using different module combinations to build these DIY devices.

You may be interested in writing an iOS app to do the monitoring. Or how about enhancing the Android app to monitor multiple device types instead of only one type? In addition, beyond monitoring, you may want to use your mobile app to control your DIY devices, such as turning on/off lights. With SAMI and various IoT modules, building a comprehensive DIY smart home can be both intuitive and enjoyable.

We will continue building our DIY smart home in the future. Stay tuned for more development blog posts by joining our mailing list at https://developer.artik.cloud/.

You might also like…

Get the ARTIK Newsletter

You like your news fresh! Sign up now and you will be the first to know about our latest software releases, coding tips, upcoming events, new blog posts and more!

By providing your contact information, you agree to our Privacy Policy and Terms of Use, confirm you are an adult 18 years or older, and authorize Samsung™ ARTIK to contact you by email with information about Samsung™ ARTIK products, events, and updates for Samsung IoT Solutions. You may unsubscribe at any time by clicking the link provided in our communications.