ESP32 WebSocket Server: Display Sensor Readings

In this guide, you’ll learn how to create a WebSocket server with the ESP32 to display sensor readings on a web page. Whenever the ESP32 has new readings available, the web page is updated automatically without the need to manually refresh it.

ESP32 WebSocket Server Display Sensor Readings Arduino IDE

To learn more about building web servers with the ESP32 from scratch, check out our eBook: Build Web Servers with the ESP32 and ESP8266.

Table of Contents

Throughout this tutorial, we’ll cover the following main topics:

We have a similar tutorial for the ESP8266 board: ESP8266 NodeMCU WebSocket Server: Display Sensor Readings

Introducing WebSocket Protocol

A WebSocket is a persistent connection between a client and a server that allows bidirectional communication between both parties using a TCP connection. This means you can send data from the client to the server and from the server to the client at any given time. 

ESP32 ESP8266 WebSocket Server How it Works

The client establishes a WebSocket connection with the server through a process known as WebSocket handshake. The handshake starts with an HTTP request/response, allowing servers to handle HTTP connections as well as WebSocket connections on the same port. Once the connection is established, the client and the server can send WebSocket data in full duplex mode.

Using the WebSockets protocol, the server (ESP32 board) can send information to the client or to all clients without being requested. This also allows us to send information to the web browser when a change occurs.

This change can be something that happened on the web page (you clicked a button) or something that happened on the ESP32 side like pressing a physical button on a circuit, or new sensor readings available.

Learn how to control the ESP32 outputs via WebSocket protocol: ESP32 WebSocket Server: Control Outputs (Arduino IDE).

Project Overview

Here’s the web page we’ll build for this project.

ESP32 Websocket Server Sensor Readings
  • We’ll create a web page that displays temperature, humidity, and pressure.
  • The web page displays the latest sensor readings when you open or refresh the web page.
  • The sensor readings update automatically whenever there’s a new reading available on the ESP32 without the need to refresh the webpage.
  • The web server works perfectly on multiple clients (multiple web browser tabs on the same device or different devices).

How does it work?

  • The ESP hosts a web server that displays a web page with three cards for the sensor readings.
  • When you open the webpage, it sends a message (getReadings) to the ESP via WebSocket protocol. The server (ESP) receives that message. When that happens, it gets new readings from the sensors and sends them back to the client (web browser), also via web socket protocol. This way, whenever you open a new tab, it always shows the current and updated values.
ESP32 Websocket server how it works
  • Every 30 seconds, the ESP gets new readings and sends them to all connected clients (all web browser tabs opened) via WebSocket protocol. The client receives that message and displays the readings on the web page.
ESP32 Websocket server how it works

Prerequisites

Before proceeding with this tutorial, make sure you check all the following prerequisites.

1) Parts Required

To follow this project you need:

For this example, we’ll use a BME280 sensor, but you can use any other sensor you’re familiar with.

You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!

2) Arduino IDE and ESP32 Boards Add-on

We’ll program the ESP32 using Arduino IDE. So, you must have the ESP32 add-on installed. Follow the next tutorial if you haven’t already:

If you want to use VS Code with the PlatformIO extension, follow the next tutorial instead to learn how to program the ESP32:

3) Filesystem Uploader Plugin

To upload the HTML, CSS, and JavaScript files needed to build this project to the ESP32 flash memory (LittleFS), we’ll use a plugin for Arduino IDE: LittleFS Filesystem uploader. Follow the next tutorial to install the filesystem uploader plugin if you haven’t already:

If you’re using VS Code with the PlatformIO extension, read the following tutorial to learn how to upload files to the filesystem:

4) Libraries

To build this project, you need to install the following libraries:

You can install the first two libraries using the Arduino Library Manager. Go to Sketch Include Library > Manage Libraries and search for the library name.

The ESPAsyncWebServer and AsynTCP libraries aren’t available to install through the Arduino Library Manager, so you need to copy the library files to the Arduino Installation Libraries folder. Alternatively, in your Arduino IDE, you can go to SketchInclude Library > Add .zip Library and select the libraries you’ve just downloaded.

