diff --git a/.gitignore b/.gitignore index 03f4a3c..03e86a6 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .pio +/index.html.min \ No newline at end of file diff --git a/icon.svg b/icon.svg new file mode 100644 index 0000000..5f29574 --- /dev/null +++ b/icon.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..5b240af --- /dev/null +++ b/index.html @@ -0,0 +1,167 @@ + + + + + + + + +
+
+
Name
+
Status
+
Initial
+
Auto Aus
+
Auto An
+
Ein
+
Aus
+
Zyklus
+
+
+ +

+
+
+
+
\ No newline at end of file
diff --git a/src/Initial.h b/src/Initial.h
index 28427fa..5b81ec0 100644
--- a/src/Initial.h
+++ b/src/Initial.h
@@ -4,15 +4,15 @@
 enum Initial {
   INITIAL_OFF,
   INITIAL_ON,
-  INITIAL_BLINK,
+  INITIAL_CYCLE,
 };
 
 inline Initial stringToInitial(const String &str) {
   if (str == "ON") {
     return INITIAL_ON;
   }
-  if (str == "BLINK") {
-    return INITIAL_BLINK;
+  if (str == "CYCLE") {
+    return INITIAL_CYCLE;
   }
   return INITIAL_OFF;
 }
@@ -21,8 +21,8 @@ inline const char *initialToString(const Initial value) {
   switch (value) {
     case INITIAL_ON:
       return "ON";
-    case INITIAL_BLINK:
-      return "BLINK";
+    case INITIAL_CYCLE:
+      return "CYCLE";
     default:
       return "OFF";
   }
diff --git a/src/Output.h b/src/Output.h
index 87c83e6..0ddcc94 100644
--- a/src/Output.h
+++ b/src/Output.h
@@ -39,7 +39,7 @@ protected:
 
   void _applyInitial() {
     _write(initial != INITIAL_OFF);
-    if (initial != INITIAL_BLINK) {
+    if (initial != INITIAL_CYCLE) {
       onCount = 0;
     } else {
       onCount = -1;
@@ -72,7 +72,7 @@ public:
     set(!get());
   }
 
-  void blink(const unsigned long onMillis_, const unsigned long offMillis_, const unsigned long onCount_ = -1) {
+  void cycle(const unsigned long onMillis_, const unsigned long offMillis_, const unsigned long onCount_ = -1) {
     this->onMillis = onMillis_;
     this->offMillis = offMillis_;
     this->onCount = onCount_;
diff --git a/src/config.cpp b/src/config.cpp
index 6bd8ec7..9ca318c 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -26,7 +26,7 @@ bool configWrite(const String &name, const long fallback, const long value) {
   if (configRead(name, fallback) == value) {
     return false;
   }
-  Serial.printf("\"%s\" = \"%ld\"", name.c_str(), value);
+  Serial.printf("[CONFIG] \"%s\" = \"%ld\"\n", name.c_str(), value);
   if (auto file = configOpen(name, "w")) {
     const auto content = String(value);
     file.write(reinterpret_cast(content.c_str()), content.length());
@@ -65,7 +65,7 @@ bool configWrite(const String &name, const String &fallback, const String &value
   if (configRead(name, fallback) == value) {
     return false;
   }
-  Serial.printf("\"%s\" = \"%s\"", name.c_str(), value.c_str());
+  Serial.printf("[CONFIG] \"%s\" = \"%s\"\n", name.c_str(), value.c_str());
   if (auto file = configOpen(name, "w")) {
     file.write(reinterpret_cast(value.c_str()), value.length());
     file.close();
diff --git a/src/http.cpp b/src/http.cpp
index 76ffbf0..8595eaa 100644
--- a/src/http.cpp
+++ b/src/http.cpp
@@ -2,6 +2,7 @@
 #include "io.h"
 
 #include 
+#include 
 
 #ifdef ESP8266
 #include 
@@ -18,6 +19,12 @@ WebServer server(80);
 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);
@@ -39,12 +46,19 @@ void httpRelay(const int index, Output &relay) {
     } else if (initial == "ON") {
       Serial.printf("[HTTP] %s = %s\n", initialKey.c_str(), initial.c_str());
       relay.setInitial(INITIAL_ON);
-    } else if (initial == "BLINK") {
+    } else if (initial == "CYCLE") {
       Serial.printf("[HTTP] %s = %s\n", initialKey.c_str(), initial.c_str());
-      relay.setInitial(INITIAL_BLINK);
+      relay.setInitial(INITIAL_CYCLE);
     }
   }
 
+  const auto onCountKey = String("onCount") + index;
+  if (server.hasArg(onCountKey)) {
+    const auto value = server.arg(onCountKey).toInt();
+    Serial.printf("[HTTP] %s = %ld\n", onCountKey.c_str(), value);
+    relay.setOnCount(value);
+  }
+
   const auto onMillisKey = String("onMillis") + index;
   if (server.hasArg(onMillisKey)) {
     const auto value = server.arg(onMillisKey).toInt();
@@ -58,13 +72,6 @@ void httpRelay(const int index, Output &relay) {
     Serial.printf("[HTTP] %s = %ld\n", offMillisKey.c_str(), value);
     relay.setOffMillis(value);
   }
-
-  const auto onCountKey = String("onCount") + index;
-  if (server.hasArg(onCountKey)) {
-    const auto value = server.arg(onCountKey).toInt();
-    Serial.printf("[HTTP] %s = %ld\n", onCountKey.c_str(), value);
-    relay.setOnCount(value);
-  }
 }
 
 void httpRelayJson(const Output &relay, const JsonObject json) {
@@ -79,12 +86,13 @@ void httpRelayJson(const Output &relay, const JsonObject json) {
 
 void httpStatus() {
   JsonDocument json;
-  json.to();
+  json["hostname"] = WiFi.getHostname();
 
-  httpRelayJson(relay1, json["relay1"].to());
-  httpRelayJson(relay2, json["relay2"].to());
-  httpRelayJson(relay3, json["relay3"].to());
-  httpRelayJson(relay4, json["relay4"].to());
+  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);
@@ -92,27 +100,60 @@ void httpStatus() {
 }
 
 void httpSet() {
+  httpRelay(0, relay0);
   httpRelay(1, relay1);
   httpRelay(2, relay2);
   httpRelay(3, relay3);
-  httpRelay(4, relay4);
   httpStatus();
 }
 
 void httpOff() {
+  relay0.set(false);
   relay1.set(false);
   relay2.set(false);
   relay3.set(false);
-  relay4.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.on("", httpSet);
-  server.on("/", httpSet);
+  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;
 }
diff --git a/src/io.cpp b/src/io.cpp
index 57b0479..a4067cb 100644
--- a/src/io.cpp
+++ b/src/io.cpp
@@ -8,23 +8,23 @@
 #define STATUS_INVERT true
 #endif
 
-Relay relay1(1, "RELAY #1", 12, false, true);
+Relay relay0(1, "RELAY #0", 12, false, true);
 
-Relay relay2(2, "RELAY #2", 5, false, true);
+Relay relay1(2, "RELAY #1", 5, false, true);
 
-Relay relay3(3, "RELAY #3", 4, false, true);
+Relay relay2(3, "RELAY #2", 4, false, true);
 
-Relay relay4(4, "RELAY #4", 15, false, true);
+Relay relay3(4, "RELAY #3", 15, false, true);
 
 Output status("Status", STATUS_PIN, STATUS_INVERT, false);
 
-Button button1(0, true, true, [](const ButtonEvent event) { buttonCallback(relay1, event); });
+Button button0(0, true, true, [](const ButtonEvent event) { buttonCallback(relay0, event); });
 
-Button button2(9, true, true, [](const ButtonEvent event) { buttonCallback(relay2, event); });
+Button button1(9, true, true, [](const ButtonEvent event) { buttonCallback(relay1, event); });
 
-Button button3(10, true, true, [](const ButtonEvent event) { buttonCallback(relay3, event); });
+Button button2(10, true, true, [](const ButtonEvent event) { buttonCallback(relay2, event); });
 
-Button button4(14, true, true, [](const ButtonEvent event) { buttonCallback(relay4, event); });
+Button button3(14, true, true, [](const ButtonEvent event) { buttonCallback(relay3, event); });
 
 void buttonCallback(Output &output, const ButtonEvent event) {
   if (event == BUTTON_PRESSED) {
diff --git a/src/io.h b/src/io.h
index 1a0afad..b3add7c 100644
--- a/src/io.h
+++ b/src/io.h
@@ -6,50 +6,50 @@
 
 void buttonCallback(Output &output, ButtonEvent event);
 
+extern Relay relay0;
+
 extern Relay relay1;
 
 extern Relay relay2;
 
 extern Relay relay3;
 
-extern Relay relay4;
-
 extern Output status;
 
+extern Button button0;
+
 extern Button button1;
 
 extern Button button2;
 
 extern Button button3;
 
-extern Button button4;
-
 inline void ioSetup() {
+  button0.setup();
   button1.setup();
   button2.setup();
   button3.setup();
-  button4.setup();
 
   status.setup();
 
+  relay0.setup();
   relay1.setup();
   relay2.setup();
   relay3.setup();
-  relay4.setup();
 }
 
 inline void ioLoop() {
+  button0.loop();
   button1.loop();
   button2.loop();
   button3.loop();
-  button4.loop();
 
   status.loop();
 
-  relay1.loop();
+  relay0.loop();
+  relay0.loop();
   relay2.loop();
   relay3.loop();
-  relay4.loop();
 }
 
 #endif
diff --git a/src/wifi.cpp b/src/wifi.cpp
index 4446b7d..ad057e5 100644
--- a/src/wifi.cpp
+++ b/src/wifi.cpp
@@ -24,7 +24,7 @@ void wifiConnect() {
   WiFi.setAutoReconnect(false);
   yield();
 
-  status.blink(500, 500);
+  status.cycle(500, 500);
 
   const auto hostname = configRead(CONFIG_HOSTNAME, DEFAULT_HOSTNAME);
   const auto wifiSSID = configRead(CONFIG_WIFI_SSID, DEFAULT_WIFI_SSID);
diff --git a/upload.sh b/upload.sh
new file mode 100644
index 0000000..82dd930
--- /dev/null
+++ b/upload.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+cd "$(dirname "$0")" || exit 1
+
+minify index.html | sed 's|http://10.42.0.204||g' > index.html.min || exit 2
+
+curl -s 'http://10.42.0.204/upload/index' -F "file=@index.html.min"
+curl -s 'http://10.42.0.204/upload/icon'  -F "file=@icon.svg"
\ No newline at end of file