16#include <ArduinoJson.h>
42 logDebug(
"Настройка сервисных маршрутов");
68 html +=
"<div class='info-block' id='status-block'>Загрузка статусов...</div>";
72 html +=
"<div class='section' style='margin-top:20px;'>";
73 html +=
"<form method='post' action='/reset' style='margin-bottom:10px'>";
75 html +=
"<form method='post' action='/reboot' style='margin-bottom:10px'>";
79 "<div class='section' style='margin-top:15px;font-size:14px;color:#555'><b>API:</b> <a "
80 "href='/service_status' target='_blank'>/service_status</a> (JSON, статусы сервисов) | <a "
81 "href='/health' target='_blank'>/health</a> (JSON, подробная диагностика)</div>";
83 html +=
"function dot(status){";
84 html +=
"if(status===true)return'<span class=\"status-dot dot-ok\"></span>';";
85 html +=
"if(status===false)return'<span class=\"status-dot dot-err\"></span>';";
86 html +=
"if(status==='warn')return'<span class=\"status-dot dot-warn\"></span>';";
87 html +=
"return'<span class=\"status-dot dot-off\"></span>';";
89 html +=
"function updateStatus(){fetch('/service_status').then(r=>r.json()).then(d=>{let html='';";
91 "html+=dot(d.wifi_connected)+'<b>WiFi:</b> '+(d.wifi_connected?'Подключено ('+d.wifi_ip+', "
92 "'+d.wifi_ssid+', RSSI '+d.wifi_rssi+' dBm)':'Не подключено')+'<br>';";
94 "html+=dot(d.mqtt_enabled?d.mqtt_connected:false)+'<b>MQTT:</b> "
95 "'+(d.mqtt_enabled?(d.mqtt_connected?'Подключено':'Ошибка'+(d.mqtt_last_error?' "
96 "('+d.mqtt_last_error+')':'')):'Отключено')+'<br>';";
98 "html+=dot(d.thingspeak_enabled?(d.thingspeak_last_error?false:true):false)+'<b>ThingSpeak:</b> "
99 "'+(d.thingspeak_enabled?(d.thingspeak_last_error?'Ошибка: "
100 "'+d.thingspeak_last_error:((d.thingspeak_last_pub && d.thingspeak_last_pub!=='0')?'Последняя "
101 "публикация: '+d.thingspeak_last_pub:'Нет публикаций')):'Отключено')+'<br>';";
103 "if(d.thingspeak_enabled && d.thingspeak_last_error){showToast('Ошибка ThingSpeak: "
104 "'+d.thingspeak_last_error,'error');}";
106 "html+=dot(d.hass_enabled)+'<b>Home Assistant:</b> '+(d.hass_enabled?'Включено':'Отключено')+'<br>';";
108 "html+=dot(d.sensor_ok)+'<b>Датчик:</b> '+(d.sensor_ok?'Ок':'Ошибка'+(d.sensor_last_error?' "
109 "('+d.sensor_last_error+')':''));";
110 html +=
"document.getElementById('status-block').innerHTML=html;";
111 html +=
"});}setInterval(updateStatus," + String(
config.webUpdateInterval) +
");updateStatus();";
114 webServer.send(200,
"text/html; charset=utf-8", html);
125 webServer.send(403,
"text/plain",
"Недоступно в режиме точки доступа");
131 "<!DOCTYPE html><html><head><meta charset='UTF-8'><meta http-equiv='refresh' "
132 "content='2;url=/service'><title>Сброс</title></head><body "
133 "style='font-family:Arial,sans-serif;text-align:center;padding-top:40px'><h2>Настройки "
134 "сброшены</h2><p>Перезагрузка...<br>Сейчас вы будете перенаправлены на страницу "
135 "сервисов.</p></body></html>";
136 webServer.send(200,
"text/html; charset=utf-8", html);
150 webServer.send(403,
"text/plain",
"Недоступно в режиме точки доступа");
155 "<!DOCTYPE html><html><head><meta charset='UTF-8'><meta http-equiv='refresh' "
156 "content='2;url=/service'><title>Перезагрузка</title></head><body "
157 "style='font-family:Arial,sans-serif;text-align:center;padding-top:40px'><h2>Перезагрузка...</"
158 "h2><p>Сейчас вы будете перенаправлены на страницу сервисов.</p></body></html>";
159 webServer.send(200,
"text/html; charset=utf-8", html);
167 webServer.on(
"/ota", HTTP_ANY, []() {
webServer.sendHeader(
"Location",
"/updates",
true);
webServer.send(302,
"text/plain",
"Redirect"); });
175 unsigned long seconds = milliseconds / 1000;
176 unsigned long minutes = seconds / 60;
177 unsigned long hours = minutes / 60;
178 unsigned long days = hours / 24;
185 if (days > 0) uptime += String(days) +
"д ";
186 if (hours > 0) uptime += String(hours) +
"ч ";
187 if (minutes > 0) uptime += String(minutes) +
"м ";
188 uptime += String(seconds) +
"с";
195 StaticJsonDocument<1024> doc;
201 doc[
"device"][
"uptime"] = millis() / 1000;
202 doc[
"device"][
"free_heap"] = ESP.getFreeHeap();
203 doc[
"device"][
"chip_model"] = ESP.getChipModel();
204 doc[
"device"][
"chip_revision"] = ESP.getChipRevision();
205 doc[
"device"][
"cpu_freq"] = ESP.getCpuFreqMHz();
208 doc[
"memory"][
"free_heap"] = ESP.getFreeHeap();
209 doc[
"memory"][
"largest_free_block"] = ESP.getMaxAllocHeap();
210 doc[
"memory"][
"heap_size"] = ESP.getHeapSize();
211 doc[
"memory"][
"psram_size"] = ESP.getPsramSize();
212 doc[
"memory"][
"free_psram"] = ESP.getFreePsram();
218 doc[
"wifi"][
"ssid"] = WiFi.SSID();
219 doc[
"wifi"][
"ip"] = WiFi.localIP().toString();
220 doc[
"wifi"][
"rssi"] = WiFi.RSSI();
221 doc[
"wifi"][
"mac"] = WiFi.macAddress();
222 doc[
"wifi"][
"gateway"] = WiFi.gatewayIP().toString();
223 doc[
"wifi"][
"dns"] = WiFi.dnsIP().toString();
227 doc[
"mqtt"][
"enabled"] = (bool)
config.flags.mqttEnabled;
228 if (
config.flags.mqttEnabled)
230 doc[
"mqtt"][
"connected"] =
mqttClient.connected();
231 doc[
"mqtt"][
"server"] =
config.mqttServer;
232 doc[
"mqtt"][
"port"] =
config.mqttPort;
237 doc[
"thingspeak"][
"enabled"] = (bool)
config.flags.thingSpeakEnabled;
238 if (
config.flags.thingSpeakEnabled)
242 doc[
"thingspeak"][
"interval"] =
config.thingSpeakInterval;
246 doc[
"homeassistant"][
"enabled"] = (bool)
config.flags.hassEnabled;
249 doc[
"sensor"][
"enabled"] = (bool)
config.flags.useRealSensor;
251 doc[
"sensor"][
"last_read"] =
sensorData.last_update;
267 doc[
"timestamp"] = millis();
268 doc[
"boot_time"] = millis();
271 serializeJson(doc, json);
272 webServer.send(200,
"application/json", json);
277 StaticJsonDocument<512> doc;
279 doc[
"wifi_ip"] = WiFi.localIP().toString();
280 doc[
"wifi_ssid"] = WiFi.SSID();
281 doc[
"wifi_rssi"] = WiFi.RSSI();
282 doc[
"mqtt_enabled"] = (bool)
config.flags.mqttEnabled;
283 doc[
"mqtt_connected"] = (bool)
config.flags.mqttEnabled &&
mqttClient.connected();
285 doc[
"thingspeak_enabled"] = (bool)
config.flags.thingSpeakEnabled;
288 doc[
"hass_enabled"] = (bool)
config.flags.hassEnabled;
293 serializeJson(doc, json);
294 webServer.send(200,
"application/json", json);
void logWebRequest(const String &method, const String &uri, const String &clientIP)
Логирование веб-запросов
const char * FIRMWARE_VERSION
#define API_SYSTEM_REBOOT
#define API_SYSTEM_HEALTH
#define API_SYSTEM_STATUS
String generateButton(ButtonType type, const char *icon, const char *text, const char *action)
void logDebug(const char *format,...)
void logSuccess(const char *format,...)
Система логгирования с красивым форматированием
const char * getMqttLastError()
void setupServiceRoutes()
Настройка сервисных маршрутов (/health, /service_status, /reset, /reboot, /ota)
static void sendHealthJson()
String formatUptime(unsigned long milliseconds)
static void sendServiceStatusJson()
const char * getThingSpeakLastPublish()
const char * getThingSpeakLastError()
static const char DEVICE_MANUFACTURER[]
static const char DEVICE_MODEL[]
String generateApModeUnavailablePage(const String &title, const String &icon)
Генерация страницы "Недоступно в AP режиме".
String generatePageHeader(const String &title, const String &icon)
Генерация заголовка HTML страницы
String generatePageFooter()
Генерация футера HTML страницы