Serveur Web NodeMCU ESP8266 : afficher les lectures du capteur dans le tableau de bord

Découvrez comment utiliser le NodeMCU ESP8266 pour créer un serveur Web permettant d'afficher les lectures des capteurs dans un tableau de bord. Par exemple, nous afficherons la température et l'humidité du capteur BME280 sur deux compteurs différents : linéaire et radial. Vous pouvez facilement modifier le projet pour tracer d'autres données. Pour construire la jauge, nous utiliserons la bibliothèque JavaScript Canvas-Gauges.

 

Aperçu du projet

Ce projet utilisera l'ESP8266 pour créer un serveur Web qui affiche les relevés de température et d'humidité du capteur BME280. Nous allons créer une jauge linéaire qui ressemble à un thermomètre pour afficher la température, et une jauge radiale pour afficher l'humidité.

 

Événements envoyés par le serveur

Utilisez les événements envoyés par le serveur (SSE) pour mettre automatiquement à jour les lectures sur la page Web.

Fichiers enregistrés sur le système de fichiers

 Pour rendre notre projet mieux organisé et plus facile à comprendre, nous enregistrerons les fichiers HTML, CSS et JavaScript pour créer la page Web sur le système de fichiers du forum (LittleFS).

conditions préalables

Avant de poursuivre le projet, assurez-vous de vérifier tous les prérequis dans cette section.

1. Installez la carte de développement ESP8266 dans l'IDE Arduino

Nous utiliserons l'IDE Arduino pour programmer l'ESP8266. Par conséquent, vous devez installer le plug-in ESP8266. Si vous ne l'avez pas encore fait, recherchez le tutoriel pour l'installer vous-même : Installez la carte de développement ESP8266 dans l'IDE Arduino (Windows, Mac OS X, Linux).

Si vous souhaitez utiliser VS Code avec l'extension PlatformIO, recherchez vous-même un didacticiel pour apprendre à programmer l'ESP8266 : Démarrez avec VS Code et PlatformIO IDE pour ESP32 et ESP8266 (Windows, Mac OS X, Linux Ubuntu).

2. Plug-in de téléchargement du système de fichiers

Pour télécharger des fichiers HTML, CSS et JavaScript sur le système de fichiers ESP8266 (LittleFS), nous utiliserons un plugin pour l'IDE Arduino :   LittleFS  Filesystem Uploader . Veuillez rechercher le didacticiel pour installer vous-même le plug-in de téléchargement du système de fichiers : Installez le programme de téléchargement du système de fichiers ESP8266 NodeMCU LittleFS dans l'IDE Arduino.

Si vous utilisez VS Code avec l'extension PlatformIO, recherchez vous-même un didacticiel pour apprendre à télécharger des fichiers sur le système de fichiers : ESP8266 NodeMCU avec VS Code et PlatformIO : Téléchargement de fichiers sur le système de fichiers (LittleFS).

3. Installez la bibliothèque

Pour construire ce projet, vous devez installer les bibliothèques suivantes :

Vous pouvez installer les trois premières bibliothèques à l'aide du gestionnaire de bibliothèques Arduino. Accédez à  Sketch   >   Inclure la bibliothèque   >   Gérer les bibliothèques  et recherchez le nom de la bibliothèque.

Les bibliothèques ESPAsyncWebServer et ESPAsynTCP ne peuvent pas être installées via Arduino Library Manager, vous devez donc copier les fichiers de bibliothèque dans le dossier Arduino Installation Libraries. Vous pouvez également télécharger le dossier .zip de la bibliothèque, puis dans votre IDE Arduino, accédez à  Sketch   >   Inclure la bibliothèque   >   Ajouter une bibliothèque .zip  et sélectionnez la bibliothèque que vous venez de télécharger.

Installer la bibliothèque (VS Code + PlatformIO)

Si vous utilisez PlatformIO pour programmer l'ESP8266, vous devez ajouter les lignes suivantes au fichier platformio.ini pour inclure la bibliothèque, modifier la vitesse du moniteur série à 115200 et utiliser LittleFS pour le système de fichiers :

