180 lines
5.2 KiB
C++
180 lines
5.2 KiB
C++
#include "http.h"
|
|
#include "io.h"
|
|
|
|
#include <ArduinoJson.h>
|
|
#include <LittleFS.h>
|
|
|
|
#include "wifi.h"
|
|
|
|
#ifdef ESP8266
|
|
#include <ESP8266WebServer.h>
|
|
|
|
ESP8266WebServer server(80);
|
|
#endif
|
|
|
|
#ifdef ESP32
|
|
#include <WebServer.h>
|
|
|
|
WebServer server(80);
|
|
#endif
|
|
|
|
bool httpRunning = false;
|
|
|
|
File httpUploadFile;
|
|
|
|
void httpString(const String &key, const std::function<void(const String &)> &modifier) {
|
|
if (server.hasArg(key)) {
|
|
const auto name = server.arg(key);
|
|
modifier(name);
|
|
}
|
|
}
|
|
|
|
void httpBool(const String &key, const std::function<void(const bool &)> &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<void(const long &)> &modifier) {
|
|
if (server.hasArg(key)) {
|
|
modifier(server.arg(key).toInt());
|
|
}
|
|
}
|
|
|
|
void httpInitial(const String &key, const std::function<void(const Initial &)> &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<JsonObject>();
|
|
wifi["hostname"] = WiFi.getHostname();
|
|
wifi["ssid"] = WiFi.SSID();
|
|
|
|
const auto mqtt = json["mqtt"].to<JsonObject>();
|
|
mqtt["user"] = getMqttUser();
|
|
mqtt["host"] = getMqttHost();
|
|
mqtt["port"] = getMqttPort();
|
|
|
|
json["gridPowerDeltaValue"] = gridPowerDeltaValue;
|
|
json["gridPowerDeltaAge"] = millis() - gridPowerDeltaMillis;
|
|
|
|
const auto relays = json["relays"].to<JsonArray>();
|
|
relay0.json(relays.add<JsonObject>());
|
|
#ifdef Ch4Pro
|
|
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() {
|
|
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");
|
|
}
|
|
}
|