Installing Libraries (VS Code + PlatformIO)

If you’re programming the ESP32 using PlatformIO, you should add the following lines to the platformio.ini file to include the libraries and set the default filesystem to LittleFS (also change the Serial Monitor speed to 115200):

platform = [email protected]
board = esp32doit-devkit-v1
framework = arduino
monitor_speed = 115200
lib_deps = ESP Async WebServer
    arduino-libraries/Arduino_JSON @ 0.1.0
    adafruit/Adafruit BME280 Library @ ^2.1.0
    adafruit/Adafruit Unified Sensor @ ^1.1.4
board_build.filesystem = littlefs

Building the Circuit

To exemplify how to display sensor readings on a web server with the ESP32, we’ll send sensor readings from a BME280 sensor to the browser. So, you need to wire a BME280 sensor to your ESP32. You can also use any other sensor you’re familiar with.

Schematic Diagram

We’re going to use I2C communication with the BME280 sensor module. For that, wire the sensor to the default ESP32 SCL (GPIO 22) and SDA (GPIO 21) pins, as shown in the following schematic diagram.

ESP32 Wiring to BME280 Schematic Diagram

Recommended reading: ESP32 Pinout Reference: Which GPIO pins should you use?

Organizing Your Files

To keep the project organized and make it easier to understand, we’ll create four files to build the web server:

  • Arduino sketch: to get the sensor readings and handle the web server;
  • index.html: to define the content of the web page to display the sensor readings;
  • style.css: to style the web page;
  • script.js: to program the behavior of the web page—handle what happens when you open the web page and display the readings received via WebSocket protocol.
Organizing your Files arduino sketch index html style css script js

You should save the HTML, CSS, and JavaScript files inside a folder called data inside the Arduino sketch folder, as shown in the previous diagram. We’ll upload these files to the ESP32 filesystem (LittleFS).

You can download all project files:

HTML File

Copy the following to the index.html file.

<!DOCTYPE html>
<html>
    <head>
        <title>ESP IOT DASHBOARD</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="icon" type="image/png" href="favicon.png">
        <link rel="stylesheet" type="text/css" href="style.css">
    </head>
    <body>
        <div class="topnav">
            <h1>SENSOR READINGS (WEBSOCKET)</h1>
        </div>
        <div class="content">
            <div class="card-grid">
                <div class="card">
                    <p class="card-title"><i class="fas fa-thermometer-threequarters" style="color:#059e8a;"></i> Temperature</p>
                    <p class="reading"><span id="temperature"></span> &deg;C</p>
                </div>
                <div class="card">
                    <p class="card-title"> Humidity</p>
                    <p class="reading"><span id="humidity"></span> &percnt;</p>
                </div>
                <div class="card">
                    <p class="card-title"> Pressure</p>
                    <p class="reading"><span id="pressure"></span> hpa</p>
                </div>
            </div>
        </div>
        <script src="script.js"></script>
    </body>
</html>

View raw code

We won’t go into much detail about the content of the HTML file. Just the relevant parts.

The following lines display a card for the temperature.

<div class="card">
    <p class="card-title"><i class="fas fa-thermometer-threequarters" style="color:#059e8a;"></i> Temperature</p>
    <p class="reading"><span id="temperature"></span> &deg;C</p>
</div>

The temperature will show up in the following paragraph between the <span> tags. Notice that you need a unique id for that HTML tag so that later we know how to refer to this HTML element. In this case, the unique id is temperature.

<span id="temperature"></span>

We do a similar procedure for the humidity and pressure. The unique ids for the HTML elements where we’ll display the humidity and pressure are humidity and pressure.

<div class="card">
      <p class="card-title"> Humidity</p>
      <p class="reading"><span id="humidity"></span> &percnt;</p>
</div>
<div class="card">
    <p class="card-title"> Pressure</p>
    <p class="reading"><span id="pressure"></span> hpa</p>
</div>

CSS File

