Introduction to the Internet of Things
An Introduction to the Internet of things by building a real-time temperature plot.
In my previous post, I said that I was interested in learning Internet of Things. Well, I was serious about it. So here comes my first tutorial on Internet of Things. I am already a full stack web developer, so I used some of my JavaScript skills in Internet of Things to build a website that shows real-time graph of your rooms (or whatever) temperature.
For the sake of presentation, it is plotting graph for every second.
Plotting Real-time graph of temperature.
Hardware Used: Arduino UNO Micro-controller, LM35 Temperature Sensor.
Software Used: Node.js, Socket.io, serialport, Chart.js.
I am going to use Arduino UNO micro-controller board with LM35 temperature sensor module to measure the temperature of my room. I will read the temperature readings in my Node.js/Express server and will send the readings to client. Client will create and update the line-graph.
Step 1: Setting up the Arduino Board and LM35 Module.
Here is the picture of my Arduino board and sensor. I have connected 3 wires from LM35 to Arduino. One for power supply, one for ground and one for output. I have connected the output wire to A3 pin.
Step 2: Write Program to get temperature readings in Arduino IDE
Here is the code:
void setup() {
Serial.begin(9600); //Connect to serial port with rate of 9600bps.
delay(1000);
}
void loop() {
int value = analogRead(A3); //Read the value from temperature sensor.
int tempC = value*0.48828125; //Convert it into temp in C.
Serial.println(tempC); //Print it on Serial Monitor.
delay(10000); //Delay, specifies gap between two readings in mili seconds.
}
Step 3: Read the temperature readings in Node.js and Express App
First of all, you need to install Node.js if you don’t have one. So go to Node.js website and follow the instructions to install it. After installing, go to a directory where you want to create this app and create a new folder and navigate to that folder in terminal / command prompt / powershell. now type npm init to create a new Node.js app and fill up all the details.
Now we have to install express, socket.IO and serialport libraries using npm. Express is a web framework based on Node.js, Socket.IO is a node module that allows bidirectional event-based communication that allows us to do things in real-time, and serialport is a node module that allows to read serial ports. I am writing temperature values in serial port ‘COM3’, so I will use serialport to read these values from ‘COM3’ and use it in Node.js server. To install these three modules, in the same directory type this in terminal/cmd.
npm install express socket.io serialport --save
Now create a index.js file. First of all, we have to create an Express server. In Express, it’s pretty easy to create a server. Now callback is a function that will be called when the server is launched.
var app = express();
var server = app.listen(4000, callback)
Now we have to bind socket.io to our server.
var io = require(‘socket.io’)(server);
Now we have to use serialport to read temperature values. So we import serialport. After this, I have made a new instance of serialport at port ‘COM3’. Because my Arduino is connected to port ‘COM3’. You can see the name of port in Arduino IDE -> Tools -> Port. Now we have to use parser to read the data from serial port. But we have to read a line. So we will set the delimiter to ‘/n’.
const SerialPort = require(‘serialport’);
const Readline = SerialPort.parsers.Readline;
const port = new SerialPort(‘COM3’);
const parser = port.pipe(new Readline({delimiter: ‘\\r\\n’}));
Now that we have set the parser. Parser will listen to data. As the data is available it will scan for next line and will read the data.
parser.on(‘data’, callback);
Now as parser reads the data, the data will be available in callback parameters. So we can send it to our clients. We can use io.sockets.emit(‘action’,object) function to emit date, time and temp to client. So that clients can make grpahs.
parser.on('data', (temp) => {
var today = new Date();
io.sockets.emit('temp', {date: today.getDate()+"-"+today.getMonth()+1+"-"+today.getFullYear(), time: (today.getHours())+":"+(today.getMinutes()), temp:temp});
});
Here is the full code of index.js
var express = require('express');
var app = express();
var server = app.listen(4000, () => { //Start the server, listening on port 4000.
console.log("Listening to requests on port 4000...");
})
var io = require('socket.io')(server); //Bind socket.io to our express server.
app.use(express.static('public')); //Send index.html page on GET /
const SerialPort = require('serialport');
const Readline = SerialPort.parsers.Readline;
const port = new SerialPort('COM3'); //Connect serial port to port COM3. Because my Arduino Board is connected on port COM3. See yours on Arduino IDE -> Tools -> Port
const parser = port.pipe(new Readline({delimiter: '\r\n'})); //Read the line only when new line comes.
parser.on('data', (temp) => { //Read data
console.log(temp);
var today = new Date();
io.sockets.emit('temp', {date: today.getDate()+"-"+today.getMonth()+1+"-"+today.getFullYear(), time: (today.getHours())+":"+(today.getMinutes()), temp:temp}); //emit the datd i.e. {date, time, temp} to all the connected clients.
});
io.on('connection', (socket) => {
console.log("Someone connected."); //show a log as a new client connects.
});
Step 4: Plotting Real-time graph
Creating charts from scratch can be a tedious work. To make this easy, there are many javascript libraries available i.e. Chart.js, D3.js, plotly etc. I will use Chart.js to make the graph. It is simple and easy to use. First of all, create a public folder in the project directory. In the public folder, create index.html file. We have to add Chart.js and socket.io.js CDN in our file, so that we can use these libraries. We have to add socket.io in our script so that it can be connected to our server.
var socket = io.connect(‘http://localhost:4000');
...
...
socket.on('temp', callback);
As it is connected to server. Client will start listening for messages. As a ‘temp’ named message is received. The message object that includes date, time and temperature is available to callback function. So we can add this data in our graph and update it. I have set a maximum limit of 15 data points in the graph. After that it will shift the array with latest data.
Here is the full index.html file.
<!DOCTYPE html>
<html>
<head>
<title>Temperature Plot</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<h1>Temperature Graph</h1>
<h4>Date: <span id="date"></span></h4>
<div class="chart-container" style="position: relative; width:75vw; margin: auto;">
<canvas id="myChart"></canvas>
</div>
<link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.4.0/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost:4000'); //connect to server
var ctx = document.getElementById('myChart').getContext('2d');
var chart = new Chart(ctx, {
// The type of chart we want to create
type: 'line',
// The data for our dataset
data: {
labels: [],
datasets: [{
label: "Temperature",
borderColor: "#FF5733",
data: [],
fill: false,
pointStyle: 'circle',
backgroundColor: '#3498DB',
pointRadius: 5,
pointHoverRadius: 7,
lineTension: 0,
}]
},
// Configuration options go here
options: {}
});
socket.on('temp', function(data) { //As a temp data is received
console.log(data.temp);
document.getElementById('date').innerHTML = data.date; //update the date
if(chart.data.labels.length != 15) { //If we have less than 15 data points in the graph
chart.data.labels.push(data.time); //Add time in x-asix
chart.data.datasets.forEach((dataset) => {
dataset.data.push(data.temp); //Add temp in y-axis
});
}
else { //If there are already 15 data points in the graph.
chart.data.labels.shift(); //Remove first time data
chart.data.labels.push(data.time); //Insert latest time data
chart.data.datasets.forEach((dataset) => {
dataset.data.shift(); //Remove first temp data
dataset.data.push(data.temp); //Insert latest temp data
});
}
chart.update(); //Update the graph.
});
</script>
</body>
<style>
h1 {
text-align: center;
font-family: 'Lato', sans-serif;
}
h4 {
text-align: center;
font-family: 'Lato', sans-serif;
}
p {
text-align: center;
font-family: 'Lato', sans-serif;
}
</style>
</html>
All done. Let’s run it.
node index
Now you can see the graph on http://localhost:4000 or you can open index.html file in public folder. Both will work. If you want to share this page with others, you can host this static page on GitHub pages too.
Things that you can add to this:
- Store temperature in database, You can use MongoDB, Mongoose to do so.
- Show average temperature of last 3 hours or something like that.
- As user loads the index.html page, send last 15 temperature data points and shift it as new data comes. You can use io.on(‘connection’, (socket) => {…}); to do this.
- Feel free to add anything you want!
GitHub repository for the source code is here. Feel free to fork.
Thank you for your time!