Программная точка доступа ESP8266: тайм-аут запроса ресурса, если на него не получен ответ в течение установленного недокументированного времени.
Я экспериментирую с чипом ESP8266 на плате Wemos D1 R2. Я пытаюсь написать код, который позволит пользователю ввести имя пользователя и пароль в HTML-форме, а затем получить ответ о том, что произошло при попытке подключения к Wi-Fi, поскольку либо они подключились, либо пароль был неправильным. После того, как я включил настройку режима точки доступа и станции на устройстве, используя:
// Поле здесь будет глобальным, чтобы другие функции могли получить к нему доступ
ESP8266WebServer server(80);
server.on("/connect", handleConnect);
server.begin();
В моей функции handleConnect я проверяю тело запроса и пытаюсь войти в систему:
if(!server.hasArg("ssid") || !server.hasArg("password")) {
server.send(200, "text/html", "You didn't submit a ssid and password");
return;
}
auto ssid = server.arg("ssid");
auto password = server.arg("password");
WiFi.begin(ssid, password);
auto status = WiFi.waitForConnectionResult();
server.send(200, "text/html", String(status));
Когда пользователь вводит правильный пароль, функция вовремя возвращает запрос, и запрос отвечает цифрой 3 (соединение установлено успешно). Однако, если пароль неправильный, время ожидания запроса истекает. Я также попробовал несколько подходов, чтобы обойти или устранить проблему, например:
Использование цикла while, вызов
WiFi.status()
, его проверка и соответствующий ответ. Этот подход заканчивается тем же тайм-аутом запроса, если пароль неверен. Примером этого может быть:while(true) { delay(1000); auto status = WiFi.status(); if(status == WL_CONNECTED) { server.send(200, "text/html", "You're connected!"); } if(status == WL_CONNECT_FAILED) { server.send(200, "text/html", "You inputted the wrong password! Try again!"); } }
Регистрация другого ресурса только для того, чтобы возвращать только то состояние, в котором находится Wi-Fi, и в исходной функции подключения для отправки обратно HTML с некоторым JavaScript в нем, который вызывает этот другой ресурс и принимает решение о том, какой текст отображать клиенту -side, но этот подход всегда возвращает 0 (когда Wi-Fi находится в процессе смены состояний, указанных в документации)
server.on("/checkConnection", checkConnection); // другой код void checkConnection() { server.send(WiFi.status()); }
- И, наконец, я экспериментировал с использованием общедоступного поля для сохранения состояния после его завершения в основной функции, где пытались установить исходное соединение, а затем использовал функцию checkConnection для возврата этого состояния и этого ЧТО-ТО работает, однако код беспорядочный, хакерский, и должен быть лучший способ сделать это, иначе это должно быть мое решение, пока библиотеки не будут обновлены, чтобы исправить это или что-то в этом роде что:
// публичное поле для статуса
int status = 0;
// другой код
void handleConnect() {
// проверка ssid и пароля
WiFi.begin(ssid, password);
// используем интервал с AJAX или этим, чтобы получить состояние соединения
server.send(200, "text/html", "Go to <a href='/checkConnection'>to check the connection</a>");
while(true) {
delay(1000);
auto s = WiFi.status();
status = s;
if(s = WL_CONNECTED) break;
}
}
void checkConnection() {
server.send(200, "text/html", status);
}
Сталкивался ли кто-нибудь с этой проблемой, и если да, то есть ли лучший способ ее решения, кроме использования общедоступной переменной, работать с которой просто утомительно? Спасибо.
@Cam, 👍2
Обсуждение2 ответа
Сделайте WiFi.begin вне обработчика веб-сервера. В обработчике сохраните ssid и пароль в переменных и отправьте ответ. В цикле() затем создайте WiFi.begin. Для получения результата выполните пул из браузера с помощью javascript.
Пример
WifiMulti wifiMulti;//объявляем глобальный.
wifiMulti.addAP(ssid,pass);//вместо WiFi.begin();
int i = 0;
//добавим ниже, чтобы дождаться соединения.
while (i < 20)
{
if (wifiMulti.run() == WL_CONNECTED)
{
return (20);
}
delay(500);
Serial.println(WiFi.status());
i++;
}
- HTTP GET запрос с использованием Arduino Uno и ESP8266
- Как составить URL-адрес HTTP-запроса GET с параметрами ключ/значение
- ESP8266 Ошибка неверного запроса 400
- ESP8266 отправляет веб-страницу клиенту, но html-коды отображаются в браузере вместо веб-страницы
- Проанализировать большой ответ json с помощью ESP8266
- ESP8266 не отвечает через случайные промежутки времени
- Код запроса ESP8266 GET -1
- esp32 http client response только 200 не получил данные после этого
1. waitForConnectionResult, вероятно, не обрабатывает ошибки так, как вы хотите. 2. WL_CONNECT_FAILED означает и другие вещи (https://github.com/esp8266/Arduino/blob/a41f55c469dbf3ecfa3aa051fa95322d8d316e2e/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp#L98), так что не хотите ли вы просто искать что-нибудь рядом с «подключено»? 3. Точка доступа должна использовать тот же канал, что и STA, поэтому я не понимаю, как это может сохранять соединение http открытым, пока/если оно изменится., @dandavis
@dandavis Спасибо за ответ. Во-первых, waitForConnectResult документируется как ожидание окончательного результата работы сети, а затем возврат состояния соединения. Во-вторых, спасибо за информацию о других значениях WL_CONNECT_FAILED. Я как бы предположил, что это могло иметь какое-то другое значение, но теперь я знаю, но в данном случае мы предполагаем, что ssid правильный и неправильный только пароль. Наконец, esp8266 имеет режим Wi-Fi под названием WIFI_AP_STA, который позволяет устройству быть точкой доступа и станцией, что очень удобно, если вы хотите сделать что-то подобное, поэтому я не думаю, что это причина., @Cam
да, в WIFI_AP_STA каналы Wi-Fi должны совпадать между ними. если ваша точка доступа загрузила другой канал, чем STA, к которой вы подключаетесь, вы (на самом деле) не сможете поддерживать открытое http-соединение во время смены канала точки доступа (неожиданной/недокументированной), независимо от действительности пароля., @dandavis