Have you ever wanted to have sensors scattered all around your house and garden reporting their temperature regularly to a central server? Then, this IoT project might be the solid launching point for you! This project uses ESP32 as the control device that easily connects to existing WiFi network & creates a Web Server. When any connected device accesses this web server, ESP32 reads in temperature & relative humidity from the DHT11, DHT22/AM2302 sensor & sends it to the web browser of that device with a nice interface. Excited? Let’s get started!
It may look intimidating, but there are a few concepts you should be familiar with, before venturing further into this tutorial. If any of the concepts below sound foreign to you, consider reading (at least skimming) through that tutorial first:
SUGGESTED READING
Problem with ESP32’s Internal Temperature Sensor
If you didn’t know, ESP32 comes with an internal temperature sensor having a range of -40°C to 125°C. The temperature sensor generates a voltage proportional to the temperature which is converted into digital form via an internal analog-to-digital converter.
As per ESP32 datasheet, the problem with this temperature sensor is that, the offset of the sensor varies from chip to chip due to process variation. Also the heat generated by the Wi-Fi circuitry affects temperature measurements. So, the internal temperature sensor is only suitable for applications that detect temperature changes instead of absolute temperatures.
However, you can achieve accurate results by calibrating the temperature sensor and using ESP32 in a minimally powered-on application to reduce CPU temperature. But the results will never be as accurate as with inexpensive temperature sensors like DHT11, DHT22/AM2302.
Wiring – Connecting DHT11, DHT22/AM2302 sensor to ESP32
Connecting DHT11/DHT22/AM2302 sensor to ESP32 is fairly simple. Start by placing the ESP32 on to your breadboard, ensuring each side of the board is on a separate side of the breadboard.
Now place the sensor on to your breadboard besides ESP32. Connect VCC pin on the sensor to the 3.3V pin on the ESP32 and ground to ground. Also connect Data pin of the sensor to D4 pin on the ESP32. Finally, we need to place a pull-up resistor of 10KΩ between VCC and data line to keep it HIGH for proper communication between sensor and MCU. If you happen to have a breakout board of the sensor, you need not add any external pull-up. It comes with a built-in pull-up resistor.
When you’re done you should have something that looks similar to the illustration shown below.
Installing DHT Sensor Library
Communicating with DHT11, DHT22/AM2302 sensors is a bunch of work, as they have their own single wire protocol for data transfer. And this protocol requires precise timing. Fortunately, we don’t have to worry much about this because we are going to use the DHT library from Adafruit which takes care of almost everything. The library is so powerful that it runs on both Arduino and ESP architecture.
To install the library navigate to the Sketch > Include Library > Manage Libraries… Wait for Library Manager to download libraries index and update list of installed libraries.
Filter your search by typing ‘DHT sensor’. There should be a couple entries. Look for DHT sensor library by Adafruit. Click on that entry, and then select Install.
The DHT sensor library uses the Adafruit Sensor support backend. So, search the library manager for Adafruit Unified Sensor and install that too (you may have to scroll a bit)
Create ESP32 Web Server using WiFi Station (STA) mode
Now let’s move on to the interesting stuff!
As the heading suggests, we are going to configure our ESP32 into Station (STA) mode, and create a web server to serve up web pages to any connected client under existing network.
Before you head for uploading the sketch, you need to make one change to make it work for you. You need to modify the following two variables with your network credentials, so that ESP32 can establish a connection with existing network.
const char* ssid = "YourNetworkName"; // Enter SSID here
const char* password = "YourPassword"; //Enter Password here
Once you are done, go ahead and try the sketch out and then we will dissect it in some detail.
#include <WiFi.h>
#include <WebServer.h>
#include "DHT.h"
// Uncomment one of the lines below for whatever DHT sensor type you're using!
//#define DHTTYPE DHT11 // DHT 11
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
/*Put your SSID & Password*/
const char* ssid = "YourNetworkName"; // Enter SSID here
const char* password = "YourPassword"; //Enter Password here
WebServer server(80);
// DHT Sensor
uint8_t DHTPin = 4;
// Initialize DHT sensor.
DHT dht(DHTPin, DHTTYPE);
float Temperature;
float Humidity;
void setup() {
Serial.begin(115200);
delay(100);
pinMode(DHTPin, INPUT);
dht.begin();
Serial.println("Connecting to ");
Serial.println(ssid);
//connect to your local wi-fi network
WiFi.begin(ssid, password);
//check wi-fi is connected to wi-fi network
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected..!");
Serial.print("Got IP: "); Serial.println(WiFi.localIP());
server.on("/", handle_OnConnect);
server.onNotFound(handle_NotFound);
server.begin();
Serial.println("HTTP server started");
}
void loop() {
server.handleClient();
}
void handle_OnConnect() {
Temperature = dht.readTemperature(); // Gets the values of the temperature
Humidity = dht.readHumidity(); // Gets the values of the humidity
server.send(200, "text/html", SendHTML(Temperature,Humidity));
}
void handle_NotFound(){
server.send(404, "text/plain", "Not found");
}
String SendHTML(float Temperaturestat,float Humiditystat){
String ptr = "<!DOCTYPE html> <html>\n";
ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
ptr +="<title>ESP32 Weather Report</title>\n";
ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n";
ptr +="p {font-size: 24px;color: #444444;margin-bottom: 10px;}\n";
ptr +="</style>\n";
ptr +="</head>\n";
ptr +="<body>\n";
ptr +="<div id=\"webpage\">\n";
ptr +="<h1>ESP32 Weather Report</h1>\n";
ptr +="<p>Temperature: ";
ptr +=(int)Temperaturestat;
ptr +="°C</p>";
ptr +="<p>Humidity: ";
ptr +=(int)Humiditystat;
ptr +="%</p>";
ptr +="</div>\n";
ptr +="</body>\n";
ptr +="</html>\n";
return ptr;
}
Accessing the Web Server
After uploading the sketch, open the Serial Monitor at a baud rate of 115200. And press the RESET button on ESP32. If everything is OK, it will output the dynamic IP address obtained from your router and show HTTP server started message.
Next, load up a browser and point it to the IP address shown on the serial monitor. The ESP32 should serve up a web page showing temperature and relative humidity.
Detailed Code Explanation
The sketch starts by including WiFi.h library. This library provides ESP32 specific WiFi methods we are calling to connect to network. Following that we also include the WebServer.h library, which has some methods available that will help us setting up a server and handle incoming HTTP requests without needing to worry about low level implementation details. Finally we include DHT.h library.
#include <WiFi.h>
#include <WebServer.h>
#include "DHT.h"
Next, we need to define the type of DHT sensor we are using. Uncomment one of the lines below accordingly!
//#define DHTTYPE DHT11 // DHT 11
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
As we are configuring ESP32 in Station (STA) mode, it will join existing WiFi network. Hence, we need to provide it with your network’s SSID & Password.
/*Put your SSID & Password*/
const char* ssid = "YourNetworkName"; // Enter SSID here
const char* password = "YourPassword"; //Enter Password here
Next, we declare an object of WebServer library, so we can access its functions. The constructor of this object takes port (where the server will be listening to) as a parameter. Since 80 is the default port for HTTP, we will use this value. Now you can access the server without needing to specify the port in the URL.
// declare an object of WebServer library
WebServer server(80);
Next, we need to define the ESP32’s pin number to which our sensor’s Data pin is connected and create a DHT object. So, that we can access special functions related to the DHT library.
// DHT Sensor
uint8_t DHTPin = 4;
// Initialize DHT sensor.
DHT dht(DHTPin, DHTTYPE);
Two float variables viz. Temperature & Humidity are declared to store respective values.
float Temperature;
float Humidity;
Inside Setup() Function
Inside Setup() Function we configure our HTTP server before actually running it. First of all, we open a serial connection for debugging purpose and set GPIO ports to INPUT. We also need to initialize the DHT object using begin()
function.
Serial.begin(115200);
delay(100);
pinMode(DHTPin, INPUT);
dht.begin();
Now, we need to join the WiFi network using WiFi.begin()
function. The function takes SSID (Network Name) and password as a parameter.
Serial.println("Connecting to ");
Serial.println(ssid);
//connect to your local wi-fi network
WiFi.begin(ssid, password);
While the ESP32 tries to connect to the network, we can check the connectivity status with WiFi.status() function.
//check wi-fi is connected to wi-fi network
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Once the ESP32 is connected to the network, the sketch prints the IP address assigned to ESP32 by displaying WiFi.localIP()
value on serial monitor.
Serial.println("");
Serial.println("WiFi connected..!");
Serial.print("Got IP: "); Serial.println(WiFi.localIP());
In order to handle incoming HTTP requests, we need to specify which code to execute when a URL is hit. To do so, we use on method. This method takes two parameters. First one is a URL path and second one is the name of function which we want to execute when that URL is hit.
The code below indicates that when a server receives an HTTP request on the root (/) path, it will trigger the handle_OnConnect
function. Note that the URL specified is a relative path.
server.on("/", handle_OnConnect);
We haven’t specified what the server should do if the client requests any URL other than specified with server.on. It should respond with an HTTP status 404 (Not Found) and a message for the user. We put this in a function as well, and use server.onNotFound
to tell it that it should execute it when it receives a request for a URI that wasn’t specified with server.on
server.onNotFound(handle_NotFound);
Now, to start our server, we call the begin method on the server object.
server.begin();
Serial.println("HTTP server started");
Inside Loop() Function
To handle the actual incoming HTTP requests, we need to call the handleClient()
method on the server object.
server.handleClient();
Next, we need to create a function we attached to root (/) URL with server.on. Remember? At the start of this function, we get the values of temperature and humidity from the sensor. In order to respond to the HTTP request, we use the send method. Although the method can be called with a different set of arguments, its simplest form consists of the HTTP response code, the content type and the content.
In our case, we are sending the code 200 (one of the HTTP status codes), which corresponds to the OK response. Then, we are specifying the content type as “text/html“, and finally we are calling SendHTML()
custom function which creates a dynamic HTML page containing values of temperature and humidity.
void handle_OnConnect()
{
Temperature = dht.readTemperature(); // Gets the values of the temperature
Humidity = dht.readHumidity(); // Gets the values of the humidity
server.send(200, "text/html", SendHTML(Temperature,Humidity));
}
Likewise, we need to create a function to handle 404 Error page.
void handle_NotFound(){
server.send(404, "text/plain", "Not found");
}
Displaying the HTML Web Page
SendHTML()
function is responsible for generating a web page whenever the ESP32 web server gets a request from a web client. It merely concatenates HTML code into a big string and returns to the server.send()
function we discussed earlier. The function takes values of temperature and humidity as a parameter to dynamically generate the HTML content.
The first text you should always send is the <!DOCTYPE> declaration that indicates that we’re sending HTML code.
String SendHTML(float Temperaturestat,float Humiditystat){
String ptr = "<!DOCTYPE html> <html>\n";
Next, the <meta> viewport element makes the web page responsive in any web browser, while title tag sets the title of the page.
ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
ptr +="<title>ESP32 Weather Report</title>\n";
Styling the Web Page
Next, we have some CSS to style the web page appearance. We choose the Helvetica font, define the content to be displayed as an inline-block and aligned at the center.
ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
Following code then sets color, font and margin around the body, H1 and p tags.
ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n";
ptr +="p {font-size: 24px;color: #444444;margin-bottom: 10px;}\n";
ptr +="</style>\n";
ptr +="</head>\n";
ptr +="<body>\n";
Setting the Web Page Heading
Next, heading of the web page is set; you can change this text to anything that suits your application.
ptr +="<div id=\"webpage\">\n";
ptr +="<h1>ESP32 Weather Report</h1>\n";
Displaying Temperature and Humidity on Web Page
To dynamically display values of Temperature & humidity, we put those values in paragraph tag. These values are converted to integer by type casting. To display degree symbol, we use HTML entity °
ptr +="<p>Temperature: ";
ptr +=(int)Temperaturestat;
ptr +="°C</p>";
ptr +="<p>Humidity: ";
ptr +=(int)Humiditystat;
ptr +="%</p>";
ptr +="</div>\n";
ptr +="</body>\n";
ptr +="</html>\n";
return ptr;
}
Styling Web Page to Look More Professional
Programmers like us are often intimidated by design – but a little effort can make your web page look more attractive and professional. Below screenshot will give you a basic idea of what we are going to do.
Pretty amazing, Right? Without further ado, let’s apply some style to our previous HTML page. To start with, copy-paste below code to replace SendHTML()
function from the sketch above. Try the new sketch out and then we will do its detailed breakdown.
String SendHTML(float TempCstat,float TempFstat,float Humiditystat){
String ptr = "<!DOCTYPE html> <html>\n";
ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
ptr +="<link href=\"https://fonts.googleapis.com/css?family=Open+Sans:300,400,600\" rel=\"stylesheet\">\n";
ptr +="<title>ESP32 Weather Report</title>\n";
ptr +="<style>html { font-family: 'Open Sans', sans-serif; display: block; margin: 0px auto; text-align: center;color: #333333;}\n";
ptr +="body{margin-top: 50px;}\n";
ptr +="h1 {margin: 50px auto 30px;}\n";
ptr +=".side-by-side{display: inline-block;vertical-align: middle;position: relative;}\n";
ptr +=".humidity-icon{background-color: #3498db;width: 30px;height: 30px;border-radius: 50%;line-height: 36px;}\n";
ptr +=".humidity-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\n";
ptr +=".humidity{font-weight: 300;font-size: 60px;color: #3498db;}\n";
ptr +=".temperature-icon{background-color: #f39c12;width: 30px;height: 30px;border-radius: 50%;line-height: 40px;}\n";
ptr +=".temperature-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\n";
ptr +=".temperature{font-weight: 300;font-size: 60px;color: #f39c12;}\n";
ptr +=".superscript{font-size: 17px;font-weight: 600;position: absolute;right: -20px;top: 15px;}\n";
ptr +=".data{padding: 10px;}\n";
ptr +="</style>\n";
ptr +="</head>\n";
ptr +="<body>\n";
ptr +="<div id=\"webpage\">\n";
ptr +="<h1>ESP32 Weather Report</h1>\n";
ptr +="<div class=\"data\">\n";
ptr +="<div class=\"side-by-side temperature-icon\">\n";
ptr +="<svg version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n";
ptr +="width=\"9.915px\" height=\"22px\" viewBox=\"0 0 9.915 22\" enable-background=\"new 0 0 9.915 22\" xml:space=\"preserve\">\n";
ptr +="<path fill=\"#FFFFFF\" d=\"M3.498,0.53c0.377-0.331,0.877-0.501,1.374-0.527C5.697-0.04,6.522,0.421,6.924,1.142\n";
ptr +="c0.237,0.399,0.315,0.871,0.311,1.33C7.229,5.856,7.245,9.24,7.227,12.625c1.019,0.539,1.855,1.424,2.301,2.491\n";
ptr +="c0.491,1.163,0.518,2.514,0.062,3.693c-0.414,1.102-1.24,2.038-2.276,2.594c-1.056,0.583-2.331,0.743-3.501,0.463\n";
ptr +="c-1.417-0.323-2.659-1.314-3.3-2.617C0.014,18.26-0.115,17.104,0.1,16.022c0.296-1.443,1.274-2.717,2.58-3.394\n";
ptr +="c0.013-3.44,0-6.881,0.007-10.322C2.674,1.634,2.974,0.955,3.498,0.53z\"/>\n";
ptr +="</svg>\n";
ptr +="</div>\n";
ptr +="<div class=\"side-by-side temperature-text\">Temperature</div>\n";
ptr +="<div class=\"side-by-side temperature\">";
ptr +=(int)TempCstat;
ptr +="<span class=\"superscript\">°C</span></div>\n";
ptr +="</div>\n";
ptr +="<div class=\"data\">\n";
ptr +="<div class=\"side-by-side humidity-icon\">\n";
ptr +="<svg version=\"1.1\" id=\"Layer_2\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n\"; width=\"12px\" height=\"17.955px\" viewBox=\"0 0 13 17.955\" enable-background=\"new 0 0 13 17.955\" xml:space=\"preserve\">\n";
ptr +="<path fill=\"#FFFFFF\" d=\"M1.819,6.217C3.139,4.064,6.5,0,6.5,0s3.363,4.064,4.681,6.217c1.793,2.926,2.133,5.05,1.571,7.057\n";
ptr +="c-0.438,1.574-2.264,4.681-6.252,4.681c-3.988,0-5.813-3.107-6.252-4.681C-0.313,11.267,0.026,9.143,1.819,6.217\"></path>\n";
ptr +="</svg>\n";
ptr +="</div>\n";
ptr +="<div class=\"side-by-side humidity-text\">Humidity</div>\n";
ptr +="<div class=\"side-by-side humidity\">";
ptr +=(int)Humiditystat;
ptr +="<span class=\"superscript\">%</span></div>\n";
ptr +="</div>\n";
ptr +="</div>\n";
ptr +="</body>\n";
ptr +="</html>\n";
return ptr;
}
We already know that <!DOCTYPE> declaration tells the browser we’re sending HTML code and the <meta> viewport element makes the web page responsive. The only addition here is we are going to use google fonts. Google has hundreds of web fonts and are free for commercial and personal use. Perfect!
We will use Google commissioned Open Sans web font for our web page. Google font is embedded using link tag in <head> of your HTML document. We have selected 300 (Light), 400 (Regular) & 600 (bold) font weight for our page. You can select as many as you want but keep in mind that selecting unnecessary font weights hamper page load time. You can also add italic style by just adding i character at the end of font weight e.g. 400i will embed italic style.
Note that you cannot see Google font, without active internet connection on the device, you are going to access this page. Google fonts are loaded on the fly.
String SendHTML(float TempCstat,float TempFstat,float Humiditystat){
String ptr = "<!DOCTYPE html> <html>\n";
ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
ptr +="<link href=\"https://fonts.googleapis.com/css?family=Open+Sans:300,400,600\" rel=\"stylesheet\">\n";
Next, we are going to apply ‘Open Sans’ font for our whole HTML. We also need to specify sans-serif as our fallback font, to ensure maximum compatibility between browsers/operating systems. If the browser does not support the first font, it tries the next font.
ptr +="<title>ESP32 Weather Report</title>\n";
ptr +="<style>html { font-family: 'Open Sans', sans-serif; display: block; margin: 0px auto; text-align: center;color: #333333;}\n";
ptr +="body{margin-top: 50px;}\n";
ptr +="h1 {margin: 50px auto 30px;}\n";
Next, we need to apply CSS for Humidity & Temperature – icons, titles and actual values. All these three things are made inline and aligned vertical. Background of icons is made circle using 50% border radius and made 30px height and width.
ptr +=".side-by-side{display: inline-block;vertical-align: middle;position: relative;}\n";
ptr +=".humidity-icon{background-color: #3498db;width: 30px;height: 30px;border-radius: 50%;line-height: 36px;}\n";
ptr +=".humidity-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\n";
ptr +=".humidity{font-weight: 300;font-size: 60px;color: #3498db;}\n";
ptr +=".temperature-icon{background-color: #f39c12;width: 30px;height: 30px;border-radius: 50%;line-height: 40px;}\n";
ptr +=".temperature-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\n";
ptr +=".temperature{font-weight: 300;font-size: 60px;color: #f39c12;}\n";
ptr +=".superscript{font-size: 17px;font-weight: 600;position: absolute;right: -20px;top: 15px;}\n";
ptr +=".data{padding: 10px;}\n";
ptr +="</style>\n";
ptr +="</head>\n";
ptr +="<body>\n";
The temperature icon is actually a Scalable Vector Graphics (SVG) defined in <svg> tag. Creating SVG doesn’t require any special programming skills. You can use Google SVG Editor for creating graphics for your page. After the icon, we are going to show the actual value of temperature from the sensor.
ptr +="<div id=\"webpage\">\n";
ptr +="<h1>ESP32 Weather Report</h1>\n";
ptr +="<div class=\"data\">\n";
ptr +="<div class=\"side-by-side temperature-icon\">\n";
ptr +="<svg version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n";
ptr +="width=\"9.915px\" height=\"22px\" viewBox=\"0 0 9.915 22\" enable-background=\"new 0 0 9.915 22\" xml:space=\"preserve\">\n";
ptr +="<path fill=\"#FFFFFF\" d=\"M3.498,0.53c0.377-0.331,0.877-0.501,1.374-0.527C5.697-0.04,6.522,0.421,6.924,1.142\n";
ptr +="c0.237,0.399,0.315,0.871,0.311,1.33C7.229,5.856,7.245,9.24,7.227,12.625c1.019,0.539,1.855,1.424,2.301,2.491\n";
ptr +="c0.491,1.163,0.518,2.514,0.062,3.693c-0.414,1.102-1.24,2.038-2.276,2.594c-1.056,0.583-2.331,0.743-3.501,0.463\n";
ptr +="c-1.417-0.323-2.659-1.314-3.3-2.617C0.014,18.26-0.115,17.104,0.1,16.022c0.296-1.443,1.274-2.717,2.58-3.394\n";
ptr +="c0.013-3.44,0-6.881,0.007-10.322C2.674,1.634,2.974,0.955,3.498,0.53z\"/>\n";
ptr +="</svg>\n";
ptr +="</div>\n";
ptr +="<div class=\"side-by-side temperature-text\">Temperature</div>\n";
ptr +="<div class=\"side-by-side temperature\">";
ptr +=(int)TempCstat;
ptr +="<span class=\"superscript\">°C</span></div>\n";
ptr +="</div>\n";
Again it’s a SVG. After printing humidity values, we are going to end all the open tags like body and html.
ptr +="<div class=\"data\">\n";
ptr +="<div class=\"side-by-side humidity-icon\">\n";
ptr +="<svg version=\"1.1\" id=\"Layer_2\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n\"; width=\"12px\" height=\"17.955px\" viewBox=\"0 0 13 17.955\" enable-background=\"new 0 0 13 17.955\" xml:space=\"preserve\">\n";
ptr +="<path fill=\"#FFFFFF\" d=\"M1.819,6.217C3.139,4.064,6.5,0,6.5,0s3.363,4.064,4.681,6.217c1.793,2.926,2.133,5.05,1.571,7.057\n";
ptr +="c-0.438,1.574-2.264,4.681-6.252,4.681c-3.988,0-5.813-3.107-6.252-4.681C-0.313,11.267,0.026,9.143,1.819,6.217\"></path>\n";
ptr +="</svg>\n";
ptr +="</div>\n";
ptr +="<div class=\"side-by-side humidity-text\">Humidity</div>\n";
ptr +="<div class=\"side-by-side humidity\">";
ptr +=(int)Humiditystat;
ptr +="<span class=\"superscript\">%</span></div>\n";
ptr +="</div>\n";
ptr +="</div>\n";
ptr +="</body>\n";
ptr +="</html>\n";
return ptr;
}
Improvement to the Code – Auto Page Refresh
One of the improvements you can do with our code is refreshing the page automatically in order to update the sensor value.
With the addition of a single meta tag into your HTML document, you can instruct the browser to automatically reload the page at a provided interval.
<meta http-equiv="refresh" content="2" >
Place this code in the the <head> tag of your document, this meta tag will instruct the browser to refresh every two seconds. Pretty nifty!
Dynamically load Sensor Data with AJAX
Refreshing a web page isn’t too practical if you have a heavy web page. A better method is to use Asynchronous Javascript And Xml (AJAX) so that we can request data from the server asynchronously (in the background) without refreshing the page.
The XMLHttpRequest object within JavaScript is commonly used to execute AJAX on webpages. It performs the silent GET request on the server and updates the element on the page. AJAX is not a new technology, or different language, just existing technologies used in new ways. Besides this, AJAX also makes it possible to
- Request data from a server after the page has loaded
- Receive data from a server after the page has loaded
- Send data to a server in the background
Here is the AJAX script that we’ll be using. Place this script just before you close </head> tag.
ptr +="<script>\n";
ptr +="setInterval(loadDoc,200);\n";
ptr +="function loadDoc() {\n";
ptr +="var xhttp = new XMLHttpRequest();\n";
ptr +="xhttp.onreadystatechange = function() {\n";
ptr +="if (this.readyState == 4 && this.status == 200) {\n";
ptr +="document.getElementById(\"webpage\").innerHTML =this.responseText}\n";
ptr +="};\n";
ptr +="xhttp.open(\"GET\", \"/\", true);\n";
ptr +="xhttp.send();\n";
ptr +="}\n";
ptr +="</script>\n";
The script starts with <script> tag, as AJAX script is nothing but a javascript so, we need to write it in <script> tag. In order for this function to be repeatedly called, we will be using the javascript setInterval() function. It takes two parameters – a function to be executed and time interval (in milliseconds) on how often to execute the function.
ptr +="<script>\n";
ptr +="setInterval(loadDoc,200);\n";
The heart of this script is a loadDoc()
function. Inside this function, an XMLHttpRequest()
object is created. This object is used to request data from a web server.
ptr +="function loadDoc() {\n";
ptr +="var xhttp = new XMLHttpRequest();\n";
The xhttp.onreadystatechange()
function is called every time the readyState changes. The readyState property holds the status of the XMLHttpRequest. It has one of the following values.
- 0: request not initialized
- 1: server connection established
- 2: request received
- 3: processing request
- 4: request finished and response is ready
The status property holds the status of the XMLHttpRequest object. It has one of the following values.
- 200: “OK”
- 403: “Forbidden”
- 404: “Page not found”
When readyState is 4 and status is 200, the response is ready. Now, the content of element with id webpage (div holding values of temperature & humidity) is updated.
ptr +="xhttp.onreadystatechange = function() {\n";
ptr +="if (this.readyState == 4 && this.status == 200) {\n";
ptr +="document.getElementById(\"webpage\").innerHTML =this.responseText}\n";
ptr +="};\n";
The HTTP request is then initiated via the open() and send() functions.
ptr +="xhttp.open(\"GET\", \"/\", true);\n";
ptr +="xhttp.send();\n";
ptr +="}\n";