Quan Zhang
Created March 22, 2016

SmartCooler

Send SMS to your phone if the temperature of your cooler is higher than a threshold.

IntermediateShowcase (no instructions)2 hours143
SmartCooler

Things used in this project

Story

Read more

Code

Backend temperature monitoring and SMS

JavaScript
/*
The Local Temperature Node.js sample application distributed within Intel XDK IoT Edition under the IoT with Node.js Projects project creation option showcases how to read analog data from a Grover Starter Kit Plus  IoT Intel Edition Temperature Sensor, start a web server and communicate wirelessly using WebSockets.

MRAA - Low Level Skeleton Library for Communication on GNU/Linux platforms
Library in C/C++ to interface with Galileo & other Intel platforms, in a structured and sane API with port nanmes/numbering that match boards & with bindings to javascript & python.

Steps for installing MRAA & UPM Library on Intel IoT Platform with IoTDevKit Linux* image
Using a ssh client: 
1. echo "src maa-upm http://iotdk.intel.com/repos/1.1/intelgalactic" > /etc/opkg/intel-iotdk.conf
2. opkg update
3. opkg upgrade

Article: https://software.intel.com/en-us/html5/articles/iot-local-temperature-nodejs-and-html5-samples
*/

var B = 3975;
var mraa = require("mraa");

// Twilio API that allow to send SMS
var client = require('twilio')(ACCOUNTSID, OAUTHTOKEN);

//GROVE Kit A0 Connector --> Aio(0)
var myAnalogPin = new mraa.Aio(0);

/*
 * This function sends a SMS to your phone.
 */ 
function SMS(temp){     
    client.messages.create({to:"+1XXXXXXXXXX",
                               from:"+1XXXXXXXXXX",
                               body:"Im2hot: Your cooler is too HOT (" + temp.toFixed(2) + "F) right now. Please add more ice."
                              }, function(error, message) {
                                if(error) {
                                    console.log("error: " + error.message);
                                }
                                else {
                                    console.log("SMS send: " + message + " on " + message.dateCreated);   
                                }
                              }
                              );                          
}



/*
Function: startSensorWatch(socket)
Parameters: socket - client communication channel
Description: Read Temperature Sensor and send temperature in degrees of Fahrenheit every 4 seconds
*/

var intervalID = 0;
function startSensorWatch(socket) {
    'use strict';
    
    // Quan: add a counter var
    // var counter = 0;
    
    
    intervalID = setInterval(function () {
        var a = myAnalogPin.read();
        //console.log("Analog Pin (A0) Output: " + a);
        //console.log("Checking....");
        
        var resistance = (1023 - a) * 10000 / a; //get the resistance of the sensor;
        //console.log("Resistance: "+resistance);
        var celsius_temperature = 1 / (Math.log(resistance / 10000) / B + 1 / 298.15) - 273.15;//convert to temperature via datasheet ;
        //console.log("Celsius Temperature "+celsius_temperature); 
        var fahrenheit_temperature = (celsius_temperature * (9 / 5)) + 32;
        console.log("Fahrenheit Temperature: " + fahrenheit_temperature.toFixed(2) + "F");
        
        /*
         * send a SMS if the temperature is higher than 85.
         * Use a counter to avoid continuously sending SMS for a short time period.
         */
        
        if (fahrenheit_temperature > 85 && counter === 0) {
            SMS(fahrenheit_temperature);
            counter = 20;
        }
        else if (counter > 0) {
            counter -= 1;
        }
        
        
        
        socket.emit("message", fahrenheit_temperature);
    }, 4000);
}

console.log("Sample Reading Grove Kit Temperature Sensor");

//Create Socket.io server
var http = require('http');
var app = http.createServer(function (req, res) {
    'use strict';
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('<h1>Hello world from Intel IoT platform!</h1>');
}).listen(1337);
var io = require('socket.io')(app);

//Attach a 'connection' event handler to the server
io.on('connection', function (socket) {
    'use strict';
    console.log('a user connected');
    //Emits an event along with a message
    socket.emit('connected', 'Welcome');

    //Start watching Sensors connected to Galileo board
    startSensorWatch(socket);

    //Attach a 'disconnect' event handler to the socket
    socket.on('disconnect', function () {
        console.log('user disconnected');
        
        // clear the startSensorWatch interval if a user disconnect.
        clearInterval(intervalID);
    });
});

