Sonoff4ChPro/src/http.cpp
2025-09-03 10:05:48 +02:00

166 lines
3.9 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, Relay &relay) {
const auto nameKey = String("name") + index;
if (server.hasArg(nameKey)) {
const auto name = server.arg(nameKey);
relay.setName(name);
}
const auto topicKey = String("topic") + index;
if (server.hasArg(topicKey)) {
const auto topic = server.arg(topicKey);
relay.setTopic(topic);
}
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 httpStatus() {
JsonDocument json;
json["hostname"] = WiFi.getHostname();
const auto relays = json["relays"].to<JsonArray>();
relay0.json(relays.add<JsonObject>());
#ifdef Sonoff4ChPro
relay1.json(relays.add<JsonObject>());
relay2.json(relays.add<JsonObject>());
relay3.json(relays.add<JsonObject>());
#endif
String response;
serializeJson(json, response);
server.send(200, "application/json", response);
}
void httpSet() {
httpRelay(0, relay0);
#ifdef Sonoff4ChPro
httpRelay(1, relay1);
httpRelay(2, relay2);
httpRelay(3, relay3);
#endif
httpStatus();
}
void httpOff() {
relay0.set(false);
#ifdef Sonoff4ChPro
relay1.set(false);
relay2.set(false);
relay3.set(false);
#endif
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");
}
}