Click here to Skip to main content
15,867,315 members
Articles / Internet of Things / Arduino

ESP32 WEB Server with Asynchronous Technology and Internal File System

Rate me:
Please Sign up or sign in to vote.
3.81/5 (15 votes)
16 Jun 2022CPOL5 min read 28.7K   684   21   7
A work for exploring the Asynchronous WEB Server, the SPIFFS File system and the exploitation of the dual core
This work is my insight into the ESP32 board and deals with a creation of a not complex but non trivial application where an Asynchronous WEB Server can produce pages based on an internal File system and the control of the application by serial link runs in separate core.

Introduction

In the article is highlighted the ease with which one can create a complex application using the Asynchronous WEB Server, how and where to store the necessary files (JavaScript sources, style sheets, images, ...) and how to take advantage of the dual core board.

The WEB Server can be accessed by any device that has a browser, this application, in particular, was created with cell phone access in mind.

You can also get the sources from my site.

Background

The user must be practical in using Arduino IDE and programming in C ++.

The article assumes that the user has installed some components, however in a dedicated paragraph, it can find the necessary references to be able to use the application.

The user accesses the application which sends to the browser a form in which it is possible to change the time on the board, request the humidity and temperature values (DHT22 sensor)1) and view the contents of the File system.

Note for Arduino IDE

If the IDE isn't able to associate COM port this means the lack of the appropriate driver, below the procedure I followed to solve.

  • I have identified the USB to serial converter chip on my ESP32 board:
    • on Windows device manager appears under Other devices the chip name, (my is CP2102 USB to UART Bridge Controller),
    • I downloaded the .zip file that contains the chip driver from the manufacturer's website;
  • I installed the driver acting with the right mouse button on the silabser.inf file and choosing install.

Using the Code

The source included is a folder with all data needed. When it is installed on ESP32 board, you must activate the Sermig_Condor WiFi service and access the IP address 192.168.1.1 by a browser.

Eventually, some commands can be sent to the board via the serial port.

The main components are:

  • The asynchronous WEB Server
  • The SPIFFS (SPI Flash File Storage) file system is hosted in Flash memory. The File System contains all files needed to the application:
    • index.html
    • formgen.js a script for generating forms (see my article A JavaScript Form Generator)
    • formgen.css a style sheet for the generated form
    • image files
  • The use of both ESP32 board processor cores.

WEB Server Creation and Behavior

C++
...
#include <WiFi.h>
#include <AsyncTCP.h>
#include "ESPAsyncWebServer.h"
...
// SSID & Password ******************************************************
const char* ssid = "Sermig_Condor";
const char* password = "";
// IP Address ***********************************************************
IPAddress local_ip(192, 168, 1, 1);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
AsyncWebServer server(80);  // Object of WebServer(HTTP port, 80 is default)
---
void setup() {
  ...
  WiFi.softAP(ssid, password);
  delay(2000);  // to avoid crash on WiFi connection
  WiFi.softAPConfig(local_ip, gateway, subnet);
  Serial.printf("Connect to Access Point: %s\n",ssid);
  server.on("/", HTTP_ANY, [](AsyncWebServerRequest *request) {
  ...
  });
  server.onNotFound([](AsyncWebServerRequest *request){request->send(404);});
  server.serveStatic("/", SPIFFS, "/");
  server.begin();
  ...
}
void loop() {
    // this can be empty
}

In the above fragment, note the required sources, the setting of the access parameters (name, IP address, etc.) and the processing of requests.