Copy the following to the style.css file.  Feel free to change it to make the web page look as you wish. We won’t explain how the CSS for this web page works because it is not relevant for this tutorial.

html {
    font-family: Arial, Helvetica, sans-serif;
    display: inline-block;
    text-align: center;
}
h1 {
    font-size: 1.8rem;
    color: white;
}
.topnav {
    overflow: hidden;
    background-color: #0A1128;
}
body {
    margin: 0;
}
.content {
    padding: 50px;
}
.card-grid {
    max-width: 800px;
    margin: 0 auto;
    display: grid;
    grid-gap: 2rem;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.card {
    background-color: white;
    box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);
}
.card-title {
    font-size: 1.2rem;
    font-weight: bold;
    color: #034078
}
.reading {
    font-size: 1.2rem;
    color: #1282A2;
}

View raw code

JavaScript File

Copy the following to the script.js file.


var gateway = `ws://${window.location.hostname}/ws`;
var websocket;
// Init web socket when the page loads
window.addEventListener('load', onload);

function onload(event) {
    initWebSocket();
}

function getReadings(){
    websocket.send("getReadings");
}

function initWebSocket() {
    console.log('Trying to open a WebSocket connection…');
    websocket = new WebSocket(gateway);
    websocket.onopen = onOpen;
    websocket.onclose = onClose;
    websocket.onmessage = onMessage;
}

// When websocket is established, call the getReadings() function
function onOpen(event) {
    console.log('Connection opened');
    getReadings();
}

function onClose(event) {
    console.log('Connection closed');
    setTimeout(initWebSocket, 2000);
}

// Function that receives the message from the ESP32 with the readings
function onMessage(event) {
    console.log(event.data);
    var myObj = JSON.parse(event.data);
    var keys = Object.keys(myObj);

    for (var i = 0; i < keys.length; i++){
        var key = keys[i];
        document.getElementById(key).innerHTML = myObj[key];
    }
}

View raw code

Here’s a list of what this code does:

  • initializes a WebSocket connection with the server;
  • sends a message to the server to get the current sensor readings;
  • uses the response to update the sensor readings on the web page;
  • handles data exchange through the WebSocket protocol.

Let’s take a look at this JavaScript code to see how it works.

The gateway is the entry point to the WebSocket interface. window.location.hostname gets the current page address (the web server IP address).

var gateway = ws://${window.location.hostname}/ws;

Create a new global variable called websocket.

var websocket;

Add an event listener that will call the onload function when the web page loads.

window.addEventListener('load', onload);

The onload() function calls the initWebSocket() function to initialize a WebSocket connection with the server.

function onload(event) {
  initWebSocket();
}

The initWebSocket() function initializes a WebSocket connection on the gateway defined earlier. We also assign several callback functions for when the WebSocket connection is opened, closed, or when a message is received.

function initWebSocket() {
  console.log('Trying to open a WebSocket connection…');
  websocket = new WebSocket(gateway);
  websocket.onopen = onOpen;
  websocket.onclose = onClose;
  websocket.onmessage = onMessage;
}

Note that when the WebSocket connection is open, we’ll call the getReadings function.

function onOpen(event) {
  console.log('Connection opened');
  getReadings();
}

The getReadings() function sends a message to the server getReadings to get the current sensor readings. Then, we must handle what happens when we receive that message on the server side (ESP32).

function getReadings(){
  websocket.send("getReadings");
}

We handle the messages received via WebSocket protocol on the onMessage() function.

// Function that receives the message from the ESP32 with the readings
function onMessage(event) {
  console.log(event.data);
  var myObj = JSON.parse(event.data);
  var keys = Object.keys(myObj);

  for (var i = 0; i < keys.length; i++){
    var key = keys[i];
    document.getElementById(key).innerHTML = myObj[key];
  }
}

The server sends the readings in JSON format, for example:

{
  temperature: 20;
  humidity: 50;
  pressure: 1023;
}

The onMessage() function simply goes through all the key values (temperature, humidity, and pressure) and places them in the corresponding places on the HTML page. In this case, the keys have the same name as the ids we’ve defined on the HTML page. So, we can simply do something like this:

