Compare commits

..

4 Commits

Author SHA1 Message Date
2652de5cb8 Relay publish after any change 2025-09-03 14:31:15 +02:00
a3076b9b2f Relay code clean 2025-09-03 14:27:58 +02:00
b8d79dbc67 mqtt buffer size FIX 2025-09-03 14:27:43 +02:00
d4282d3fba gridPowerDelta Relay logging 2025-09-03 13:52:16 +02:00
3 changed files with 40 additions and 26 deletions

View File

@ -37,7 +37,7 @@ protected:
digitalWrite(pin, wanted ^ inverted ? HIGH : LOW); digitalWrite(pin, wanted ^ inverted ? HIGH : LOW);
publish(); publish();
if (logState) { if (logState) {
Serial.printf("[RELAY] \"%s\" = %s\n", name.c_str(), wanted ? "ON" : "OFF"); Serial.printf("[RELAY] \"%s\": %s\n", name.c_str(), wanted ? "ON" : "OFF");
} }
stateMillis = millis(); stateMillis = millis();
} }
@ -70,8 +70,8 @@ public:
} }
virtual void set(const bool state) { virtual void set(const bool state) {
_write(state);
onCount = 0; onCount = 0;
_write(state);
} }
void toggle() { void toggle() {

View File

@ -27,7 +27,7 @@ class Relay final : public Output {
long gridPowerDeltaOffDelay = 0; long gridPowerDeltaOffDelay = 0;
unsigned long gridPowerDeltaLast = 0; unsigned long gridPowerDeltaAlarmSince = 0;
public: public:
@ -64,56 +64,67 @@ public:
void setName(const String &value) override { void setName(const String &value) override {
Output::setName(value); Output::setName(value);
storeString(path("name"), nameFallback, value); storeString(path("name"), nameFallback, value);
publish();
} }
void setInitial(const Initial value) override { void setInitial(const Initial value) override {
Output::setInitial(value); Output::setInitial(value);
storeInitial(path("initial"), INITIAL_OFF, value); storeInitial(path("initial"), INITIAL_OFF, value);
publish();
} }
void setOnMillis(const unsigned long value) override { void setOnMillis(const unsigned long value) override {
Output::setOnMillis(value); Output::setOnMillis(value);
storeLong(path("onMillis"), 0L, value); storeLong(path("onMillis"), 0L, value);
publish();
} }
void setOffMillis(const unsigned long value) override { void setOffMillis(const unsigned long value) override {
Output::setOffMillis(value); Output::setOffMillis(value);
storeLong(path("offMillis"), 0L, value); storeLong(path("offMillis"), 0L, value);
publish();
} }
void setTopic(const String &value) { void setTopic(const String &value) {
topic = value; topic = value;
storeString(path("topic"), topicFallback, value); storeString(path("topic"), topicFallback, value);
publish();
} }
void setGridPowerDeltaOnEnabled(const bool value) { void setGridPowerDeltaOnEnabled(const bool value) {
gridPowerDeltaOnEnabled = value; gridPowerDeltaOnEnabled = value;
storeBool(path("gridPowerDeltaOnEnabled"), false, value); storeBool(path("gridPowerDeltaOnEnabled"), false, value);
publish();
} }
void setGridPowerDeltaOnThreshold(const long value) { void setGridPowerDeltaOnThreshold(const long value) {
gridPowerDeltaOnThreshold = value; gridPowerDeltaOnThreshold = value;
storeLong(path("gridPowerDeltaOnThreshold"), 0L, value); storeLong(path("gridPowerDeltaOnThreshold"), 0L, value);
publish();
} }
void setGridPowerDeltaOnDelay(const long value) { void setGridPowerDeltaOnDelay(const long value) {
gridPowerDeltaOnDelay = value; gridPowerDeltaOnDelay = value;
storeLong(path("gridPowerDeltaOnDelay"), 0L, value); storeLong(path("gridPowerDeltaOnDelay"), 0L, value);
publish();
} }
void setGridPowerDeltaOffEnabled(const bool value) { void setGridPowerDeltaOffEnabled(const bool value) {
gridPowerDeltaOffEnabled = value; gridPowerDeltaOffEnabled = value;
storeBool(path("gridPowerDeltaOffEnabled"), false, value); storeBool(path("gridPowerDeltaOffEnabled"), false, value);
publish();
} }
void setGridPowerDeltaOffThreshold(const long value) { void setGridPowerDeltaOffThreshold(const long value) {
gridPowerDeltaOffThreshold = value; gridPowerDeltaOffThreshold = value;
storeLong(path("gridPowerDeltaOffThreshold"), 0L, value); storeLong(path("gridPowerDeltaOffThreshold"), 0L, value);
publish();
} }
void setGridPowerDeltaOffDelay(const long value) { void setGridPowerDeltaOffDelay(const long value) {
gridPowerDeltaOffDelay = value; gridPowerDeltaOffDelay = value;
storeLong(path("gridPowerDeltaOffDelay"), 0L, value); storeLong(path("gridPowerDeltaOffDelay"), 0L, value);
publish();
} }
void json(const JsonObject json) const { void json(const JsonObject json) const {
@ -125,6 +136,8 @@ public:
json["topic"] = topic; json["topic"] = topic;
json["gridPowerDeltaAlarmSince"] = gridPowerDeltaAlarmSince;
json["gridPowerDeltaOffEnabled"] = gridPowerDeltaOffEnabled; json["gridPowerDeltaOffEnabled"] = gridPowerDeltaOffEnabled;
json["gridPowerDeltaOnThreshold"] = gridPowerDeltaOnThreshold; json["gridPowerDeltaOnThreshold"] = gridPowerDeltaOnThreshold;
json["gridPowerDeltaOnDelay"] = gridPowerDeltaOnDelay; json["gridPowerDeltaOnDelay"] = gridPowerDeltaOnDelay;
@ -138,8 +151,8 @@ public:
} }
void set(const bool state) override { void set(const bool state) override {
gridPowerDeltaAlarmSince = 0;
Output::set(state); Output::set(state);
gridPowerDeltaLast = 0;
} }
protected: protected:
@ -174,19 +187,19 @@ private:
if (!gridPowerDeltaOffEnabled) { if (!gridPowerDeltaOffEnabled) {
return; return;
} }
const auto invalid = isnan(gridPowerDeltaValue) || millis() - gridPowerDeltaMillis > 10000 || gridPowerDeltaConfigInvalid(); const auto now = max(1UL, millis());
const auto invalid = isnan(gridPowerDeltaValue) || now - gridPowerDeltaMillis > 10000 || gridPowerDeltaConfigInvalid();
if (gridPowerDeltaValue > gridPowerDeltaOffThreshold || invalid) { if (gridPowerDeltaValue > gridPowerDeltaOffThreshold || invalid) {
if (gridPowerDeltaLast == 0 && gridPowerDeltaOffDelay > 0) { if (gridPowerDeltaAlarmSince == 0 && gridPowerDeltaOffDelay > 0) {
Serial.printf("[RELAY] \"%s\": CONSUMING TOO MUCH: Preparing to power OFF...\n", name.c_str()); Serial.printf("[RELAY] \"%s\": CONSUMING TOO MUCH: Powering OFF in %ld ms...\n", name.c_str(), gridPowerDeltaOffDelay);
gridPowerDeltaLast = max(1UL, millis()); gridPowerDeltaAlarmSince = now;
} else { }
if (millis() - gridPowerDeltaLast > gridPowerDeltaOffDelay) { if (now - gridPowerDeltaAlarmSince >= gridPowerDeltaOffDelay) {
Serial.printf("[RELAY] \"%s\": CONSUMING TOO MUCH: Powering OFF!\n", name.c_str());
set(false); set(false);
} }
} } else if (gridPowerDeltaAlarmSince > 0) {
} else if (gridPowerDeltaLast > 0) {
Serial.printf("[RELAY] \"%s\": Powering off CANCELED!\n", name.c_str()); Serial.printf("[RELAY] \"%s\": Powering off CANCELED!\n", name.c_str());
gridPowerDeltaLast = 0;
} }
} }
@ -194,18 +207,18 @@ private:
if (!gridPowerDeltaOnEnabled) { if (!gridPowerDeltaOnEnabled) {
return; return;
} }
const auto now = max(1UL, millis());
if (gridPowerDeltaValue < gridPowerDeltaOnThreshold && !gridPowerDeltaConfigInvalid()) { if (gridPowerDeltaValue < gridPowerDeltaOnThreshold && !gridPowerDeltaConfigInvalid()) {
if (gridPowerDeltaLast == 0 && gridPowerDeltaOnDelay > 0) { if (gridPowerDeltaAlarmSince == 0 && gridPowerDeltaOnDelay > 0) {
Serial.printf("[RELAY] \"%s\": PRODUCING TOO MUCH: Preparing to power ON...\n", name.c_str()); Serial.printf("[RELAY] \"%s\": PRODUCING TOO MUCH: Powering ON in %ld ms...\n", name.c_str(), gridPowerDeltaOnDelay);
gridPowerDeltaLast = max(1UL, millis()); gridPowerDeltaAlarmSince = now;
} else { }
if (millis() - gridPowerDeltaLast > gridPowerDeltaOnDelay) { if (now - gridPowerDeltaAlarmSince >= gridPowerDeltaOnDelay) {
Serial.printf("[RELAY] \"%s\": PRODUCING TOO MUCH: Powering ON!\n", name.c_str());
set(true); set(true);
} }
} } else if (gridPowerDeltaAlarmSince > 0) {
} else if (gridPowerDeltaLast > 0) {
Serial.printf("[RELAY] \"%s\": Powering on CANCELED!\n", name.c_str()); Serial.printf("[RELAY] \"%s\": Powering on CANCELED!\n", name.c_str());
gridPowerDeltaLast = 0;
} }
} }

