ESP32 Server-Sent Events (SSE) Web Server (Arduino IDE)

In this user guide, we will learn how to create an ESP32 Server-Sent Events (SSE) web server using the Arduino IDE. With this technique, we will build an ESP32-controlled web server that automatically updates sensor readings, such as temperature, pressure, and humidity, to all connected web clients. The clients will receive these updates from the ESP32 board via SSE through an HTTP connection. This feature is highly useful as it allows new sensor readings to be sent to the web client automatically whenever they become available, without the need for additional requests. Consequently, the webpage will update spontaneously.

You can use any suitable sensor, such as DS18B20, BME680, LM35, or MPU6050, for this project. However, for the purpose of this article, we will use a BME280 sensor, which measures temperature, pressure, and humidity.

We have a similar guide with ESP8266 NodeMCU:

ESP8266 NodeMCU Server-Sent Events (SSE) Web Server (Arduino IDE)

Server-Sent Events (SSE) Server Introduction

A Server-Sent Event (SSE) server is a web server that provides a real-time communication mechanism between the server and the client over a single HTTP connection. SSE is a web technology that allows the server to push updates to connected clients, enabling real-time data streaming from the server to the web browser without the need for the client to constantly poll or request updates.

Server-Sent Events also known as SSE is a protocol whereby clients receive automatically updated data from a server through an HTTP connection whenever something changes on the server side. It involves an initial handshake between the client and server. The SSE connection is started from the client’s side and the server uses EventSource to update the client accordingly.

How SSE Works?

In a previous article, we built an ESP web server through WebSocket protocol (ESP32 WebSocket Server using Arduino IDE – Control GPIOs and Relays). In that web server, all the connected clients (smartphones, tablets, computers, laptops, etc.) were updated instantaneously whenever a change occurred. This time, however, we will look at a different way to notify events to our client through SSE protocol. One of the major differences between the two protocols is that whereas WebSocket has bi-directional server-client transmission, in Server-Sent Events only the server (ESP32) can send updates to the client and not vice-versa. Hence SSE follows one-way communication only after the initial handshake. This can be seen in the diagram below:

SSE protocol

Client-Side Setup: The web client (usually a browser) establishes a connection to the SSE server using the JavaScript EventSource API.

Server-Side Setup: On the server side, the SSE server sends data to the connected clients through an HTTP response. The response uses the MIME type “text/event-stream” to indicate that it contains event stream data.

Event Stream Data: The data sent from the server to the client is formatted as a series of events. Each event consists of a data field, which contains the actual payload, and an optional event name field that categorizes the event.

Continuous Connection: Unlike traditional HTTP requests, the SSE connection remains open for a long duration, allowing the server to send updates whenever new data is available. The connection stays open until either the client or the server decides to close it.

Automatic Updates: As the server pushes data to the client, the client’s JavaScript code can handle these updates and update the web page in real time, displaying the latest information.

Note: Make sure you use a web browser which supports SSE. For more information about compatible browsers follow the link for further information: Link

ESP32 Server-Sent Events Web Server Project Overview

We will create a web server based on the Server-Sent Events (SSE) protocol. It will consist of a title, “ESP32 & BME280 SSE Web server,” and three boxes each for temperature, pressure, and humidity. Each box will contain a heading and its value underneath it. We aim to build a webpage that will display sensor readings obtained from BME280 connected with the ESP32 module. This transmission of data from the server (ESP32) to the client (web page) will occur through Server-Sent Events. These readings will automatically update after every 30 seconds to new values when the web page receives them. Through SSE protocol, it will be very easy to update the sensor readings on our web page without adding any additional requests.

ESP32 and BME280 SSE Web server

Working Process

  1. The client starts the SSE connection. It sends an HTTP request to the ESP32 module. This will cause the module to send events to the web page.
  2. ESP32 connected with BME280 receives sensor readings after every 30 seconds.
  3. These readings are marked as ‘events’ of the following names: ‘temperature’, ‘pressure’, and ‘humidity’.
  4. These events sent by the module have event listeners associated with them on the client side. All the updated readings are received by the client on the said events.
  5. As in the case with SSE, only the ESP32 board will be able to send events to the webpage. The web page gets updated accordingly and the process continues.
