ESPAsyncWebserver: Code im Main-Loop-Thread ausführen

English Deutsch

Bei der Arbeit mit ESPAsyncWebserver werden Sie bald auf eine seiner grundlegendsten Einschränkungen stoßen: Dessen Code wird immer in Interrupts ausgeführt, daher können Sie delay() oder jede Funktion, die delay() oder ähnliche Funktionen intern verwendet, nicht nutzen.

Es gibt jedoch ein einfaches Programmiermuster, das es Ihnen ermöglicht, Code im Main-Thread auszuführen, wenn der Webserver dies anfordert. Hinweis: In diesem Beispiel behandeln wir nur, wie man Code im Main-Loop vom Webserver aus aktiviert, aber die Antwort wird gesendet, bevor der Code im Main-Loop ausgeführt wird - daher ist die Antwort nur {"status": "ok"} und hängt nicht davon ab, was im Main-Loop passiert.

Die Idee ist, ein globales Flag zu haben:

esp_async_request_flag.cpp
bool request_serial_output = false;

das im Webserver-Handler-Code gesetzt wird, während die Main-Loop das Flag wiederholt prüft:

esp_async_main_loop_handler.cpp
void loop() {
  if(request_serial_output) {
    request_serial_output = false; // Flag löschen
    // TODO Hier Behandlungscode einfügen
  }
}

Vollständiges Beispiel

Dieses Beispiel verwendet PlatformIO und sollte auf jedem ESP32-Board funktionieren.

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);
  // WLAN verbinden, Neustart bei Verbindungsfehler
  // 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 connecting...");
      notConnectedCounter++;
      if(notConnectedCounter > 50) { // Board zurücksetzen, wenn nach 5s keine Verbindung
          Serial.println("Resetting due to Wifi not connecting...");
          ESP.restart();
      }
  }
  Serial.print("Wifi verbunden, IP-Adresse: ");
  Serial.println(WiFi.localIP());

  // Webserver-URLs initialisieren
  server.on("/api/test", HTTP_GET, [](AsyncWebServerRequest *request) {
      // Anfrage an Main-Loop senden
      request_serial_output = true;
      // JSON "ok"-Antwort senden.
      // HINWEIS: Die Antwort wird gesendet, BEVOR der Main-Loop die
      // Anfrage verarbeitet hat
      AsyncResponseStream *response = request->beginResponseStream("application/json");
      DynamicJsonDocument json(1024);
      json["status"] = "ok";
      serializeJson(json, *response);
      request->send(response);
  });

  // Webserver starten
  server.begin();
}

void loop() {
  if(request_serial_output) {
    request_serial_output = false; // Flag löschen
    // Serielle Ausgabe
    Serial.println("Erste Nachricht. Warte jetzt eine Sekunde...");
    // 1s warten. Das können Sie nicht im Webserver-Handler tun!
    delay(1000);
    // Weitere Nachricht auf Serial ausgeben
    Serial.println("Zweite Nachricht!");
  }
}
platformio.ini
[env:nodemcu-32s]
platform = espressif32
board = nodemcu-32s
framework = arduino
monitor_speed = 115200
lib_deps =
  ESP Async [email protected]
  [email protected]

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