Introduction: Showing Charts and Gauges of IOT Device Data Using Arduino Web Server With JavaScript

About: Teacher that enjoys working with students

In this instructables we are going to show how to show charts and gauges on an IOT device sensor data with Arduino web server with JavaScript. An Arduino compatible board with WIFI module has been used to act as a webserver that is going to show IOT device sensor data and status.

Benefits of using Web server

The Internet of things or IoT is the internetworking of physical devices, vehicles (also referred to as "connected devices" and "smart devices"), buildings, and other items—embedded with electronics, software, sensors, actuators, and network connectivity that enable these objects to collect and exchange data. In 2013 the Global Standards Initiative on Internet of Things (IoT-GSI) defined the IoT as "the infrastructure of the information society." The IoT allows objects to be sensed and/or controlled remotely across existing network infrastructure, creating opportunities for more direct integration of the physical world into computer-based systems, and resulting in improved efficiency, accuracy and economic benefit. When IoT is augmented with sensors and actuators, the technology becomes an instance of the more general class of cyber-physical systems, which also encompasses technologies such as smart grids, smart homes, intelligent transportation and smart cities. Each thing is uniquely identifiable through its embedded computing system but is able to interoperate within the existing Internet infrastructure.

Typically, IoT is expected to offer advanced connectivity of devices, systems, and services that goes beyond machine-to-machine (M2M) communications and covers a variety of protocols, domains, and applications. The interconnection of these embedded devices (including smart objects), is expected to usher in automation in nearly all fields, while also enabling advanced applications like a smart grid, and expanding to the areas such as smart cities.

There are many ways that an IoT device can communicate with other devices. Some has two way communications like Bluetooth and other ways like using wired or wireless internet protocol. For better communication and interfacing we need efficient way with less efforts, using bluetooth means you need to develop apps and software but if you use an IoT with a builtin webserver device makes it much simpler and you can access the data and presentation of data with only a web browser that can be run in a smartphone, tablet or PC.

BOM:

1. Adafruit Feather M0 WiFi - ATSAMD21 + ATWINC1500

2. some sensor (Temperature, Humidity, ....)

Step 1: Arduino Sketch

We have used WiFiWebServer Arduino sketch which Serves a webpage from the WiFi shield. This sketch was modified to show charts and gauges using plotly Javascript.

Arduino WiFi101 library

This library allows you to use the Arduino WiFi compatible Shield 101 and the MKR1000 compatible board. These are powerful IoT solutions with crypto-authentication, developed with ATMEL, that connects your Arduino or Genuino to the internet wirelessly. Connecting the board or the shield to a WiFi network is simple, no further configuration in addition to the SSID and the password are required. It can serve as either a server accepting incoming connections or a client making outgoing ones. The library supports WEP and WPA2 Personal encryption. Compared to the retired WiFi Shield and the related library, this product and library support all the same methods plus the connectSSL(). The board connected to the shield communicates with the WiFi shield 101 compatible using the SPI bus. The WiFi101 library is very similar to the Ethernet and the library WiFi, and many of the function calls are the same.

Arduino sketch

/*
  WiFi Web Server with JavaScript

 A simple web server that shows the value of the analog input pins.
 using a WiFi shield.

 Circuit:
 * WiFi shield attached
 * Analog inputs attached to pin A0
 
 */

#include <SPI.h>
#include <WiFi101.h>


char ssid[] = "YOURHOTSPOT"; //  your network SSID (name)
char pass[] = "PASSWORD";   // your network password
int keyIndex = 0;                 // your network key Index number (needed only for WEP)

int status = WL_IDLE_STATUS;

WiFiServer server(80);

float Gain_A     = 0.154   ; // Sensor A
int   analogPin0 = A0       ; // Sensor A  

const int numReadings = 1000;
int readsens2=0;
int readsens3=0;
int readsens4=0;
int readsens5=0;
int readsens=0;
void setup() {
  IPAddress ip(192, 168, 1, 100);    
   WiFi.setPins(8,7,4,2);
//Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
   ; // wait for serial port to connect. Needed for native USB port only
  }
  analogReadResolution(12);
  analogReference(AR_INTERNAL);  //Reference voltage set to 1.1 V

// check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
//   Serial.println("WiFi shield not present");
// don't continue:
    while (true);
  }

// attempt to connect to Wifi network:
  while ( status != WL_CONNECTED) {
   Serial.print("Attempting to connect to SSID: ");
   Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    WiFi.config(ip);  
    status = WiFi.begin(ssid, pass);

// wait 10 seconds for connection:
    delay(10000);
  }
  server.begin();
// you're connected now, so print out the status:
  printWifiStatus();
}