ESP32 and BME280 server sent events Web server working process
Working Process

Connecting BME280 sensor with the ESP32 development board

The BME280 sensor is used to measure readings regarding ambient temperature, barometric pressure, and relative humidity. It is mostly used in web and mobile applications where low power consumption is key. This sensor uses I2C or SPI to communicate data with the microcontrollers. Although there are several different versions of BME280 available in the market, the one we will be studying uses the I2C communication protocol and SPI.

Recommended Readings:

Schematic Diagram

The connection of BME280 with the ESP32 boards is very easy. We have to connect the VCC terminal with 3.3V, ground with the ground (common ground), SCL of the sensor with SCL of the module, and SDA of the sensor with the SDA pin of the ESP modules.

The I2C pin in ESP32 for SDA is GPIO21 and for SCL is GPIO22.

Required Components:

We will need the following components to connect our ESP32 board with the BME280 sensor.

  • ESP32 board
  • BME280 Sensor
  • Connecting Wires
  • Breadboard

Follow the schematic diagram below for the ESP32 module and connect them accordingly.

BME280 with ESP32 MicroPython
Connection Diagram

In some BME280 sensors as seen in the above connection diagram, the SCK terminal means the SCL pin and is connected with its respective GPIO pin on the ESP board. Likewise, the SDI terminal means the SDA pin and is connected with its respective GPIO pin on the board. Vin is connected with a 3.3V pin on the module and both the ESP board and the sensor is commonly grounded.

Setting up Arduino IDE

We will use Arduino IDE to program our ESP32 development board. Thus, you should have the latest version of Arduino IDE. Additionally, you also need to install the ESP32 plugin.

If your IDE does not have the plugin installed you can visit the link below: Installing ESP32 library in Arduino IDE and upload code.

Installing BME280 Libraries

As we are connecting the BME280 sensor with ESP32 so we will have to install BME280 libraries to our module. We will require two libraries for this project:

  1. Adafruit BME280 library
  2. Adafruit Unified Sensor library

We will use the Library Manager in our Arduino IDE to install the latest versions of the libraries. Open your Arduino IDE and go to Sketch > Include Libraries > Manage Libraries. Type each library name in the search bar and install them both.

Adafruit BME280 library Arduino IDE
Adafruit unified sensor library install

Installing ESPAsyncWebServer Library and Async TCP Library

We will need two additional libraries to build our web server. The ESPAsyncWebServer library will help us in creating our web server easily. With this library, we will set up an asynchronous HTTP server. AsyncTCP is another library that we will be incorporating as it a dependency for the ESPAsyncWebServer library. Both of these libraries are not available in the Arduino library manager so we will have to download and load them in our ESP32 board ourselves.

  • To install the ESPAsyncWebServer library for free, click here to download. You will download the library as a .zip folder which you will extract and rename as ‘ESPAsyncWebServer.’ Then, transfer this folder to the installation library folder in your Arduino IDE.
  • To install the Async TCP library for free, click here to download. You will download the library as a .zip folder which you will extract and rename as ‘AsyncTCP.’ Then, transfer this folder to the installation library folder in your Arduino IDE.

Likewise, you can also go to Sketch > Include Library > Add .zip Library inside the IDE to add the libraries as well. After installation of the libraries, restart your IDE.

ESP32 Server-Sent Events Web Server Arduino Sketch

Open your Arduino IDE and go to File > New. A new file will open. Copy the code given below in that file and save it. Replace the network credentials to successfully connect.

#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

const char* ssid = "PTCL-BB";  //Replace with your SSID
const char* password = "*********";   //Repalce with your password

AsyncWebServer server(80);

// Create an Event Source on /events
AsyncEventSource events("/events");

unsigned long last_time = 0;  
unsigned long Delay = 30000;

Adafruit_BME280 bme;         

float temperature;
float humidity;
float pressure;

// Initialize BME280
void initBME(){
    if (!bme.begin(0x76)) {
    Serial.println("BME280 sensor not connected properly!");
    while (1);
  }
}

