Базовый скетч v.2 с настройкой title и редиректом после сохранения на главную страницу
Скетч для ESP8266, реализующий автономное Wi-Fi-устройство с веб-интерфейсом настройки и периодическим получением команды от HTTP-сервера.
При запуске ESP8266 загружает из EEPROM сохранённые параметры устройства: название страницы конфигурации, SSID и пароль Wi-Fi, URL сервера и номер GPIO. После загрузки настроек контроллер пытается подключиться к указанной Wi-Fi-сети. Во время подключения встроенный светодиод мигает, а после успешного соединения выключается.
При наличии Wi-Fi-соединения устройство каждые 2 секунды обращается к заданному HTTP-серверу. Полученный ответ обрабатывается как команда управления: значение 1 включает выход, а 0 выключает его. Благодаря возможности задавать GPIO через веб-интерфейс скетч можно адаптировать для управления различными исполнительными устройствами.
При отсутствии сохранённых параметров Wi-Fi или невозможности подключения ESP8266 переходит в режим точки доступа ESP8266-Setup. На встроенном веб-сервере доступна страница конфигурации, позволяющая изменить:
- название страницы устройства;
- SSID Wi-Fi;
- пароль Wi-Fi;
- URL HTTP-сервера;
- номер GPIO.
После сохранения параметры записываются в EEPROM и остаются доступными после перезагрузки устройства.
В отличие от предыдущей версии, после сохранения настроек контроллер не перезагружается. Вместо этого пользователю показывается сообщение об успешном сохранении, после чего через 2 секунды браузер автоматически возвращается на главную страницу конфигурации.
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#include <EEPROM.h>
// Настройки по умолчанию
const char* AP_SSID = "ESP8266-Setup";
const unsigned long CHECK_INTERVAL = 2000;
String SERVER_URL = "http://192.168.1.207/get_handler.php?id=pap1";
int LED_PIN = LED_BUILTIN;
String PAGE_TITLE = "ESP8266 Configuration";
// Глобальные переменные
ESP8266WebServer server(80);
String wifi_ssid = "";
String wifi_password = "";
unsigned long last_check_time = 0;
// HTML страница для настройки
const char* config_page = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
<title>%PAGE_TITLE%</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body { font-family: Arial; margin: 20px; }
form { max-width: 300px; }
.form-group { margin-bottom: 15px; }
label { display: block; margin-bottom: 5px; }
input[type="text"], input[type="password"], input[type="url"], input[type="number"] {
width: 100%; padding: 8px; box-sizing: border-box; }
input[type="submit"] { padding: 10px 20px; background: #4CAF50; color: white; border: none; }
</style>
</head>
<body>
<h1>%PAGE_TITLE%</h1>
<form action="/save" method="POST">
<div class="form-group">
<label>Page Title:</label>
<input type="text" name="page_title" value="%PAGE_TITLE%">
</div>
<div class="form-group">
<label>Wi-Fi SSID:</label>
<input type="text" name="ssid" value="%SSID%">
</div>
<div class="form-group">
<label>Wi-Fi Password:</label>
<input type="password" name="password" value="%PASSWORD%">
</div>
<div class="form-group">
<label>Server URL:</label>
<input type="url" name="server_url" value="%SERVER_URL%">
</div>
<div class="form-group">
<label>LED Pin (GPIO number):</label>
<input type="number" name="led_pin" value="%LED_PIN%">
</div>
<input type="submit" value="Save Settings">
</form>
</body>
</html>
)rawliteral";
void setup() {
Serial.begin(115200);
EEPROM.begin(512);
loadSettings();
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
WiFi.mode(WIFI_STA);
connectToWiFi();
setupWebServer();
}
void loop() {
server.handleClient();
if (WiFi.status() == WL_CONNECTED && millis() - last_check_time >= CHECK_INTERVAL) {
last_check_time = millis();
checkServer();
}
}
void connectToWiFi() {
if (wifi_ssid.length() == 0) {
startAPMode();
return;
}
Serial.printf("Connecting to %s\n", wifi_ssid.c_str());
WiFi.begin(wifi_ssid.c_str(), wifi_password.c_str());
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
delay(500);
Serial.print(".");
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
attempts++;
}
if (WiFi.status() == WL_CONNECTED) {
digitalWrite(LED_PIN, HIGH);
Serial.printf("\nConnected! IP: %s\n", WiFi.localIP().toString().c_str());
} else {
Serial.println("\nFailed to connect. Starting AP mode...");
startAPMode();
}
}
void startAPMode() {
WiFi.mode(WIFI_AP);
WiFi.softAP(AP_SSID);
Serial.printf("AP Mode. SSID: %s, IP: %s\n", AP_SSID, WiFi.softAPIP().toString().c_str());
digitalWrite(LED_PIN, LOW);
}
void setupWebServer() {
server.on("/", HTTP_GET, handleRoot);
server.on("/save", HTTP_POST, handleSave);
server.begin();
Serial.println("HTTP server started");
}
void handleRoot() {
String page = config_page;
page.replace("%PAGE_TITLE%", PAGE_TITLE);
page.replace("%SSID%", wifi_ssid);
page.replace("%PASSWORD%", wifi_password);
page.replace("%SERVER_URL%", SERVER_URL);
page.replace("%LED_PIN%", String(LED_PIN));
server.send(200, "text/html", page);
}
void handleSave() {
if (server.hasArg("page_title") && server.hasArg("ssid") && server.hasArg("password") &&
server.hasArg("server_url") && server.hasArg("led_pin")) {
PAGE_TITLE = server.arg("page_title");
wifi_ssid = server.arg("ssid");
wifi_password = server.arg("password");
SERVER_URL = server.arg("server_url");
LED_PIN = server.arg("led_pin").toInt();
saveSettings();
String redirectPage = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="refresh" content="2; url=/">
<title>Settings Saved</title>
<style>
body { font-family: Arial; text-align: center; margin-top: 50px; }
.message { color: #4CAF50; font-size: 24px; }
</style>
</head>
<body>
<div class="message">Settings saved successfully!</div>
<p>Redirecting to main page...</p>
</body>
</html>
)rawliteral";
server.send(200, "text/html", redirectPage);
} else {
server.send(400, "text/plain", "Missing required parameters");
}
}
void loadSettings() {
wifi_ssid = readEEPROM(0);
wifi_password = readEEPROM(64);
SERVER_URL = readEEPROM(128);
LED_PIN = readEEPROM(192).toInt();
PAGE_TITLE = readEEPROM(256);
if (PAGE_TITLE.length() == 0) {
PAGE_TITLE = "ESP8266 Configuration";
}
Serial.printf("Loaded settings:\nTitle: '%s'\nSSID: '%s'\nPass: '%s'\nURL: '%s'\nLED Pin: %d\n",
PAGE_TITLE.c_str(), wifi_ssid.c_str(), wifi_password.c_str(), SERVER_URL.c_str(), LED_PIN);
}
void saveSettings() {
writeEEPROM(0, wifi_ssid);
writeEEPROM(64, wifi_password);
writeEEPROM(128, SERVER_URL);
writeEEPROM(192, String(LED_PIN));
writeEEPROM(256, PAGE_TITLE);
EEPROM.commit();
Serial.printf("Saved settings:\nTitle: '%s'\nSSID: '%s'\nPass: '%s'\nURL: '%s'\nLED Pin: %d\n",
PAGE_TITLE.c_str(), wifi_ssid.c_str(), wifi_password.c_str(), SERVER_URL.c_str(), LED_PIN);
}
String readEEPROM(int offset) {
String value;
for (int i = offset; i < offset + 64; ++i) {
char c = EEPROM.read(i);
if (c == 0) break;
value += c;
}
return value;
}
void writeEEPROM(int offset, String value) {
for (int i = 0; i < value.length(); ++i) {
EEPROM.write(offset + i, value[i]);
}
EEPROM.write(offset + value.length(), 0);
}
void checkServer() {
WiFiClient client;
HTTPClient http;
Serial.printf("Requesting URL: %s\n", SERVER_URL.c_str());
if (http.begin(client, SERVER_URL)) {
int httpCode = http.GET();
if (httpCode == HTTP_CODE_OK) {
String payload = http.getString();
payload.trim();
Serial.printf("Server response: %s\n", payload.c_str());
if (payload == "1") {
digitalWrite(LED_PIN, LOW);
Serial.println("LED ON");
} else if (payload == "0") {
digitalWrite(LED_PIN, HIGH);
Serial.println("LED OFF");
}
} else {
Serial.printf("HTTP error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
} else {
Serial.println("Failed to connect to server");
}
}