ESPAsyncWebServer WiFi.scanNetworks() Мягкий сброс WDT
Я использую Arduino IDE (2.3.5), ESP8266 (3.1.2) и ESPAsyncWebServer (3.7.4), ESPAsyncTCP (2.0.0). Мне нужно просканировать сеть Wi-Fi и вывести результат через веб-интерфейс. Если я использую WiFiScanNetworks(), ESP8266 выполняет программный сброс WDT. То же самое происходит и при использовании yield(). Мой тестовый код выглядит следующим образом:
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
// Создать объект AsyncWebServer на порту 80
AsyncWebServer web_server(80);
// Замените на ваши сетевые учетные данные
const char* ssid = "your SSID";
const char* password = "your Password";
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<title>ESPAsyncWebServer</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
</head>
<body>
<h2>ESPAsyncWebServer</h2>
<h4>Use 'WiFi.scanNetworks();' or 'yield();' Soft WDT reset</h4>
<input type="button" onclick="location.href='/test_scan';" value="Test Scan" />
<input type="button" onclick="location.href='/test_yield';" value="Test yield" />
<input type="button" onclick="location.href='/test_normal';" value="Test normal" />
</body>
</html>
)rawliteral";
void setup(){
Serial.begin(115200);
// Подключиться к Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
// Печать локального IP-адреса ESP
Serial.println(WiFi.localIP());
// Маршрут для корня / веб-страницы
web_server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html);
});
web_server.on("/test_scan", HTTP_GET, [](AsyncWebServerRequest *request){
int n = WiFi.scanNetworks();
//Строковое значение = "Всего: " + String(n) + "найдено сетей.";
request->send(200, "text/plain", "Test WiFi Scannetworks() PASS");
});
web_server.on("/test_yield", HTTP_GET, [](AsyncWebServerRequest *request){
yield();
request->send(200, "text/plain", "Test yield() PASS");
});
web_server.on("/test_normal", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, "text/plain", "Test normal PASS");
});
web_server.begin();
}
void loop() {
}
@Seafox, 👍1
Обсуждение2 ответа
Вы делаете слишком много в одном запросе обратного вызова от веб-сервера, а в другом вызываете yield(), что недопустимо.
web_server.on("/test_scan", HTTP_GET, [](AsyncWebServerRequest *request){
int n = WiFi.scanNetworks();
//String value = "Total : " + String(n) + " networks found.";
request->send(200, "text/plain", "Test WiFi Scannetworks() PASS");
});
web_server.on("/test_yield", HTTP_GET, [](AsyncWebServerRequest *request){
yield();
request->send(200, "text/plain", "Test yield() PASS");
});
В документации по ESPAsyncWebServer четко указано yield():
Вы не можете использовать yield или delay или любую функцию, которая их использует внутри обратные вызовы
Вызов yield() бесполезен, если вы не хотите, чтобы ваша программа аварийно завершилась, поэтому удалите его.
Вы не можете знать, вызывает ли WiFi.scanNetworks() метод yield() или delay(). Даже если сейчас это безопасно, в обновлении это может быть небезопасно. Поэтому вам не следует его вызывать.
Вместо этого используйте логическую переменную в качестве флага, установите ее так, чтобы она указывала на необходимость начать сканирование сетей Wi-Fi, а затем в loop() проверьте ее. Если она истинна, вызовите WiFi.scanNetworks() и установите ее в значение false.
Спасибо, @romkey. При использовании WebServer код работает. При использовании AsyncWebServer ESP8266 падает. Функция yield() добавлена в код, чтобы показать, что сбой не связан со временем обработки. Как вы и сказали, использовать её бессмысленно. Я могу сделать то, что вы сказали, только с помощью WebSocket. Я ищу способ сделать это без WebSocket. Можете привести пример без WebSocket?, @Seafox
Я объяснил, почему происходит сбой. Не понимаю, что вы подразумеваете под необходимостью веб-сокетов. Это не нужно. Сбой *вызван* вызовом yield(). В обратных вызовах нельзя использовать WiFi.scanNetworks() или yield(). Измените структуру кода так, чтобы они не использовались., @romkey
Ещё раз спасибо, @romkey. В документации по ESPAsyncWebServer приведён пример для scanNetworks. Как указано в документации, scanNetworks не может найти сеть при первом сканировании. Поэтому я выполнил первое сканирование в разделе «Настройка». Для тех, у кого возникли проблемы, вот рабочий пример.
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
// Создать объект AsyncWebServer на порту 80
AsyncWebServer web_server(80);
// Замените на ваши сетевые учетные данные
const char* ssid = "your SSID";
const char* password = "your Password";
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<title>ESPAsyncWebServer</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
</head>
<body>
<h2>ESPAsyncWebServer</h2>
<h4>Use 'WiFi.scanNetworks();' or 'yield();' Soft WDT reset</h4>
<input type="button" onclick="location.href='/test_scan';" value="Test Scan" />
<input type="button" onclick="location.href='/test_scan2';" value="Test Scan PASS" />
<input type="button" onclick="location.href='/test_yield';" value="Test yield" />
<input type="button" onclick="location.href='/test_normal';" value="Test normal" />
</body>
</html>
)rawliteral";
void setup(){
Serial.begin(115200);
// Подключиться к Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
// Печать локального IP-адреса ESP
Serial.println(WiFi.localIP());
//Первое сканирование
int n = WiFi.scanNetworks();
// Маршрут для корня / веб-страницы
web_server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html);
});
web_server.on("/test_scan", HTTP_GET, [](AsyncWebServerRequest *request){
int n = WiFi.scanNetworks();
//Строковое значение = "Всего: " + String(n) + "найдено сетей.";
request->send(200, "text/plain", "Test WiFi Scannetworks() PASS");
});
web_server.on("/test_scan2", HTTP_GET, [](AsyncWebServerRequest *request){
String json = "[";
int n = WiFi.scanComplete();
if(n == -2){
WiFi.scanNetworks(true);
} else if(n){
for (int i = 0; i < n; ++i){
if(i) json += ",";
json += "{";
json += "\"rssi\":"+String(WiFi.RSSI(i));
json += ",\"ssid\":\""+WiFi.SSID(i)+"\"";
json += ",\"bssid\":\""+WiFi.BSSIDstr(i)+"\"";
json += ",\"channel\":"+String(WiFi.channel(i));
json += ",\"secure\":"+String(WiFi.encryptionType(i));
json += ",\"hidden\":"+String(WiFi.isHidden(i)?"true":"false");
json += "}";
}
WiFi.scanDelete();
if(WiFi.scanComplete() == -2){
WiFi.scanNetworks(true);
}
}
json += "]";
request->send(200, "application/json", json);
json = String();
});
web_server.on("/test_yield", HTTP_GET, [](AsyncWebServerRequest *request){
yield();
request->send(200, "text/plain", "Test yield() PASS");
});
web_server.on("/test_normal", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, "text/plain", "Test normal PASS");
});
web_server.begin();
}
void loop() {
}
- Трассировка стека сброса ESP12E Soft WDT ведет к библиотекам
- Несколько клиентских серверов через Wi-Fi
- Как получить параметры запроса от ESPAsyncWebServer?
- контент» не захватывается
- ESP8266 — Отправка команды сброса программного обеспечения
- Как разрешить междоменные запросы на ESP8266 WebServer
- Почему мы используем client.flush() в коде, когда мы подключаем Esp8266 к Интернету или серверу?
- Создание веб-сервера на Wemos D1 mini pro
какой у вас вопрос? ... пожалуйста, отредактируйте свой пост ... добавьте вопрос ... не пишите вопрос в комментарии, @jsotola