Serveur Web ESP32 utilisant les événements envoyés par le serveur (SSE)

Serveur Web ESP32 utilisant les événements envoyés par le serveur (SSE)

Ce tutoriel montre comment utiliser les événements envoyés par le serveur (SSE) dans un serveur Web ESP32 programmé avec Arduino IDE. SSE permet au navigateur de recevoir des mises à jour automatiques d’un serveur via une connexion HTTP. Ceci est utile pour envoyer des lectures de capteur mises à jour au navigateur, par exemple. Chaque fois qu’une nouvelle lecture est disponible, l’ESP32 l’envoie au client et la page Web peut être mise à jour automatiquement sans qu’il soit nécessaire de faire des demandes supplémentaires.

Serveur Web ESP32 utilisant les lectures de capteur de mise à jour des événements envoyés par le serveur (SSE) automatiquement Arduino

À titre d’exemple, nous allons créer un serveur Web qui affiche les lectures d’un capteur de température, d’humidité et de pression BME280. Pour en savoir plus sur le BME280, lisez notre guide :

Nous avons également un guide similaire sur les événements envoyés par le serveur pour l’ESP8266.

Présentation des événements envoyés par le serveur (SSE)

Les événements envoyés par le serveur (SSE) permettent au client de recevoir des mises à jour automatiques d’un serveur via une connexion HTTP.

ESP32 ESP8266 Serveur Web d'événements envoyés par le serveur Comment ça marche

Le client initie la connexion SSE et le serveur utilise le protocole de source d’événement pour envoyer des mises à jour au client. Le client recevra des mises à jour du serveur, mais il ne pourra pas envoyer de données au serveur après la poignée de main initiale.

Ceci est utile pour envoyer des lectures de capteur mises à jour au navigateur. Chaque fois qu’une nouvelle lecture est disponible, l’ESP32 l’envoie au client et la page Web peut être mise à jour automatiquement sans avoir besoin de nouvelles demandes. Au lieu de lectures de capteurs, vous pouvez envoyer toutes les données qui pourraient être utiles pour votre projet comme les états GPIO, les notifications lorsqu’un mouvement est détecté, etc.

Important : les événements envoyés par le serveur (SSE) ne sont pas pris en charge sur Internet Explorer.

Aperçu du projet

Voici la page Web que nous allons créer pour ce projet.

Serveur Web BME280 utilisant les événements envoyés par le serveur (SSE) ESP32 Arduino
  • Le serveur Web ESP32 affiche trois cartes avec des lectures de température, d’humidité et de pression BME280;
  • L’ESP32 obtient de nouvelles lectures du capteur toutes les 30 secondes ;
  • Chaque fois qu’une nouvelle lecture est disponible, la carte (serveur) l’envoie au client à l’aide d’événements envoyés par le serveur ;
  • Le client reçoit les données et met à jour la page Web en conséquence ;
  • Cela permet à la page Web d’être mise à jour automatiquement chaque fois que de nouvelles lectures sont disponibles.

Comment ça fonctionne?

Le schéma suivant résume le fonctionnement des événements envoyés par le serveur pour mettre à jour la page Web.

Serveur Web ESP32 BME280 avec événements envoyés par le serveur (SSE) Comment ça marche
  1. Le client initie la connexion SSE et le serveur utilise le protocole de source d’événement sur l’URL /events pour envoyer des mises à jour au client ;
  2. L’ESP32 obtient de nouvelles lectures de capteur ;
  3. Il envoie les lectures sous forme d’événements avec les noms suivants au client : ‘température’, ‘humidité’ et ‘pression’ ;
  4. Le client dispose d’écouteurs d’événements pour les événements envoyés par le serveur et reçoit les lectures de capteur mises à jour sur ces événements ;
  5. Il met à jour la page Web avec les dernières lectures.

Préparation de l’IDE Arduino

Nous programmerons le ESP32 carte à l’aide de l’IDE Arduino, assurez-vous donc de l’avoir installé dans votre IDE Arduino.

Installation de bibliothèques – Serveur Web asynchrone

Pour construire le serveur Web, nous utiliserons le ESPAsyncWebServer bibliothèque. Cette bibliothèque a besoin de AsyncTCP bibliothèque pour fonctionner correctement. Cliquez sur les liens ci-dessous pour télécharger les bibliothèques.

