Интернет-сервер Arduino IDE + ESP32 — как перенаправить на root после нажатия кнопки
Я пытаюсь использовать ESP32 + Arduino IDE для управления реле.
Я начал с использования библиотеки и приведенного ниже кода.
Проблема, с которой я столкнулся:
после нажатия на кнопку и активации контакта, если оставить браузер в таком виде, а затем по ошибке обновить страницу, действие повторится.
Я подумал, что это может помочь, если при любом нажатии на кнопку активируется контакт, а затем я получаю перенаправление обратно в корень страницы. поэтому обновление не вызовет никаких проблем.
Я искал по всему Интернету и не смог найти ничего убедительного, кроме этого фрагмента кода, который, кажется, не имеет никакого значения, где бы я ни разместил его в основном коде
client.println("HTTP/1.1 307 Temporary Redirect");
client.println("Location: /");
client.println("Connection: Close");
client.println();
client.stop();
а это основной код:
// Загрузить библиотеку Wi-Fi
#include <WiFi.h>
// Замените учетными данными вашей сети
const char* ssid = "WalrusnTiny";
const char* password = "994483329I";
// Установить номер порта веб-сервера на 80
WiFiServer server(80);
// Переменная для хранения HTTP-запроса
String header;
// Вспомогательные переменные для хранения текущего состояния вывода
String output26State = "off";
String output27State = "off";
// Назначаем выходные переменные контактам GPIO
const int output26 = 26;
const int output27 = 27;
void setup() {
Serial.begin(115200);
// Инициализировать выходные переменные как выходы
pinMode(output26, OUTPUT);
pinMode(output27, OUTPUT);
// Установить выходы на НИЗКИЙ уровень
digitalWrite(output26, LOW);
digitalWrite(output27, LOW);
// Подключаемся к сети 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 /26/on") >= 0) {
client.println();
output26State = "on";
digitalWrite(output26, HIGH);
} else if (header.indexOf("GET /26/off") >= 0) {
Serial.println("GPIO 26 off");
output26State = "off";
digitalWrite(output26, LOW);
} else if (header.indexOf("GET /27/on") >= 0) {
Serial.println("GPIO 27 on");
output27State = "on";
digitalWrite(output27, HIGH);
} else if (header.indexOf("GET /27/off") >= 0) {
Serial.println("GPIO 27 off");
output27State = "off";
digitalWrite(output27, 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: #4CAF50; border: none; color: white; padding: 16px 40px;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".button2 {background-color: #555555;}</style></head>");
// Заголовок веб-страницы
client.println("<body><h1>ESP32 Web Server</h1>");
// Отображение текущего состояния и кнопки ВКЛ/ВЫКЛ для GPIO 26
client.println("<p>GPIO 26 - State " + output26State + "</p>");
// Если output26State выключен, отображается кнопка ON
if (output26State=="off") {
client.println("<p><a href=\"/26/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/26/off\"><button class=\"button button2\">OFF</button></a></p>");
}
// Отображение текущего состояния и кнопки ВКЛ/ВЫКЛ для GPIO 27
client.println("<p>GPIO 27 - State " + output27State + "</p>");
// Если output27State выключен, отображается кнопка ON
if (output27State=="off") {
client.println("<p><a href=\"/27/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/27/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 = "";
// Закрыть соединение
Serial.println("Client disconnected.");
Serial.println("");
}
}
Любая помощь будет принята с благодарностью. Заранее спасибо.
@Dragos, 👍1
2 ответа
Решено:
Просто нужно было добавить этот код при каждом нажатии кнопки,
client.print("<HEAD>");
client.print("<meta http-equiv=\"refresh\" content=\"0;url=/\">");
client.print("</head>");
Сначала, возможно, стоит упомянуть, что это слишком много для веб-сервера
добавление
include <WebServer.h>
вы можете легко обрабатывать эти конечные точки
См. https://lastminuteengineers.com/creating-esp32-web-server-arduino-ide. /
В основном:
setup() {
...
server.on("/", handle_OnConnect);
server.on("/led1on", handle_led1on);
server.on("/led1off", handle_led1off);
server.on("/led2on", handle_led2on);
server.on("/led2off", handle_led2off);
server.onNotFound(handle_NotFound);
server.begin();
Serial.println("HTTP server started");
}
void loop() {
server.handleClient();
...
}
void handle_led1on() {
LED1status = HIGH;
Serial.println("GPIO4 Status: ON");
server.send(200, "text/html", SendHTML(true,LED2status));
}
В любом случае, это все еще неправильно, так как вы заканчиваете с той же проблемой, /led1on
отображается как ваша главная страница
Лучшим решением было бы использовать обработчики этой конечной точки для установки переменной и просто перенаправления:
Вот полное решение
#include <WiFi.h>
include <WebServer.h>
// Замените учетными данными вашей сети
const char* ssid = "SSID";
const char* password = "password";
// Установить номер порта веб-сервера на 80
WebServer server(80);
uint8_t led1Pin = 12;
uint8_t led2Pin = 13;
bool led1State = LOW;
bool led2State = LOW;
void setup() {
Serial.begin(115200);
// Инициализировать выходные переменные как выходы
pinMode(led1Pin, OUTPUT);
pinMode(led2Pin, OUTPUT);
// Установить выходы на НИЗКИЙ уровень
led1State = LOW;
led2State = LOW;
digitalWrite(led1Pin, led1State);
digitalWrite(led2Pin, led2State);
// Подключаемся к сети 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.on("/", handle_root);
server.on("/led/1/on", handle_led1on);
server.on("/led/1/off", handle_led1off);
server.on("/led/2/on", handle_led2on);
server.on("/led/2/off", handle_led2off);
server.onNotFound(handle_NotFound);
server.begin();
Serial.println("HTTP Server started");
}
void handle_root() {
server.send(200, "text/html", sendHTML());
}
void handle_led1on() {
led1State = HIGH;
Serial.println("led1 state: ON");
server.sendHeader("Location", "/",true);
server.send(302, "text/plain", "");
}
void handle_led1off() {
led1State = LOW;
Serial.println("led1 state: OFF");
server.sendHeader("Location", "/",true);
server.send(302, "text/plain", "");
}
void handle_led2on() {
led2State = HIGH;
Serial.println("led2 state: ON");
server.sendHeader("Location", "/",true);
server.send(302, "text/plain", "");
}
void handle_led2off() {
led2State = LOW;
Serial.println("led2 state: OFF");
server.sendHeader("Location", "/",true);
server.send(302, "text/plain", "");
}
void handle_NotFound() {
server.send(404, "text/html", sendPageUnknown());
}
String sendPageUnknown() {
String ptr = "<!DOCTYPE html> <html>\n";
ptr += "<head>";
ptr += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
//ptr += "<meta http-equiv=\"обновить\" содержание=\"0;url=/\">";
ptr += "<title>Page unknown</title>\n";
ptr += "</head>\n";
ptr += "<body>\n";
ptr += "<h1>Page unknown</h1>\n";
ptr += "<a href=\"/\">Return to main page</a>\n";
ptr += "</body>\n";
ptr += "</html>\n";
return ptr;
}
String sendHTML() {
digitalWrite(led1Pin, led1State);
digitalWrite(led2Pin, led2State);
String ptr = "<!DOCTYPE html> <html>\n";
ptr += "<head>";
ptr += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
ptr += "<title>LED Dashboard</title>\n";
ptr += "<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
ptr += "body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n";
ptr += ".button {display: block;width: 80px;background-color: #3498db;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n";
ptr += ".button-on {background-color: #3498db;}\n";
ptr += ".button-on:active {background-color: #2980b9;}\n";
ptr += ".button-off {background-color: #34495e;}\n";
ptr += ".button-off:active {background-color: #2c3e50;}\n";
ptr += "p {font-size: 14px;color: #888;margin-bottom: 10px;}\n";
ptr += "</style>\n";
ptr += "</head>\n";
ptr += "<body>\n";
ptr += "<h1>ESP32 Web Server</h1>\n";
if (led1State)
{
ptr += "<p>LED1: ON</p><a class=\"button button-off\" href=\"/led/1/off\">OFF</a>\n";
}
else
{
ptr += "<p>LED1: OFF</p><a class=\"button button-on\" href=\"/led/1/on\">ON</a>\n";
}
if (led2State)
{
ptr += "<p>LED2: ON</p><a class=\"button button-off\" href=\"/led/2/off\">OFF</a>\n";
}
else
{
ptr += "<p>LED2: OFF</p><a class=\"button button-on\" href=\"/led/2/on\">ON</a>\n";
}
ptr += "</body>\n";
ptr += "</html>\n";
return ptr;
}
void loop() {
server.handleClient();
}
Даже это неоптимально, так как конечные точки светодиода должны быть не GET конечными точками, а POST (на самом деле PUT, поскольку он только обновляет информацию, но для простоты давайте придерживаться POST)
Вот версия, использующая POST и уникальную конечную точку /led для обработки любого меньшего числа для управления:
#include <WebServer.h>
// Замените учетными данными вашей сети
const char* ssid = "SSID";
const char* password = "password";
// Установить номер порта веб-сервера на 80
WebServer server(80);
uint8_t led1Pin = 12;
uint8_t led2Pin = 13;
bool led1State = LOW;
bool led2State = LOW;
void setup() {
Serial.begin(115200);
// Инициализировать выходные переменные как выходы
pinMode(led1Pin, OUTPUT);
pinMode(led2Pin, OUTPUT);
// Установить выходы на НИЗКИЙ уровень
led1State = LOW;
led2State = LOW;
digitalWrite(led1Pin, led1State);
digitalWrite(led2Pin, led2State);
// Подключаемся к сети 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.on("/", handle_root);
server.on("/led", HTTP_POST, handle_led);
server.onNotFound(handle_NotFound);
server.begin();
Serial.println("HTTP Server started");
}
void handle_root() {
server.send(200, "text/html", sendHTML());
}
uint8_t evaluate_led_state(String ledState) {
uint8_t state;
if (ledState == "on") {
Serial.println("led state: ON");
state = HIGH;
} else if (ledState == "off") {
Serial.println("led state: OFF");
state = LOW;
} else {
Serial.println("unknow led state: "+ledState);
}
return state;
}
void handle_led() {
String ledPin = server.arg("ledPin");
String ledState = server.arg("ledState");
if (ledPin == "1") {
Serial.println("setting led1");
led1State = evaluate_led_state(ledState);
} else if (ledPin == "2") {
Serial.println("setting led2");
led2State = evaluate_led_state(ledState);
} else {
Serial.println("led unknow: "+ledPin);
}
server.sendHeader("Location", "/",true);
server.send(302, "text/plain", "");
}
void handle_NotFound() {
server.send(404, "text/html", sendPageUnknown());
}
String sendPageUnknown() {
String ptr = "<!DOCTYPE html> <html>\n";
ptr += "<head>";
ptr += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
ptr += "<title>Page unknown</title>\n";
ptr += "</head>\n";
ptr += "<body>\n";
ptr += "<h1>Page unknown</h1>\n";
ptr += "<a href=\"/\">Return to main page</a>\n";
ptr += "</body>\n";
ptr += "</html>\n";
return ptr;
}
String build_led_form(String ledPin, uint8_t ledState) {
String ptr = "<form action=\"led\" method=\"post\">\n";
ptr += " <input type=\"hidden\" name=\"ledPin\" value=\""+ledPin+"\">\n";
String ledStateStr;
if (ledState)
{
ledStateStr = "off";
}
else
{
ledStateStr = "on";
}
ptr += " <input type=\"hidden\" name=\"ledState\" value=\""+ledStateStr+"\">\n";
ptr += " <label>Led"+ledPin+"</label>\n";
ptr += " <input type=\"submit\" class=\"button button-"+ledStateStr+"\" value=\"";
ledStateStr.toUpperCase();
ptr += ledStateStr+"\">\n";
ptr += "</form>\n";
return ptr;
}
String sendHTML() {
digitalWrite(led1Pin, led1State);
digitalWrite(led2Pin, led2State);
String ptr = "<!DOCTYPE html> <html>\n";
ptr += "<head>";
ptr += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
ptr += "<title>LED Dashboard</title>\n";
ptr += "<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
ptr += "body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;} form {margin-bottom: 30px;}\n";
ptr += ".button {display: block;width: 80px;background-color: #3498db;border: none;color: white;text-decoration: none;font-size: 25px;margin: auto;cursor: pointer;border-radius: 4px;}\n";
ptr += ".button-on {background-color: #3498db;}\n";
ptr += ".button-on:active {background-color: #2980b9;}\n";
ptr += ".button-off {background-color: #34495e;}\n";
ptr += ".button-off:active {background-color: #2c3e50;}\n";
ptr += "p {font-size: 14px;color: #888;margin-bottom: 10px;}\n";
ptr += "</style>\n";
ptr += "</head>\n";
ptr += "<body>\n";
ptr += "<h1>ESP32 Web Server</h1>\n";
ptr += build_led_form("1", led1State);
ptr += build_led_form("2", led2State);
ptr += "</body>\n";
ptr += "</html>\n";
return ptr;
}
void loop() {
server.handleClient();
}
Для нетривиального управления вы, вероятно, захотите использовать spiffs
https://randomnerdtutorials.com/esp32-web-server-spiffs- файловая система spi-flash/
- ESP32 в Arduino-IDE с FS.h и SPIFFS
- Автоматическая веб-страница ESP32 AP
- Изменить цвет формы css с esp32, если оператор
- Несколько клиентских серверов через Wi-Fi
- WebSocketsServer.h: No such file or directory
- Программаторы для этой платы отсутствуют - Программирование ESP32 Cam с помощью Ardunio IDE
- Установка значения float до двух знаков после запятой
- ESP32-CAM первый: 0x8 TG1WDT_SYS_RESET загрузочный цикл
Отметьте свое решение как принятое., @RooiWillie