Pièces requises

Pour suivre ce tutoriel vous aurez besoin des pièces suivantes :

  • Carte de développement ESP8266
  • Capteur BME280
  • Sauteur
  • Planche à pain

Vous pouvez utiliser n'importe quel autre capteur, ou afficher toute autre valeur utile pour votre projet. Si vous n'avez pas de capteur, vous pouvez également essayer d'utiliser des valeurs aléatoires pour voir comment fonctionne l'élément.

Diagramme schématique, diagramme schématique

Nous enverrons les relevés de température et d'humidité du capteur BME280. Nous utiliserons la communication I2C avec le module capteur BME280. Pour ce faire, connectez les capteurs aux broches par défaut ESP8266 SCL ( interface 5 ) et SDA ( interface 4 ), comme indiqué dans l'image ci-dessous.

 

Organiser les fichiers

Pour garder le projet organisé et le rendre plus facile à comprendre, nous allons créer quatre fichiers pour construire le serveur Web :

  • Code du serveur Arduino qui gère le serveur web ;
  • index.html : Définir le contenu de la page Web ;
  • sytle.css : Définissez le style de la page Web ;
  • script.js : Programmer le comportement des pages Web - gérer les réponses du serveur Web, les événements, créer une instrumentation, etc.

Vous devez enregistrer les fichiers HTML, CSS et JavaScript dans  un dossier appelé data à l'intérieur du dossier de croquis Arduino, comme indiqué dans l'image ci-dessus.  Nous téléchargerons ces fichiers sur le système de fichiers ESP8266 (LittleFS).

Fichier HTML

Copiez le contenu suivant dans le fichier index.html .

<!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" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" href="style.css">
    <script src="http://cdn.rawgit.com/Mikhus/canvas-gauges/gh-pages/download/2.1.7/all/gauge.min.js"></script>
  </head>
  <body>
    <div class="topnav">
      <h1>ESP WEB SERVER GAUGES</h1>
    </div>
    <div class="content">
      <div class="card-grid">
        <div class="card">
          <p class="card-title">Temperature</p>
          <canvas id="gauge-temperature"></canvas>
        </div>
        <div class="card">
          <p class="card-title">Humidity</p>
          <canvas id="gauge-humidity"></canvas>
        </div>
      </div>
    </div>
    <script src="script.js"></script>
  </body>
</html>

Le fichier HTML de ce projet est très simple. Il inclut la bibliothèque JavaScript Canvas-Gauges en tête du fichier HTML :

<script src="https://cdn.rawgit.com/Mikhus/canvas-gauges/gh-pages/download/2.1.7/all/gauge.min.js"></script>

Il y a une balise <canvas> avec un identifiant mesurant la température, où nous restituerons le thermomètre plus tard.

<canvas id="gauge-temperature"></canvas>

Il existe également une balise <canvas> avec un identifiant mesurant l'humidité , où nous restituerons l'hygromètre plus tard.

<canvas id="gauge-humidity"></canvas>

document

Copiez les styles suivants dans votre fichier style.css . Il utilise des couleurs et des styles simples pour concevoir des pages Web.

html {
  font-family: Arial, Helvetica, sans-serif; 
  display: inline-block; 
  text-align: center;
}
h1 {
  font-size: 1.8rem; 
  color: white;
}
p { 
  font-size: 1.4rem;
}
.topnav { 
  overflow: hidden; 
  background-color: #0A1128;
}
body {  
  margin: 0;
}
.content { 
  padding: 5%;
}
.card-grid { 
  max-width: 1200px; 
  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
}

Fichier JavaScript (créer un instrument)

Copiez le contenu suivant dans le fichier script.js .

// Get current sensor readings when the page loads  
window.addEventListener('load', getReadings);

