From f72c04b9b3f3faf15f324d86c4409a5bc9566004 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Ha=C3=9Fel?= Date: Wed, 3 Sep 2025 11:09:07 +0200 Subject: [PATCH] gridPowerDelta --- src/Output.h | 2 +- src/Relay.h | 129 ++++++++++++++++++++++++++++++++----------------- src/config.cpp | 2 +- src/mqtt.cpp | 4 +- src/mqtt.h | 2 +- 5 files changed, 89 insertions(+), 50 deletions(-) diff --git a/src/Output.h b/src/Output.h index edaf97e..b860c3c 100644 --- a/src/Output.h +++ b/src/Output.h @@ -69,7 +69,7 @@ public: return (digitalRead(pin) == HIGH) ^ inverted; } - void set(const bool state) { + virtual void set(const bool state) { _write(state); onCount = 0; } diff --git a/src/Relay.h b/src/Relay.h index 77824b9..520af0e 100644 --- a/src/Relay.h +++ b/src/Relay.h @@ -15,10 +15,14 @@ class Relay final : public Output { String topic; + bool gridPowerDeltaOffEnabled = false; + long gridPowerDeltaOnThreshold = 0; long gridPowerDeltaOnDelay = 0; + bool gridPowerDeltaOnEnabled = false; + long gridPowerDeltaOffThreshold = 0; long gridPowerDeltaOffDelay = 0; @@ -41,11 +45,13 @@ public: topic = configRead(path("topic"), topicFallback); - gridPowerDeltaOnThreshold = configRead(path("autoOnThreshold"), -400L); - gridPowerDeltaOnDelay = configRead(path("autoOnDelay"), 30000L); + gridPowerDeltaOnEnabled = configRead(path("gridPowerDeltaOnEnabled"), false); + gridPowerDeltaOnThreshold = configRead(path("gridPowerDeltaOnThreshold"), 0L); + gridPowerDeltaOnDelay = configRead(path("gridPowerDeltaOnDelay"), 0L); - gridPowerDeltaOffThreshold = configRead(path("autoOffThreshold"), 100L); - gridPowerDeltaOffDelay = configRead(path("autoOffDelay"), 30000L); + gridPowerDeltaOffEnabled = configRead(path("gridPowerDeltaOffEnabled"), false); + gridPowerDeltaOffThreshold = configRead(path("gridPowerDeltaOffThreshold"), 0L); + gridPowerDeltaOffDelay = configRead(path("gridPowerDeltaOffDelay"), 0L); _applyInitial(); } @@ -80,30 +86,38 @@ public: configWrite(path("topic"), topicFallback, value); } - void setAutoOnThreshold(const long value) { + void setGridPowerDeltaOnEnabled(const bool value) { + gridPowerDeltaOnEnabled = value; + configWrite(path("gridPowerDeltaOnEnabled"), false, value); + } + + void setGridPowerDeltaOnThreshold(const long value) { gridPowerDeltaOnThreshold = value; - configWrite(path("autoOnThreshold"), 0L, value); + configWrite(path("gridPowerDeltaOnThreshold"), 0L, value); } - void setAutoOnDelay(const long value) { + void setGridPowerDeltaOnDelay(const long value) { gridPowerDeltaOnDelay = value; - configWrite(path("autoOnDelay"), 0L, value); + configWrite(path("gridPowerDeltaOnDelay"), 0L, value); } - void setAutoOffThreshold(const long value) { + void setGridPowerDeltaOffEnabled(const bool value) { + gridPowerDeltaOffEnabled = value; + configWrite(path("gridPowerDeltaOffEnabled"), false, value); + } + + void setGridPowerDeltaOffThreshold(const long value) { gridPowerDeltaOffThreshold = value; - configWrite(path("autoOffThreshold"), 0L, value); + configWrite(path("gridPowerDeltaOffThreshold"), 0L, value); } - void setAutoOffDelay(const long value) { + void setGridPowerDeltaOffDelay(const long value) { gridPowerDeltaOffDelay = value; - configWrite(path("autoOffDelay"), 0L, value); + configWrite(path("gridPowerDeltaOffDelay"), 0L, value); } void json(const JsonObject json) const { json["name"] = name; - json["state"] = get(); - json["stateAgeMillis"] = millis() - stateMillis; json["initial"] = initialToString(initial); json["onCount"] = onCount; json["onMillis"] = onMillis; @@ -111,10 +125,21 @@ public: json["topic"] = topic; - json["autoOnThreshold"] = gridPowerDeltaOnThreshold; - json["autoOnDelay"] = gridPowerDeltaOnDelay; - json["autoOffThreshold"] = gridPowerDeltaOffThreshold; - json["autoOffDelay"] = gridPowerDeltaOffDelay; + json["gridPowerDeltaOffEnabled"] = gridPowerDeltaOffEnabled; + json["gridPowerDeltaOnThreshold"] = gridPowerDeltaOnThreshold; + json["gridPowerDeltaOnDelay"] = gridPowerDeltaOnDelay; + + json["gridPowerDeltaOnEnabled"] = gridPowerDeltaOnEnabled; + json["gridPowerDeltaOffThreshold"] = gridPowerDeltaOffThreshold; + json["gridPowerDeltaOffDelay"] = gridPowerDeltaOffDelay; + + json["state"] = get(); + json["stateAgeMillis"] = millis() - stateMillis; + } + + void set(const bool state) override { + Output::set(state); + gridPowerDeltaMillis = 0; } protected: @@ -134,37 +159,51 @@ private: } void doGridPowerDelta() { - const auto age = millis() - gridPowerDeltaMillis; + if (isnan(gridPowerDeltaValue) || millis() - gridPowerDeltaMillis > 10000) { + return; + } if (get()) { - if (gridPowerDelta > gridPowerDeltaOffThreshold) { - if (gridPowerDeltaMillis == 0) { - Serial.printf("[%s] CONSUMING TOO MUCH: Preparing to power OFF...\n", name.c_str()); - gridPowerDeltaMillis = max(1UL, millis()); - } else { - if (age > gridPowerDeltaOffDelay) { - gridPowerDeltaMillis = 0; - set(false); - } - } - } else if (gridPowerDeltaMillis > 0) { - Serial.printf("[%s] Powering off CANCELED!\n", name.c_str()); - gridPowerDeltaMillis = 0; - } + gridPowerDeltaOff(); } else { - if (gridPowerDelta < gridPowerDeltaOnThreshold) { - if (gridPowerDeltaMillis == 0) { - Serial.printf("[%s] PRODUCING TOO MUCH: Preparing to power ON...\n", name.c_str()); - gridPowerDeltaMillis = max(1UL, millis()); - } else { - if (age > gridPowerDeltaOnDelay) { - gridPowerDeltaMillis = 0; - set(true); - } + gridPowerDeltaOn(); + } + } + + void gridPowerDeltaOff() { + if (!gridPowerDeltaOffEnabled) { + return; + } + if (gridPowerDeltaValue > gridPowerDeltaOffThreshold) { + if (gridPowerDeltaMillis == 0) { + Serial.printf("[%s] CONSUMING TOO MUCH: Preparing to power OFF...\n", name.c_str()); + gridPowerDeltaMillis = max(1UL, millis()); + } else { + if (millis() - gridPowerDeltaMillis > gridPowerDeltaOffDelay) { + set(false); } - } else if (gridPowerDeltaMillis > 0) { - Serial.printf("[%s] Powering on CANCELED!\n", name.c_str()); - gridPowerDeltaMillis = 0; } + } else if (gridPowerDeltaMillis > 0) { + Serial.printf("[%s] Powering off CANCELED!\n", name.c_str()); + gridPowerDeltaMillis = 0; + } + } + + void gridPowerDeltaOn() { + if (!gridPowerDeltaOnEnabled) { + return; + } + if (gridPowerDeltaValue < gridPowerDeltaOnThreshold) { + if (gridPowerDeltaMillis == 0) { + Serial.printf("[%s] PRODUCING TOO MUCH: Preparing to power ON...\n", name.c_str()); + gridPowerDeltaMillis = max(1UL, millis()); + } else { + if (millis() - gridPowerDeltaMillis > gridPowerDeltaOnDelay) { + set(true); + } + } + } else if (gridPowerDeltaMillis > 0) { + Serial.printf("[%s] Powering on CANCELED!\n", name.c_str()); + gridPowerDeltaMillis = 0; } } diff --git a/src/config.cpp b/src/config.cpp index a19e9ad..b8ba4d5 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -75,7 +75,7 @@ void doLog(const String &path, const String &value, const bool isPassword, const return; } Serial.printf( - "[CONFIG] %-25s = %-30s [%s]\n", + "[CONFIG] %-40s = %-30s [%s]\n", path.c_str(), isPassword ? "*" : value.c_str(), type == CONFIG_LOG_FALLBACK ? "fallback" : type == CONFIG_LOG_READ ? "READ" : type == CONFIG_LOG_UNCHANGED ? "UNCHANGED" : type == CONFIG_LOG_WRITE ? "WRITE" : "" diff --git a/src/mqtt.cpp b/src/mqtt.cpp index c4b1724..743c026 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -21,7 +21,7 @@ void mqttSetup() { mqttShouldConnect = true; } -double gridPowerDelta = NAN; +double gridPowerDeltaValue = NAN; double gridPowerDeltaMillis = 0; @@ -34,7 +34,7 @@ void mqttReceive(const char *topic, const uint8_t *bytes, const unsigned int len memcpy(string, bytes, length); const auto payload = String(string); if (GRID_POWER_DELTA_TOPIC == topic) { - gridPowerDelta = payload.toDouble(); + gridPowerDeltaValue = payload.toDouble(); gridPowerDeltaMillis = millis(); } else { Serial.printf("[MQTT] Received unexpected topic: %s\n", topic); diff --git a/src/mqtt.h b/src/mqtt.h index 1fc5787..1d6d53c 100644 --- a/src/mqtt.h +++ b/src/mqtt.h @@ -3,7 +3,7 @@ #include -extern double gridPowerDelta; +extern double gridPowerDeltaValue; extern double gridPowerDeltaMillis;