for (var i = 0; i < keys.length; i++){
  var key = keys[i];
  document.getElementById(key).innerHTML = myObj[key];
}

Code for ESP32 WebSocket Server (Sensor Readings)

Copy the following code to your Arduino IDE.

/*********
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete instructions at https://RandomNerdTutorials.com/esp32-websocket-server-sensor/
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*********/
#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include "LittleFS.h"
#include <Arduino_JSON.h>
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

// Create a WebSocket object
AsyncWebSocket ws("/ws");

// Json Variable to Hold Sensor Readings
JSONVar readings;

// Timer variables
unsigned long lastTime = 0;
unsigned long timerDelay = 30000;

// Create a sensor object
Adafruit_BME280 bme;

// Init BME280
void initBME(){
  if (!bme.begin(0x76)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }
}

// Get Sensor Readings and return JSON object
String getSensorReadings(){
  readings["temperature"] = String(bme.readTemperature());
  readings["humidity"] =  String(bme.readHumidity());
  readings["pressure"] = String(bme.readPressure()/100.0F);
  String jsonString = JSON.stringify(readings);
  return jsonString;
}

// Initialize LittleFS
void initLittleFS() {
  if (!LittleFS.begin(true)) {
    Serial.println("An error has occurred while mounting LittleFS");
  }
  Serial.println("LittleFS mounted successfully");
}

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

void notifyClients(String sensorReadings) {
  ws.textAll(sensorReadings);
}

void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) {
  AwsFrameInfo *info = (AwsFrameInfo*)arg;
  if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
    //data[len] = 0;
    //String message = (char*)data;
    // Check if the message is "getReadings"
    //if (strcmp((char*)data, "getReadings") == 0) {
      //if it is, send current sensor readings
      String sensorReadings = getSensorReadings();
      Serial.print(sensorReadings);
      notifyClients(sensorReadings);
    //}
  }
}

void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
  switch (type) {
    case WS_EVT_CONNECT:
      Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
      break;
    case WS_EVT_DISCONNECT:
      Serial.printf("WebSocket client #%u disconnected\n", client->id());
      break;
    case WS_EVT_DATA:
      handleWebSocketMessage(arg, data, len);
      break;
    case WS_EVT_PONG:
    case WS_EVT_ERROR:
      break;
  }
}

void initWebSocket() {
  ws.onEvent(onEvent);
  server.addHandler(&ws);
}

void setup() {
  Serial.begin(115200);
  initBME();
  initWiFi();
  initLittleFS();
  initWebSocket();

  // Web Server Root URL
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
    request->send(LittleFS, "/index.html", "text/html");
  });

  server.serveStatic("/", LittleFS, "/");

  // Start server
  server.begin();
}

void loop() {
  if ((millis() - lastTime) > timerDelay) {
    String sensorReadings = getSensorReadings();
    Serial.print(sensorReadings);
    notifyClients(sensorReadings);
    lastTime = millis();
  }
  ws.cleanupClients();
}

View raw code

How the Code Works

Continue reading to learn how the code works, or skip to the demonstration section.

Including Libraries

The Adafruit_Sensor and Adafruit_BME280 libraries are needed to interface with the BME280 sensor.

#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

The WiFi, ESPAsyncWebServer and AsyncTCP libraries are used to create the web server.

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

We’ll save the HTML, CSS, and JavaScript files on the ESP32 filesystem, so we also need to include the LittleFS.h library.

#include "LittleFS.h"

To create JSON objects, we’ll use the Arduino_JSON library.

#include <Arduino_JSON.h>

Network Credentials

Insert your network credentials in the following variables, so that the ESP32 can connect to your local network using Wi-Fi.

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

AsyncWebServer and AsyncWebSocket

Create an AsyncWebServer object on port 80.

AsyncWebServer server(80);

The following line creates a new websocket object on /ws.

// Create a WebSocket object
AsyncWebSocket ws("/ws");

Timer Variables

