#include "http.h" #include "io.h" #include #include #include "wifi.h" #ifdef ESP8266 #include ESP8266WebServer server(80); #endif #ifdef ESP32 #include WebServer server(80); #endif bool httpRunning = false; File httpUploadFile; void httpString(const String &key, const std::function &modifier) { if (server.hasArg(key)) { const auto name = server.arg(key); modifier(name); } } void httpBool(const String &key, const std::function &modifier) { if (server.hasArg(key)) { const auto state = server.arg(key); if (state == "true") { modifier(true); } else if (state == "false") { modifier(false); } } } void httpLong(const String &key, const std::function &modifier) { if (server.hasArg(key)) { modifier(server.arg(key).toInt()); } } void httpInitial(const String &key, const std::function &modifier) { httpString(key, [&modifier](const String &value) { if (value == "OFF") { modifier(INITIAL_OFF); } else if (value == "ON") { modifier(INITIAL_ON); } else if (value == "CYCLE") { modifier(INITIAL_CYCLE); } }); } void httpRelay(const int index, Relay &relay) { const String suffix(index); httpString("name" + suffix, [&relay](const String &value) { relay.setName(value); }); httpInitial("initial" + suffix, [&relay](const Initial &value) { relay.setInitial(value); }); httpLong("onCount" + suffix, [&relay](const long &value) { relay.setOnCount(value); }); httpLong("onMillis" + suffix, [&relay](const long &value) { relay.setOnMillis(value); }); httpLong("offMillis" + suffix, [&relay](const long &value) { relay.setOffMillis(value); }); httpString("topic" + suffix, [&relay](const String &value) { relay.setTopic(value); }); httpBool("gridPowerDeltaOnEnabled" + suffix, [&relay](const long &value) { relay.setGridPowerDeltaOnEnabled(value); }); httpLong("gridPowerDeltaOnThreshold" + suffix, [&relay](const long &value) { relay.setGridPowerDeltaOnThreshold(value); }); httpLong("gridPowerDeltaOnDelay" + suffix, [&relay](const long &value) { relay.setGridPowerDeltaOnDelay(value); }); httpBool("gridPowerDeltaOffEnabled" + suffix, [&relay](const long &value) { relay.setGridPowerDeltaOffEnabled(value); }); httpLong("gridPowerDeltaOffThreshold" + suffix, [&relay](const long &value) { relay.setGridPowerDeltaOffThreshold(value); }); httpLong("gridPowerDeltaOffDelay" + suffix, [&relay](const long &value) { relay.setGridPowerDeltaOffDelay(value); }); httpBool("state" + suffix, [&relay](const bool &value) { relay.set(value); }); } void httpStatus() { JsonDocument json; const auto wifi = json["wifi"].to(); wifi["hostname"] = WiFi.getHostname(); wifi["ssid"] = WiFi.SSID(); const auto mqtt = json["mqtt"].to(); mqtt["user"] = getMqttUser(); mqtt["host"] = getMqttHost(); mqtt["port"] = getMqttPort(); json["gridPowerDeltaValue"] = gridPowerDeltaValue; json["gridPowerDeltaAge"] = millis() - gridPowerDeltaMillis; const auto relays = json["relays"].to(); relay0.json(relays.add()); #ifdef Ch4Pro relay1.json(relays.add()); relay2.json(relays.add()); relay3.json(relays.add()); #endif String response; serializeJson(json, response); server.send(200, "application/json", response); } void httpSet() { httpString("wifiHostname", wifiSetHostname); httpString("wifiSSID", wifiSetSSID); httpString("wifiPassword", wifiSetPassword); httpString("mqttHost", mqttSetHost); httpLong("mqttPort", mqttSetPort); httpString("mqttUser", mqttSetUser); httpString("mqttPassword", mqttSetPassword); httpRelay(0, relay0); #ifdef Ch4Pro httpRelay(1, relay1); httpRelay(2, relay2); httpRelay(3, relay3); #endif httpStatus(); } void httpUpload(const char *name) { yield(); const auto upload = server.upload(); if (upload.status == UPLOAD_FILE_START) { char path[64]; snprintf(path, sizeof(path), "/%s", name); httpUploadFile = LittleFS.open(path, "w"); Serial.printf("[HTTP] Uploading: %s\n", name); } else if (upload.status == UPLOAD_FILE_WRITE) { if (httpUploadFile) { httpUploadFile.write(upload.buf, upload.currentSize); } } else if (upload.status == UPLOAD_FILE_END) { if (httpUploadFile) { httpUploadFile.close(); Serial.printf("[HTTP] Upload complete: %s (%d bytes)\n", name, upload.currentSize); server.send(200); } } } void httpSetup() { server.enableCORS(true); server.serveStatic("", LittleFS, "/index.html"); server.serveStatic("/", LittleFS, "/index.html"); server.serveStatic("/icon.svg", LittleFS, "/icon.svg"); server.on("/status", httpSet); server.on("/status/", httpSet); server.on("/upload/index", HTTP_POST, [] { server.send(200); }, [] { httpUpload("index.html"); }); server.on("/upload/icon", HTTP_POST, [] { server.send(200); }, [] { httpUpload("icon.svg"); }); server.begin(); Serial.println("[HTTP] Server started"); httpRunning = true; } void httpLoop() { server.handleClient(); } void httpStop() { if (httpRunning) { httpRunning = false; server.stop(); Serial.println("[HTTP] Server stopped"); } }