View File

@ -85,6 +85,7 @@ void mqttLoop() {
if (mqttLast == 0 || millis() - mqttLast >= 3000) { if (mqttLast == 0 || millis() - mqttLast >= 3000) {
mqttLast = max(1UL, millis()); mqttLast = max(1UL, millis());
client.setServer(mqttHost.c_str(), mqttPort); client.setServer(mqttHost.c_str(), mqttPort);
client.setBufferSize(512);
Serial.printf("[MQTT] Connecting: %s:%ld\n", mqttHost.c_str(), mqttPort); Serial.printf("[MQTT] Connecting: %s:%ld\n", mqttHost.c_str(), mqttPort);
if (client.connect(WiFi.getHostname(), mqttUser.c_str(), mqttPass.c_str())) { if (client.connect(WiFi.getHostname(), mqttUser.c_str(), mqttPass.c_str())) {
Serial.printf("[MQTT] Connected.\n"); Serial.printf("[MQTT] Connected.\n");
@ -106,9 +107,9 @@ void mqttPublish(const String &topic, const JsonDocument &json) {
if (!mqttShouldConnect) { if (!mqttShouldConnect) {
return; return;
} }
char buffer[256]; char buffer[512];
const auto size = serializeJson(json, buffer); serializeJson(json, buffer);
client.publish(topic.c_str(), buffer, size); client.publish(topic.c_str(), buffer);
} }
String getMqttUser() { String getMqttUser() {