Sonoff4ChPro/src/http.cpp
2025-08-29 10:10:46 +02:00

164 lines
4.1 KiB
C++

#include "http.h"
#include "io.h"
#include <ArduinoJson.h>
#include <LittleFS.h>
#ifdef ESP8266
#include <ESP8266WebServer.h>
ESP8266WebServer server(80);
#endif
#ifdef ESP32
#include <WebServer.h>
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<JsonArray>();
httpRelayJson(relay0, relays.add<JsonObject>());
httpRelayJson(relay1, relays.add<JsonObject>());
httpRelayJson(relay2, relays.add<JsonObject>());
httpRelayJson(relay3, relays.add<JsonObject>());
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");
}
}