65.9K
CodeProject 正在变化。 阅读更多。
Home

ESP32 Web 服务器(异步技术和内部文件系统)

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.81/5 (15投票s)

2021年4月27日

CPOL

5分钟阅读

viewsIcon

32948

downloadIcon

756

一项探索异步 Web 服务器、SPIFFS 文件系统和双核利用的工程

引言

文章重点介绍了使用异步 Web 服务器创建复杂应用程序的简便性,以及如何以及在哪里存储必要的文件(JavaScript 源文件、样式表、图像等)以及如何利用双核板。

任何拥有浏览器的设备都可以访问 Web 服务器,此应用程序尤其考虑了手机访问。

您也可以从 我的网站获取源代码。

背景

用户必须熟练使用 Arduino IDE 并用 C++ 编程。

文章假设用户已安装某些组件,但在专门的段落中,他们可以找到使用该应用程序所需的参考。

用户访问应用程序,该应用程序向浏览器发送一个表单,在该表单中可以更改板上的时间、请求湿度和温度值(DHT22 传感器)1) 并查看文件系统的内容。

Arduino IDE 注意事项

如果 IDE 无法关联 COM 端口,则表示缺少相应的驱动程序,以下是我为解决此问题而遵循的步骤。

  • 我已识别出我的 ESP32 板上的 USB 转串行转换器芯片
    • 在 Windows 设备管理器中,它出现在 其他设备 下方的芯片名称(我的是 CP2102 USB to UART Bridge Controller),
    • 我从制造商网站下载了包含芯片驱动程序的 .zip 文件;
  • 我通过右键单击 silabser.inf 文件并选择 安装 来安装驱动程序。

Using the Code

包含的源代码是一个包含所有必要数据的文件夹。当它安装在 ESP32 板上时,您必须激活 Sermig_Condor WiFi 服务,并通过浏览器访问 IP 地址 192.168.1.1

最终,可以通过串行端口将某些命令发送到板。

主要组件是

  • 异步 Web 服务器
  • SPIFFS (SPI Flash File Storage) 文件系统托管在 Flash 内存中。文件系统包含应用程序所需的所有文件
    • index.html
    • formgen.js 一个用于生成表单的脚本(请参阅我的文章 A JavaScript Form Generator
    • formgen.css 一个用于生成表单的样式表
    • 图像文件
  • 同时使用 ESP32 板的两个处理器核心。

Web 服务器的创建和行为

...
#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
}

在上面的片段中,请注意所需的源代码、访问参数(名称、IP 地址等)的设置以及请求的处理。

请求的处理在

  • server.on(... 其中第一个参数是资源请求,在示例中是根目录,第二个参数指示接受哪种类型的请求,HTTP_ANY 同时接受 HTTP_GETHTTP_PUT。这意味着请求的任何参数都可以采用内联形式 ?key=value,就像在提交的表单中一样;第三个参数是处理请求的函数。对于每个需要特殊处理的请求,都必须存在 server.on
  • server.onNotFound(... 用于处理未知资源请求。
  • server.serveStatic("/", SPIFFS, "/"); 这告诉 Web 服务器发送浏览器请求的、包含在 SPIFFS 文件系统中的文件,例如图像、样式表、JavaScript 源文件等。这意味着我们不必处理请求文件的 MIME 类型。

与板交互的选择是将请求直接放在地址之后

  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

上面的片段处理形式为 /[GET data] 的请求,对象请求公开了获取参数和发送响应的方法;如果没有找到参数,则发送初始页面,即文件 index.html;因此,请求和响应可以是

192.168.1.1 发送表单(index.html
192.168.1.1/fnz=Clock&time=hh:mm:ss 内部时钟已更新
192.168.1.1/fnz=Dir 发送文件系统内容
192.168.1.1/fnz=Temp 发送湿度和温度值

请求的数据以纯文本形式发送,但可以包含 HTML 标签,例如下面显示文件系统内容的函数

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>";
}

可以通过串行链接发送命令与板进行交互

  • d[ir] 用于显示文件系统内容
  • r 重启板
  • t 查看湿度和温度

串行监听器在核心 0 上运行,在下面的片段中,展示了它是如何实现的。

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 */
}

组件说明

异步 Web 服务器

文档: https://github.com/me-no-dev/ESPAsyncWebServer

我们需要以下两个库

并将它们解压缩到 Arduino 的 libraries 文件夹中,注意删除文件夹名称中的 -master 后缀。

SPIFFS 文件系统

SPIFFS 文件系统很有用,但也有一些限制,请在此 处查看文档

  • 它具有扁平结构,即不支持目录。
  • 目前,它不会检测或处理坏块。
  • 闪存的写入次数限制为 10,000 次。
  • 带扩展名的文件名最多限制为 31 个字符。

安装(来自此 教程

  • sketch 文件夹中创建一个名为 data 的文件夹,并将“site”文件放在其中。
  • 下载文件 ESP32FS-1.0.zip
  • 将下载的 .zip 文件夹解压缩到 Arduino 的 Tools 文件夹(如果位于 ...\ArduinoData\packages 并且不存在,则必须创建它)。

如果安装成功,IDE 菜单 Tools 中会出现 ESP32 Sketch Data Upload 项,它允许将 data 文件夹的内容上传到 SPIFFS 文件系统。2)

我们可以通过 **Tools** −> **Partition Scheme** 查看文件系统大小。

结论

异步 Web 服务器与文件系统结合使用,可以构建非平凡的应用程序,开发者只需关注应用程序的逻辑。

注释

1) 该应用程序可以独立于此传感器运行。
2) 上传使用串行端口,请关闭任何串行监视器。

历史

  • 2021 年 4 月 27:初始版本
© . All rights reserved.