添加 main.ino

This commit is contained in:
ldeyun 2025-08-26 09:47:03 +00:00
commit 0756b0b4f3

681
main.ino Normal file
View File

@ -0,0 +1,681 @@
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <WiFiClient.h>
#include <EEPROM.h>
#include <DNSServer.h>
#define AP_TIMEOUT 300000 // 5分钟AP模式超时(毫秒)
const byte DNS_PORT = 53;
DNSServer dnsServer;
ESP8266WebServer server(80);
// 配置结构体
struct Config {
char wifiSSID[32];
char wifiPass[64];
char mqttServer[40];
char mqttPort[6];
char clientID[24];
char mqttUser[24];
char mqttPass[24];
char subTopic[32];
char pubTopic[32];
};
Config config;
bool isAPMode = false;
// 函数前置声明
void handleRoot();
void handleCustom();
void handleWiFi();
void handleInfo();
void handleReset();
void handleReboot();
void handleSave();
void handleConnect();
void handleScan();
void handleCheckWiFi();
void handleWiFiStatus();
#include <PubSubClient.h>
WiFiClient espClient;
PubSubClient mqttClient(espClient);
// MQTT消息回调函数
void callback(char* topic, byte* payload, unsigned int length) {
Serial.write(payload, length);
}
unsigned long connectStartTime = 0;
unsigned long lastMqttReconnectAttempt = 0;
unsigned long lastMqttPing = 0;
const unsigned long mqttPingInterval = 60000; // 每60秒发送一次心跳包
bool connecting = false;
String pendingSSID = "";
String pendingPass = "";
bool shouldConnectWiFi = false;
int wifiConnectAttempts = 0;
const int maxWifiConnectAttempts = 5; // WiFi最大连接尝试次数
int mqttReconnectAttempts = 0;
const int maxMqttReconnectAttempts =20; // MQTT最大重连尝试次数
void enableTransparentMode() {
// 检查模块是否响应
Serial.println("AT");
if (waitForResponse("OK", 1000)) {
Serial.println("AT+CWMODE=1");
if (waitForResponse("OK", 1000)) {
Serial.println("AT+CIPMODE=1");
if (waitForResponse("OK", 1000)) {
Serial.println("AT+CIPSEND");
waitForResponse(">", 1000);
}
}
}
}
// 辅助函数,等待模块响应
bool waitForResponse(const char* response, unsigned long timeout) {
unsigned long startTime = millis();
while (millis() - startTime < timeout) {
if (Serial.find(response)) {
return true;
}
}
return false;
}
bool reconnect() {
if (mqttClient.connect(config.clientID, config.mqttUser, config.mqttPass)) {
mqttClient.subscribe(config.subTopic);
WiFi.mode(WIFI_STA);
enableTransparentMode();
}
return mqttClient.connected();
}
void startAPMode() {
isAPMode = true;
WiFi.mode(WIFI_AP);
String mac = WiFi.macAddress();
mac.replace(":", "");
String apName = "znkg_" + mac.substring(mac.length() - 6);
WiFi.softAP(apName.c_str(), "12345678");
// DNS重定向到配网页面
dnsServer.start(DNS_PORT, "*", WiFi.softAPIP());
startWebServer();
}
void setup() {
Serial.begin(9600);
EEPROM.begin(sizeof(Config));
loadConfig();
// 设置MQTT回调函数
mqttClient.setCallback(callback);
// 首次通电或配置为空时进入AP模式
if (strlen(config.wifiSSID) == 0 || strlen(config.mqttServer) == 0) {
WiFi.mode(WIFI_AP);
startAPMode();
} else {
// 设置MQTT服务器
mqttClient.setServer(config.mqttServer, atoi(config.mqttPort));
// 尝试连接保存的WiFi
WiFi.mode(WIFI_AP_STA);
WiFi.begin(config.wifiSSID, config.wifiPass);
connectStartTime = millis();
wifiConnectAttempts++;
// 等待15秒连接
for (int i = 0; i < 15; i++) {
if (WiFi.status() == WL_CONNECTED) {
Serial.println("WiFi连接成功");
wifiConnectAttempts = 0;
break;
}
delay(1000);
}
if (WiFi.status() != WL_CONNECTED) {
wifiConnectAttempts++; // 递增尝试次数
Serial.printf("WiFi连接失败当前尝试次数: %d/%d\n", wifiConnectAttempts, maxWifiConnectAttempts);
if (wifiConnectAttempts >= maxWifiConnectAttempts) {
Serial.println("已达到最大WiFi连接尝试次数进入AP模式");
WiFi.mode(WIFI_AP);
startAPMode();
} else {
delay(5000); // 等待5秒后重试
WiFi.begin(config.wifiSSID, config.wifiPass); // 重新尝试连接
}
} else {
startWebServer();
}
// 未连接则判断是否超过最大尝试次数
// 原代码(直接重启)
// 修改后代码(递增尝试次数)
}
}
void loop() {
static unsigned long apStartTime = millis();
// 处理AP模式超时
if (isAPMode && millis() - apStartTime > AP_TIMEOUT) {
ESP.restart();
}
// 处理DNS请求
if (isAPMode) {
dnsServer.processNextRequest();
}
// 处理STC串口数据转发到MQTT
if (Serial.available() > 0 && mqttClient.connected()) {
String data = Serial.readStringUntil('\n');
if (data == "rest") {
memset(&config, 0, sizeof(config));
saveConfig();
ESP.restart();
}
mqttClient.publish(config.pubTopic, data.c_str());
}
// MQTT重连机制
if (!mqttClient.connected()) {
unsigned long now = millis();
if (now - lastMqttReconnectAttempt > 5000) {
lastMqttReconnectAttempt = now;
mqttReconnectAttempts++;
if (reconnect()) {
Serial.println("MQTT连接成功");
lastMqttPing = now;
mqttReconnectAttempts = 0;
} else {
Serial.printf("MQTT重连失败当前尝试次数: %d/%d\n", mqttReconnectAttempts, maxMqttReconnectAttempts);
if (mqttReconnectAttempts >= maxMqttReconnectAttempts) {
Serial.println("已达到最大MQTT重连尝试次数设备即将自动重启");
startAPMode();
ESP.restart();
}
}
startWebServer();
}
} else {
unsigned long now = millis();
if (now - lastMqttPing > mqttPingInterval) {
if (mqttClient.loop()) {
lastMqttPing = now;
} else {
// ping失败断开连接触发重连
mqttClient.disconnect();
}
}
mqttClient.loop();
}
server.handleClient();
}
void startWebServer() {
server.on("/", handleRoot);
server.on("/custom", handleCustom);
server.on("/wifi", handleWiFi);
server.on("/info", handleInfo);
server.on("/reset", handleReset);
server.on("/reboot", handleReboot);
server.on("/save", handleSave);
server.on("/connect", handleConnect);
server.on("/scan", handleScan);
server.on("/check_wifi", handleCheckWiFi);
server.on("/wifi_status", handleWiFiStatus);
// 添加强制门户重定向
server.on("/generate_204", handleRoot); // 安卓设备
server.on("/fwlink", handleRoot); // 微软设备
server.on("/hotspot-detect.html", handleRoot); // 苹果设备
server.on("/ncsi.txt", []() {
server.send(200, "text/plain", "OK");
});
// 未知请求重定向到首页
server.onNotFound([]() {
server.sendHeader("Location", "http://" + WiFi.softAPIP().toString(), true);
server.send(302, "text/plain", "");
});
server.begin();
}
// 网页处理函数
void handleRoot() {
String html = "<!DOCTYPE html><html><head>"
"<meta charset=\"UTF-8\">"
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
"<title>配网页面</title>"
"<style>"
"* {box-sizing: border-box; margin: 0; padding: 0; font-family: Arial, sans-serif;}"
"body {background-color: #f5f5f5; padding: 20px; color: #333;}"
".container {max-width: 500px; margin: 0 auto; background: white; border-radius: 10px; padding: 25px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);}"
"h1 {text-align: center; margin-bottom: 30px; color: #2c3e50; font-size: 28px;}"
".btn {display: block; width: 100%; padding: 15px; margin: 12px 0; background-color: #3498db; color: white; border: none; border-radius: 6px; font-size: 16px; cursor: pointer; transition: background-color 0.3s;}"
".btn:hover {background-color: #2980b9;}"
".btn:nth-child(odd) {background-color: #2ecc71;}"
".btn:nth-child(odd):hover {background-color: #27ae60;}"
".btn-danger {background-color: #e74c3c;}"
".btn-danger:hover {background-color: #c0392b;}"
"</style></head>"
"<body>"
"<div class=\"container\">"
"<h1>配网页面</h1>"
"<button class=\"btn\" onclick=\"location.href='/custom'\">自定义设置</button>"
"<button class=\"btn\" onclick=\"location.href='/wifi'\">WiFi设置</button>"
"<button class=\"btn\" onclick=\"location.href='/info'\">网络信息</button>"
"<button class=\"btn\" onclick=\"location.href='/reset'\">重 置</button>"
"<button class=\"btn\" onclick=\"location.href='/reboot'\">重 启</button>"
"<button class=\"btn\" onclick=\"window.close()\">退 出</button>"
"</div>"
"</body></html>";
server.send(200, "text/html", html);
}
void handleCustom() {
String html = "<!DOCTYPE html><html><head>"
"<meta charset=\"UTF-8\">"
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
"<title>自定义设置</title>"
"<style>"
"* {box-sizing: border-box; margin: 0; padding: 0; font-family: Arial, sans-serif;}"
"body {background-color: #f5f5f5; padding: 20px; color: #333;}"
".container {max-width: 500px; margin: 0 auto; background: white; border-radius: 10px; padding: 25px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);}"
"h1 {text-align: center; margin-bottom: 30px; color: #2c3e50; font-size: 24px;}"
".input-group {margin-bottom: 20px;}"
".input-group label {display: block; margin-bottom: 8px; font-weight: bold; color: #555;}"
".input-group input {width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 16px;}"
".btn {display: block; width: 100%; padding: 15px; margin: 15px 0; background-color: #3498db; color: white; border: none; border-radius: 6px; font-size: 16px; cursor: pointer; transition: background-color 0.3s;}"
".btn:hover {background-color: #2980b9;}"
".btn-back {background-color: #95a5a6;}"
".btn-back:hover {background-color: #7f8c8d;}"
"</style></head>"
"<body>"
"<div class=\"container\">"
"<h1>自定义设置</h1>"
"<form action=\"/save\">"
"<div class=\"input-group\">"
"<label>MQTT地址:</label>"
"<input type=\"text\" name=\"mqtt_server\" value=\""
+ String(config.mqttServer) + "\">"
"</div>"
"<div class=\"input-group\">"
"<label>MQTT端口:</label>"
"<input type=\"text\" name=\"mqtt_port\" value=\""
+ String(config.mqttPort) + "\">"
"</div>"
"<div class=\"input-group\">"
"<label>客户端ID:</label>"
"<input type=\"text\" name=\"client_id\" value=\""
+ String(config.clientID) + "\">"
"</div>"
"<div class=\"input-group\">"
"<label>用户名称:</label>"
"<input type=\"text\" name=\"mqtt_user\" value=\""
+ String(config.mqttUser) + "\">"
"</div>"
"<div class=\"input-group\">"
"<label>输入密码:</label>"
"<input type=\"password\" name=\"mqtt_pass\" value=\""
+ String(config.mqttPass) + "\">"
"</div>"
"<div class=\"input-group\">"
"<label>发布主题:</label>"
"<input type=\"text\" name=\"pub_topic\" value=\""
+ String(config.pubTopic) + "\">"
"</div>"
"<div class=\"input-group\">"
"<label>订阅主题:</label>"
"<input type=\"text\" name=\"sub_topic\" value=\""
+ String(config.subTopic) + "\">"
"</div>"
"<button type=\"submit\" class=\"btn\">保 存</button>"
"</form>"
"<button onclick=\"window.location.replace('/');\" class=\"btn btn-back\">返 回</button>"
"</div>"
"</body></html>";
server.send(200, "text/html", html);
}
void handleWiFi() {
String html = "<!DOCTYPE html><html><head>"
"<meta charset=\"UTF-8\">"
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
"<title>WiFi设置</title>"
"<style>"
"* {box-sizing: border-box; margin: 0; padding: 0; font-family: Arial, sans-serif;}"
"body {background-color: #f5f5f5; padding: 20px; color: #333;}"
".container {max-width: 500px; margin: 0 auto; background: white; border-radius: 10px; padding: 25px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);}"
"h1 {text-align: center; margin-bottom: 20px; color: #2c3e50; font-size: 24px;}"
"#networks {margin-bottom: 20px; max-height: 300px; overflow-y: auto; border: 1px solid #eee; border-radius: 6px; padding: 10px;}"
"#networks div {padding: 12px; border-bottom: 1px solid #eee; cursor: pointer; transition: background-color 0.2s;}"
"#networks div:hover {background-color: #f9f9f9;}"
"form {margin-bottom: 20px;}"
"input {width: 100%; padding: 12px; margin-bottom: 15px; border: 1px solid #ddd; border-radius: 6px; font-size: 16px;}"
".btn {display: block; width: 100%; padding: 15px; margin: 15px 0; background-color: #3498db; color: white; border: none; border-radius: 6px; font-size: 16px; cursor: pointer; transition: background-color 0.3s;}"
".btn:hover {background-color: #2980b9;}"
".btn-back {background-color: #95a5a6;}"
".btn-back:hover {background-color: #7f8c8d;}"
"</style>"
"<script>"
"function loadNetworks() {"
" fetch('/scan')"
" .then(r => r.json())"
" .then(data => {"
" let networksDiv = document.getElementById('networks');"
" networksDiv.innerHTML = '';"
" data.forEach(net => {"
" let div = document.createElement('div');"
" div.textContent = net;"
" div.style.cursor = 'pointer';"
" div.onclick = function() {"
" document.getElementById('ssid').value = net;"
" };"
" networksDiv.appendChild(div);"
" });"
" });"
"}"
"window.onload = loadNetworks;"
"</script></head>"
"<body>"
"<div class=\"container\">"
"<h1>WiFi设置</h1>"
"<div id=\"networks\"></div>"
"<form action=\"/connect\">"
"<input type=\"text\" id=\"ssid\" name=\"ssid\" placeholder=\"WiFi名称\">"
"<input type=\"password\" name=\"pass\" placeholder=\"WiFi密码\">"
"<button type=\"submit\" class=\"btn\">连 接</button>"
"</form>"
"<button onclick=\"window.location.href='/';\" class=\"btn btn-back\">返 回</button>"
"</div>"
"</body></html>";
server.send(200, "text/html", html);
}
void handleInfo() {
String html = "<!DOCTYPE html><html><head>"
"<meta charset=\"UTF-8\">"
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
"<title>网络信息</title>"
"<style>"
"* {box-sizing: border-box; margin: 0; padding: 0; font-family: Arial, sans-serif;}"
"body {background-color: #f5f5f5; padding: 20px; color: #333;}"
".container {max-width: 500px; margin: 0 auto; background: white; border-radius: 10px; padding: 25px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);}"
"h1 {text-align: center; margin-bottom: 30px; color: #2c3e50; font-size: 24px;}"
".info {margin-bottom: 15px; padding: 15px; background-color: #f9f9f9; border-radius: 6px; font-size: 16px;}"
".info strong {color: #2c3e50;}"
".connected {color: #27ae60; font-weight: bold;}"
".disconnected {color: #c0392b; font-weight: bold;}"
".btn {display: block; width: 100%; padding: 15px; margin: 20px 0 0; background-color: #3498db; color: white; border: none; border-radius: 6px; font-size: 16px; cursor: pointer; transition: background-color 0.3s;}"
".btn:hover {background-color: #2980b9;}"
"</style></head>"
"<body>"
"<div class=\"container\">"
"<h1>网络信息</h1>"
"<div class=\"info\"><strong>IP地址:</strong> "
+ WiFi.localIP().toString() + "</div>"
"<div class=\"info\"><strong>MAC地址:</strong> "
+ WiFi.macAddress() + "</div>"
"<div class=\"info\"><strong>工作模式:</strong> "
+ (WiFi.getMode() == WIFI_AP ? "AP" : "STA") + "</div>"
"<div class=\"info\"><strong>信号强度:</strong> "
+ String(WiFi.RSSI()) + " dBm</div>"
"<div class=\"info\"><strong>MQTT连接状态:</strong> <span class=\"" + (mqttClient.connected() ? "connected" : "disconnected") + "\">" + (mqttClient.connected() ? "已连接" : "未连接") + "</span></div>"
"<div class=\"info\"><strong>MQTT地址:</strong> "
+ String(config.mqttServer) + "</div>"
"<div class=\"info\"><strong>MQTT端口:</strong> "
+ String(config.mqttPort) + "</div>"
"<div class=\"info\"><strong>客户端ID:</strong> "
+ String(config.clientID) + "</div>"
"<div class=\"info\"><strong>发布主题:</strong> "
+ String(config.pubTopic) + "</div>"
"<div class=\"info\"><strong>订阅主题:</strong> "
+ String(config.subTopic) + "</div>"
"<button onclick=\"window.location.href='/';\" class=\"btn\">返 回</button>"
"</div>"
"</body></html>";
server.send(200, "text/html", html);
}
void handleReboot() {
String html = "<!DOCTYPE html><html><head>"
"<meta charset=\"UTF-8\">"
"<title>重启</title>"
"<style>"
"body {background:#000;color:#fff;font-size:40px;text-align:center;}"
"</style></head>"
"<body>"
"<h1>设备重启中...</h1>"
"<script>"
"setTimeout(function() {"
" window.location.href = '/';"
"}, 3000);"
"</script>"
"</body></html>";
server.send(200, "text/html", html);
delay(1000);
ESP.restart();
}
void handleSave() {
if (server.method() == HTTP_GET) {
// 保存MQTT配置
strncpy(config.mqttServer, server.arg("mqtt_server").c_str(), sizeof(config.mqttServer));
strncpy(config.mqttPort, server.arg("mqtt_port").c_str(), sizeof(config.mqttPort));
strncpy(config.clientID, server.arg("client_id").c_str(), sizeof(config.clientID));
strncpy(config.mqttUser, server.arg("mqtt_user").c_str(), sizeof(config.mqttUser));
strncpy(config.mqttPass, server.arg("mqtt_pass").c_str(), sizeof(config.mqttPass));
strncpy(config.subTopic, server.arg("sub_topic").c_str(), sizeof(config.subTopic));
strncpy(config.pubTopic, server.arg("pub_topic").c_str(), sizeof(config.pubTopic));
saveConfig();
// 设置MQTT服务器
mqttClient.setServer(config.mqttServer, atoi(config.mqttPort));
// 尝试连接MQTT
bool connected = mqttClient.connect(config.clientID, config.mqttUser, config.mqttPass);
String html;
if (connected) {
html = "<!DOCTYPE html><html><head><title>连接成功</title>";
html += "<meta http-equiv='refresh' content='3;url=/'>";
html += "</head><body><h1>配置保存成功MQTT连接成功</h1>";
html += "<p>设备将在 3 秒后跳转...</p></body></html>";
enableTransparentMode();
} else {
html = "<!DOCTYPE html><html><head><title>连接失败</title>";
html += "<meta http-equiv='refresh' content='5;url=/custom'>";
html += "</head><body><h1>配置保存成功但MQTT连接失败</h1>";
html += "<p>请检查MQTT配置页面将在 5 秒后跳转至配置页面...</p></body></html>";
}
server.send(200, "text/html", html);
}
}
void handleConnect() {
if (server.hasArg("ssid") && server.hasArg("pass") && !connecting) {
pendingSSID = server.arg("ssid");
pendingPass = server.arg("pass");
strncpy(config.wifiSSID, pendingSSID.c_str(), sizeof(config.wifiSSID));
strncpy(config.wifiPass, pendingPass.c_str(), sizeof(config.wifiPass));
saveConfig();
connecting = true;
connectStartTime = millis();
WiFi.mode(WIFI_STA);
WiFi.begin(pendingSSID, pendingPass);
}
String html = "<!DOCTYPE html><html><head>"
"<meta charset=\"UTF-8\">"
"<title>WiFi连接状态</title>"
"<style>"
"body {background:#000;color:#fff;font-size:40px;text-align:center;}"
" .info {margin:15px 0;font-size:40px;}"
" button {background:#0066cc;color:#fff;border:none;padding:15px 30px;margin:15px;cursor:pointer; font-size: 40px;}"
"</style></head>"
"<body>"
"<h1>WiFi连接状态</h1>";
if (WiFi.status() == WL_CONNECTED) {
html += "</head><body>"
"<h1 style=\"color:green\">连接成功</h1>"
"<p>SSID: "
+ WiFi.SSID() + "</p>"
"<p>IP地址: "
+ WiFi.localIP().toString() + "</p>"
"<button onclick=\"window.location.href='/';\">返回首页</button>";
connecting = false;
} else if (connecting && millis() - connectStartTime < 30000) {
html += "</head><body>"
"<h1>正在连接中...</h1>"
"<meta http-equiv=\"refresh\" content=\"5\">";
} else {
html += "</head><body>"
"<h1 style=\"color:red\">连接失败</h1>"
"<button onclick=\"window.location.href='/wifi';\">重新选择WiFi</button>";
connecting = false;
}
html += "</body></html>";
server.send(200, "text/html", html);
}
void handleScan() {
String json = "[";
int n = WiFi.scanNetworks();
for (int i = 0; i < n; ++i) {
if (i) json += ",";
json += "\"" + WiFi.SSID(i) + "\"";
}
json += "]";
server.send(200, "application/json", json);
}
// 保存配置到EEPROM
void saveConfig() {
EEPROM.put(0, config);
EEPROM.commit();
}
// 从EEPROM加载配置
void loadConfig() {
EEPROM.get(0, config);
// 检查是否为首次使用
if (config.mqttPort[0] == 0) {
strcpy(config.mqttPort, "1883");
}
}
void handleCheckWiFi() {
String html = "<!DOCTYPE html><html><head>"
"<meta charset=\"UTF-8\">"
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
"<title>WiFi连接状态</title>"
"<style>"
"* {box-sizing: border-box; margin: 0; padding: 0; font-family: Arial, sans-serif;}"
"body {background-color: #f5f5f5; padding: 20px; color: #333;}"
".container {max-width: 500px; margin: 0 auto; background: white; border-radius: 10px; padding: 25px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);}"
"h1 {text-align: center; margin-bottom: 20px; font-size: 24px;}"
".connected {color: #27ae60;}"
".disconnected {color: #c0392b;}"
".info {margin: 15px 0; padding: 15px; background-color: #f9f9f9; border-radius: 6px; font-size: 16px;}"
".btn {display: block; width: 100%; padding: 15px; margin: 20px 0 0; background-color: #3498db; color: white; border: none; border-radius: 6px; font-size: 16px; cursor: pointer; transition: background-color 0.3s;}"
".btn:hover {background-color: #2980b9;}"
"</style></head>"
"<body>"
"<div class=\"container\">";
if (WiFi.status() == WL_CONNECTED) {
html += "<h1 class=\"connected\">连接成功</h1>"
"<div class=\"info\"><strong>SSID:</strong> "
+ WiFi.SSID() + "</div>"
"<div class=\"info\"><strong>IP地址:</strong> "
+ WiFi.localIP().toString() + "</div>"
"<div class=\"info\"><strong>信号强度:</strong> "
+ String(WiFi.RSSI()) + " dBm</div>";
} else {
html += "<h1 class=\"disconnected\">未连接</h1>";
}
html += "<button onclick=\"window.location.href='/';\" class=\"btn\">返回首页</button>"
"</div>"
"</body></html>";
server.send(200, "text/html", html);
}
void handleWiFiStatus() {
String html = "<!DOCTYPE html><html><head>"
"<meta charset=\"UTF-8\">"
"<title>WiFi连接状态</title>"
"<style>"
"body {background:#000;color:#fff;font-size:40px;text-align:center;}"
" .info {margin:15px 0;font-size:40px;}"
" button {background:#0066cc;color:#fff;border:none;padding:15px 30px;margin:15px;cursor:pointer; font-size: 40px;}"
"h1 {font-size:24px;}"
"p {margin: 15px 0;}"
"</style></head>"
"<body>";
if (WiFi.status() == WL_CONNECTED) {
html += "<h1 style=\"color:green\">连接成功</h1>"
"<p>SSID: "
+ WiFi.SSID() + "</p>"
"<p>IP地址: "
+ WiFi.localIP().toString() + "</p>"
"<p>信号强度: "
+ String(WiFi.RSSI()) + " dBm</p>";
} else {
html += "<h1 style=\"color:red\">未连接</h1>";
}
html += "<button onclick=\"window.location.href='/';\">返回首页</button>"
"</body></html>";
server.send(200, "text/html", html);
}
void handleReset() {
memset(&config, 0, sizeof(config));
saveConfig();
String html = "<!DOCTYPE html><html><head>"
"<meta charset=\"UTF-8\">"
"<title>重置成功</title>"
"<style>"
"body {background:#000;color:#fff;text-align:center;}"
"</style></head>"
"<body>"
"<h1>重置成功</h1>"
"<p>WiFi配置已清除设备将重启进入AP模式</p>"
"<script>"
"setTimeout(function() {"
" window.location.href = '/reboot';"
"}, 3000);"
"</script>"
"</body></html>";
server.send(200, "text/html", html);
}