// Create Temperature Gauge
var gaugeTemp = new LinearGauge({
  renderTo: 'gauge-temperature',
  width: 120,
  height: 400,
  units: "Temperature C",
  minValue: 0,
  startAngle: 90,
  ticksAngle: 180,
  maxValue: 40,
  colorValueBoxRect: "#049faa",
  colorValueBoxRectEnd: "#049faa",
  colorValueBoxBackground: "#f1fbfc",
  valueDec: 2,
  valueInt: 2,
  majorTicks: [
      "0",
      "5",
      "10",
      "15",
      "20",
      "25",
      "30",
      "35",
      "40"
  ],
  minorTicks: 4,
  strokeTicks: true,
  highlights: [
      {
          "from": 30,
          "to": 40,
          "color": "rgba(200, 50, 50, .75)"
      }
  ],
  colorPlate: "#fff",
  colorBarProgress: "#CC2936",
  colorBarProgressEnd: "#049faa",
  borderShadowWidth: 0,
  borders: false,
  needleType: "arrow",
  needleWidth: 2,
  needleCircleSize: 7,
  needleCircleOuter: true,
  needleCircleInner: false,
  animationDuration: 1500,
  animationRule: "linear",
  barWidth: 10,
}).draw();
  
// Create Humidity Gauge
var gaugeHum = new RadialGauge({
  renderTo: 'gauge-humidity',
  width: 300,
  height: 300,
  units: "Humidity (%)",
  minValue: 0,
  maxValue: 100,
  colorValueBoxRect: "#049faa",
  colorValueBoxRectEnd: "#049faa",
  colorValueBoxBackground: "#f1fbfc",
  valueInt: 2,
  majorTicks: [
      "0",
      "20",
      "40",
      "60",
      "80",
      "100"

  ],
  minorTicks: 4,
  strokeTicks: true,
  highlights: [
      {
          "from": 80,
          "to": 100,
          "color": "#03C0C1"
      }
  ],
  colorPlate: "#fff",
  borderShadowWidth: 0,
  borders: false,
  needleType: "line",
  colorNeedle: "#007F80",
  colorNeedleEnd: "#007F80",
  needleWidth: 2,
  needleCircleSize: 3,
  colorNeedleCircleOuter: "#007F80",
  needleCircleOuter: true,
  needleCircleInner: false,
  animationDuration: 1500,
  animationRule: "linear"
}).draw();

// Function to get current readings on the webpage when it loads for the first time
function getReadings(){
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      var myObj = JSON.parse(this.responseText);
      console.log(myObj);
      var temp = myObj.temperature;
      var hum = myObj.humidity;
      gaugeTemp.value = temp;
      gaugeHum.value = hum;
    }
  }; 
  xhr.open("GET", "/readings", true);
  xhr.send();
}

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('new_readings', function(e) {
    console.log("new_readings", e.data);
    var myObj = JSON.parse(e.data);
    console.log(myObj);
    gaugeTemp.value = myObj.temperature;
    gaugeHum.value = myObj.humidity;
  }, false);
}

Voici un résumé de ce que fait ce code :

  • Initialiser le protocole de la source d'événement ;
  • pour l' événement new_readings ;
  • Créer des instruments ;
  • Obtenez les dernières lectures des capteurs de l'événement new_readings et affichez-les dans la jauge correspondante ;
  • Lorsque vous accédez pour la première fois à une page Web, une requête HTTP GET est effectuée pour la lecture actuelle du capteur.

Obtenez des lectures

Lorsque vous visitez une page Web pour la première fois, nous demandons au serveur d'obtenir les lectures actuelles du capteur. Sinon, nous devrons attendre l'arrivée de nouvelles lectures du capteur (via des événements envoyés par le serveur), ce qui peut prendre un certain temps en fonction de l'intervalle de temps que vous avez défini sur le serveur.

Ajoutez un écouteur d'événements qui est appelé pour que les lectures s'exécutent lors du chargement de la page Web.

// Get current sensor readings when the page loads
window.addEventListener('load', getReadings);