The following variables are used to create timers in our code. In our case, we’ll send sensor readings to the client via WebSocket protocol every 30000 milliseconds (30 seconds). You can change the timerDelay variable to any other value that makes sense for your project.

// Timer variables
unsigned long lastTime = 0;
unsigned long timerDelay = 30000;

Initializing the BME280 Sensor

The following line creates an Adafruit_BME280 object to refer to the sensor called bme.

// Create a sensor object
Adafruit_BME280 bme;

The initBME() function initializes the sensor. It will be called later in the setup().

// Init BME280
void initBME(){
  if (!bme.begin(0x76)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }
}

Getting Sensor Readings (JSON String)

The getSensoreadings() function creates a JSON string with the current sensor readings.

// Get Sensor Readings and return JSON object
String getSensorReadings(){
  readings["temperature"] = String(bme.readTemperature());
  readings["humidity"] = String(bme.readHumidity());
  readings["pressure"] = String(bme.readPressure()/100.0F);
  String jsonString = JSON.stringify(readings);
  return jsonString;
}

Initializing the Filesystem

The initLittleFS() function initializes LittleFS, the ESP32 filesystem we’re using in this project to save the HTML, CSS, and Javascript files.

// Initialize LittleFS
void initLittleFS() {
  if (!LittleFS.begin(true)) {
    Serial.println("An error has occurred while mounting LittleFS");
  }
  Serial.println("LittleFSmounted successfully");
}

Initializing Wi-Fi

The following function initializes Wi-Fi and connects to your network using the credentials you used previously. This function will be called later in the setup().

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

Notifying all Clients Via WebSocket

The notifyClients() function notifies all clients with the current sensor readings. Calling this function is what allows us to notify changes in all clients whenever we get new sensor readings (every 30 seconds).

void notifyClients(String sensorReadings) {
  ws.textAll(sensorReadings);
}

Handling WebSocket Messages

The handleWebSocketMessage(), as the name suggests, handles what happens when the server receives a message from the client via WebSocket protocol. We’ve seen in the JavaScript file, that the server can receive the getReadings message.

When the ESP32 receives the getReadings message, it sends the current sensor readings.

void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) {
  AwsFrameInfo *info = (AwsFrameInfo*)arg;
  if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
    data[len] = 0;
    String message = (char*)data;
    //Check if the message is "getReadings"
    if (strcmp((char*)data, "getReadings") == 0) {
      if it is, send current sensor readings
      String sensorReadings = getSensorReadings();
      Serial.print(sensorReadings);
      notifyClients(sensorReadings);
    }
  }
}

Handling WebSocket Events

The onEvent() function handles other WebSocket events.

void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
  switch (type) {
    case WS_EVT_CONNECT:
      Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
      break;
    case WS_EVT_DISCONNECT:
      Serial.printf("WebSocket client #%u disconnected\n", client->id());
      break;
    case WS_EVT_DATA:
      handleWebSocketMessage(arg, data, len);
      break;
    case WS_EVT_PONG:
    case WS_EVT_ERROR:
      break;
  }
}

Initializing WebSocket Protocol

The initWebSocket() function initializes the WebSocket protocol.

void initWebSocket() {
  ws.onEvent(onEvent);
  server.addHandler(&ws);
}

setup()

In the setup(), we initialize the Serial Monitor, the BME280 sensor, Wi-Fi, the filesystem, and the WebSocket protocol by calling the functions we’ve created previously.

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

The following lines will serve the index.html and the other referenced static files saved on LittleFS (style.css and script.js) when you access the web server.

// Web Server Root URL
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
  request->send(LittleFS, "/index.html", "text/html");
});

server.serveStatic("/", LittleFS, "/");

Finally, start the server.

// Start server
server.begin();

loop()

In the loop(), we get and send new sensor readings every 30000 milliseconds (30 seconds).

void loop() {
  if ((millis() - lastTime) > timerDelay) {
    String sensorReadings = getSensorReadings();
    Serial.print(sensorReadings);
    notifyClients(sensorReadings);

    lastTime = millis();

  }

  ws.cleanupClients();
}