Ces bibliothèques ne peuvent pas être installées via le gestionnaire de bibliothèque Arduino, vous devez donc copier les fichiers de bibliothèque dans le dossier Bibliothèques d’installation Arduino. Alternativement, dans votre IDE Arduino, vous pouvez aller à Sketch> Inclure la bibliothèque> Ajouter une bibliothèque .zip et sélectionner les bibliothèques que vous venez de télécharger.

Installation des bibliothèques – Capteur BME280

Pour obtenir des lectures du module de capteur BME280, nous utiliserons le Bibliothèque Adafruit_BME280. Vous devez également installer le Bibliothèque Adafruit_Sensor. Suivez les étapes suivantes pour installer les bibliothèques dans votre IDE Arduino :

1. Ouvrez votre IDE Arduino et accédez à Sketch > Inclure la bibliothèque > Gérer les bibliothèques. Le gestionnaire de bibliothèque devrait s’ouvrir.

2. Recherchez « adafruit bme280 » dans la zone de recherche et installez la bibliothèque.

Installation de la bibliothèque BME280 dans l'IDE Arduino

Pour utiliser la bibliothèque BME280, vous devez également installer le Capteur unifié Adafruit. Suivez les étapes suivantes pour installer la bibliothèque dans votre IDE Arduino :

3. Recherchez « Adafruit Unified Sensor » dans la zone de recherche. Faites défiler vers le bas pour trouver la bibliothèque et installez-la.

Installation de la bibliothèque Adafruit Unified Sensor Driver

Après avoir installé les bibliothèques, redémarrez votre IDE Arduino.

Pour en savoir plus sur le capteur BME280, lisez notre guide : ESP32 avec capteur BME280 utilisant Arduino IDE (pression, température, humidité).

Construire le circuit

Pour illustrer comment utiliser les événements envoyés par le serveur avec l’ESP32, nous enverrons les lectures de capteur d’un capteur BME280 au navigateur. Vous devez donc câbler un capteur BME280 à votre ESP32.

Pièces requises

Pour terminer ce tutoriel, vous avez besoin des pièces suivantes :

Vous pouvez utiliser les liens précédents ou accéder directement à MakerAdvisor.com/tools pour trouver toutes les pièces pour vos projets au meilleur prix !

1680420371 610 Serveur Web ESP32 utilisant les evenements envoyes par le serveur

Diagramme schématique

Nous allons utiliser la communication I2C avec le module de capteur BME280. Pour cela, câblez le capteur aux broches ESP32 SCL (GPIO 22) et SDA (GPIO 21) par défaut, comme indiqué dans le schéma suivant.

Schéma de câblage ESP32 vers BME280

Lecture recommandée : Référence de brochage ESP32 : Quelles broches GPIO devez-vous utiliser ?

Code pour le serveur Web ESP32 utilisant les événements envoyés par le serveur (SSE)

Copiez le code suivant dans votre IDE Arduino.