Cet objet fenêtre représente une fenêtre ouverte dans le navigateur. Cela ajoute la méthode event listeningr() pour configurer une fonction à appeler lorsqu'un événement spécifique se produit. Dans ce cas, nous appellerons la fonction Get Readings lors du chargement de la page ( 'load' ) pour obtenir les lectures actuelles du capteur.

Examinons maintenant la fonction Obtenir des lectures . Créez un nouvel objet XMLHttpRequest . Ensuite, envoyez une requête get /read URL au serveur à l’aide des méthodes open() et send() .

function getReadings() {
  var xhr = new XMLHttpRequest();
  xhr.open("GET", "/readings", true);
  xhr.send();
}

Lorsque nous enverrons cette demande, ESP enverra une réponse contenant les informations requises. Nous devons donc gérer ce qui se passe lorsque la réponse est reçue. Nous utiliserons onreadystatechange pour définir les propriétés d'une fonction lorsque la propriété d'état prêt change. Cette propriété ReadyState contient l'état de XMLHttpRequest . Lorsque la réponse à la demande est prête, l'état Prêt est 4 et l'état est 200 .

  • L'état Prêt = 4 signifie que la demande est terminée et que la réponse est prête ;
  • status = 200 signifie "ok"

La requête devrait donc ressembler à ceci :

function getStates(){
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      … DO WHATEVER YOU WANT WITH THE RESPONSE …
    }
  };
  xhr.open("GET", "/states", true);
  xhr.send();
}

La réponse envoyée par ESP est le texte suivant au format JSON (ce ne sont que des valeurs arbitraires).

{
  "temperature" : "25.02",
  "humidity" : "64.01",
}

Nous devons convertir la chaîne JSON en objet JSON à l’aide de la méthode parse() . Le résultat est enregistré dans la variable myObj .

var myObj = JSON.parse(this.responseText);

La variable myObj est un objet JSON contenant des relevés de température et d'humidité. Nous souhaitons mettre à jour la valeur du compteur avec la lecture correspondante.

La mise à jour de la valeur d'un compteur est simple. Par exemple, notre thermomètre s'appelle Gauge Temp (nous le verrons plus tard), et pour mettre à jour une valeur nous pouvons simplement appeler : gaugeTemp.value = NEW_VALUE . Dans notre cas, la nouvelle valeur est un objet JSON enregistré dans myObj

gaugeTemp.value = myObj.temperature;

C'est similaire à l'humidité (notre hygromètre s'appelle un compteur buzz ).

gaugeHum.value = myObj.humidity;

Il s'agit de la fonction getRead() complète .

function getReadings(){
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      var myObj = JSON.parse(this.responseText);
      console.log(myObj);
      var temp = myObj.temperature;
      var hum = myObj.humidity;
      gaugeTemp.value = temp;
      gaugeHum.value = hum;
    }
  }; 
  xhr.open("GET", "/readings", true);
  xhr.send();
}

Créer une jauge

La bibliothèque de graphiques en toile vous permet de créer des jauges linéaires et radiales pour afficher vos lectures. Il fournit plusieurs exemples et est très simple à utiliser. Nous vous recommandons de consulter la documentation et d'explorer toutes les fonctionnalités de l'instrumentation :

thermomètre

Les lignes suivantes créent une jauge qui affiche la température.

// Create Temperature Gauge
var gaugeTemp = new LinearGauge({
  renderTo: 'gauge-temperature',
  width: 120,
  height: 400,
  units: "Temperature C",
  minValue: 0,
  startAngle: 90,
  ticksAngle: 180,
  maxValue: 40,
  colorValueBoxRect: "#049faa",
  colorValueBoxRectEnd: "#049faa",
  colorValueBoxBackground: "#f1fbfc",
  valueDec: 2,
  valueInt: 2,
  majorTicks: [
      "0",
      "5",
      "10",
      "15",
      "20",
      "25",
      "30",
      "35",
      "40"
  ],
  minorTicks: 4,
  strokeTicks: true,
  highlights: [
      {
          "from": 30,
          "to": 40,
          "color": "rgba(200, 50, 50, .75)"
      }
  ],
  colorPlate: "#fff",
  colorBarProgress: "#CC2936",
  colorBarProgressEnd: "#049faa",
  borderShadowWidth: 0,
  borders: false,
  needleType: "arrow",
  needleWidth: 2,
  needleCircleSize: 7,
  needleCircleOuter: true,
  needleCircleInner: false,
  animationDuration: 1500,
  animationRule: "linear",
  barWidth: 10,
}).draw();

