ESPAsyncWebserver: Code im Main-Loop-Thread ausführen
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:
bool request_serial_output = false;das im Webserver-Handler-Code gesetzt wird, während die Main-Loop das Flag wiederholt prüft:
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.
#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!");
}
}[env:nodemcu-32s]
platform = espressif32
board = nodemcu-32s
framework = arduino
monitor_speed = 115200
lib_deps =
ESP Async [email protected]
[email protected]