Веб-сервер ESP8266 недоступен через 2 минуты после сброса
У меня есть Keyes Espressif ESP8266 NodeMCU, у меня есть два светодиода, которыми я хочу управлять и которые подключены к ESP. Когда я открываю веб-страницу http://10.0.0.5/5
после загрузки скетча, она работает нормально. Если я не открою и не закрою веб-сайт до ~ 02:30 [мм: сс], сервер станет недоступным, даже если я закрою существующее соединение и открою новое соединение в новой вкладке, выдает ту же ошибку: ERR_CONNECTION_TIMED_OUT
Если я не открою веб-страницу до ~ 02:30[мм:сс], я также получу сообщение об ошибке ERR_CONNECTION_TIMED_OUT
Веб-сервер становится доступным только после полной перезагрузки платы, после чего применяются те же правила, что и выше.
ESP.getFullVersion() outputs:
SDK:2.2.1(cfd48f3)/Core:2.5.1=20501000/lwIP:STABLE-2_1_2_RELEASE/glue:1.1-7-g82abda3/BearSSL:a143020
Вопрос:
Как сделать веб-сервер доступным постоянно?
С помощью @Juraj я попытался перейти на SDK V3, но это не помогло. Я также пробовал:
- Все варианты lwip
Мой код:
// Загружаем библиотеку Wi-Fi
#include <ESP8266WiFi.h>
// Замените учетными данными вашей сети
const char* ssid = "DO_231455";
const char* password = "0828842107";
// Установить номер порта веб-сервера на 80
WiFiServer server(80);
// Переменная для хранения HTTP-запроса
String header;
// Вспомогательные переменные для хранения текущего состояния вывода
String output5State = "off";
String output4State = "off";
// Назначаем выходные переменные контактам GPIO
const int output5 = 16;
const int output4 = 4;
void setup() {
Serial.begin(115200);
// Инициализировать выходные переменные как выходы
pinMode(output5, OUTPUT);
pinMode(output4, OUTPUT);
// Установить выходы на НИЗКИЙ уровень
digitalWrite(output5, LOW);
digitalWrite(output4, LOW);
Serial.print(ESP.getFullVersion());
//WiFi.disconnect() ;
// WiFi.persistent(false);
//WiFi.setSleepMode(WIFI_NONE_SLEEP);
// Подключаемся к сети Wi-Fi с SSID и паролем
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// Выводим локальный IP-адрес и запускаем веб-сервер
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
}
void loop(){
WiFiClient client = server.available(); // Слушаем входящих клиентов
if (client) { // Если подключается новый клиент,
Serial.println("New Client."); // вывести сообщение в последовательный порт
String currentLine = ""; // создаем строку для хранения входящих данных от клиента
while (client.connected()) { // цикл, пока клиент подключен
if (client.available()) { // если есть байты для чтения от клиента,
char c = client.read(); // прочитать байт, затем
Serial.write(c); // вывести его на серийный монитор
header += c;
if (c == '\n') { // если байт является символом новой строки
// если текущая строка пуста, вы получили два символа новой строки подряд.
// это конец клиентского HTTP-запроса, поэтому отправьте ответ:
if (currentLine.length() == 0) {
// Заголовки HTTP всегда начинаются с кода ответа (например, HTTP/1.1 200 OK)
// и тип контента, чтобы клиент знал, что придет, затем пустая строка:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
// включает и выключает GPIO
if (header.indexOf("GET /5/on") >= 0) {
Serial.println("GPIO 5 on");
output5State = "on";
digitalWrite(output5, HIGH);
} else if (header.indexOf("GET /5/off") >= 0) {
Serial.println("GPIO 5 off");
output5State = "off";
digitalWrite(output5, LOW);
} else if (header.indexOf("GET /4/on") >= 0) {
Serial.println("GPIO 4 on");
output4State = "on";
digitalWrite(output4, HIGH);
} else if (header.indexOf("GET /4/off") >= 0) {
Serial.println("GPIO 4 off");
output4State = "off";
digitalWrite(output4, LOW);
}
// Отображение веб-страницы в формате HTML
client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"icon\" href=\"data:,\">");
// CSS для оформления кнопок включения/выключения
// Не стесняйтесь изменять атрибуты background-color и font-size в соответствии с вашими предпочтениями
client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".button2 {background-color: #77878A;}</style></head>");
// Заголовок веб-страницы
client.println("<body><h1>ESP8266 Web Server</h1>");
// Отображение текущего состояния и кнопки ВКЛ/ВЫКЛ для GPIO 5
client.println("<p>GPIO 5 - State " + output5State + "</p>");
// Если output5State выключен, отображается кнопка ON
if (output5State=="off") {
client.println("<p><a href=\"/5/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/5/off\"><button class=\"button button2\">OFF</button></a></p>");
}
// Отображение текущего состояния и кнопки ВКЛ/ВЫКЛ для GPIO 4
client.println("<p>GPIO 4 - State " + output4State + "</p>");
// Если output4State выключен, отображается кнопка ON
if (output4State=="off") {
client.println("<p><a href=\"/4/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/4/off\"><button class=\"button button2\">OFF</button></a></p>");
}
client.println("</body></html>");
// Ответ HTTP заканчивается еще одной пустой строкой
client.println();
// Выход из цикла while
break;
} else { // если вы получили новую строку, то очищаем currentLine
currentLine = "";
}
} else if (c != '\r') { // если вы получили что-то еще, кроме символа возврата каретки,
currentLine += c; // добавляем его в конец currentLine
}
}
}
// Очистить переменную заголовка
header = "";
// Закрыть соединение
client.stop();
Serial.println("Client disconnected.");
Serial.println("");
}
}
Стоит отметить (во время отладки):
Новый клиент отключается.
@Brandon Pillay, 👍1
Обсуждение2 ответа
Лучший ответ:
Короткий ответ: настройте статический IP-адрес!
Посмотрев на Git Issue #2371, я обнаружил, что мне нужно создать статический IP-адрес, чтобы исправить Эта проблема. Я могу сделать это, вставив WiFi.config(ip, gateway, subnet)
непосредственно перед WiFi.mode(WIFI_STA)
в приведенном выше коде.
- Сначала я нашел информацию
gateway
&subnet
мне нужно, открыв командную строку на компьютере, подключенном к точке доступа (маршрутизатору), как к ESP8266, который работает в режиме станции. Я сделал это в Windows, выполнив поиск вCommand Prompt
, а затем набравipconfig
, чтобы получить следующую информацию:
Замените точки запятыми! См. эту ссылки для получения дополнительной информации о других параметрах и DNS.
Чтобы создать IP-адрес, вам нужно увидеть свой IP-адрес в красном квадрате на картинке выше, взятой из командной строки. Первые три октета (числа) IP-адреса вашего маршрутизатора (вероятно,
10.0.0.x
,192.168.0.x
или192.168.1.x
) должен соответствовать выбранному вами статическому IP-адресу. В моем примере совпадающие числа будут10.0.0
.Затем мне нужно было получить диапазон DCHP для моего маршрутизатора. Мой маршрутизатор — это маршрутизатор Netgear Wireless ADSL2+ с модемом DG834Gv5. Чтобы получить диапазон, мне нужно было получить доступ к настройкам моего маршрутизатора. Чтобы получить к нему доступ, я искал HTTP-ссылку под маршрутизатором. Для моего маршрутизатора это был
http://10.0.0.2
вместе с именем пользователя и паролем, которые былиadmin
,admin
соответственно. Вот как это выглядит:
Это зависит от вашего маршрутизатора. Затем я зашел в Дополнительные настройки и увидел диапазон DHCP. Это ошибка с моей стороны, отмеченная @djsfantasi. См. его ответ относительно выбора диапазона DHCP.Новый статический IP-адрес должен находиться в пределах диапазона DHCP. Согласно одному из комментариев Диапазон DHCP выглядит следующим образом: brendanmatkin
в Git Issue #2371 последний номер моего статического IP (это ZZ
в WW.XX.YY .ZZ
) должен быть за пределами этого диапазона. У меня это не сработало, сработало, когда я использовал значение внутри этого диапазона, но brendanmatkin
знает гораздо больше меня, я просто новичок. Возможны последствия, о которых я не знаю, поэтому я думаю, что их стоит изучить.
Мой вставленный код выглядит следующим образом:
void setup(void) {
.
.
.
Serial.begin(115200);
//WiFi.disconnect(); //Запретить подключение к Wi-Fi на основе предыдущей конфигурации
IPAddress ip(10,0,0,15); // эти 3 строки для фиксированного IP-адреса
IPAddress gateway(10,0,0,2);
IPAddress subnet(255,255,255,0);
// WiFi.hostname ("ESP8266"); // Имя хоста DHCP (полезно для поиска устройства для статической аренды)
WiFi.config(ip, gateway, subnet);
//Режим станции:
WiFi.mode(WIFI_STA);
.
.
.
}
Пожалуйста, прокомментируйте для получения дополнительной информации :)
Дополнительная информация и изменения, которые я внес в IDE:
ОС: Windows 8.1
IDE: Arduino IDE V1.9.8
Плата: Keyes ESP8266
Arduino IDE > Инструменты > Плата (в диспетчере плат): Универсальная плата ESP8266
Arduino IDE > Инструменты >lwip: мало памяти V2
Arduino IDE > Инструменты >Esp FW:"nonos.." : nonos-sdk pr-3(известные проблемы)*
Электропитание: USB COM от настольного блока питания мощностью 300 Вт. Выходной ток ~ 1,5А.
Большое спасибо @Juraj. Юрай
Это работало, когда IP-адрес находился в диапазоне, потому что за его пределами не было действительных IP-адресов.
WW.XX.YY.0 и WW.XX.YY.255 зарезервированы. Маршрутизатор использует адреса .1 и .2. Остается 3-254 доступных, которые, как мы видим, являются адресами в пределах диапазона DHCP.
Вы можете назначить статический IP-адрес в диапазоне DHCP, но рискуете отключить 1 или 2 устройства. DHCP не знает, что вы использовали один из его адресов, поэтому может назначить его другому устройству. Бум! Два устройства с одинаковым адресом и оба не будут работать.
Правильный способ решить эту проблему – войти в систему маршрутизатора и изменить диапазон DHCP. Например, увеличьте нижний предел с 3 до (случайный выбор) 20. Теперь DHCP не будет беспокоить и с радостью раздаст адреса вашим устройствам. Но если вам нужен статический IP-адрес, вы определили пул от WW.XX.YY.3 до WW.XX.YY.19
- Несколько клиентских серверов через Wi-Fi
- Управление реле 5В с помощью Wemos D1 R1
- WebSocketsServer.h: No such file or directory
- ESP8266 Аналоговое чтение мешает Wi-Fi?
- Каково использование зарезервированных контактов и контактов SDD2, SDD3 NodeMCU?
- Как разрешить междоменные запросы на ESP8266 WebServer
- ESP8266 TCP-соединение WiFiClient проблема
- ESP8266 отправляет TCP HEX-пакет из 4 символов
если клиент возвращается с сервера, то проблема в скетче, @Juraj
Какие ресурсы вы бы посоветовали мне посмотреть, чтобы узнать, как решить эту проблему?, @Brandon Pillay
помогает ли перезапуск WiFi-маршрутизатора/точки доступа?, @Juraj
Никакого эффекта, сайт по-прежнему падает, если не запрашивается из моего браузера W8.1 Chrome в течение 2 минут после сброса или загрузки., @Brandon Pillay
он перестает работать через две минуты - даже если вы не делаете к нему никаких запросов, пока не пройдет 2 минуты? Или он останавливается после определенного количества запросов, выполнение которых занимает около 2 минут?? Дело в том, происходит ли сбой после определенного количества запросов или после определенного периода работы - независимо от рабочей нагрузки???, @GMc
Я проверил это, сбрасывая, а затем открывая и закрывая соединение в моем браузере каждую минуту - я мог делать это в течение 30 минут и продолжать делать это после этого, но если я не устанавливаю новое соединение в течение ~ 2 минут 35 секунд, время сервера вне. Как будто ESP переходит в спящий режим после отсутствия запросов., @Brandon Pillay
он печатает «Новый клиент», поэтому он не спит, @Juraj
Да, время ожидания ESP истекает, только если новый запрос не сделан. Я пытаюсь найти способ предотвратить тайм-аут веб-сервера., @Brandon Pillay
это не тайм-аут. он возвращает клиента. скетч печатает "Новый клиент", @Juraj
Это только в том случае, если я отправлю запрос на веб-сервер, а не в том случае, если он будет бездействовать. Если он остается бездействующим, время ожидания истекает., @Brandon Pillay
и следующий клиент после этого времени возвращается сервером. только не обработано в вашем скетче, @Juraj
Есть ли лучший способ решить эту проблему, чем то, как я справился с ней в своем ответе ниже?, @Brandon Pillay
Мне нужно .stop() для старого (первого) клиента!, @Brandon Pillay
вы останавливаете () клиент, @Juraj
в моем случае я добирался через http://esp8266.local/. Я заметил, что все еще могу получить доступ через ip, но mdns не удалось, я думаю, @nerkn