Upload Code and Files

After inserting your network credentials, save the code. Go to Sketch > Show Sketch Folder, and create a folder called data.

Arduino IDE Open Sketch Folder to create data folder

Inside that folder, you should place the HTML, CSS, and JavaScript files.

Upload those files to the filesystem: press [Ctrl] + [Shift] + [P] on Windows or [] + [Shift] + [P] on MacOS to open the command palette. Search for the Upload LittleFS to Pico/ESP8266/ESP32 command and click on it.

If you don’t have this option is because you didn’t install the filesystem uploader plugin. Check this tutorial.

ESP32 Sketch Data Upload LittleFS Arduino IDE

Important: make sure the Serial Monitor is closed before uploading to the filesystem. Otherwise, the upload will fail.

Then, upload the code to your ESP32 board. Make sure you modified the code with your network credentials.

Arduino IDE 2 Upload Button

When everything is successfully uploaded, open the Serial Monitor at a baud rate of 115200. Press the ESP32 EN/RST button, and it should print the ESP32 IP address.

Demonstration

Open a browser on your local network and paste the ESP32 IP address. You should get access to the web server page that displays the sensor readings.

ESP32 Websocket Server Sensor Readings

The readings update automatically on the web page every 30 seconds.

You can have multiple clients on different web browser tabs or devices and it will update automatically on all clients.

ESP32 WebSocket Server Display Sensor Readings Arduino IDE Demonstration

Wrapping Up

In this tutorial, you’ve learned how to build a websocket server with the ESP32 that serves a web page to display sensor readings. The sensor readings update automatically on the web page without the need to manually refresh it.

We hope you learned a lot from this tutorial. Let us know in the comments below if you successfully followed this tutorial and got the project working.

To learn more about building web servers with the ESP32, we really recommend taking a look at our eBook:

Learn more about the ESP32 with our resources:

Thank you for reading.



Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Enjoyed this project? Stay updated by subscribing our newsletter!