The dealing of the requests is on:

  • server.on(... where the first parameters is the resource request in the example is the root, the second parameter tells what type of request is accepted, HTTP_ANY is both HTTP_GET and HTTP_PUT. This means that the eventual parameters of a request can be in the inline form ?key=value as in a submitted form; the third parameter is the function which will process the request. server.on must be present for each request that needs special processing.
  • server.onNotFound(... for deals with unknown resource requested.
  • server.serveStatic("/", SPIFFS, "/"); this tells WEB Server to send the files request by the browser that are contained in the SPIFFS Filesystem such as images, style sheets, JavaScript sources, etc. This means we don't have to deal with mime types of files requested.

The choice for interacting with the board has been to put the request directly after the address:

C++
server.on("/", HTTP_ANY, [](AsyncWebServerRequest *request) {
 if(request->hasArg("fnz")) {
   String type = request->arg("fnz");
   AsyncResponseStream *response = request->beginResponseStream("text/html");
   if (type == "Dir") {           // send Filesystem contents
      response->print(dir());
      request->send(response);
   } else if (type == "Clock") {  // set an internal Clock
      setTime(toSeconds(request->arg("time").c_str()));
      response->printf("New time: %s", getTime());
      request->send(response);
   } else if (type == "Temp") {   // get humidity and temperature
      response->printf("%s %s",getTime(),getTemperature());
      request->send(response);
   }
  } else request->send(SPIFFS, "/index.html");  // send the form

The fragment above handles the request that has the form /[GET data] the object request exposes methods for getting the parameters and for sending the responses, if no parameters are found, it is sent the initial page, i.e., the file index.html; so the requests and responses can be:

192.168.1.1 The form is sent (index.html)
192.168.1.1/fnz=Clock&time=hh:mm:ss An internal clock is updated
192.168.1.1/fnz=Dir The content of Filesystem is sent
192.168.1.1/fnz=Temp The humidity and temperature values are sent

The data for the requests are sent as plain text but can contain HTML tags like the function below that shows the Filesystem contents:

C++
String dir(void) {
   String x = "<table>";
   File root = SPIFFS.open("/");
   if(!root) {
        return "Failed to open directory";
    }
    if(!root.isDirectory()) {
        return "Not a directory";
    }
    File file = root.openNextFile();
    while(file) {
         x += "<tr><td>"+String(file.name());
        if(file.isDirectory()){
          x += "<td>DIR";
        } else {
          x += "<td style='text-align:right'>"+String(file.size());
        }
        file = root.openNextFile();
    }
    x += "<tr><td>Occupied space<td style='text-align:right'>"+String(SPIFFS.usedBytes());
    x += "<tr><td>Total space<td style='text-align:right'>"+String(SPIFFS.totalBytes());
    return x+"</table>";
}

It is possible to interact with the board by Serial link sending the commands:

  • d[ir] for displaying the contents of the FileSystem
  • r resets the board
  • t for seeing humidity and temperature

The serial listener runs in core 0, in the fragment below, it is shown how this is realized.

C++
void serialListener( void * pvParameters ) {  // this runs in core 0
  Serial.print("Serial Listener running on core ");
  Serial.println(xPortGetCoreID());
  delay(100);
  for(;;){
    while (Serial.available() > 0) {
      char cmd = Serial.read() | 0b00100000;
      switch (cmd) {
        case 100:         // d[ir]
          dir_ls();
          break;
        case 114:         // r reset Board
          Serial.print("\nReset board\n");
          delay(200);
          ESP.restart();
          break;
        case 116:         // t get temperature/humidity
          sprintf(workBuffer, "%s %s", getTime(),getTemperature());
          Serial.println(workBuffer);
          break;
      }
    }
    vTaskDelay(150 / portTICK_PERIOD_MS);   // 150 millisecond
  }
}
void setup() { 
...
  xTaskCreatePinnedToCore (
      serialListener,     /* Function to implement the task */
      "WiFi-WEBServer",   /* Name of the task */
      10000,              /* Stack size in words */
      NULL,               /* Task input parameter */
      1,                  /* Priority of the task */
      NULL,               /* Task handle. */
      0);                 /* Core where the task should run */
}

Notes on Components

Asynchronous WEB Server

Documentation: https://github.com/me-no-dev/ESPAsyncWebServer

We need the two libraries below:

and unzip under the Arduino libraries folder taking care to delete the suffix -master from the folder name.

SPIFFS Filesystem

SPIFFS Filesystem is useful but has certain limitations see here the documentation.

  • It has a flat structure, i.e., it does not support directories.
  • For now, it does not detect or handle bad blocks.
  • The flash memory is limited to 10,000 write cycles.
  • File name with extension is limited to 31 characters.

Installation (from this tutorial):

  • Create a folder named data in the sketch folder where put the "site" files.
  • Download the file ESP32FS-1.0.zip.
  • Unzip the downloaded .zip folder to the Arduino Tools folder (if is locate in ...\ArduinoData\packages and if it not exists must be created).

If the installation is successful in the IDE menu Tools appears the item ESP32 Sketch Data Upload that it permits to upload the contents of the folder data into the SPIFFS File system.2)

We can see the File system dimension by Tools −> Partition Scheme.

Conclusion

The Asynchronous WEB Server together with a File system allows to build non-trivial applications where the developer only has to worry about the logic of the application.

Notes

1) The application however can run without this sensor.
2) The upload uses the serial port so close any serial monitor.

History

  • 27th April, 2021: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Condor Informatique
Italy Italy
Computer literacy (software) : Languages: PHP, Javascript, SQL Autoit,Basic4Android; Frameworks: JOOMLA!
Teaching/Training skills on Office, WEB site development and programming languages.
Others : WEB site development.
UNDP Missions
feb – may 2003 Congo DR Bukavu: ground IT computer course
nov 2003 Burundi Bujumbura: Oracle Data Base course
feb 2005 Burundi Bujumbura: JAVA course
mar 2005 Mali Kati: MS Office course
oct 2006 Mali Kati: MS Office course
jun 2006 Burkina Faso Bobo Dioulasso: MS Office course
jun 2007 Burkina Faso Bobo Dioulasso: MS Office course
may 2007 Argentina Olavarria hospital: Internet application for access to medical records
apr 2008 Burkina Faso Ouagadougou: MS ACCESS and dynamic Internet applications
jun 2008 Niger Niamey: analysis of the computing needs of the Niamey hospital
may 2009 Burkina Faso Ouagadougou: MS ACCESS and dynamic Internet applications
oct 2010 Niger Niamey: analysis of the computing needs of the Niamey hospital (following)
Region Piedmont project Evaluation
mar 2006 Burkina Faso, Niger
mar 2007 Benin, Burkina Faso, Niger
sep 2008 Benin, Burkina Faso, Niger
Others
feb 2010 Burundi Kiremba hospital: MS Office course
feb 2011 Congo DR Kampene hospital: MS Office course

Comments and Discussions

 
Questiondescription different from the source code ?!? Pin
kst116-Jun-22 0:39
kst116-Jun-22 0:39 
AnswerRe: description different from the source code ?!? Pin
Member 420697416-Jun-22 5:41
Member 420697416-Jun-22 5:41 
Hi kst1
I apologize, it was an old teorically unpublished version.
I updated the zip file in my site www.condorinformatique.com and I am updatinng also CodeProject site.
Best regards
Giovanni Rossati

(PS I am working on a new version with FAT file system)
GeneralDifference solved by a newer version from Jun 2022 Pin
kst116-Jun-22 6:27
kst116-Jun-22 6:27 
GeneralRe: Difference solved by a newer version from Jun 2022 Pin
Member 420697416-Jun-22 8:57
Member 420697416-Jun-22 8:57 
AnswerDifference solved by a newer version from Jun 2022 Pin
kst117-Jun-22 4:01
kst117-Jun-22 4:01 
GeneralRe: Difference solved by a newer version from Jun 2022 Pin
Member 420697417-Jun-22 9:45
Member 420697417-Jun-22 9:45 
GeneralMy vote of 5 Pin
Ștefan-Mihai MOGA25-May-22 0:26
professionalȘtefan-Mihai MOGA25-May-22 0:26 
PraiseMessage Closed Pin
26-Apr-21 23:17
garden deco26-Apr-21 23:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.