ESPAsyncWebserver:如何在主循环线程中运行代码

使用 ESPAsyncWebserver 时,你很快会遇到其最基本的限制之一:其代码始终在中断中运行,因此你不能使用 delay() 或任何内部使用 delay() 或类似函数的函数。

然而,有一个简单的编程模式可以让你在 webserver 请求时在主线程中执行代码。***注意:***在此示例中,我们只涵盖如何从 webserver 激活主循环中的代码,但响应将在主循环中的代码运行之前发送 - 因此,响应只是 {"status": "ok"},它不依赖于主循环上发生的任何事情。

想法是有一个全局标志:

esp_async_request_flag.cpp
bool request_serial_output = false;

它在 webserver 处理程序代码中设置,而主循环反复检查该标志:

esp_async_main_loop_handler.cpp
void loop() {
  if(request_serial_output) {
    request_serial_output = false; // 清除标志
    // TODO 在此处添加处理代码
  }
}

完整示例

此示例使用 PlatformIO,应该适用于任何 ESP32 板。

esp_async_full_example.cpp
#include <Arduino.h>
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>

AsyncWebServer server(80);

bool request_serial_output = false;

void setup() {
  Serial.begin(115200);
  // 连接 Wifi,如果不连接则重启
  // https://techoverflow.net/2021/01/21/how-to-fix-esp32-not-connecting-to-the-wifi-network/
  WiFi.begin("MyWifi", "mywifipassword");
  uint32_t notConnectedCounter = 0;
  while (WiFi.status() != WL_CONNECTED) {
      delay(100);
      Serial.println("Wifi 连接中...");
      notConnectedCounter++;
      if(notConnectedCounter > 50) { // 5 秒后未连接则重置板
          Serial.println("由于 Wifi 未连接而重置...");
          ESP.restart();
      }
  }
  Serial.print("Wifi 已连接,IP 地址:");
  Serial.println(WiFi.localIP());

  // 初始化 webserver URL
  server.on("/api/test", HTTP_GET, [](AsyncWebServerRequest *request) {
      // 向主循环发送请求
      request_serial_output = true;
      // 发送 JSON "ok" 响应。
      // 注意:响应将在主循环完成处理
      // 请求之前发送
      AsyncResponseStream *response = request->beginResponseStream("application/json");
      DynamicJsonDocument json(1024);
      json["status"] = "ok";
      serializeJson(json, *response);
      request->send(response);
  });

  // 启动 webserver
  server.begin();
}

void loop() {
  if(request_serial_output) {
    request_serial_output = false; // 清除标志
    // 输出串口
    Serial.println("第一条消息。现在等待一秒...");
    // 等待 1 秒。你不能在 webserver 处理程序中这样做!
    delay(1000);
    // 在 Serial 上输出另一条消息
    Serial.println("第二条消息!");
  }
}
platformio.ini
[env:nodemcu-32s]
platform = espressif32
board = nodemcu-32s
framework = arduino
monitor_speed = 115200
lib_deps =
  ESP Async Webserver@1.2.3
  ArduinoJSON@6.17.2

Check out similar posts by category: ESP8266/ESP32, PlatformIO