samedi 14 octobre 2023

Septembre 2023 : Actualité des Blogs du Mois

 



Actualité des Blogs du Mois


Sur le blog d'Yves Pelletier :

Sur  Framboise 314 :

Sur  MCHobby :

Sur Anacorp :


Cordialement

Henri 

 

ESP32 : servir une image


ESP32 : servir une image

 

Lorsque l'on développe un WebServer sur ESP32, on utilise différentes librairies : 

  • WifiServer
  • WebServer
  • EspAsyncWebServer
  • etc.

Je ne vais pas rappeler les multiples avantages d'EspAsyncWebServer, mais il peut entre autres :

  • servir des fichiers HTML, JavaScript, images, etc. à partir du système de fichiers en FLASH
  • gérer des templates à la manière de Cheetah sur un serveur PC

Le cas de WifiServer est à part. Son utilisation se rapproche de celle de la librairie Arduino Ethernet, ce qui veut dire que l'effort de développement est très important. Il n'est même pas capable de récupérer les arguments au sein d'une URL de manière simple. Je n'en parlerai donc pas.

Voyons le cas d'une image.

1. Avec EspAsyncWebServer

EspAsyncWebServer n'est pas une librairie présente dans le package ESP32 standard. Il faut l'installer : 

  • en la téléchargeant depuis https://github.com/me-no-dev/ESPAsyncWebServer
  • à l'aide du gestionnaire de bibliothèques de l'IDE ARDUINO

Ce petit exemple renvoie une image au client :

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

const char *ssid = "xxxxx";
const char *password = "xxxxx";

AsyncWebServer server(80);

void handleNotFound(AsyncWebServerRequest * request) {
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += request->url();
  message += "\nMethod: ";
  message += request->methodToString();
  message += "\nArguments: ";
  message += request->args();
  message += "\n";
  for (uint8_t i = 0; i < request->args(); i++) {
    message += " " + request->argName(i) + ": " + request->arg(i) + "\n";
  }
  request->send(404, "text/plain", message);
}

void setup(void) {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  if (!SPIFFS.begin(true)) {
    Serial.println("An Error has occurred while mounting SPIFFS");
    return;
  }
  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send(200, "text/plain", "hello from esp32!");
  });
  server.on("/arduino.jpg", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send(SPIFFS, "/arduino.jpg", "image/jpg");
  });

  server.onNotFound(handleNotFound);

  server.begin();
  Serial.println("HTTP server started");
}

void loop(void) {
}

Ce code renvoie une image nommée arduino.jpg située à la racine du système de fichiers SPIFFS. Deux lignes suffisent (en gras).

2. Avec WebServer

WebServer est la librairie par défaut présente dans le package ESP32 standard.

Elle nécessite un effort de programmation un peu plus conséquent : 

    #include <WiFi.h>

    #include <WebServer.h>
    #include <FS.h>
    #include <SPIFFS.h>

    const char *ssid = "xxxxx";
    const char *password = "xxxxx";

    WebServer server(80);

    void handleRoot()
    {
      server.send(200, "text/plain", "hello from esp32!");
    }

    void handleImage()
    {
      File file = SPIFFS.open("/arduino.jpg");
      if (!file) {
        Serial.println("Failed to open file for reading");
        return;
      }
      if (server.streamFile(file, "image/jpg") != file.size()) {
        Serial.println("Sent less data than expected!");
      }
      file.close();
    }

    void handleNotFound() {
      String message = "File Not Found\n\n";
      message += "URI: ";
      message += server.uri();
      message += "\nMethod: ";
      message += (server.method() == HTTP_GET) ? "GET" : "POST";
      message += "\nArguments: ";
      message += server.args();
      message += "\n";
      for (uint8_t i = 0; i < server.args(); i++) {
        message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
      }
      server.send(404, "text/plain", message);
    }

    void setup(void) {
      Serial.begin(115200);
      WiFi.mode(WIFI_STA);
      WiFi.begin(ssid, password);
      Serial.println("");

      // Wait for connection
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      }
      Serial.println("");
      Serial.print("Connected to ");
      Serial.println(ssid);
      Serial.print("IP address: ");
      Serial.println(WiFi.localIP());

      if(!SPIFFS.begin(true)){
        Serial.println("An Error has occurred while mounting SPIFFS");
        return;
      }
      server.on("/", handleRoot);
      server.on("/arduino.jpg", handleImage);

      server.onNotFound(handleNotFound);

      server.begin();
      Serial.println("HTTP server started");
    }

    void loop(void) {
      server.handleClient();
    }

    Le code utilisé pour la gestion de l'image est également en gras. Il est un peu plus complexe. Il faut bien connaître la librairie WebServer pour s'en sortir, en particulier l'existence de la méthode streamFile().

    3. Les points communs

    Dans les deux cas, le fichier arduino.jpg doit être chargé dans le système de fichier SPIFFS. Ce fichier doit être créé dans un sous-répertoire data du projet : 

    projet / projet.ino

    ........../ data / arduino.jpg

    Le fichier doit être chargé dans la mémoire FLASH de l'ESP32 à l'aide du menu "Outils/ESP32 Sketch Data Upload".

    Avant cela, si ce n'est pas déjà fait, il faut installer le plugin :

    https://github.com/me-no-dev/arduino-esp32fs-plugin

    Pour essayer ces deux exemples, il suffit de les charger dans un ESP32, après avoir modifié ces deux lignes :

    const char *ssid = "xxxxx";
    const char *password = "xxxxx";

    Il suffit de remplacer xxxxx par vos identifiants WIFI.

    Ensuite entrez dans votre navigateur l'adresse IP affichée dans le serial monitor. Il affichera ceci :

    hello from esp32!

    Si vous ajoutez /arduino.jpg à l'URL (exemple : http://192.168.1.27/arduino.jpg) Il affichera l'image que vous avez choisi.

    On peut bien évidemment intégrer l'image dans une page HTML de son choix à l'aide de la balise adéquate : 

    <img src="arduino.jpg">

    4. Conclusion

    Bien que la version WebServer ne soit pas d'une complexité insurmontable, la version EspAsyncWebServer est nettement préférable, surtout si l'on considère que l'on pourra stocker dans SPIFFS non seulement des images, mais aussi le code HTML, et éventuellement JavaScript.

    Servir un fichier HTML ou JavaScript sera extrêmement simple : 

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

    Ensuite il reste à explorer les templates, qui prendront en charge les données variables des pages HTML.

    https://techtutorialsx.com/2018/07/22/esp32-arduino-http-server-template-processing/

    Les templates sont le point fort d'EspAsyncWebServer, et permettent de développer très simplement des serveurs assez conséquents.


    Cordialement

    Henri