From f7ba0ba95ecf3fde9d52acb3f0030a9e487e436d Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Mon, 2 Nov 2020 20:44:07 -0300 Subject: [PATCH] Switches: MQTT decoupling --- tasmota/settings.h | 3 ++- tasmota/support_switch.ino | 50 ++++++++++++++++++++++++++++++++++--- tasmota/support_tasmota.ino | 2 +- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index d75c40bcd..0031e33d5 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -139,7 +139,8 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu typedef union { // Restricted by MISRA-C Rule 18.4 but so useful... uint32_t data; // Allow bit manipulation using SetOption struct { // SetOption114 .. SetOption145 - uint32_t spare00 : 1; // bit 0 + uint32_t mqtt_switches : 1; // bit 0 (V9.0.0.3) Detach Swiches from relays and enable MQTT action state for all the SwitchModes + //uint32_t spare00 : 1; // bit 0 uint32_t spare01 : 1; // bit 1 uint32_t spare02 : 1; // bit 2 uint32_t spare03 : 1; // bit 3 diff --git a/tasmota/support_switch.ino b/tasmota/support_switch.ino index b1822a1b0..90a21a869 100644 --- a/tasmota/support_switch.ino +++ b/tasmota/support_switch.ino @@ -34,6 +34,10 @@ const uint8_t AC_PERIOD = (20 + SWITCH_FAST_PROBE_INTERVAL - 1) / SWITCH_FAST_PR #define SM_NO_TIMER_MASK 0xFF #define SM_FIRST_PRESS 0x40 #define SM_SECOND_PRESS 0x80 +#define POWER_NONE 99 + +const char kSwitchPressStates[] PROGMEM = + "||||POWER_INCREMENT|POWER_INV|POWER_CLEAR|POWER_RELEASE|POWER_100|"; #include @@ -240,6 +244,7 @@ void SwitchHandler(uint8_t mode) if (PinUsed(GPIO_SWT1, i) || (mode)) { uint8_t button = Switch.virtual_state[i]; uint8_t switchflag = POWER_TOGGLE +1; + uint8_t MqttAction = POWER_NONE; if (Switch.hold_timer[i] & (((Settings.switchmode[i] == PUSHHOLDMULTI) | (Settings.switchmode[i] == PUSHHOLDMULTI_INV)) ? SM_TIMER_MASK: SM_NO_TIMER_MASK)) { Switch.hold_timer[i]--; @@ -266,22 +271,28 @@ void SwitchHandler(uint8_t mode) if (NOT_PRESSED == button) { Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 25; SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); // Execute command via MQTT + MqttAction = POWER_INCREMENT; } else { Switch.hold_timer[i]= 0; SendKey(KEY_SWITCH, i +1, POWER_CLEAR); // Execute command via MQTT + MqttAction = POWER_CLEAR; } break; case PUSHHOLDMULTI_INV: if (PRESSED == button) { Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 25; SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); // Execute command via MQTT + MqttAction = POWER_INCREMENT; + } else { Switch.hold_timer[i]= 0; SendKey(KEY_SWITCH, i +1, POWER_CLEAR); // Execute command via MQTT + MqttAction = POWER_CLEAR; } break; default: SendKey(KEY_SWITCH, i +1, POWER_HOLD); // Execute command via MQTT + MqttAction = POWER_HOLD; break; } } @@ -333,6 +344,7 @@ void SwitchHandler(uint8_t mode) if (Switch.hold_timer[i]) { Switch.hold_timer[i] = 0; SendKey(KEY_SWITCH, i +1, POWER_HOLD); // Execute command via MQTT + MqttAction = POWER_HOLD; } else { Switch.hold_timer[i] = loops_per_second / 2; // 0.5 second multi press window } @@ -342,6 +354,7 @@ void SwitchHandler(uint8_t mode) if ((Switch.hold_timer[i] & SM_TIMER_MASK) != 0) { Switch.hold_timer[i] = ((Switch.hold_timer[i] & ~SM_TIMER_MASK) == SM_FIRST_PRESS) ? SM_SECOND_PRESS : 0; SendKey(KEY_SWITCH, i +1, POWER_INV); // Execute command via MQTT + MqttAction = POWER_INV; } } else { if ((Switch.hold_timer[i] & SM_TIMER_MASK) > loops_per_second * Settings.param[P_HOLD_TIME] / 25) { @@ -351,11 +364,13 @@ void SwitchHandler(uint8_t mode) } else{ SendKey(KEY_SWITCH, i +1, POWER_100); // Execute command via MQTT + MqttAction = POWER_100; Switch.hold_timer[i]= 0; } } else { Switch.hold_timer[i]= 0; SendKey(KEY_SWITCH, i +1, POWER_RELEASE); // Execute command via MQTT + MqttAction = POWER_RELEASE; } } Switch.hold_timer[i] = (Switch.hold_timer[i] & ~SM_TIMER_MASK) | loops_per_second * Settings.param[P_HOLD_TIME] / 10; @@ -365,6 +380,7 @@ void SwitchHandler(uint8_t mode) if ((Switch.hold_timer[i] & SM_TIMER_MASK) != 0) { Switch.hold_timer[i] = ((Switch.hold_timer[i] & ~SM_TIMER_MASK) == SM_FIRST_PRESS) ? SM_SECOND_PRESS : 0; SendKey(KEY_SWITCH, i +1, POWER_INV); // Execute command via MQTT + MqttAction = POWER_INV; } } else { if ((Switch.hold_timer[i] & SM_TIMER_MASK)> loops_per_second * Settings.param[P_HOLD_TIME] / 25) { @@ -374,11 +390,13 @@ void SwitchHandler(uint8_t mode) } else{ SendKey(KEY_SWITCH, i +1, POWER_100); // Execute command via MQTT + MqttAction = POWER_100; Switch.hold_timer[i]= 0; } } else { Switch.hold_timer[i]= 0; SendKey(KEY_SWITCH, i +1, POWER_RELEASE); // Execute command via MQTT + MqttAction = POWER_RELEASE; } } Switch.hold_timer[i] = (Switch.hold_timer[i] & ~SM_TIMER_MASK) | loops_per_second * Settings.param[P_HOLD_TIME] / 10; @@ -400,14 +418,40 @@ void SwitchHandler(uint8_t mode) Switch.last_state[i] = button; } if (switchflag <= POWER_TOGGLE) { - if (!SendKey(KEY_SWITCH, i +1, switchflag)) { // Execute command via MQTT - ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); // Execute command internally (if i < TasmotaGlobal.devices_present) - } + if (!Settings.flag5.mqtt_switches) { // SetOption114 (0) - Detach Swiches from relays and enable MQTT action state for all the SwitchModes + if (!SendKey(KEY_SWITCH, i +1, switchflag)) { // Execute command via MQTT + ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); // Execute command internally (if i < TasmotaGlobal.devices_present) + } + } else { MqttAction = switchflag; } + } + if (MqttAction != POWER_NONE && Settings.flag5.mqtt_switches) { + MqttSwitchTopic(i +1, MqttAction); // SetOption114 (0) - Detach Swiches from relays and enable MQTT action state for all the SwitchModes + MqttAction = POWER_NONE; } } } } +void MqttSwitchTopic(uint8_t switch_id, uint8_t MqttAction) +{ + char scommand[CMDSZ]; + char stopic[TOPSZ]; + char mqttstate[16]; + + if (!Settings.flag.hass_discovery) { + if (MqttAction <= 3) { + if (MqttAction != 3) { SendKey(KEY_SWITCH, switch_id, MqttAction); } + snprintf_P(mqttstate, sizeof(mqttstate), PSTR("%s"), SettingsText(SET_STATE_TXT1 + MqttAction)); + } else { + GetTextIndexed(mqttstate, sizeof(mqttstate), MqttAction, kSwitchPressStates); + } + snprintf_P(scommand, sizeof(scommand), PSTR("SWITCH%d"), switch_id); + GetTopic_P(stopic, STAT, TasmotaGlobal.mqtt_topic, scommand); + Response_P(S_JSON_COMMAND_SVALUE, "ACTION", mqttstate); + MqttPublish(stopic); + } +} + void SwitchLoop(void) { if (Switch.present) { diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 6304562b9..f805ee57e 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -497,7 +497,7 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state) XdrvCall(FUNC_ANY_KEY); XdrvMailbox.payload = payload_save; #ifdef USE_PWM_DIMMER - result = true; + if (PWM_DIMMER == TasmotaGlobal.module_type) result = true; } #endif // USE_PWM_DIMMER return result;