Hello readers, I hope you all are doing great. In this tutorial, we will learn how to update a webpage using Server-Sent Events and the ESP32 web server.
What is Server-Sent Events (SSE)?
It is a server push technology that enables the client devices to receive automatic updates from a server over HTTP (Hypertext Transfer Protocol) connection. SSE also describes how the server can initiate data transmission towards the client once an initial connection with the client has been established.
We have already posted a tutorial on how to implement Web socket protocol with ESP32 which is also a protocol used to notify events to a web client. Both the Server-Sent Events (SSE) and Web-Socket technologies seem to be quite similar but they are not.
The major difference between the two is that SSE is unidirectional, where the web client can only receive the updates from the ESP32 but it can’t send updates back to ESP32. On the other hand, the Web-socket protocol is bi-directional where both the web client and ESP32 can send and receive updates/events.
Fig. 1 Server-Sent event
How does the Server-Sent Event works?
The Server-Sent Event process initiates with an HTTP request from the web client or web page to the ESP32 web server. After that, the ESP32 is ready to send updates or events to the web client as they happen. But the web client can’t send any response or data to the ESP32 server after the initial handshake takes place.
Server-sent event technology can be used to communicate an event, GPIO states or to send sensor readings to the web client, whenever a new reading is observed.
Project Overview
For demonstration purpose, we are using a DHT11 sensor with the ESP32 module. ESP32 web server will display two things i.e., temperature and humidity observed using the DHT11 sensor. So, whenever a new reading is being observed, the ESP32 sends the reading to the Web Client over Server-sent events. After receiving the latest sensor reading the client updates the web page data.
Software and Hardware requirements
- ESP32 development board
- DHT11 sensor
- Connecting Wires
- Breadboard
- Arduino IDE
- Necessary Libraries
DHT11 (a Temperature and Humidity sensor)
Fig. 2 DHT11 sensor
DHT11 is a humidity and temperature sensor that measures its surrounding environment. It measures the temperature and humidity in a given area. It is made up of an NTC (negative temperature co-efficient) temperature sensor and a resistive humidity sensor. It also has an 8-bit microcontroller. The microcontroller is in charge of ADC (analog to digital conversion) and provides a digital output over the single wire protocol.
The DHT11 sensor can measure humidity from 20% to 90% with +-5 percent accuracy (RH or relative humidity) and temperature from 0 degrees Celsius to 50 degrees Celsius with +-2C accuracy.
DHT11 sensors can also be used to build a wired sensor network with a cable length of up to 20 meters.
Interfacing DHT11 with ESP32 module
Table 1
Note: Connect a 10K resistor between data and power (+5V) pin of DHT11 sensor module.
Fig. 3 ESP32 and DHT11 connections/wiring
Programming with Arduino IDE
We are using Arduino IDE to compile and upload code into the ESP32 module. You must have ESP32 board manager installed on your Arduino IDE to program the ESP32 module. To know more about Arduino IDE and how to use it, follow our previous tutorial i.e., on ESP32 programming series. The link is given below:
https://www.theengineeringprojects.com/2021/11/introduction-to-esp32-programming-series.html
Steps to add the necessary libraries in Arduino IDE:
- Go to Tools >> Manage Libraries.
Fig. 4 manage libraries
- Search for the necessary library in Library Manager and click Install.
- We are attaching an image, where we are installing the DHT11 sensor library.
Fig. 5 Install DHT sensor library
- Follow the similar procedure for rest of the libraries.
- After successfully installing all the required libraries close the Library Manager tab.
ESP32 board manager doesn’t come with inbuilt libraries to create an asynchronous web server. So we need to download the library file from external sources and then add into Arduino IDE.
We need to install two library files:
- ESPAsynWebServer: Follow the link https://github.com/me-no-dev/ESPAsyncWebServer to download the respective library.
- AsyncTCP: You can download the AsyncTCP library from the following link https://github.com/me-no-dev/AsyncTCP
Once you have successfully downloaded the required libraries, next step it to install or add these libraries in Arduino IDE.
To add the libraries in Arduino IDE, go to Sketch >> Include Library >> Add .zip library and then select the downloaded library files.
Fig. 6 adding necessary libraries
Arduino Code
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include “DHT.h”
#define DHTPIN 4 // Digital pin connected to the DHT sensor
#define DHTTYPE DHT11 // DHT 11
// Initializing the DHT11 sensor.
DHT dht(DHTPIN, DHTTYPE);
// Replace with your network credentials
const char* ssid = “SSID”;
const char* password = “password”;
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
// Create an Event Source on /events
AsyncEventSource events(“/events”);
// Timer variables
unsigned long lastTime = 0;
unsigned long timerDelay = 20000; //20 sec timer delay
//==== Creating web page
const char index_html[] PROGMEM = R”rawliteral(
<!DOCTYPE HTML><html>
<head>
<title>SSE with ESP32 Web Server</title>
<meta name=”viewport” content=”width=device-width, initial-scale=1″>
<link rel=”stylesheet” href=”https://ift.tt/DQ8Ignj; integrity=”sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr” crossorigin=”anonymous”>
<link rel=”icon” href=”data:,”>
<style>
html {font-family: Times New Roman; display: inline-block; text-align: justify;}
p { font-size: 1.2rem;}
body { margin: 0;}
.topnav { overflow: hidden; background-color: blue; color: white; font-size: 1rem; }
.content { padding: 20px; }
.card { background-color: #ADD8E6; box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5); }
.cards { max-width: 600px; margin: 0 auto; display: grid; grid-gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.reading { font-size: 1.4rem; }
</style>
</head>
<body>
<div class=”topnav”>
<h1>Server-Sent Events </h1>
<h2> DHT11 Sensor Data </h2>
</div>
<div class=”content”>
<div class=”cards”>
<div class=”card”>
<p> DHT11 Temperature</p><p><span class=”reading”><span id=”temp”>%TEMPERATURE%</span> °C</span></p>
</div>
<div class=”card”>
<p> DHT11 Humidity</p><p><span class=”reading”><span id=”hum”>%HUMIDITY%</span> %</span></p>
</div>
</div>
</div>
<script>
if (!!window.EventSource)
{
var source = new EventSource(‘/events’);
source.addEventListener(‘open’, function(e)
{
console.log(“Events Connected”);
}, false);
source.addEventListener(‘error’, function(e)
{
if (e.target.readyState != EventSource.OPEN)
{
console.log(“Events Disconnected”);
}
}, false);
source.addEventListener(‘message’, function(e)
{
console.log(“message”, e.data);
}, false);
source.addEventListener(‘temperature’, function(e)
{
console.log(“temperature”, e.data);
document.getElementById(“temp”).innerHTML = e.data;
}, false);
source.addEventListener(‘humidity’, function(e)
{
console.log(“humidity”, e.data);
document.getElementById(“hum”).innerHTML = e.data;
}, false);
}
</script>
</body>
</html>)rawliteral”;
void setup() {
Serial.begin(115200); //initialize serial monitor
//===set and initialize Wi-Fi
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.print(“Connecting to WiFi ..”);
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(‘.’);
delay(1000);
}
Serial.print(“IP Address: “);
Serial.println(WiFi.localIP()); // print the IP address
//====Initialize DHT11 sensor
dht.begin();
//====Handle Web Server
server.on(“/”, HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, “text/html”, index_html);
});
// Handle Web Server Events
events.onConnect([](AsyncEventSourceClient *client)
{
if(client->lastId())
{
Serial.printf(“Client reconnected! Last message ID that it got is: %u\n”,
client->lastId());
}
// send event with message “hello!”, id current millis
// and set reconnect delay to 1 second
client->send(“hello!”, NULL, millis(), 10000);
});
server.addHandler(&events);
server.begin();
}
void loop()
{
delay(2000);
float humidity = dht.readHumidity();
// Read temperature as Celsius (the default)
float temperature = dht.readTemperature();
// Check if any reads failed and exit early (to try again).
if (isnan(humidity) || isnan(temperature))
{
Serial.println(F(“Failed to read from DHT sensor!”));
return;
}
if ((millis() – lastTime) > timerDelay)
{
// Send Events to the Web Server with the Sensor Readings
events.send(“ping”,NULL,millis());
events.send(String(temperature).c_str(),”temperature”,millis());
events.send(String(humidity).c_str(),”humidity”,millis());
Serial.print(F(“Humidity(%): “));
Serial.println(humidity);
Serial.print(F(“Temp.: “));
Serial.print(temperature);
Serial.println(F(“°C “));
}
}
Code Description
- Here we are using four libraries:
- The first one is WiFi.h, which is used to enable the Wi-Fi module and hence wireless network connectivity.
- DHT.h is used to call the necessary functions required to interface DHT sensor with ESP32.
- ESPAsynchWenServer library file is responsible for creating an asynchronous web server.
- AsyncTCP is used to enable multi-connection network for ESP32 (Espressif’s) microcontroller unit.
Fig. 7 Header files
- Next step is the declaration of variables for DHT11 sensor.
- We are declaring 2 variables, the first one is the DHTPIN to store the GPIO number receiving input from DHT11 sensor and another variables is to define the type of DHT (i.e., whether DHT11 or DHT22).
Fig. 8 Global declarations
- Next we are creating a DHT object called dht in the DHT sensor type (defined earlier) and the DHT pin.
Fig. 9
- Enter the network credentials in place of SSID and PASSWORD.
Fig. 10 Enter Network credentials
- While creating a web server we also need to assign a port and usually port 80 is used for local web server.
Fig. 11 Server port
- Next step is creating a new event source(on /events).
Fig. 12 Event source
- Timer variable declaration: the timerDelay and lastTime variables are declared to add delay using timer, instead of using delay() function. Here we are adding a delay of 20 seconds which means the web browser will be updated with new sensor reading in every 20 sec.
Fig. 13 Timer Variables
Creating the Web Page
- !DOCTYPE html><html> is used to describe/indicate that we are transmitting HTML, this command should always be the first thing we send.
- <title> tag is used to write title for the web page.
Fig. 14
- The <style> tag is used to style the webpage, which includes the type of font, alignment, display, color, dimensions etc. You can make changes in the <style> tag as per your requirements.
Fig. 15
- The content, which is to be displayed on the Web page is written inside the <body> tag. The <body> tag includes two headings h1 and h2 and sensor readings (temperature and humidity).
Fig. 16
Initializing an Event-Source connection
- JavaScript is written inside the inside the <script> tag, which is responsible for initializing an event source connection with the web server and also to handle the events received from the web server.
- An object EventSource is created and along with that the URL of the webpage sending the updates is also specified.
- addEventListener() function is used to listen to the messages coming from the web server, once the event source is initiated successfully.
Fig. 17
- Next task is adding an event listener for Whenever a new temperature reading is observed from the DHT11 sensor, ESP32 sends a “temperature” event to the web client.
Fig. 18
- Similarly, another event is generated for It prints the latest readings on the web browser & puts the received data into the element with respective ID on the webpage.
Fig. 19
Setup
- Initialize the serial monitor at a 115200 baud rate for debugging purposes.
- begin() function is used to initialize the Wi-Fi module with Wi-Fi credentials used as arguments.
- The While loop will continuously run until the ESP32 is connected to the Wi-Fi network.
Fig. 20
- If the device is connected to a local Wi-Fi network then print the details on the serial monitor.
- localIP() function is used to fetch the IP address.
- Print the IP address on the serial monitor using println() function.
Fig. 21 Fetch/obtain the IP address
Fig. 22 Initialize DHT sensor
Handling HTTP GET requests
- The next part in the programming includes handling HTTP GET requests.
- When we access the route URL, we send the web page to the client along with the data input fields.
- We have defined a variable namely index_html to save the HTML text.
Fig. 23
Handling Server Event source
- The next task is setting up the event source on the webserver.
Fig. 24 Handling server events
Initializing web server
- Initialize the webserver using begin() function.
Fig. 24 initializing web server
Loop()
- DHT11 is a very slow sensor. It takes almost 250ms to read temperature and humidity.
- So it is preferred to wait a few seconds before a new measurement or updated sensor reading.
- Next, we are defining a float type variable ‘h’ to store humidity measured from the DHT11 sensor.
- readHumidity() function is used to observe the humidity value.
- readTemperature() function is used to read the surrounding temperature with the DHT11 sensor.
Fig. 25
- If somehow the sensor fails to read or observer temperature and humidity values, then the respective results will be printed on the serial monitor.
Fig. 26 If error occurs while reading data from DHT11
Sending Events to the server
- Send the updated events or the latest observation from the DHT11 sensor the web browser over the local network.
- The sensor readings will be updated in every 20 second as per the code instructions.
Fig. 27 Sending events to the server
- Print the temperature and humidity readings (observer form the DHT11 sensor) on the Serial monitor.
Fig. 28 Print Sensor data on the Serial monitor
Testing
- Open your Arduino IDE and paste the above code.
- Change the network credentials, that is the SSID and PASSWORD as per you network setup.
- Compile and upload the code into ESP32 development board.
- Before uploading the code make sure that you have selected the correct development board and COM port.
Fig. 29 Select development board and COM port
- Once the code is uploaded successfully, open the Serial monitor and select the 1115200 baud rate (as per your code instructions).
- Make sure Wi-Fi to which your ESP device is supposed to connect is ON.
- Once your ESP32 is connected to the internet, the IP address of the device will be printed on the Serial monitor.
- Copy the IP address.
- Open the browser and paste the IP address and press
- A web page will appear, as shown below:
Fig. 30
- The web page will be updated with new data every 20 seconds, as per the code instructions and we do not even need to refresh the web page for latest event updates due to SSE technology.
Fig. 31
This concludes the tutorial. I hope you found this of some help and also hope to see you soon with a new tutorial on ESP32.
JLCPCB – Prototype 10 PCBs for $2 (For Any Color)
China’s Largest PCB Prototype Enterprise, 600,000+ Customers & 10,000+ Online Orders Daily
How to Get PCB Cash Coupon from JLCPCB: https://bit.ly/2GMCH9w
The post Server-Sent Events with ESP32 and DHT11 appeared first on The Engineering Projects.
No comments:
Post a Comment