27 thoughts on “ESP32 WebSocket Server: Display Sensor Readings”

  1. Does anyone know the max number of clients you can have one this at the same time?
    Would it be the same as HTTP clients ie 4 or 5

    Reply
  2. Obrigado pelo Post.
    No passado tive problemas com o AsyncWebServer e AsynTCP, quando enviada vários eventos em pouco espaço de tempo. A memória do Esp32 ficava cheia e crashava.
    Quando vi este post, ganhei uma esperança que isso não aconteça.
    Conseguem dar-me algum feedback?
    Muito obrigado,
    Miguel

    Reply
    • Yes, you would just need to give the device a public IP, or use NAT Forwarding to open a public port that forwards to an internal IP.

      Reply
  3. The next challenge is to store measurements and allow a client to access these measurements (eg to have the soil humidity in a plant over a week, with one measurement per hour). Sending large amounts of data via an ESP32 webserver is not easy, particularly if the transmission can be interrupted by the connection of a new client. Do you have any views on how to approach this? Can it reasonably be done without cloud storage of the data?

    Reply
    • Hi.
      You can store the readings in a txt file in the filesystem, and then serve that file via a web server.
      Regards,
      Sara

      Reply
  4. Following up on Ahmeds question: Could the ESP32 be used as an AP and at the same time run the web page? Then a client (like a smartphone) could connect to the AP and then access the webpage via a browser. That way you could read sensor data wireless even without a WiFi network – like for checking sensors on a field far from the farmhouse.

    Reply
  5. Hi There!
    After spend the day, I have a successful BME280 and Web Server running on an ESP32S3 Devkit board! I was unable to determine from documentation what the default TWI was on the board, and had an incorrect address for the Adafruit-BME280.
    Simpler of the 2 for me was finding the address of the BME280. It turned out to be 0x77, even though the solder jumper was not jumped. Documentation said it defaulted to 0x76. After an I2C scan and a bunch of fooling around, I fount it was 0x77, and when I turned it over to check the jumper….wouldn’t you know it! It was 0x77 right on the silkscreen! Boy did I feel dumb!

    I also found I could specify the pins I wanted to use with a ‘Wire.begin(3,4); ‘ directly above the ‘initBME(); ‘ on setup(), and it works! WOO-HOO!

    It was a tough day, but very rewarding. I am quite sure I would’ve had none of this had I used an older DO-IT board, but I really wanted to make this work with an S3 so yay!

    If anyone knows of any default i2c bus on the ESP32S3 Devkit board, please let me know, as I could not locate the info on line.

    Thanks RNT for another great project!
    Dave K.

    Reply
    • Hi Dave.
      Thanks for sharing that information.
      I still haven’t started playing with the ESP32S3. So, I’m not familiar with its pinout yet.
      With a quick search, it seems the default I2C pins for the ESP32S3 are GPIO 8 (SDA) GPIO9 (SCL), but I haven’t tried it.
      Regards,
      Sara

      Reply
      • Hi Sara,
        This morning I tried those pins after removing the ‘Wire.begin(3,4)’ statement, and yes indeed those are the pins as you described. I don’t know where you found that information, but I thank you for your efforts. I looked at the ESP32-S3 DevKitC-1 pinout. TWI on espressif’s site for the S3, and on StackExchange, not to mention various other sites scanned from searches. What did you search for? I must have over complicated things as I tend to do!

        Thanks Again,
        Dave

        Reply
  6. Hi all,
    I am unable to get this project to build on PlatformIO.
    I get this error
    c:/users/mweir/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld.exe: .pio\build\esp32doit-devkit-v1\lib346\libESP Async WebServer.a(AsyncWebSocket.cpp.o):(.literal._ZN22AsyncWebSocketResponseC2ERK6StringP14AsyncWebSocket+0x10): undefined reference to `SHA1Init’ and others referring to SHA1.
    Can anyone point me in right direction?

    Cheers

    Mark

    Reply
  7. Hello , Thanks for your Free Projects of ESP32 and ALso 8266 , I have a question is it possible that I buy WeMos D1 and Work with these projects?

    Reply
  8. ESP32, IDE2.1.1, Windows10: Why this error?
    exit status 1
    Compilation error: ‘class AsyncWebSocket’ has no member named ‘cleanupClients’; did you mean ‘hasClient’?

    Reply
  9. Hi!

    I have tried this project, but I do not get any readings on the Web page. It display only the box whit the Text Temperature, humidity and Pressure. Have check the code and it is the same as the example. What can be wrong?
    In the serial monitor it displays the data in a long string, tried with a Serial.print(sensorReadings); , but now luck. How to fiks this.

    Regards
    Stein

    Reply
    • Hi.
      Do you get any errors on the serial monitor?
      What about the web page? If you open the Javascript console on the web browser, do you get any errors?
      Regards,
      Sara

      Reply
      • Hi Sara!

        Thanks for answer.
        I do not get any errors on the serial monitor. There is no errors on the web page on the PC or phone.
        Not possible to attach any files the I could send some screenshots.
        This is an ESP32 Dev Module.

        Regards
        Stein

        Reply
        • Do you have the required files in the data folder? Did you upload the data folder to the board? You probably forgot to upload the script.js file.
          Regards,
          Sara

          Reply
          • Hi Sara!

            I just read the contents of the script.js and it is there.

            Just downloaded the 3 files again and now it works ????
            Do not know why.

            Thanks for the help.
            Regards
            Stein

  10. Mind explaining what does the code at the start of handleWebSocketMessage() supposed to be doing? seems a bit redundant doing these checkes. When are these expected to not be true?

    Reply
  11. Thank you very much for this tutorial.

    Can you explain how to set up websockets including the port when using portforwarding?

    If i forward my ESPs port 80 and websockets start on /ws, it cant receive ws data.

    On browsers debug window it says an error on line Socket = new WebSocket(ws://${window.location.hostname}/ws);

    Error is “WebSocket connection to ‘ws://myurlishiddentokeepprivacy/ws’ failed:”

    Any idea how to set this up?

    Reply

Leave a Comment

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.