/
ellersseer
/
MyCheat
Обзор
Документация
Войти
/
ellersseer
/
MyCheat
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
2
CI/CD
Аналитика
Безопасность
master
src/web_config.cpp
365 строк
12 KB
Dmitry Zhiltsov
feat(logs): Добавить логи в WEB
20 фев 2026, 20:39
20 фев 2026, 20:39
dae6bcf
Код
Авторство
О чём код?
#include "web_config.h" #include "config.h" #include "app_state.h" #include "sensor_api.h" #include "ota_handler.h" #include "log_buffer.h" #include "web_html_settings.h" #include <ArduinoJson.h> #include <AsyncJson.h> // Global instance WebConfig webConfig; // DNS server port #define DNS_PORT 53 void WebConfig::begin(AsyncWebServer *server) { webServer = server; logCapture.println("[WebConfig] Initializing..."); setupRoutes(); logCapture.println("[WebConfig] Routes configured"); } void WebConfig::beginCaptivePortal() { if (captivePortalActive) return; logCapture.println("[WebConfig] Starting captive portal..."); dnsServer = new DNSServer(); // Redirect all DNS queries to the AP IP dnsServer->start(DNS_PORT, "*", WiFi.softAPIP()); captivePortalActive = true; logCapture.println("[WebConfig] Captive portal active"); } void WebConfig::stopCaptivePortal() { if (!captivePortalActive) return; logCapture.println("[WebConfig] Stopping captive portal..."); if (dnsServer) { dnsServer->stop(); delete dnsServer; dnsServer = nullptr; } captivePortalActive = false; } void WebConfig::loop() { if (captivePortalActive && dnsServer) { dnsServer->processNextRequest(); } } void WebConfig::setupRoutes() { // Settings page webServer->on("/settings", HTTP_GET, [this](AsyncWebServerRequest *request) { handleSettingsPage(request); }); // Captive portal detection endpoints webServer->on("/generate_204", HTTP_GET, [this](AsyncWebServerRequest *request) { request->redirect("/settings"); }); webServer->on("/fwlink", HTTP_GET, [this](AsyncWebServerRequest *request) { request->redirect("/settings"); }); webServer->on("/hotspot-detect.html", HTTP_GET, [this](AsyncWebServerRequest *request) { request->redirect("/settings"); }); webServer->on("/connecttest.txt", HTTP_GET, [this](AsyncWebServerRequest *request) { request->redirect("/settings"); }); // API: Get current config webServer->on("/api/config", HTTP_GET, [this](AsyncWebServerRequest *request) { handleGetConfig(request); }); // API: Save WiFi settings AsyncCallbackJsonWebHandler *wifiHandler = new AsyncCallbackJsonWebHandler( "/api/config/wifi", [](AsyncWebServerRequest *request, JsonVariant &json) { JsonObject obj = json.as<JsonObject>(); WifiSettings settings; settingsManager.loadWifiSettings(settings); if (obj.containsKey("ssid")) { strncpy(settings.ssid, obj["ssid"].as<const char *>(), WIFI_SSID_MAX_LEN - 1); settings.ssid[WIFI_SSID_MAX_LEN - 1] = '\0'; } if (obj.containsKey("password")) { strncpy(settings.password, obj["password"].as<const char *>(), WIFI_PASSWORD_MAX_LEN - 1); settings.password[WIFI_PASSWORD_MAX_LEN - 1] = '\0'; } settings.configured = true; if (settingsManager.saveWifiSettings(settings)) { JsonDocument response; response["success"] = true; response["message"] = "WiFi settings saved. Device will restart."; response["restart"] = true; String responseStr; serializeJson(response, responseStr); request->send(200, "application/json", responseStr); // Schedule restart delay(1000); safeRestart(); } else { request->send(500, "application/json", "{\"success\":false,\"message\":\"Failed to save settings\"}"); } }); webServer->addHandler(wifiHandler); // API: Save MQTT settings AsyncCallbackJsonWebHandler *mqttHandler = new AsyncCallbackJsonWebHandler( "/api/config/mqtt", [](AsyncWebServerRequest *request, JsonVariant &json) { JsonObject obj = json.as<JsonObject>(); MqttSettings settings; settingsManager.loadMqttSettings(settings); if (obj.containsKey("server")) { strncpy(settings.server, obj["server"].as<const char *>(), MQTT_SERVER_MAX_LEN - 1); settings.server[MQTT_SERVER_MAX_LEN - 1] = '\0'; } if (obj.containsKey("port")) { settings.port = obj["port"].as<uint16_t>(); } if (obj.containsKey("user")) { strncpy(settings.user, obj["user"].as<const char *>(), MQTT_USER_MAX_LEN - 1); settings.user[MQTT_USER_MAX_LEN - 1] = '\0'; } if (obj.containsKey("password")) { strncpy(settings.password, obj["password"].as<const char *>(), MQTT_PASSWORD_MAX_LEN - 1); settings.password[MQTT_PASSWORD_MAX_LEN - 1] = '\0'; } if (obj.containsKey("client_id")) { strncpy(settings.client_id, obj["client_id"].as<const char *>(), MQTT_CLIENT_ID_MAX_LEN - 1); settings.client_id[MQTT_CLIENT_ID_MAX_LEN - 1] = '\0'; } if (obj.containsKey("topic_prefix")) { strncpy(settings.topic_prefix, obj["topic_prefix"].as<const char *>(), MQTT_TOPIC_PREFIX_MAX_LEN - 1); settings.topic_prefix[MQTT_TOPIC_PREFIX_MAX_LEN - 1] = '\0'; } if (obj.containsKey("enabled")) { settings.enabled = obj["enabled"].as<bool>(); } if (settingsManager.saveMqttSettings(settings)) { // Update global mqttSettings for hot-reload memcpy(&mqttSettings, &settings, sizeof(MqttSettings)); // Signal for MQTT hot-reload if (mqttTaskHandle != NULL) { // Task is running - signal reconfiguration mqttNeedsReconfigure = true; } else if (settings.enabled && strlen(settings.server) > 0) { // Task was not started - request dynamic start mqttShouldStart = true; } JsonDocument response; response["success"] = true; response["message"] = "MQTT settings applied"; String responseStr; serializeJson(response, responseStr); request->send(200, "application/json", responseStr); // No restart needed - hot-reload! } else { request->send(500, "application/json", "{\"success\":false,\"message\":\"Failed to save settings\"}"); } }); webServer->addHandler(mqttHandler); // API: WiFi scan webServer->on("/api/wifi/scan", HTTP_GET, [this](AsyncWebServerRequest *request) { handleWifiScan(request); }); // API: Factory reset AsyncCallbackJsonWebHandler *resetHandler = new AsyncCallbackJsonWebHandler( "/api/factory-reset", [](AsyncWebServerRequest *request, JsonVariant &json) { JsonObject obj = json.as<JsonObject>(); if (!obj.containsKey("confirm") || !obj["confirm"].as<bool>()) { request->send(400, "application/json", "{\"success\":false,\"message\":\"Confirmation required\"}"); return; } settingsManager.factoryReset(); JsonDocument response; response["success"] = true; response["message"] = "Factory reset complete. Device will restart."; String responseStr; serializeJson(response, responseStr); request->send(200, "application/json", responseStr); delay(1000); safeRestart(); }); webServer->addHandler(resetHandler); // API: Reboot webServer->on("/api/reboot", HTTP_POST, [this](AsyncWebServerRequest *request) { handleReboot(request); }); // API: OTA firmware upload setupOtaRoutes(webServer); } void WebConfig::handleSettingsPage(AsyncWebServerRequest *request) { // Load settings for template processor settingsManager.loadWifiSettings(cachedWifi); settingsManager.loadMqttSettings(cachedMqtt); settingsManager.loadSensorSettings(cachedSensors); request->send_P(200, "text/html", SETTINGS_HTML, [this](const String &var) -> String { return settingsTemplateProcessor(var); }); } String WebConfig::settingsTemplateProcessor(const String &var) { if (var == "WIFI_SSID") return String(cachedWifi.ssid); if (var == "MQTT_ENABLED_CHECKED") return cachedMqtt.enabled ? "checked" : ""; if (var == "MQTT_SERVER") return String(cachedMqtt.server); if (var == "MQTT_PORT") return String(cachedMqtt.port); if (var == "MQTT_USER") return String(cachedMqtt.user); if (var == "MQTT_CLIENT_ID") return String(cachedMqtt.client_id); if (var == "MQTT_TOPIC_PREFIX") return String(cachedMqtt.topic_prefix); if (var == "STALE_TIMEOUT") return String(cachedSensors.staleTimeoutMinutes); return String(); } void WebConfig::handleGetConfig(AsyncWebServerRequest *request) { WifiSettings wifi; MqttSettings mqtt; settingsManager.loadWifiSettings(wifi); settingsManager.loadMqttSettings(mqtt); JsonDocument doc; // WiFi settings (password masked) JsonObject wifiObj = doc["wifi"].to<JsonObject>(); wifiObj["ssid"] = wifi.ssid; wifiObj["password"] = strlen(wifi.password) > 0 ? "********" : ""; wifiObj["configured"] = wifi.configured; // Current WiFi status wifiObj["connected"] = wifiManager.isConnected(); wifiObj["mode"] = wifiManager.getModeString(); wifiObj["ip"] = wifiManager.getIP().toString(); if (wifiManager.isConnected()) { wifiObj["rssi"] = wifiManager.getRSSI(); wifiObj["current_ssid"] = wifiManager.getConnectedSSID(); } // MQTT settings (password masked) JsonObject mqttObj = doc["mqtt"].to<JsonObject>(); mqttObj["server"] = mqtt.server; mqttObj["port"] = mqtt.port; mqttObj["user"] = mqtt.user; mqttObj["password"] = strlen(mqtt.password) > 0 ? "********" : ""; mqttObj["client_id"] = mqtt.client_id; mqttObj["topic_prefix"] = mqtt.topic_prefix; mqttObj["enabled"] = mqtt.enabled; // Device info JsonObject deviceObj = doc["device"].to<JsonObject>(); deviceObj["firmware_version"] = FIRMWARE_VERSION; deviceObj["uptime"] = millis() / 1000; deviceObj["free_heap"] = ESP.getFreeHeap(); deviceObj["chip_model"] = ESP.getChipModel(); String response; serializeJson(doc, response); request->send(200, "application/json", response); } void WebConfig::handleWifiScan(AsyncWebServerRequest *request) { logCapture.println("[WebConfig] WiFi scan requested"); WifiNetwork networks[20]; int count = wifiManager.scanNetworks(networks, 20); logCapture.printf("[WebConfig] Building JSON for %d networks\n", count); JsonDocument doc; JsonArray arr = doc["networks"].to<JsonArray>(); for (int i = 0; i < count; i++) { JsonObject net = arr.add<JsonObject>(); net["ssid"] = networks[i].ssid; net["rssi"] = networks[i].rssi; net["open"] = networks[i].isOpen; // Signal quality percentage int quality = 0; if (networks[i].rssi >= -50) quality = 100; else if (networks[i].rssi <= -100) quality = 0; else quality = 2 * (networks[i].rssi + 100); net["quality"] = quality; } String response; serializeJson(doc, response); logCapture.printf("[WebConfig] Sending response: %d bytes\n", response.length()); request->send(200, "application/json", response); } void WebConfig::handleReboot(AsyncWebServerRequest *request) { request->send(200, "application/json", "{\"success\":true,\"message\":\"Rebooting...\"}"); delay(1000); safeRestart(); }