Receiver on client

JavaScript
var chart_data = [];
/*Creation of the d3 ScatterPlot*/
var splot_dataset = [];
var chart_counter = 0;
//shifting of line graph
var xshift = -1;

//Creation of the d3 Chart
var chart_data = [];

//Creation of d3 LineGraph with an initial value
var chart_data_line = [10];

//Creation of the d3 ScatterPlot
var isPurged = 0;

var chart_purge_time = 0;

//Set the height of the gauge
document.getElementById("gauge").setAttribute("style", "height:" + 0.20 * window.innerHeight + "px");

//Create a JSON style object for the margin
var margin = {
    top: 10,
    right: 20,
    bottom: 20,
    left: 20
};

var height = 0.5 * window.innerHeight;

//Scatterplot-Selects the specified DOM element for appending the svg 
var chart_svg = d3.select("#chart").append("svg").attr("id", "container1").attr("width", window.innerWidth).attr("height", 0.6 * height).append("g");

chart_svg.attr("transform", "translate(25," + margin.top + ")");

var x1 = d3.scale.linear().domain([0, 5000]).range([0, 100000]);

var y1 = d3.scale.linear().domain([0, 200]).range([0.5 * height, 0]);

//Add X Axis grid lines
chart_svg.selectAll("line.y1")
    .data(y1.ticks(10))
    .enter().append("line")
    .attr("class", "y")
    .attr("x1", 0)
    .attr("x2", 100000)
    .attr("y1", y1)
    .attr("y2", y1)
    .style("stroke", "rgba(8, 16, 115, 0.2)");

//This is for the Scatterplot X axis label
chart_svg.append("text").attr("fill", "red").attr("text-anchor", "end").attr("x", 0.5 * window.innerWidth).attr("y", 0.55 * height).text("Periods");

var x1Axis = d3.svg.axis().scale(x1).orient("top").tickPadding(0).ticks(1000);
var y1Axis = d3.svg.axis().scale(y1).orient("left").tickPadding(0);

chart_svg.append("g").attr("class", "x axis").attr("transform", "translate(0," + y1.range()[0] + ")").call(x1Axis);

chart_svg.append("g").attr("class", "y axis").call(y1Axis);


chart_purge_time = Math.round(((window.innerWidth * 40) / 969) - 2);

function purgeData() {
    'use strict';
    chart_counter = 0;
    xshift = -1;
    chart_data_line = [10];
    splot_dataset = [];
    //Remove all of the nodes from the charts
    chart_svg.selectAll("#chart_graph").remove();
    //Data has been purged
    isPurged = 1;
}

function plot() {
    /*-------------------------------For the Line Graph-------------------------------*/
    'use strict';
    chart_data.unshift(chart_counter);
    //Add new element to the end of the array
    splot_dataset.push(chart_data);
    //Empty heart rate data array
    chart_data = [];
    chart_counter++;
    //Draw Line Graph && Draw circles
    chart_svg.selectAll("circle").data(splot_dataset).enter().append("svg").attr("id", "chart_graph").append("circle")
        .attr("cx", function (d, i) {
            return x1(d[0]);
        }).attr("cy", function (d) {
            return y1(d[1]);
        }).attr("r", 3).attr("class", "dot")
        .style("fill", function (d) {
            if (d[1] > 85) {
                // Quan: show text alert in the bottom of the screen.
                $("#feedback_log").text("High temperature alert: " + d[1].toFixed(2) + "F");
                
                return "red";
            } else if ((d[1] > 49) && (d[1] <= 85)) {
                $("#feedback_log").text("");
                return "green";
            } else {
                $("#feedback_log").text("");
                return "white";
            }
        }).attr("stroke", "black").attr("stroke-width", 1);
    //Handle purging data
    if ((chart_purge_time === chart_counter) || (chart_counter > chart_purge_time)) {
        purgeData();
    }
}

