#include "http.h" #include "io.h" #include #include #ifdef ESP8266 #include ESP8266WebServer server(80); #endif #ifdef ESP32 #include WebServer server(80); #endif bool httpRunning = false; void httpRelay(const int index, Output &relay) { const auto nameKey = String("name") + index; if (server.hasArg(nameKey)) { const auto name = server.arg(nameKey); relay.setName(name); } const auto stateKey = String("state") + index; if (server.hasArg(stateKey)) { const auto state = server.arg(stateKey); if (state == "true") { relay.set(true); } else if (state == "false") { relay.set(false); } } const auto initialKey = String("initial") + index; if (server.hasArg(initialKey)) { const auto initial = server.arg(initialKey); if (initial == "OFF") { relay.setInitial(INITIAL_OFF); } else if (initial == "ON") { relay.setInitial(INITIAL_ON); } else if (initial == "CYCLE") { relay.setInitial(INITIAL_CYCLE); } } const auto onCountKey = String("onCount") + index; if (server.hasArg(onCountKey)) { const auto value = server.arg(onCountKey).toInt(); relay.setOnCount(value); } const auto onMillisKey = String("onMillis") + index; if (server.hasArg(onMillisKey)) { const auto value = server.arg(onMillisKey).toInt(); relay.setOnMillis(value); } const auto offMillisKey = String("offMillis") + index; if (server.hasArg(offMillisKey)) { const auto value = server.arg(offMillisKey).toInt(); relay.setOffMillis(value); } } void httpRelayJson(const Output &relay, const JsonObject json) { json["name"] = relay.getName(); json["state"] = relay.get(); json["stateMillis"] = relay.getStateMillis(); json["initial"] = initialToString(relay.getInitial()); json["onCount"] = relay.getOnCount(); json["onMillis"] = relay.getOnMillis(); json["offMillis"] = relay.getOffMillis(); } void httpStatus() { JsonDocument json; json["hostname"] = WiFi.getHostname(); const auto relays = json["relays"].to(); httpRelayJson(relay0, relays.add()); httpRelayJson(relay1, relays.add()); httpRelayJson(relay2, relays.add()); httpRelayJson(relay3, relays.add()); String response; serializeJson(json, response); server.send(200, "application/json", response); } void httpSet() { httpRelay(0, relay0); httpRelay(1, relay1); httpRelay(2, relay2); httpRelay(3, relay3); httpStatus(); } void httpOff() { relay0.set(false); relay1.set(false); relay2.set(false); relay3.set(false); httpStatus(); } File httpUploadFile; void httpUpload(const char *name) { 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("/set", httpSet); server.on("/set/", httpSet); server.on("/off", httpOff); server.on("/off/", httpOff); 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"); } }