Pour créer une nouvelle jauge linéaire, utilisez la nouvelle  méthode LinearGauge() et transmettez les propriétés de la jauge en tant que paramètres.

var gaugeTemp = new LinearGauge({
     
     

Dans la ligne suivante, définissez l'endroit où vous souhaitez que le graphique soit placé (il doit s'agir d'un élément <canvas> ). Dans notre cas, nous voulons le mettre dans un élément HTML <canvas> avec l'identifiant de température mesurée - voir la section du fichier HTML.

renderTo: 'gauge-temperature',

Ensuite, nous définissons des propriétés supplémentaires pour personnaliser notre jauge. Le nom est explicite, mais nous vous recommandons d'examiner toutes les configurations possibles et de modifier le compteur en fonction de vos besoins.

Enfin, vous devez appliquer la méthode draw() pour afficher réellement la jauge sur le canevas.

}).draw();

Portez une attention particulière au fait que si vous devez modifier la plage, vous devez modifier les caractéristiques minimales et maximales :

minValue: 0,
maxValue: 40,

Vous devrez également ajuster les valeurs affichées sur l'axe du marqueur principal.

majorTicks: [
    "0",
    "5",
    "10",
    "15",
    "20",
    "25",
    "30",
    "35",
    "40"
],

hygromètre

La création d'un hygromètre est similaire, mais nous utilisons à la place la nouvelle fonction RadialGauge(), qui est présentée au <canvas> avec l'ID d'humidité mesurée . Notez que nous appliquons la méthode draw() sur le compteur afin de le dessiner sur le canevas.

// Create Humidity Gauge
var gaugeHum = new RadialGauge({
  renderTo: 'gauge-humidity',
  width: 300,
  height: 300,
  units: "Humidity (%)",
  minValue: 0,
  maxValue: 100,
  colorValueBoxRect: "#049faa",
  colorValueBoxRectEnd: "#049faa",
  colorValueBoxBackground: "#f1fbfc",
  valueInt: 2,
  majorTicks: [
      "0",
      "20",
      "40",
      "60",
      "80",
      "100"

  ],
  minorTicks: 4,
  strokeTicks: true,
  highlights: [
      {
          "from": 80,
          "to": 100,
          "color": "#03C0C1"
      }
  ],
  colorPlate: "#fff",
  borderShadowWidth: 0,
  borders: false,
  needleType: "line",
  colorNeedle: "#007F80",
  colorNeedleEnd: "#007F80",
  needleWidth: 2,
  needleCircleSize: 3,
  colorNeedleCircleOuter: "#007F80",
  needleCircleOuter: true,
  needleCircleInner: false,
  animationDuration: 1500,
  animationRule: "linear"
}).draw();

gérer les événements

Mettre à jour les relevés sur le compteur lorsque le client reçoit les relevés sur l' événement new_readings du compteur

Créez un nouvel objet source d'événement et spécifiez l'URL de la page à laquelle envoyer les mises à jour. Dans notre cas, c'est /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 en ajoutant eventListener() .

Ce sont les écouteurs d'événements par défaut, comme indiqué dans la  documentation d'AsyncWebServer .

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énements new_readings .

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

Lorsque de nouvelles lectures sont disponibles, l'ESP8266 envoie un événement ( new_readings ) au client. Les lignes suivantes gèrent ce qui se passe lorsque le navigateur reçoit cet événement.