void loop() {
  // listen for incoming clients
  WiFiClient client = server.available();
  if (client) {
      Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
//===========================================================================
// Web server text starts from here		  
char messagesp[] ="<!DOCTYPE html>"
"\n<html>"
"\n<head>"
"\n  <!-- Plotly.js -->"
"\n  <script src='https://cdn.plot.ly/plotly-latest.min.js'></script>"    // Java script for defining chart functions
"\n</head>"
"\n  "
"\n<body>"
"\n  <div id='myDiv' style='width: 480px; height: 400px;'><!-- Plotly chart will be drawn inside this DIV --></div>"
"\n  <script>"
"\nvar trace1 = {"
"\n  x: [1, 2, 3, 4, 5],";

char messagesp3[] ="\n  mode: 'markers',"
"\n  name: 'Sensor data'"
"\n};"
"\n "
"\nvar trace2 = {"
"\n  x: [1, 2, 3, 4, 5],"
"\n  y: [27, 24, 24, 24, 24],"
"\n  mode: 'lines',"
"\n  name: 'Temp'"
"\n};"
"\n "
"\nvar trace3 = {"
"\n  x: [1, 2, 3, 4,5],"
"\n  y: [32, 31, 35, 33, 27],"
"\n  mode: 'lines+markers',"
"\n  name: 'Humidity'"
"\n};"
"\n "
"\nvar data = [trace1, trace2, trace3];"
"\n "
"\nvar layout = {"
"\n  title: '--IoT device data chart--',"
"\n  xaxis: {"
"\n    title: 'Time sec'"
"\n  },"
"\n  yaxis: {"
"\n    title: 'Sensor output'"
"\n  }"
"\n};"
"\n "
"\nPlotly.newPlot('myDiv', data, layout);"
"\n  </script>"
"\n</body>"
"\n</html>";


          client.println("HTTP/1.1 200 OK");
          
          client.println("Content-Type: text/html");
 
          client.println();
//client.println("Connection: keep-alive");
          client.println();
          client.write(messagesp);
//=============================================          
//    Substituting sensor data values inside web server text 
int readsens=analogRead(analogPin0)*Gain_A;

client.print("\n  y: [");
client.print(readsens5);
client.print(", "); 
client.print(readsens4);

client.print(", "); 
client.print(readsens3);

client.print(", "); 
client.print(readsens2);

client.print(", "); 
client.print(readsens);
readsens5=readsens4;
client.print("],");
readsens4=readsens3;
readsens3=readsens2;
readsens2=readsens;
//===============================================
           client.write(messagesp3);

          client.println();
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);

    // close the connection:
    client.stop();
   Serial.println("client disonnected");
  }
}


void printWifiStatus() {
// print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

// print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

Result is shown as Line chart.

Step 2: Using Javascript for Showing Charts and Gauges

I have used Plotly's JavaScript charting library to show charts and gauges. Plotly is the modern platform for agile business intelligence and data science.

What is plotly.js?
Built on top of d3.js and stack.gl, plotly.js is a high-level, declarative charting library. plotly.js ships with 20 chart types, including 3D charts, statistical graphs, and SVG maps. Learn about why we open sourced plotly.js or view the source on GitHub.

Step 3: Substituting Sensor Data in Web Server Text for a Gauge

Web site text is HTML with JavaScript inside, for example for showing a gauge html part is

HTML Part================================

<head>
  <!-- Plotly.js -->
  <script src="https://cdn.plot.ly/plotly-latest.min.j"></script>
</head>

<body>
  
  <div id="myDiv" style="width: 480px; height: 400px;">
<!-- Plotly chart will be drawn inside this DIV --></div>
  <script>
    <!-- JAVASCRIPT CODE GOES HERE -->
  </script>
</body>

JAVASCRIPT CODE ================================================

// Enter a speed between 0 and 180
var level = 175;

// Trig to calc meter point
var degrees = 180 - level,
     radius = .5;
var radians = degrees * Math.PI / 180;
var x = radius * Math.cos(radians);
var y = radius * Math.sin(radians);

// Path: may have to change to create a better triangle
var mainPath = 'M -.0 -0.025 L .0 0.025 L ',
     pathX = String(x),
     space = ' ',
     pathY = String(y),
     pathEnd = ' Z';
var path = mainPath.concat(pathX,space,pathY,pathEnd);

var data = [{ type: 'scatter',
   x: [0], y:[0],
    marker: {size: 28, color:'850000'},
    showlegend: false,
    name: 'speed',
    text: level,
    hoverinfo: 'text+name'},
  { values: [50/6, 50/6, 50/6, 50/6, 50/6, 50/6, 50],
  rotation: 90,
  text: ['TOO FAST!', 'Pretty Fast', 'Fast', 'Average',
            'Slow', 'Super Slow', ''],
  textinfo: 'text',
  textposition:'inside',
  marker: {colors:['rgba(14, 127, 0, .5)', 'rgba(110, 154, 22, .5)',
                         'rgba(170, 202, 42, .5)', 'rgba(202, 209, 95, .5)',
                         'rgba(210, 206, 145, .5)', 'rgba(232, 226, 202, .5)',
                         'rgba(255, 255, 255, 0)']},
  labels: ['151-180', '121-150', '91-120', '61-90', '31-60', '0-30', ''],
  hoverinfo: 'label',
  hole: .5,
  type: 'pie',
  showlegend: false
}];

var layout = {
  shapes:[{
      type: 'path',
      path: path,
      fillcolor: '850000',
      line: {
        color: '850000'
      }
    }],
  title: '<b>Gauge</b> <br> Speed 0-100',
  height: 1000,
  width: 1000,
  xaxis: {zeroline:false, showticklabels:false,
             showgrid: false, range: [-1, 1]},
  yaxis: {zeroline:false, showticklabels:false,
             showgrid: false, range: [-1, 1]}
};

Plotly.newPlot('myDiv', data, layout);

Resault is shown as Gauge

Step 4: Substituting Sensor Data in Web Server Text for a Line Chart

Just substitute javascript part inside HTML and include the sensor data as I did in Arduino sketch between lines 147 to 169. The complete we page text will be something like Image.

IoT Builders Contest

Participated in the
IoT Builders Contest

Arduino Contest 2016

Participated in the
Arduino Contest 2016