/*********
  Rui Santos
  Complete project details at https://Raspberryme.com/esp32-web-server-sent-events-sse/
  
  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 <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.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 an Event Source on /events
AsyncEventSource events("/events");

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

// Create a sensor object
Adafruit_BME280 bme;         // BME280 connect to ESP32 I2C (GPIO 21 = SDA, GPIO 22 = SCL)

float temperature;
float humidity;
float pressure;

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

void getSensorReadings(){
  temperature = bme.readTemperature();
  // Convert temperature to Fahrenheit
  //temperature = 1.8 * bme.readTemperature() + 32;
  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(WiFi.localIP());
}

String processor(const String& var){
  getSensorReadings();
  //Serial.println(var);
  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>ESP 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: Arial; display: inline-block; text-align: center;}
    p { font-size: 1.2rem;}
    body {  margin: 0;}
    .topnav { overflow: hidden; background-color: #50B8B4; color: white; font-size: 1rem; }
    .content { padding: 20px; }
    .card { background-color: white; box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5); }
    .cards { 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>BME280 WEB SERVER (SSE)</h1>
  </div>
  <div class="content">
    <div class="cards">
      <div class="card">
        <p><i class="fas fa-thermometer-half" style="color:#059e8a;"></i> TEMPERATURE</p><p><span class="reading"><span id="temp">%TEMPERATURE%</span> &deg;C</span></p>
      </div>
      <div class="card">
        <p><i class="fas fa-tint" style="color:#00add6;"></i> HUMIDITY</p><p><span class="reading"><span id="hum">%HUMIDITY%</span> &percnt;</span></p>
      </div>
      <div class="card">
        <p><i class="fas fa-angle-double-down" style="color:#e1e437;"></i> PRESSURE</p><p><span class="reading"><span id="pres">%PRESSURE%</span> hPa</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);
 
 source.addEventListener('pressure', function(e) {
  console.log("pressure", e.data);
  document.getElementById("pres").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());
    }
    // 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() {
  if ((millis() - lastTime) > timerDelay) {
    getSensorReadings();
    Serial.printf("Temperature = %.2f ºC \n", temperature);
    Serial.printf("Humidity = %.2f \n", humidity);
    Serial.printf("Pressure = %.2f hPa \n", pressure);
    Serial.println();

    // Send Events to the Web Client 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());
    
    lastTime = millis();
  }
}

Afficher le code brut

Insérez vos informations d’identification réseau dans les variables suivantes et le code fonctionnera immédiatement.

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

Comment fonctionne le code

Continuez à lire pour savoir comment le code fonctionne ou passez à la Manifestation section.

Y compris les bibliothèques

Les bibliothèques Adafruit_Sensor et Adafruit_BME280 sont nécessaires pour s’interfacer avec le capteur BME280.

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

Les librairies WiFi, ESPAsyncWebServer et AsyncTCP sont utilisées pour créer le serveur web.

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

Informations d’identification réseau

Insérez vos informations d’identification réseau dans les variables suivantes, afin que l’ESP32 puisse se connecter à votre réseau local en utilisant le Wi-Fi.

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

AsyncWebServer et AsyncEventSource

Créez un objet AsyncWebServer sur le port 80.

AsyncWebServer server(80);

La ligne suivante crée une nouvelle source d’événement sur /events.

AsyncEventSource events("/events");

Déclaration de variables

Les variables lastTime et timerDelay seront utilisées pour mettre à jour les lectures du capteur toutes les X secondes. Par exemple, nous obtiendrons de nouvelles lectures de capteur toutes les 30 secondes (30 000 millisecondes). Vous pouvez modifier ce délai dans la variable timerDelay.

unsigned long lastTime = 0;
unsigned long timerDelay = 30000;

Créez un objet Adafruit_BME280 appelé bme sur les broches ESP32 I2C par défaut.

Adafruit_BME280 bme;

Les variables flottantes de température, d’humidité et de pression seront utilisées pour conserver les lectures du capteur BME280.

float temperature;
float humidity;
float pressure;

Initialiser BME280

La fonction suivante peut être appelée pour initialiser le capteur BME280.

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

Obtenez des lectures BME280

La fonction getSensorReading() obtient les lectures de température, d’humidité et de pression du capteur BME280 et les enregistre sur les variables de température, d’humidité et de pression.

void getSensorReadings(){
  temperature = bme.readTemperature();
  // Convert temperature to Fahrenheit
  //temperature = 1.8 * bme.readTemperature() + 32;
  humidity = bme.readHumidity();
  pressure = bme.readPressure()/ 100.0F;
}

Initialiser le Wi-Fi

La fonction suivante définit l’ESP32 en tant que station Wi-Fi et se connecte à votre routeur à l’aide du ssid et du mot de passe définis précédemment.

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

Processeur

La fonction processor() remplace tous les espaces réservés du texte HTML utilisé pour créer la page Web avec les lectures actuelles du capteur avant de l’envoyer au navigateur.

String processor(const String& var){
  getSensorReadings();
  //Serial.println(var);
  if(var == "TEMPERATURE"){
    return String(temperature);
  }
  else if(var == "HUMIDITY"){
    return String(humidity);
  }
  else if(var == "PRESSURE"){
    return String(pressure);
  }
}

Cela nous permet d’afficher les lectures actuelles du capteur sur la page Web lorsque vous y accédez pour la première fois. Sinon, vous verriez un espace vide jusqu’à ce que de nouvelles lectures soient disponibles (ce qui peut prendre un certain temps en fonction du délai que vous avez défini sur le code).

Construire la page Web

La variable index_html contient tout le HTML, CSS et JavaScript pour construire la page Web.

Remarque : pour la simplicité de ce tutoriel, nous plaçons tout le nécessaire pour construire la page Web sur la variable index_html que nous utilisons sur le sketch Arduino. Notez qu’il peut être plus pratique d’avoir des fichiers HTML, CSS et JavaScript séparés que vous téléchargez ensuite sur le système de fichiers ESP32 et que vous les référencez dans le code.

Voici la variable index_html de contenu :

<!DOCTYPE HTML>
<html>
<head>
  <title>ESP 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: Arial; 
      display: inline-block; 
      text-align: center;
    }
    p { 
      font-size: 1.2rem;
    }
    body {  
      margin: 0;
    }
    .topnav { 
      overflow: hidden; 
      background-color: #50B8B4; 
      color: white; 
      font-size: 1rem; 
    }
    .content { 
      padding: 20px; 
    }
    .card { 
      background-color: white; 
      box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5); 
    }
    .cards { 
      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>BME280 WEB SERVER (SSE)</h1>
  </div>
  <div class="content">
    <div class="cards">
      <div class="card">
        <p><i class="fas fa-thermometer-half" style="color:#059e8a;"></i> TEMPERATURE</p>
        <p><span class="reading"><span id="temp">%TEMPERATURE%</span> &deg;C</span></p>
      </div>
      <div class="card">
        <p><i class="fas fa-tint" style="color:#00add6;"></i> HUMIDITY</p>
        <p><span class="reading"><span id="hum">%HUMIDITY%</span> &percnt;</span></p>
      </div>
      <div class="card">
        <p><i class="fas fa-angle-double-down" style="color:#e1e437;"></i> PRESSURE</p><p><span class="reading"><span id="pres">%PRESSURE%</span> hPa</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);

  source.addEventListener('pressure', function(e) {
    console.log("pressure", e.data);
    document.getElementById("pres").innerHTML = e.data;
  }, false);
}
</script>
</body>
</html>

Nous n’entrerons pas dans les détails sur le fonctionnement du HTML et du CSS. Nous allons juste voir comment gérer les événements envoyés par le serveur.

CSS

Entre les balises

, nous incluons les styles pour styliser la page Web à l’aide de CSS. N’hésitez pas à le modifier pour que la page Web s’affiche comme vous le souhaitez. Nous n’expliquerons pas le fonctionnement du CSS de cette page Web car il n’est pas pertinent pour ce didacticiel.

<style>
  html {
    font-family: Arial; 
    display: inline-block; 
    text-align: center;
  }
  p { 
    font-size: 1.2rem;
  }
  body {  
    margin: 0;
  }
  .topnav { 
    overflow: hidden; 
    background-color: #50B8B4; 
    color: white; 
    font-size: 1rem; 
  }
  .content { 
    padding: 20px; 
  }
  .card { 
    background-color: white; 
    box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5); 
  }
  .cards { 
    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

Entre les balises , nous ajoutons le contenu de la page Web visible par l’utilisateur.

<body>
  <div class="topnav">
    <h1>BME280 WEB SERVER (SSE)</h1>
  </div>
  <div class="content">
    <div class="cards">
      <div class="card">
        <p><i class="fas fa-thermometer-half" style="color:#059e8a;"></i> TEMPERATURE</p>
        <p><span class="reading"><span id="temp">%TEMPERATURE%</span> &deg;C</span></p>
      </div>
      <div class="card">
        <p><i class="fas fa-tint" style="color:#00add6;"></i> HUMIDITY</p>
        <p><span class="reading"><span id="hum">%HUMIDITY%</span> &percnt;</span></p>
      </div>
      <div class="card">
        <p><i class="fas fa-angle-double-down" style="color:#e1e437;"></i> PRESSURE</p><p><span class="reading"><span id="pres">%PRESSURE%</span> hPa</span></p>
      </div>
    </div>
  </div>

Il y a un titre 1 avec le contenu « BME280 WEB SERVER (SSE) ». C’est le texte qui s’affiche sur la barre supérieure. N’hésitez pas à modifier ce texte.

<h1>BME280 WEB SERVER (SSE)</h1>

Ensuite, nous affichons les lectures du capteur dans des balises div séparées. Jetons un coup d’œil rapide aux paragraphes qui affichent la température :

<p><i class="fas fa-thermometer-half" style="color:#059e8a;"></i> TEMPERATURE</p>
<p><span class="reading"><span id="temp">%TEMPERATURE%</span> &deg;C</span></p>

Le premier paragraphe affiche simplement le texte « TEMPÉRATURE ». Nous définissons la couleur et aussi une icône.

Dans le deuxième paragraphe, vous pouvez voir que l’espace réservé %TEMPERATURE% est entouré de balises . L’attribut HTML id est utilisé pour spécifier un identifiant unique pour un élément HTML.

Il est utilisé pour pointer vers un style spécifique ou il peut être utilisé par JavaScript pour accéder et manipuler l’élément avec cet identifiant spécifique. C’est ce que nous allons faire. Par exemple, lorsque le client reçoit un nouvel événement avec la dernière lecture de température, il met à jour l’élément HTML avec l’id « temp » avec la nouvelle lecture.

Un processus similaire est effectué pour mettre à jour les autres lectures.

JavaScript – Source d’événement

Le JavaScript se place entre les balises . Il est chargé d’initialiser une connexion EventSource avec le serveur et de gérer les événements reçus du serveur.

<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);

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

Voyons comment cela fonctionne.

Gérer les événements

Créez un nouvel objet EventSource et spécifiez l’URL de la page qui envoie les mises à jour. Dans notre cas, il s’agit de /events.

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

Une fois que vous avez instancié une source d’événement, vous pouvez commencer à écouter les messages du serveur avec addEventListener().

Ce sont les écouteurs d’événements par défaut, comme indiqué ici dans AsyncWebServer Documentation.

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);

Ensuite, ajoutez l’écouteur d’événement pour « température ».

source.addEventListener('temperature', function(e) {

Lorsqu’une nouvelle lecture de température est disponible, l’ESP32 envoie un événement (« température ») au client. Les lignes suivantes gèrent ce qui se passe lorsque le navigateur reçoit cet événement.

console.log("temperature", e.data);
document.getElementById("temp").innerHTML = e.data;

Fondamentalement, imprimez les nouvelles lectures sur la console du navigateur et placez les données reçues dans l’élément avec l’identifiant correspondant (« temp ») sur la page Web.

Un processeur similaire est fait pour l’humidité et la pression.

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

installation()

Dans le setup(), initialisez le Serial Monitor, initialisez le Wi-Fi et le capteur BME280.

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

Traiter les demandes

Lorsque vous accédez à l’adresse IP ESP32 sur la root/URL, envoyez le texte qui est stocké sur la variable index_html pour construire la page Web et passez le processeur comme argument, afin que tous les espaces réservés soient remplacés par les dernières lectures de capteur.

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

Source d’événement du serveur

Configurez la source d’événement sur le serveur.

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

Enfin, démarrez le serveur.

server.begin();

boucle()

Dans la boucle(), obtenez de nouvelles lectures de capteur :

getSensorReadings();

Imprimez les nouvelles lectures dans le moniteur série.

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

Enfin, envoyez des événements au navigateur avec les dernières lectures de capteur pour mettre à jour la page Web.

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

Manifestation

Après avoir inséré vos informations d’identification réseau sur les variables ssid et mot de passe, vous pouvez télécharger le code sur votre carte. N’oubliez pas de vérifier si vous avez sélectionné la bonne carte et le bon port COM.

Après avoir téléchargé le code, ouvrez le moniteur série à un débit en bauds de 115200 et appuyez sur le bouton EN/RST intégré. L’adresse IP ESP doit être imprimée.

Serveur Web ESP32 utilisant la démonstration du moniteur série des événements envoyés par le serveur

Ouvrez un navigateur sur votre réseau local et insérez l’adresse IP ESP32. Vous devriez avoir accès à la page Web pour surveiller les lectures du capteur.

Serveur Web BME280 utilisant les événements envoyés par le serveur ESP32

Les lectures sont mises à jour automatiquement toutes les 30 secondes.

En même temps, vous devriez obtenir de nouvelles lectures de capteur sur le moniteur série, comme indiqué dans l’écran d’impression précédent. De plus, vous pouvez vérifier si le client reçoit les événements. Sur votre navigateur, ouvrez la console en appuyant sur Ctrl+Maj+J.

Console du navigateur d'événements envoyés par le serveur Démonstration du serveur Web ESP2

Conclusion

Dans ce didacticiel, vous avez appris à utiliser les événements envoyés par le serveur avec l’ESP32. Les événements envoyés par le serveur permettent à une page Web (client) d’obtenir des mises à jour d’un serveur. Cela peut être utilisé pour afficher automatiquement les nouvelles lectures de capteur sur la page du serveur Web lorsqu’elles sont disponibles.

Nous avons un tutoriel similaire mais utilisant le capteur environnemental BME680. Vous pouvez consulter le tutoriel sur le lien suivant :

Au lieu des événements envoyés par le serveur, vous pouvez également utiliser le protocole WebSocket pour maintenir la page Web à jour. Jetez un œil au tutoriel suivant pour savoir comment configurer un serveur WebSocket avec l’ESP32 :

En savoir plus sur l’ESP32 avec nos ressources :

Cette vidéo vous emmène dans l’histoire de Raspberry Pi :

YouTube video