source.addEventListener('new_readings', function(e) {
  console.log("new_readings", e.data);
  var myObj = JSON.parse(e.data);
  console.log(myObj);
  gaugeTemp.value = myObj.temperature;
  gaugeHum.value = myObj.humidity;
}, false);

Fondamentalement, imprimez la nouvelle lecture sur la console du navigateur, convertissez les données en un objet JSON et affichez la lecture sur le compteur correspondant.

Présentation de l'Arduino

Copiez le code suivant dans votre fichier Arduino IDE ou main.cpp si vous utilisez PlatformIO.

/*********
  Rui Santos
  Complete instructions at https://RandomNerdTutorials.com/esp8266-web-server-gauges/
  
  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 <ESP8266WiFi.h>
#include <ESPAsyncTCP.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 an Event Source on /events
AsyncEventSource events("/events");

// 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;         // BME280 connect to ESP32 I2C (GPIO 21 = SDA, GPIO 22 = SCL)

// 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());
  String jsonString = JSON.stringify(readings);
  return jsonString;
}

// Initialize LittleFS
void initFS() {
  if (!LittleFS.begin()) {
    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 setup() {
  Serial.begin(115200);
  initBME();
  initWiFi();
  initFS();

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

  server.serveStatic("/", LittleFS, "/");
  
  // Request for the latest sensor readings
  server.on("/readings", HTTP_GET, [](AsyncWebServerRequest *request){
    String json = getSensorReadings();
    request->send(200, "application/json", json);
    json = String();
  });

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

  // Start server
  server.begin();
}

void loop() {
  if ((millis() - lastTime) > timerDelay) {
    // Send Events to the client with the Sensor Readings Every 30 seconds
    events.send("ping",NULL,millis());
    events.send(getSensorReadings().c_str(),"new_readings" ,millis());
    lastTime = millis();
  }
}

Comment fonctionne le code

Jetons un coup d'œil au code et voyons comment il utilise les événements envoyés par le serveur pour envoyer des lectures au client.

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 bibliothèques ESP8266WiFi , ESPAsyncWebServer et ESPAsyncTCP sont utilisées pour créer des serveurs Web.

#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>

Nous utiliserons LittleFS pour enregistrer les fichiers afin de créer un serveur Web.

#include "LittleFS.h"

Vous souhaiterez également inclure la bibliothèque Arduino_JSON qui facilite le travail avec les chaînes JSON.

#include <Arduino_JSON.h>

identifiants réseau

Insérez vos informations d'identification réseau dans les variables suivantes afin que l'ESP8266 puisse se connecter à votre réseau local via Wi-Fi.

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

AsyncWebServer et AsyncEventSource

Créez un objet serveur Web asynchrone sur le port 80.

AsyncWebServer server(80);

La ligne suivante crée une nouvelle source d'événement /event .

AsyncEventSource events("/events");

déclarer des variables

Les lectures  sont une variable JSON qui contient les lectures du capteur au format JSON.

JSONVar readings;

Les dernières variables de temps et de temporisation seront utilisées pour mettre à jour les lectures du capteur toutes les 30 secondes. Par exemple, nous obtiendrons une nouvelle lecture du capteur toutes les 30 secondes (30 000 millisecondes). Vous pouvez attribuer une valeur à une variable de délai de temporisation .

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

Créez un objet Adafruit_BME280 appelé bme sur la broche ESP I2C par défaut.

Adafruit_BME280 bme;

Initialiser le capteur BME280

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

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

Obtenez des lectures BME280

Pour obtenir la température et l'humidité à partir de la température du BME280, utilisez la méthode suivante pour les obtenir dans l' instance bme :

  • Méthode bme.readTemperature()
  • bme.readHumidity()

Cette fonction getSensorReading() récupère les lectures des capteurs et les enregistre dans un tableau JSON de lectures .

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

Cette lecture est ensuite convertie en variable de chaîne JSON à l'aide de la méthode stringify() et enregistrée dans la chaîne json de la variable.

Cette fonction renvoie une chaîne json qui change avec la lecture actuelle du capteur. La chaîne JSON a le format suivant (les valeurs ne sont que des nombres arbitraires à des fins d'explication).

{
  "temperature" : "25",
  "humidity" : "50"
}

Installation()

Dans setup() , initialisez le moniteur série, le Wi-Fi, le système de fichiers et le capteur BME280.

void setup() {
  // Serial port for debugging purposes
  Serial.begin(115200);
  initBME();
  initWiFi();
  initFS();

Traiter la demande

Lorsque vous accédez à l'adresse IP / URL de l'ESP8266 en tant que root , envoyez le fichier stocké dans index.html pour créer la page Web.

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

Servir d'autres fichiers statiques (style.cs et script.js) demandés par le client.

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

Lorsque vous recevez une demande, envoyez une chaîne JSON / URL de lecture contenant la lecture actuelle du capteur.

// Request for the latest sensor readings
server.on("/readings", HTTP_GET, [](AsyncWebServerRequest *request){
  String json = getSensorReadings();
  request->send(200, "application/json", json);
  json = String();
});

Cette variable JSON contient les lectures du capteur de la fonction get(). Pour envoyer une chaîne JSON en réponse, la méthode send() accepte le code de réponse comme premier paramètre ( 200 ), le second est le type de contenu ( "application/json" ) et enfin le contenu ( JSON mutable ).

Source d'événement du serveur

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

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

À l'intérieur de loop() , un événement est envoyé au navigateur avec la dernière lecture du capteur toutes les 30 secondes pour mettre à jour la page Web.

events.send("ping",NULL,millis());
events.send(getSensorReadings().c_str(),"new_readings" ,millis());

Utilisez la méthode send() sur l'objet événement et transmettez le contenu à envoyer et le nom de l'événement comme arguments. Dans ce cas, nous souhaitons envoyer les lectures du capteur envoyées par la fonction get(). Cette méthode send() accepte une variable de type char , nous devons donc utiliser la méthode c_str() pour convertir la variable. Le nom de l'événement est new_readings .

Généralement, nous envoyons également un message ping toutes les X secondes. Cette ligne n'est pas obligatoire. Il est utilisé côté client pour vérifier si le serveur est actif.

events.send("ping",NULL,millis());

Télécharger du code et des fichiers

Après avoir inséré les informations d'identification réseau, enregistrez le code. Accédez à  Sketch   >   Show Sketch Folder et créez un  dossier appelé data .

Dans ce dossier, vous devez enregistrer les fichiers HTML, CSS et JavaScript.

Ensuite, téléchargez le code sur votre carte ESP8266. Assurez-vous de sélectionner la bonne carte et le bon port COM. Assurez-vous également d'avoir ajouté vos informations d'identification réseau.

Après avoir téléchargé le code, vous devez télécharger le fichier. Accédez à  Outils  >   ESP8266 LittleFS Data Upload  et attendez que le fichier soit téléchargé.

Lorsque tout a été téléchargé avec succès, ouvrez le moniteur série à un débit en bauds de 115 200. Appuyez sur le bouton ESP8266 EN/RST et il devrait imprimer l'adresse IP de l'ESP8266.

manifestation

Ouvrez un navigateur et entrez l'adresse IP de l'ESP8266. Vous devriez pouvoir accéder à une page Web affichant le compteur avec les dernières lectures du capteur.

Vous pouvez également vérifier votre jauge à l'aide de votre smartphone (la page Web est adaptée aux mobiles).

Résumer

Dans ce didacticiel, vous avez appris à créer un serveur Web pour afficher les lectures des capteurs d'instruments linéaires et radiaux. Par exemple, nous affichons la température et l'humidité du capteur BME280. Vous pouvez utiliser ces jauges pour afficher toute autre valeur susceptible d'avoir un sens pour votre projet.

 

Je suppose que tu aimes

Origine blog.csdn.net/hhqidi/article/details/130983541
conseillé
Classement