From d6337f7500183dee047296fd6b9480faa203d673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Kristan?= Date: Thu, 3 Jun 2021 12:18:11 +0200 Subject: [PATCH] Added MQTT support for buttons and simplified switch. Added PIR sensor option. --- wled00/button.cpp | 58 +++++++++++++++++++++++++++-------- wled00/const.h | 3 +- wled00/data/settings_leds.htm | 5 +-- 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/wled00/button.cpp b/wled00/button.cpp index 7d4839c6..01462b0f 100644 --- a/wled00/button.cpp +++ b/wled00/button.cpp @@ -6,6 +6,8 @@ #define WLED_DEBOUNCE_THRESHOLD 50 //only consider button input of at least 50ms as valid (debouncing) +static const char _mqtt_topic_button[] PROGMEM = "%s/button/%d"; // optimize flash usage + void shortPressAction(uint8_t b) { if (!macroButton[b]) @@ -15,6 +17,13 @@ void shortPressAction(uint8_t b) } else { applyPreset(macroButton[b]); } + + // publish MQTT message + if (WLED_MQTT_CONNECTED) { + char subuf[64]; + sprintf_P(subuf, _mqtt_topic_button, mqttDeviceTopic, (int)b); + mqtt->publish(subuf, 0, false, "short"); + } } bool isButtonPressed(uint8_t i) @@ -29,7 +38,7 @@ bool isButtonPressed(uint8_t i) if (digitalRead(btnPin[i]) == LOW) return true; break; case BTN_TYPE_PUSH_ACT_HIGH: - case BTN_TYPE_SWITCH_ACT_HIGH: + case BTN_TYPE_PIR_SENSOR: if (digitalRead(btnPin[i]) == HIGH) return true; break; case BTN_TYPE_TOUCH: @@ -43,6 +52,7 @@ bool isButtonPressed(uint8_t i) void handleSwitch(uint8_t b) { + // isButtonPressed() handles inverted/noninverted logic if (buttonPressedBefore[b] != isButtonPressed(b)) { buttonPressedTime[b] = millis(); buttonPressedBefore[b] = !buttonPressedBefore[b]; @@ -51,17 +61,26 @@ void handleSwitch(uint8_t b) if (buttonLongPressed[b] == buttonPressedBefore[b]) return; if (millis() - buttonPressedTime[b] > WLED_DEBOUNCE_THRESHOLD) { //fire edge event only after 50ms without change (debounce) - if (buttonPressedBefore[b]) { //LOW, falling edge, switch closed + if (!buttonPressedBefore[b]) { // on -> off if (macroButton[b]) applyPreset(macroButton[b]); else { //turn on if (!bri) {toggleOnOff(); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);} } - } else { //HIGH, rising edge, switch opened + } else { // off -> on if (macroLongPress[b]) applyPreset(macroLongPress[b]); else { //turn off if (bri) {toggleOnOff(); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);} } } + + // publish MQTT message + if (WLED_MQTT_CONNECTED) { + char subuf[64]; + if (buttonType[b] == BTN_TYPE_PIR_SENSOR) sprintf_P(subuf, PSTR("%s/motion/%d"), mqttDeviceTopic, (int)b); + else sprintf_P(subuf, _mqtt_topic_button, mqttDeviceTopic, (int)b); + mqtt->publish(subuf, 0, false, !buttonPressedBefore[b] ? "off" : "on"); + } + buttonLongPressed[b] = buttonPressedBefore[b]; //save the last "long term" switch state } } @@ -74,6 +93,9 @@ void handleAnalog(uint8_t b) #else uint16_t aRead = analogRead(btnPin[b]) >> 4; // convert 12bit read to 8bit #endif + + if (buttonType[b] == BTN_TYPE_ANALOG_INVERTED) aRead = 255 - aRead; + // remove noise & reduce frequency of UI updates aRead &= 0xFC; @@ -132,8 +154,6 @@ void handleAnalog(uint8_t b) seg.setOption(SEG_OPTION_ON, 1); } // this will notify clients of update (websockets,mqtt,etc) - //call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification) - // 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa updateInterfaces(NOTIFIER_CALL_MODE_BUTTON); } } else { @@ -141,8 +161,6 @@ void handleAnalog(uint8_t b) // we can either trigger a preset depending on the level (between short and long entries) // or use it for RGBW direct control } - //call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification) - // 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa colorUpdated(NOTIFIER_CALL_MODE_BUTTON); } @@ -152,17 +170,18 @@ void handleButton() for (uint8_t b=0; b 250) { // button is not a button but a potentiometer + if ((buttonType[b] == BTN_TYPE_ANALOG || buttonType[b] == BTN_TYPE_ANALOG_INVERTED) && millis() - lastRead > 250) { // button is not a button but a potentiometer if (b+1 == WLED_MAX_BUTTONS) lastRead = millis(); handleAnalog(b); continue; } - if (buttonType[b] == BTN_TYPE_SWITCH || buttonType[b] == BTN_TYPE_SWITCH_ACT_HIGH) { //button is not momentary, but switch. This is only suitable on pins whose on-boot state does not matter (NOT gpio0) + //button is not momentary, but switch. This is only suitable on pins whose on-boot state does not matter (NOT gpio0) + if (buttonType[b] == BTN_TYPE_SWITCH || buttonType[b] == BTN_TYPE_PIR_SENSOR) { handleSwitch(b); continue; } @@ -179,6 +198,13 @@ void handleButton() if (macroLongPress[b]) {applyPreset(macroLongPress[b]);} else _setRandomColor(false,true); + // publish MQTT message + if (WLED_MQTT_CONNECTED) { + char subuf[64]; + sprintf_P(subuf, _mqtt_topic_button, mqttDeviceTopic, (int)b); + mqtt->publish(subuf, 0, false, "long"); + } + buttonLongPressed[b] = true; } } @@ -197,8 +223,16 @@ void handleButton() else if (!buttonLongPressed[b]) { //short press if (macroDoublePress[b]) { - if (doublePress) applyPreset(macroDoublePress[b]); - else buttonWaitTime[b] = millis(); + if (doublePress) { + applyPreset(macroDoublePress[b]); + + // publish MQTT message + if (WLED_MQTT_CONNECTED) { + char subuf[64]; + sprintf_P(subuf, _mqtt_topic_button, mqttDeviceTopic, (int)b); + mqtt->publish(subuf, 0, false, "double"); + } + } else buttonWaitTime[b] = millis(); } else shortPressAction(b); } buttonPressedBefore[b] = false; diff --git a/wled00/const.h b/wled00/const.h index 19c2853e..767dac1a 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -160,9 +160,10 @@ #define BTN_TYPE_PUSH 2 #define BTN_TYPE_PUSH_ACT_HIGH 3 #define BTN_TYPE_SWITCH 4 -#define BTN_TYPE_SWITCH_ACT_HIGH 5 +#define BTN_TYPE_PIR_SENSOR 5 #define BTN_TYPE_TOUCH 6 #define BTN_TYPE_ANALOG 7 +#define BTN_TYPE_ANALOG_INVERTED 8 //Ethernet board types #define WLED_NUM_ETH_TYPES 5 diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 65992c6f..925b4789 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -283,11 +283,12 @@ Reverse (rotated 180°): c += ``; c += ` ×
`; gId("btns").innerHTML = c;