/*
Function: validateIP()
Description: Attempt to connect to server/Intel IoT platform
*/
function validateIP() {
    'use strict';
    var socket,
    //Get values from text fields
        ip_addr = $("#ip_address").val(),
        port = $("#port").val(),
        script = document.createElement("script");

    //create script tag for socket.io.js file located on your IoT platform (development board)
    script.setAttribute("src", "http://" + ip_addr + ":" + port + "/socket.io/socket.io.js");
    document.head.appendChild(script);
    
    //Wait 1 second before attempting to connect
    setTimeout(function(){
        try {
            //Connect to Server
            socket = io.connect("http://" + ip_addr + ":" + port);

            //Attach a 'connected' event handler to the socket
            socket.on("connected", function (message) {
                //Apache Cordova Notification
                // Comment out 
                // If you update your Intel App Preview to the latest version,
                // the navigation does not work.
                /*
                navigator.notification.alert(
                    "Great Job!",  // message
                    "",                     // callback
                    'You are Connected!',            // title
                    'Ok'                  // buttonName
                );
                */
                //Set all Back button to not show
                $.ui.showBackButton = false;
                //Load page with transition
                $.ui.loadContent("#main", false, false, "fade");
            });

            socket.on("message", function (message) {
                chart_data.push(message);
                plot();
                //Update log
                //$("#feedback_log").text("Last Updated at " + Date().substr(0, 21));
            });
        } catch (e) {
            /*
                // Comment out
                // If you update your Intel App Preview to the latest version,
                // the navigation does not work.
            navigator.notification.alert(
                "Server Not Available!",  // message
                "",                     // callback
                'Connection Error!',            // title
                'Ok'                  // buttonName
                
            
            );
            */
        }
    }, 1000);

}

LCD Dispaly

C/C++
#include <Wire.h>
#include "rgb_lcd.h"
#include <SPI.h>
#include <WiFi.h>

rgb_lcd lcd;
const int pinTemp = A0;      // pin of temperature sensor
const int pinButton = 2;
float temperature;           // Creating temperature variable
int B=3975;                  // B value of the thermistor
float resistance;            // Creating resistance variable
int buttonState = LOW;
int onoff = 1;
int before = -1;
int after = 1;
int status = WL_IDLE_STATUS;
void setup() 
{
    lcd.begin(16, 2);
    lcd.noDisplay();            // set up the LCD's number of columns and rows:
    pinMode(pinButton, INPUT);
    while ( status != WL_CONNECTED) {
      status = WiFi.begin("WSU-PUBLIC");
      delay(20000);
    }
}

void loop() 
{
	  // update temperature   
    buttonState = digitalRead(pinButton);
    if (buttonState == HIGH) {
      int tmp = before;
      before = after;
      after = tmp;
    }

    if (before == -1 && after == 1) {
      onoff = 1;
      lcd.display();
      lcd.clear();                                
      int val = analogRead(pinTemp);                               // get analog value
      resistance=(float)(1023-val)*10000/val;                      // get resistance
      temperature=1/(log(resistance/10000)/B+1/298.15)-273.15;     // calc temperature
      temperature=(temperature*9.0)/5.0 + 32.0;
      lcd.setCursor(0,0);                                          //position of the cursor
      if (temperature >= 85)                                       //when temp is greater than or equal to 25C
      {
        lcd.setRGB(255,0,0);                                       //light LCD red
      }
      else if (temperature < 85)                                   // when temp is less than 25C
      {
        lcd.setRGB(0,0,255);                                       //Light LCLCDD Blue
      }
      //lcd.print("Temperature:");

      
      IPAddress ip = WiFi.localIP();
      lcd.print("IP:");
      lcd.print(ip[0], DEC);
      lcd.print(".");
      lcd.print(ip[1], DEC);
      lcd.print(".");
      lcd.print(ip[2], DEC);
      lcd.print(".");
      lcd.print(ip[3], DEC);

      
      lcd.setCursor(0, 1);
      lcd.print("Temp: ");
      lcd.print(temperature);                                      // Print Temperature on screen       
      lcd.setCursor(12,1);
      lcd.write(0b11011111);
      lcd.setCursor(13,1);
      lcd.print("F");
      delay(1000);
    }
    else if (before == 1 && after == -1) {
      if (onoff == 1) {
        lcd.clear();
        lcd.setCursor(0,0);   
        lcd.print("Turning off ...");
        delay(2000);
        lcd.setRGB(0,0,0);   
        lcd.noDisplay();
      }
      onoff = 0;
    }
}

Credits

Quan Zhang

Quan Zhang

1 project • 1 follower
Thanks to Zhifeng Yu.

Comments