void Obtain_SensorReadings(){
  temperature = bme.readTemperature();
  humidity = bme.readHumidity();
  pressure = bme.readPressure()/ 100.0F;
}

// Initialize WiFi
void initWiFi() {
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    Serial.print("Connecting to WiFi ..");
    while (WiFi.status() != WL_CONNECTED) {
        Serial.print('.');
        delay(1000);
    }
    Serial.println();
    Serial.println("IP Address: ");
    Serial.println(WiFi.localIP());
}

String processor(const String& var){
  Obtain_SensorReadings();
  if(var == "TEMPERATURE"){
    return String(temperature);
  }
  else if(var == "HUMIDITY"){
    return String(humidity);
  }
  else if(var == "PRESSURE"){
    return String(pressure);
  }
  return String();
}

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <title>ESP32 & BME280 SSE Web server</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
  <link rel="icon" href="data:,">
  <style>
    html {font-family: Times New Roman; display: inline-block; text-align: center;}
    p { font-size: 1.2rem;}
    body {  margin: 0;}
    .topnav { overflow: hidden; background-color: #381d75; color: white; font-size: 1rem; }
    .content { padding: 20px; }
    .box { background-color: #e6eef2;  outline: 1px solid;}
    .boxes { max-width: 800px; 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>ESP32 & BME280 SSE Web server</h1>
  </div>
  <div class="content">
    <div class="boxes">
      <div class="box">
        <p><i class="fas fa-thermometer-three-quarters" style="color:#15ab3a;"></i> Temperature</p><p><span class="reading"><span id="temp">%TEMPERATURE%</span> &deg;C</span></p>
      </div> 
      <div class="box">
         <p><i class="fas fa-arrow-circle-down" style="color:#070807;"></i> Pressure</p><p><span class="reading"><span id="pres">%PRESSURE%</span> hPa</span></p>
      </div>  
      <div class="box">
        <p><i class="fas fa-tint" style="color:#8ccbed;"></i> Humidity</p><p><span class="reading"><span id="hum">%HUMIDITY%</span> &percnt;</span></p>
      </div> 
    </div>
  </div>
<script>
if (!!window.EventSource) {
 var source = new EventSource('/events');
 
 source.addEventListener('open', function(e) {
  console.log("Events got Connected!");
 }, false);
 source.addEventListener('error', function(e) {
  if (e.target.readyState != EventSource.OPEN) {
    console.log("Events got 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('pressure', function(e) {
  console.log("pressure", e.data);
  document.getElementById("pres").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);
  initWiFi();
  initBME();


  // Handle Web Server
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });

  // 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());
    }

    client->send("hi!", NULL, millis(), 10000);
  });
  server.addHandler(&events);
  server.begin();
}

void loop() {
  if ((millis() - last_time) > Delay) {
    Obtain_SensorReadings();
    Serial.printf("Temperature = %.2f ºC \n", temperature);
    Serial.printf("Humidity = %.2f percent \n", humidity);
    Serial.printf("Pressure = %.2f hPa \n", pressure);
    Serial.println();

    // 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());
    events.send(String(pressure).c_str(),"pressure",millis());
    
    last_time = millis();
  }
}

How does the Code Work?

Including Libraries

Firstly, we will include the necessary libraries. For this project, we are using five of them. As we have to connect our ESP32 to a wireless network hence we need WiFi.h library for that purpose. The other libraries are the ones that we recently downloaded and will be required for the building of the asynchronous web server and the functionality of the sensor respectively.

#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

Setting Network Credentials

Next, we will create two global variables, one for the SSID and the other for the password. These will hold our network credentials which will be used to connect to our wireless network. Replace both of them with your credentials to ensure a successful connection.

const char* ssid = "Your_SSID"; //replace with your SSID
const char* password = "Your_Password"; //replace with your password

Creating an AsyncWebServer Object

The AsyncWebServer object will be used to set up the ESP32 web server. We will pass the default HTTP port which is 80, as the input to the constructor. This will be the port where the server will listen to the requests.

AsyncWebServer server(80);

Defining an EventSource

Next, we will define an event source called ‘/events.’ You can use any appropriate name.

AsyncEventSource events("/events");

Adding delay

The web server will update sensor readings after every 30 seconds. We will incorporate this value in the ‘Delay’ variable in milliseconds.

unsigned long last_time = 0;
unsigned long Delay = 30000;

Creating BME280 Object

Additionally, we will also create an object of Adafruit_BME280 called ‘bme’ which we will use later on to initialize the sensor.

Adafruit_BME280 bme;

Sensor Data Variables

We will now create three variables to store the sensor readings individually. These will be called ‘temperature’, ‘humidity’, and ‘pressure.’

float temperature;
float humidity;
float pressure;

Initializing Sensor

The following function will initialize the BME280 sensor. If the connection between the module and the sensor is incorrect it will print that message on the serial monitor. This function will be called inside the setup() function.

void initBME(){
    if (!bme.begin(0x76)) {
    Serial.println("BME280 sensor not connected properly!");
    while (1);
  }
}

Getting Sensor Readings (Obtain_SensorReadings())

Next, we will define a function in named Obtain_SensorReadings(). We will use the bme object on the following methods: readTemperature(), readHumidity() and readPressure() individually to access each reading. These sensor readings will be saved in the variables which we previously defined above: temperature, humidity and pressure.

void Obtain_SensorReadings(){
  temperature = bme.readTemperature();
  humidity = bme.readHumidity();
  pressure = bme.readPressure()/ 100.0F;
}

Initializing WIFI connection (initWiFi())

In the following function, we will connect our ESP32 board with the local network whose network credentials we already specified above using the WiFi.begin() function. After the connection will be established, the IP address of the module will get printed on the serial monitor. Through that IP address, we will be able to access our web page.

void initWiFi() {
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    Serial.print("Connecting to WiFi ..");
    while (WiFi.status() != WL_CONNECTED) {
        Serial.print('.');
        delay(1000);
    }
    Serial.println();
    Serial.println("IP Address: ");
    Serial.println(WiFi.localIP());
}

Processor() function

Inside the processor() function, we will replace all the placeholders which we created on our HTML text with the current sensor readings. This will occur whenever the web page will be accessed and if the placeholder is found inside the HTML script. As you already know, we will update sensor readings on our web page after every 30 seconds. With the help of the processor() function, we will have a continuous display of readings until the new ones arrive and get displayed.

String processor(const String& var){
  Obtain_SensorReadings();
  if(var == "TEMPERATURE"){
    return String(temperature);
  }
  else if(var == "HUMIDITY"){
    return String(humidity);
  }
  else if(var == "PRESSURE"){
    return String(pressure);
  }
  return String();
}

Building the Web Page (HTML, CSS and JavaScript)

We will create an index_html variable to store all the HTML, CSS and JavaScript text which will be required to build our web page. It is more convenient to have separate HTML, CSS and JavaScript files saved on the ESP32 SPIFFS. All of these three files will later be linked together. For this article, we will not be using this approach but include everything inside our Arduino sketch instead.

We will start with the title of the web page. The <title> tag will indicate the beginning of the title and the </title> tag will indicate the ending. In between these tags, we will specify “ESP32 & BME280 Web server” which will be displayed in the browser’s title bar.

  <title>ESP32 & BME280 SSE Web server</title>

Next, we will create a meta tag to make sure our web server is available for all browsers e.g., smartphones, laptops, computers etc.

<meta name="viewport" content="width=device-width, initial-scale=1">

CSS styling

Inside the index_html variable, we have the <style> </style> tags which mark the beginning and end of the CSS styling file.

We will set the display text to the font type Times New Roman and align it in the centre of the webpage. For all the different texts and boxes, the font size, font type, colour, and positioning relating to the overall visuals of the webpage will be specified. This section of code shows the CSS styling which we will incorporate in our webpage.

<style>
    html {font-family: Times New Roman; display: inline-block; text-align: center;}
    p { font-size: 1.2rem;}
    body {  margin: 0;}
    .topnav { overflow: hidden; background-color: #381d75; color: white; font-size: 1rem; }
    .content { padding: 20px; }
    .box { background-color: #e6eef2;  outline: 1px solid;}
    .boxes { max-width: 800px; margin: 0 auto; display: grid; grid-gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
    .reading { font-size: 1.4rem; }
  </style>

HTML Body

The next step will be to define the HTML web page body. This will go inside the <body></body> tags which mark the beginning and the ending of the script. This part will include the heading of the web page and the buttons. We will include the heading of our webpage inside the <h1></h1> tags and it will be the same as that of the web browser title.

    <h1>ESP32 & BME280 SSE Web server</h1>

Displaying Sensor Readings

Next, we will include several paragraphs to display texts and boxes for temperature, pressure, and humidity readings.

Firstly, we will display the temperature readings in a box. We will specify the name, icon, and color in the first paragraph. The name of the first box will be ‘Temperature’ and an icon of a thermometer will be displayed beside it. We used the icons from the Font Awesome Icons website. You can use any appropriate icon of your choice. In the next paragraph, we used a placeholder for the temperature reading inside the %% signs like %TEMPERATURE%. The processor() function will handle the task of replacing the placeholder with the current sensor reading.

Also, JavaScript will be in charge of handling the received data so that the reading will be updated correctly. This will be accomplished by using an id (<span id=”temp”>) which we will reference in our script.

<p><i class="fas fa-thermometer-three-quarters" style="color:#15ab3a;"></i> Temperature</p><p><span class="reading"><span id="temp">%TEMPERATURE%</span> &deg;C</span></p>

Secondly, we will display the pressure readings in the second box. We will specify the name, icon, and color in the paragraph. The name of the second box will be ‘Pressure’ and an icon will also be displayed beside it. In the next paragraph, we used a placeholder for the pressure reading inside the %% signs like %PRESSURE%. The SI unit will also get displayed with the sensor reading.

Also, JavaScript will be in charge of handling the received data so that the reading will be updated correctly. This will be accomplished by using an id (<span id=”pres”>) which we will reference in our script.

 <p><i class="fas fa-arrow-circle-down" style="color:#070807;"></i> Pressure</p><p><span class="reading"><span id="pres">%PRESSURE%</span> hPa</span></p>

Likewise, the same steps will be followed for the humidity readings in the third box.

 <p><i class="fas fa-tint" style="color:#8ccbed;"></i> Humidity</p><p><span class="reading"><span id="hum">%HUMIDITY%</span> &percnt;</span></p>

Thus, whenever the client will receive a new event with the updated readings, the HTML elements with their respective ids ‘temp’, ‘hum’, and ‘pres’ will get updated to newer values.

JavaScript (Receiving and handling SSE events)

Inside the tags <script></script>, we will include JavaScript to handle the SSE protocol. Its main aim will be to start the EventSource connection with the server and to handle the events which will be received from the server. We will mainly handle four kinds of occurrences:

  1. Connection
  2. Disconnection
  3. Messages sent by the server
  4. events

Firstly, we will define an event source and pass the /events URL inside it. This URL will send the updates to our web page.

if (!!window.EventSource) {
 var source = new EventSource('/events');

Then, we will use the addEventListener() function to listen to incoming events. It will have two arguments. The first will be the event name and the second will be function(e).

The following are listeners for connection, disconnection and incoming messages from the server. We used the default event listeners in this case which were listed in the Documentation.

source.addEventListener('open', function(e) {
  console.log("Events got Connected!");
 }, false);
 source.addEventListener('error', function(e) {
  if (e.target.readyState != EventSource.OPEN) {
    console.log("Events got Disconnected!");
  }
 }, false);
 
 source.addEventListener('message', function(e) {
  console.log("message", e.data);
 }, false);

Next, we will include listeners for temperature, pressure and humidity. As you already know, we used the Obtain_SensorReadings() function to save the readings obtained from the BME280 sensor in their respective variables temperature, pressure and humidity. We will use the same variables here as well to listen to the incoming events.

Firstly, we will look at how event listener for temperature works. After every 30 seconds (Delay) the ESP32 will receive new sensor readings from BME280. This event (temperature) will be sent to the web server. When the client will receive the particular event, it will print the reading on the browser console. Additionally, the new reading will also get saved to the element with the HTML id ‘temp.’

source.addEventListener('temperature', function(e) {
  console.log("temperature", e.data);
  document.getElementById("temp").innerHTML = e.data;
 }, false);

Likewise, the event listener will work in a similar way for pressure and humidity as well. In this case, we will use their respective variables and HTML ids like ‘pressure’ and ‘humidity’ and ‘pres’ and ‘hum’ respectively.

 source.addEventListener('pressure', function(e) {
  console.log("pressure", e.data);
  document.getElementById("pres").innerHTML = e.data;
 }, false);

  source.addEventListener('humidity', function(e) {
  console.log("humidity", e.data);
  document.getElementById("hum").innerHTML = e.data;
 }, false);

setup() function

Inside the setup() function, we will open a serial connection at a baud rate of 115200. Moreover, we will call the relevant functions to initialize the WIFI connection and the BME280 sensor.

Serial.begin(115200);
  initWiFi();
  initBME();

Handling Requests

We will configure the root / URL where our server will listen to HTTP GET requests.
The handling function will respond to the client by using the send_P() method on the request object. This method will take in four parameters. The first is 200 which is the HTTP status code for ‘ok’. The second is “text/html” which will correspond to the content type of the response. The third input is the text saved on the index_html variable. Finally, the last parameter is the processor function which will be sent as the response.

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });

The event source will be set up on our ESP32 board through the following lines of code:

events.onConnect([](AsyncEventSourceClient *client){
    if(client->lastId()){
      Serial.printf("Client reconnected! Last message ID that it got is: %u\n", client->lastId());
    }

    client->send("hi!", NULL, millis(), 10000);
  });
  server.addHandler(&events);

To start the server, we will call the begin() on our server object.

  server.begin();

loop() function

In the loop() function we will check if 30 seconds have passed since the sensor readings were updated. Then we will call the Obtain_SensorReadings() function. On the serial monitor, these current sensor readings will get displayed with their units.

    Obtain_SensorReadings();
    Serial.printf("Temperature = %.2f ºC \n", temperature);
    Serial.printf("Humidity = %.2f percent \n", humidity);
    Serial.printf("Pressure = %.2f hPa \n", pressure);
    Serial.println();

Lastly, we will send all these updated sensor readings to the web browser. The web server will now get updated to new sensor readings.

    events.send("ping",NULL,millis());
    events.send(String(temperature).c_str(),"temperature",millis());
    events.send(String(humidity).c_str(),"humidity",millis());
    events.send(String(pressure).c_str(),"pressure",millis());

Demonstration

Choose the correct board and COM port before uploading your code to the board.
Go to Tools > Board and select ESP32 Dev Module.

select esp32 board

Next, go to Tools > Port and select the appropriate port through which your board is connected.

Selecting COM PORT ESP32

Click on the upload button to upload the code into the ESP32 development board. After you have uploaded your code to the ESP32 development board press its ENABLE button.

ESP32 enable reset button

In your Arduino IDE, open up the serial monitor and you will be able to see the IP address of your ESP module. Copy that address into a web browser and press enter. The web server will look something like this:

ESP32 and BME280 SSE Web server demo1

You can view all three sensor readings After every 30 seconds the sensor readings will get updated on both the serial monitor and the web page.

ESP32 and BME280 SSE Web server demo serial monitor

Moreover, press Ctrl+Shift+J to open your browser console. You will be able to view the client receiving all the different events.

ESP32 and BME280 SSE erver sent events Web server demo console

Conclusion

In conclusion, we have successfully explored server-sent events and implemented a web server using this technology. The use of server-sent events allowed us to achieve continuous updates of sensor readings without the need to include additional requests. This real-time data streaming capability enhances the efficiency and responsiveness of our application, making it a powerful tool for automatically delivering the latest sensor data to connected clients.

If you found this ESP32 web server project interesting, you may also like to read:

Leave a Comment