From 52c36ef6a4fe1ceefeeab14ff1c86a7772c22460 Mon Sep 17 00:00:00 2001 From: Hermann Kraus Date: Thu, 20 Jan 2022 00:26:07 +0100 Subject: [PATCH 1/5] Add Home Assisant MQTT autodiscovery for usermod multi_relay. --- usermods/multi_relay/readme.md | 2 +- usermods/multi_relay/usermod_multi_relay.h | 53 ++++++++++++++++++++-- 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/usermods/multi_relay/readme.md b/usermods/multi_relay/readme.md index ebf2056a..267bb54a 100644 --- a/usermods/multi_relay/readme.md +++ b/usermods/multi_relay/readme.md @@ -36,7 +36,7 @@ wled/deviceMAC/relay/0 on|off 1. Register the usermod by adding `#include "../usermods/multi_relay/usermod_multi_relay.h"` at the top and `usermods.add(new MultiRelay());` at the bottom of `usermods_list.cpp`. or -2. Use `#define USERMOD_MULTI_RELAY` in wled.h or `-D USERMOD_MULTI_RELAY`in your platformio.ini +2. Use `#define USERMOD_MULTI_RELAY` in wled.h or `-D USERMOD_MULTI_RELAY` in your platformio.ini You can override the default maximum number (4) of relays by defining MULTI_RELAY_MAX_RELAYS. diff --git a/usermods/multi_relay/usermod_multi_relay.h b/usermods/multi_relay/usermod_multi_relay.h index 9a92d4e2..9073051b 100644 --- a/usermods/multi_relay/usermod_multi_relay.h +++ b/usermods/multi_relay/usermod_multi_relay.h @@ -55,12 +55,12 @@ class MultiRelay : public Usermod { static const char _button[]; - void publishMqtt(const char* state, int relay) { + void publishMqtt(int relay) { //Check if MQTT Connected, otherwise it will crash the 8266 if (WLED_MQTT_CONNECTED){ char subuf[64]; sprintf_P(subuf, PSTR("%s/relay/%d"), mqttDeviceTopic, relay); - mqtt->publish(subuf, 0, false, state); + mqtt->publish(subuf, 0, false, _relay[relay].state ? "on" : "off"); } } @@ -105,7 +105,7 @@ class MultiRelay : public Usermod { for (int i=0; ivalue(), ',', i); if (value==-1) { - error = F("There must be as much arugments as relays"); + error = F("There must be as many arguments as relays"); } else { // Switch if (_relay[i].external) switchRelay(i, (bool)value); @@ -118,7 +118,7 @@ class MultiRelay : public Usermod { for (int i=0;ivalue(), ',', i); if (value==-1) { - error = F("There must be as mutch arugments as relays"); + error = F("There must be as many arguments as relays"); } else { // Toggle if (value && _relay[i].external) toggleRelay(i); @@ -199,7 +199,7 @@ class MultiRelay : public Usermod { _relay[relay].state = mode; pinMode(_relay[relay].pin, OUTPUT); digitalWrite(_relay[relay].pin, mode ? !_relay[relay].mode : _relay[relay].mode); - publishMqtt(mode ? "on" : "off", relay); + publishMqtt(relay); } /** @@ -252,6 +252,49 @@ class MultiRelay : public Usermod { strcpy(subuf, mqttDeviceTopic); strcat_P(subuf, PSTR("/relay/#")); mqtt->subscribe(subuf, 0); + publishHomeAssistantAutodiscovery(); + for (uint8_t i=0; i= 0 && _relay[i].external) { + StaticJsonDocument<1024> json; + sprintf(buf, "%s Switch %d", serverDescription, i); //max length: 33 + 8 + 3 = 44 + json[F("name")] = buf; + + sprintf(buf, "%s/relay/%d", mqttDeviceTopic, i); //max length: 33 + 7 + 3 = 43 + json["~"] = buf; + strcat(buf, "/command"); + mqtt->subscribe(buf, 0); + + json[F("stat_t")] = "~"; + json[F("cmd_t")] = "~/command"; + json[F("pl_off")] = F("off"); + json[F("pl_on")] = F("on"); + json[F("uniq_id")] = uid; + + strcpy(buf, mqttDeviceTopic); //max length: 33 + 7 = 40 + strcat(buf, "/status"); + json[F("avty_t")] = buf; + json[F("pl_avail")] = F("online"); + json[F("pl_not_avail")] = F("offline"); + //TODO: dev + payload_size = serializeJson(json, json_str); + } else { + //Unpublish disabled or internal relays + json_str[0] = 0; + payload_size = 0; + } + sprintf(buf, "homeassistant/switch/%s/config", uid); + mqtt->publish(buf, 0, true, json_str, payload_size); } } From 255347ab7747e79dfae44848f5cc20bd77a6dad5 Mon Sep 17 00:00:00 2001 From: Blaz Kristan Date: Thu, 20 Jan 2022 17:38:18 +0100 Subject: [PATCH 2/5] Minor clenup. --- usermods/multi_relay/usermod_multi_relay.h | 27 +++++++++++----------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/usermods/multi_relay/usermod_multi_relay.h b/usermods/multi_relay/usermod_multi_relay.h index 9073051b..e089ed4e 100644 --- a/usermods/multi_relay/usermod_multi_relay.h +++ b/usermods/multi_relay/usermod_multi_relay.h @@ -254,6 +254,7 @@ class MultiRelay : public Usermod { mqtt->subscribe(subuf, 0); publishHomeAssistantAutodiscovery(); for (uint8_t i=0; i= 0 && _relay[i].external) { StaticJsonDocument<1024> json; - sprintf(buf, "%s Switch %d", serverDescription, i); //max length: 33 + 8 + 3 = 44 + sprintf_P(buf, PSTR("%s Switch %d"), serverDescription, i); //max length: 33 + 8 + 3 = 44 json[F("name")] = buf; - sprintf(buf, "%s/relay/%d", mqttDeviceTopic, i); //max length: 33 + 7 + 3 = 43 + sprintf_P(buf, PSTR("%s/relay/%d"), mqttDeviceTopic, i); //max length: 33 + 7 + 3 = 43 json["~"] = buf; - strcat(buf, "/command"); + strcat_P(buf, PSTR("/command")); mqtt->subscribe(buf, 0); - json[F("stat_t")] = "~"; - json[F("cmd_t")] = "~/command"; - json[F("pl_off")] = F("off"); - json[F("pl_on")] = F("on"); + json[F("stat_t")] = "~"; + json[F("cmd_t")] = F("~/command"); + json[F("pl_off")] = F("off"); + json[F("pl_on")] = F("on"); json[F("uniq_id")] = uid; strcpy(buf, mqttDeviceTopic); //max length: 33 + 7 = 40 - strcat(buf, "/status"); - json[F("avty_t")] = buf; - json[F("pl_avail")] = F("online"); + strcat_P(buf, PSTR("/status")); + json[F("avty_t")] = buf; + json[F("pl_avail")] = F("online"); json[F("pl_not_avail")] = F("offline"); //TODO: dev payload_size = serializeJson(json, json_str); } else { //Unpublish disabled or internal relays - json_str[0] = 0; + json_str[0] = 0; payload_size = 0; } - sprintf(buf, "homeassistant/switch/%s/config", uid); + sprintf_P(buf, PSTR("homeassistant/switch/%s/config"), uid); mqtt->publish(buf, 0, true, json_str, payload_size); } } From 5608425a1268f38136d829a57655236c837634dc Mon Sep 17 00:00:00 2001 From: Blaz Kristan Date: Fri, 21 Jan 2022 15:55:25 +0100 Subject: [PATCH 3/5] Added comments. Fix for incorrect boot state. --- usermods/multi_relay/usermod_multi_relay.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/usermods/multi_relay/usermod_multi_relay.h b/usermods/multi_relay/usermod_multi_relay.h index e089ed4e..73b80117 100644 --- a/usermods/multi_relay/usermod_multi_relay.h +++ b/usermods/multi_relay/usermod_multi_relay.h @@ -310,7 +310,7 @@ class MultiRelay : public Usermod { if (!pinManager.allocatePin(_relay[i].pin,true, PinOwner::UM_MultiRelay)) { _relay[i].pin = -1; // allocation failed } else { - if (!_relay[i].external) _relay[i].state = offMode; + if (!_relay[i].external) _relay[i].state = !offMode; switchRelay(i, _relay[i].state); _relay[i].active = false; } @@ -399,6 +399,8 @@ class MultiRelay : public Usermod { buttonPressedBefore[b] = true; if (now - buttonPressedTime[b] > 600) { //long press + //longPressAction(b); //not exposed + //handled = false; //use if you want to pass to default behaviour buttonLongPressed[b] = true; } @@ -415,7 +417,8 @@ class MultiRelay : public Usermod { if (!buttonLongPressed[b]) { //short press // if this is second release within 350ms it is a double press (buttonWaitTime!=0) if (doublePress) { - //doublePressAction(b); + //doublePressAction(b); //not exposed + //handled = false; //use if you want to pass to default behaviour } else { buttonWaitTime[b] = now; } @@ -423,9 +426,10 @@ class MultiRelay : public Usermod { buttonPressedBefore[b] = false; buttonLongPressed[b] = false; } - // if 450ms elapsed since last press/release it is a short press + // if 350ms elapsed since last press/release it is a short press if (buttonWaitTime[b] && now - buttonWaitTime[b] > 350 && !buttonPressedBefore[b]) { buttonWaitTime[b] = 0; + //shortPressAction(b); //not exposed for (uint8_t i=0; i=0 && _relay[i].button == b) { toggleRelay(i); From fe6b1c13c40075c4aaaa6465dbfb0afd754e7ed4 Mon Sep 17 00:00:00 2001 From: Blaz Kristan Date: Fri, 21 Jan 2022 16:08:02 +0100 Subject: [PATCH 4/5] Periodic broadcasts. --- usermods/multi_relay/usermod_multi_relay.h | 34 +++++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/usermods/multi_relay/usermod_multi_relay.h b/usermods/multi_relay/usermod_multi_relay.h index 73b80117..e69812fe 100644 --- a/usermods/multi_relay/usermod_multi_relay.h +++ b/usermods/multi_relay/usermod_multi_relay.h @@ -45,6 +45,9 @@ class MultiRelay : public Usermod { // status of initialisation bool initDone = false; + uint16_t periodicBroadcastSec = 60; + unsigned long lastBroadcast = 0; + // strings to reduce flash memory usage (used more than twice) static const char _name[]; static const char _enabled[]; @@ -53,7 +56,7 @@ class MultiRelay : public Usermod { static const char _activeHigh[]; static const char _external[]; static const char _button[]; - + static const char _broadcast[]; void publishMqtt(int relay) { //Check if MQTT Connected, otherwise it will crash the 8266 @@ -68,15 +71,19 @@ class MultiRelay : public Usermod { * switch off the strip if the delay has elapsed */ void handleOffTimer() { + unsigned long now = millis(); bool activeRelays = false; for (uint8_t i=0; i 0 && millis() - _switchTimerStart > (_relay[i].delay*1000)) { + if (_relay[i].active && _switchTimerStart > 0 && now - _switchTimerStart > (_relay[i].delay*1000)) { if (!_relay[i].external) toggleRelay(i); _relay[i].active = false; + } else if (periodicBroadcastSec && now - lastBroadcast > (periodicBroadcastSec*1000)) { + if (_relay[i].pin>=0) publishMqtt(i); } activeRelays = activeRelays || _relay[i].active; } if (!activeRelays) _switchTimerStart = 0; + if (periodicBroadcastSec && now - lastBroadcast > (periodicBroadcastSec*1000)) lastBroadcast = now; } /** @@ -254,8 +261,8 @@ class MultiRelay : public Usermod { mqtt->subscribe(subuf, 0); publishHomeAssistantAutodiscovery(); for (uint8_t i=0; i=0 && pinManager.allocatePin(_relay[i].pin, true, PinOwner::UM_MultiRelay)) { if (!_relay[i].external) { - switchRelay(i, offMode); + _relay[i].state = !offMode; + switchRelay(i, _relay[i].state); + _oldMode = offMode; } } else { _relay[i].pin = -1; @@ -597,7 +614,7 @@ class MultiRelay : public Usermod { DEBUG_PRINTLN(F(" config (re)loaded.")); } // use "return !top["newestParameter"].isNull();" when updating Usermod with new features - return !top[F("relay-0")][FPSTR(_button)].isNull(); + return !top[FPSTR(_broadcast)].isNull(); } /** @@ -618,3 +635,4 @@ const char MultiRelay::_delay_str[] PROGMEM = "delay-s"; const char MultiRelay::_activeHigh[] PROGMEM = "active-high"; const char MultiRelay::_external[] PROGMEM = "external"; const char MultiRelay::_button[] PROGMEM = "button"; +const char MultiRelay::_broadcast[] PROGMEM = "broadcast-sec"; From 26ae6d36916710bfb93c42414ce5da53116edbad Mon Sep 17 00:00:00 2001 From: Blaz Kristan Date: Sat, 22 Jan 2022 20:49:43 +0100 Subject: [PATCH 5/5] Added config option for HA autodiscovery. --- usermods/multi_relay/usermod_multi_relay.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/usermods/multi_relay/usermod_multi_relay.h b/usermods/multi_relay/usermod_multi_relay.h index e69812fe..23dcc1e2 100644 --- a/usermods/multi_relay/usermod_multi_relay.h +++ b/usermods/multi_relay/usermod_multi_relay.h @@ -45,6 +45,8 @@ class MultiRelay : public Usermod { // status of initialisation bool initDone = false; + bool HAautodiscovery = false; + uint16_t periodicBroadcastSec = 60; unsigned long lastBroadcast = 0; @@ -57,6 +59,7 @@ class MultiRelay : public Usermod { static const char _external[]; static const char _button[]; static const char _broadcast[]; + static const char _HAautodiscovery[]; void publishMqtt(int relay) { //Check if MQTT Connected, otherwise it will crash the 8266 @@ -259,7 +262,7 @@ class MultiRelay : public Usermod { strcpy(subuf, mqttDeviceTopic); strcat_P(subuf, PSTR("/relay/#")); mqtt->subscribe(subuf, 0); - publishHomeAssistantAutodiscovery(); + if (HAautodiscovery) publishHomeAssistantAutodiscovery(); for (uint8_t i=0; i