diff --git a/tasmota/support_button_v2.ino b/tasmota/support_button_v2.ino index 456caa45c..47213619e 100644 --- a/tasmota/support_button_v2.ino +++ b/tasmota/support_button_v2.ino @@ -306,13 +306,15 @@ void MqttButtonTopic(uint8_t button_id, uint8_t action, uint8_t hold) char stopic[TOPSZ]; char mqttstate[7]; - GetTextIndexed(mqttstate, sizeof(mqttstate), action, kMultiPress); - SendKey(KEY_BUTTON, button_id, (hold) ? 3 : action +9); - snprintf_P(scommand, sizeof(scommand), PSTR("BUTTON%d"), button_id); - GetTopic_P(stopic, STAT, mqtt_topic, scommand); - Response_P(S_JSON_COMMAND_SVALUE, "ACTION", (hold) ? SettingsText(SET_STATE_TXT4) : mqttstate); - MqttPublish(stopic); + + if (!Settings.flag.hass_discovery) { + GetTextIndexed(mqttstate, sizeof(mqttstate), action, kMultiPress); + snprintf_P(scommand, sizeof(scommand), PSTR("BUTTON%d"), button_id); + GetTopic_P(stopic, STAT, mqtt_topic, scommand); + Response_P(S_JSON_COMMAND_SVALUE, "ACTION", (hold) ? SettingsText(SET_STATE_TXT4) : mqttstate); + MqttPublish(stopic); + } } void ButtonLoop(void) diff --git a/tasmota/xdrv_12_home_assistant.ino b/tasmota/xdrv_12_home_assistant.ino index f33d6ffde..71ccb65ca 100644 --- a/tasmota/xdrv_12_home_assistant.ino +++ b/tasmota/xdrv_12_home_assistant.ino @@ -132,6 +132,12 @@ const char HASS_TRIGGER_TYPE[] PROGMEM = const char kHAssTriggerType[] PROGMEM = "none|button_short_press|button_long_press|button_double_press"; +const char kHAssTriggerTypeButtons[] PROGMEM = + "|button_short_press|button_double_press|button_triple_press|button_quadruple_press|button_quintuple_press|button_long_press|"; + +const char kHAssTriggerStringButtons[] PROGMEM = + "|SINGLE|DOUBLE|TRIPLE|QUAD|PENTA|HOLD|"; + uint8_t hass_init_step = 0; uint8_t hass_mode = 0; int hass_tele_period = 0; @@ -258,7 +264,7 @@ void HAssAnnounceRelayLight(void) } } -void HAssAnnouncerTriggers(uint8_t device, uint8_t present, uint8_t key, uint8_t toggle, uint8_t hold) +void HAssAnnouncerTriggers(uint8_t device, uint8_t present, uint8_t key, uint8_t toggle, uint8_t hold, uint8_t single, uint8_t trg_start, uint8_t trg_end) { // key 0 = button // key 1 = switch @@ -266,11 +272,13 @@ void HAssAnnouncerTriggers(uint8_t device, uint8_t present, uint8_t key, uint8_t char stemp1[TOPSZ]; char stemp2[TOPSZ]; char unique_id[30]; + char trigger2[8]; mqtt_data[0] = '\0'; // Clear retained message - for (uint8_t i = 2; i <= 3; i++) { - snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d_%s"), ESP_getChipId(), key ? "SW" : "BTN", device + 1, GetStateText(i)); + for (uint8_t i = trg_start; i <= trg_end; i++) { + GetTextIndexed(trigger2, sizeof(trigger2), i, kHAssTriggerStringButtons); + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d_%s"), ESP_getChipId(), key ? "SW" : "BTN", device + 1, key ? GetStateText(i) : trigger2); snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/device_automation/%s/config"), unique_id); if (Settings.flag.hass_discovery && present) { // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59) @@ -289,13 +297,23 @@ void HAssAnnouncerTriggers(uint8_t device, uint8_t present, uint8_t key, uint8_t char param[21]; char subtype[9]; uint8_t pload = toggle; - - if ((i == 2 && toggle != 0) || (i == 3 && hold != 0)) { - if (i == 3) { pload = hold; } - GetTextIndexed(param, sizeof(param), pload, kHAssTriggerType); - snprintf_P(subtype, sizeof(subtype), PSTR("%s_%d"), key ? "switch" : "button", device + 1); - Response_P(HASS_TRIGGER_TYPE, state_topic, GetStateText(i), param, subtype, ESP_getChipId()); - } else { mqtt_data[0] = '\0'; } // Need to be cleaned again to avoid duplicate. + if (key) { + if ((i == 2 && toggle != 0) || (i == 3 && hold != 0)) { + if (i == 3) { pload = hold; } + GetTextIndexed(param, sizeof(param), pload, kHAssTriggerType); + snprintf_P(subtype, sizeof(subtype), PSTR("switch_%d"), device + 1); + Response_P(HASS_TRIGGER_TYPE, state_topic, GetStateText(i), param, subtype, ESP_getChipId()); + } else { mqtt_data[0] = '\0'; } // Need to be cleaned again to avoid duplicate + } else { + char trigger1[24]; + GetTextIndexed(trigger1, sizeof(trigger1), i, kHAssTriggerTypeButtons); + snprintf_P(subtype, sizeof(subtype), PSTR("button_%d"), device + 1); + if (i > 1 && single) { + mqtt_data[0] = '\0'; // Need to be cleaned again to avoid duplicate + } else { + Response_P(HASS_TRIGGER_TYPE, state_topic, trigger2, trigger1, subtype, ESP_getChipId()); + } + } } MqttPublish(stopic, true); } @@ -408,12 +426,12 @@ void HAssAnnounceSwitches(void) case PUSHON: case PUSHON_INV: toggle = 0; - pir = 1; // Binary sensor with only ON state and automatic OFF after 1 second. + pir = 1; // Binary sensor with only ON state and automatic OFF after 1 second } } else { switch_present = 0;} - HAssAnnouncerTriggers(switch_index, switch_present, 1, toggle, hold); + HAssAnnouncerTriggers(switch_index, switch_present, 1, toggle, hold, 0, 2, 3); HAssAnnouncerBinSensors(switch_index, switch_present, dual, toggle, pir); } } @@ -424,8 +442,7 @@ void HAssAnnounceButtons(void) for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) { uint8_t button_present = 0; - uint8_t toggle = 1; - uint8_t hold = 0; + uint8_t single = 0; #ifdef ESP8266 if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) @@ -439,43 +456,28 @@ void HAssAnnounceButtons(void) } } - // button matrix for triggers generation when buttontopic is set as custom (default TOGGLE = 1 HOLD = 0): - // N SetOption1 SetOption11 SetOption13 PRESS DOUBLE PRESS HOLD T,H - // 1 0 0 0 TOGGLE (button_short_press) NONE (toggle real relay) NONE (reset device) 1,0 - // 2 1 0 0 TOGGLE (button_short_press) NONE (toggle real relay) HOLD (button_long_press) 1,2 - // 3 0 1 0 NONE (toggle real relay) TOGGLE (button_double_press) NONE (reset device) 3,0 - // 4 1 1 0 NONE (toggle real relay) TOGGLE (button_double_press) HOLD (button_long_press) 3,2 - // 5 0 0 1 TOGGLE (button_short_press) NONE (toggle real relay) NONE (reset device) 1,0 - // 6 1 0 1 TOGGLE (button_short_press) NONE (toggle real relay) NONE (MQTT HOLD) 1,0 - // 7 0 1 1 NONE (toggle real relay) NONE (toggle real relay) NONE (reset device) 0,0 - // 8 1 1 1 NONE (toggle real relay) NONE (toggle real relay) NONE (MQTT HOLD) 0.0 + // Button matrix for triggers generation when SetOption73 is enabled: + // N SetOption1 SetOption11 SetOption13 PRESS MULTI PRESS HOLD + // 1 0 0 0 SINGLE (10 - button_short_press) DOUBLE to PENTA YES (button_long_press) + // 2 1 0 0 SINGLE (10 - button_short_press) DOUBLE to PENTA YES (button_long_press) + // 3 0 1 0 DOUBLE (11 - button_short_press) SINGLE then TRIPLE TO PENTA YES (button_long_press) + // 4 1 1 0 DOUBLE (11 - button_short_press) SINGLE then TRIPLE TO PENTA YES (button_long_press) + // 5 0 0 1 SINGLE (10 - button_short_press) NONE NONE + // 6 1 0 1 SINGLE (10 - button_short_press) NONE NONE + // 7 0 1 1 SINGLE (10 - button_short_press) NONE NONE + // 8 1 1 1 SINGLE (10 - button_short_press) NONE NONE - // Trigger types: "0 = none | 1 = button_short_press | 2 = button_long_press | 3 = button_double_press"; + // Trigger types: 10 = button_short_press | 11 = button_double_press | 12 = button_triple_press | 13 = button_quadruple_press | 14 = button_quintuple_press | 3 = button_long_press - if (Settings.flag.button_restrict) { // [SetOption1] Enable/Disable button multipress - if (!Settings.flag.button_single) { - hold = 2; // Default TOGGLE (button_short_press) + HOLD (button_long_press) trigger if [SetOption13] is OFF - } + if (!Settings.flag3.mqtt_buttons) { // Enable buttons discovery [SetOption73] - Decouple button from relay and send just mqtt topic + button_present = 0; + } else { + if (Settings.flag.button_single) { // [SetOption13] Immediate action on button press, just SINGLE trigger + single = 1; + } } - if (Settings.flag.button_swap) { // [SetOption11] Swap button single and double press functionality - if (!Settings.flag.button_single) { - if (!Settings.flag.button_restrict) { - hold = 0; // TOGGLE (button_double_press) and remove HOLD (button_long_press) trigger if [SetOption1] is OFF - } - toggle = 3; // TOGGLE (button_double_press) - } else {toggle = 0; hold = 0;} // [SetOption13] Immediate action on button press, no TOGGLE or HOLD triggers - } - - if (KeyTopicActive(0)) { // Enable Discovery for Buttons only if Buttontopic is set to 1 or a custom name - - if (!strcmp(SettingsText(SET_MQTT_BUTTON_TOPIC), mqtt_topic)) { - toggle = 0; // When ButtonTopic is set to 1, TOGGLE is not allowed but an HOLD trigger can be generated. - } - - } else { button_present = 0; } - - HAssAnnouncerTriggers(button_index, button_present, 0, toggle, hold); + HAssAnnouncerTriggers(button_index, button_present, 0, 0, 0, single, 1, 6); } } @@ -621,7 +623,7 @@ void HAssAnnounceSensors(void) } while (hass_xsns_index != 0); } -void HAssAnnounceStatusSensor(void) +void HAssAnnounceDeviceInfoAndStatusSensor(void) { char stopic[TOPSZ]; char stemp1[TOPSZ]; @@ -642,13 +644,13 @@ void HAssAnnounceStatusSensor(void) char *state_topic = stemp1; char *availability_topic = stemp2; - snprintf_P(name, sizeof(name), PSTR("%s status"), SettingsText(SET_FRIENDLYNAME1)); + snprintf_P(name, sizeof(name), PSTR("%s status"), ModuleName().c_str()); GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_HASS_STATE)); GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); TryResponseAppend_P(HASS_DISCOVER_SENSOR_HASS_STATUS, state_topic); - TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO, unique_id, ESP_getChipId(), SettingsText(SET_FRIENDLYNAME1), + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO, unique_id, ESP_getChipId(), ModuleName().c_str(), ModuleName().c_str(), my_version, my_image); TryResponseAppend_P(PSTR("}")); } @@ -698,7 +700,7 @@ void HAssDiscovery(void) HAssAnnounceSensors(); // Send info about status sensor - HAssAnnounceStatusSensor(); + HAssAnnounceDeviceInfoAndStatusSensor(); } } @@ -717,7 +719,7 @@ void HAssAnyKey(void) uint32_t key = (XdrvMailbox.payload >> 16) & 0xFF; // 0 = Button, 1 = Switch uint32_t device = XdrvMailbox.payload & 0xFF; // Device number or 1 if more Buttons than Devices - uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; // 0 = Off, 1 = On, 2 = Toggle, 3 = Hold + uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; // 0 = Off, 1 = On, 2 = Toggle, 3 = Hold, 10,11,12,13 and 14 for Button Multipress if (!key && KeyTopicActive(0)) { // Button and ButtonTopic is active device = (XdrvMailbox.payload >> 24) & 0xFF; // Button number @@ -726,19 +728,26 @@ void HAssAnyKey(void) char scommand[CMDSZ]; char sw_topic[TOPSZ]; char key_topic[TOPSZ]; + char trg_state[8]; char *tmpbtn = SettingsText(SET_MQTT_BUTTON_TOPIC); char *tmpsw = SettingsText(SET_MQTT_SWITCH_TOPIC); uint8_t evkey = 0; // Flag to select the correct topic for a trigger or a binary_sensor Format(sw_topic, tmpsw, sizeof(sw_topic)); Format(key_topic, tmpbtn, sizeof(key_topic)); - if (state == 2 || state == 3 ) { evkey = 1;} + if (state >= 2) { evkey = 1;} snprintf_P(scommand, sizeof(scommand), PSTR("%s%d%s"), (key) ? "SWITCH" : "BUTTON", device, (evkey) ? "T" : ""); char stopic[TOPSZ]; + if (state == 3) { + snprintf_P(trg_state, sizeof(trg_state), GetStateText(3)); + } else { + GetTextIndexed(trg_state, sizeof(trg_state), state -9, kHAssTriggerStringButtons); + } + GetTopic_P(stopic, STAT, mqtt_topic, scommand); - Response_P(S_JSON_COMMAND_SVALUE, (evkey) ? "TRIG" : PSTR(D_RSLT_STATE), GetStateText(state)); + Response_P(S_JSON_COMMAND_SVALUE, (evkey) ? "TRIG" : PSTR(D_RSLT_STATE), (key) ? GetStateText(state) : trg_state); MqttPublish(stopic); }