From be19af15e2ed65d4c9b445f159a458557289c362 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 4 Dec 2018 21:31:23 +0100 Subject: [PATCH 1/3] Announce switches --- sonoff/sonoff.ino | 3 +- sonoff/xdrv_12_home_assistant.ino | 137 ++++++++++++++++++++---------- 2 files changed, 92 insertions(+), 48 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 0772e76f2..947f5d165 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1310,7 +1310,8 @@ boolean SendKey(byte key, byte device, byte state) Format(key_topic, tmp, sizeof(key_topic)); if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) { if (!key && (device > devices_present)) device = 1; // Only allow number of buttons up to number of devices - GetTopic_P(stopic, CMND, key_topic, GetPowerDevice(scommand, device, sizeof(scommand), key)); // cmnd/switchtopic/POWERx + GetTopic_P(stopic, CMND, key_topic, GetPowerDevice(scommand, device, sizeof(scommand), + Settings.flag.device_index_enable)); // cmnd/switchtopic/POWERx if (9 == state) { mqtt_data[0] = '\0'; } else { diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 78b8b4841..b002049a2 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -33,16 +33,21 @@ const char HASS_DISCOVER_RELAY[] PROGMEM = "\"payload_available\":\"" D_ONLINE "\"," // Online "\"payload_not_available\":\"" D_OFFLINE "\""; // Offline -const char HASS_DISCOVER_BUTTON[] PROGMEM = +const char HASS_DISCOVER_BUTTON_SWITCH[] PROGMEM = "{\"name\":\"%s\"," // dualr2 1 BTN "\"state_topic\":\"%s\"," // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",") // "\"value_template\":\"{{value_json.%s}}\"," // POWER2 - "\"payload_on\":\"%s\"," // TOGGLE + "\"payload_on\":\"%s\"," // TOGGLE / ON // "\"optimistic\":\"false\"," // false is Hass default when state_topic is set "\"availability_topic\":\"%s\"," // tele/dualr2/LWT "\"payload_available\":\"" D_ONLINE "\"," // Online - "\"payload_not_available\":\"" D_OFFLINE "\"," // Offline - "\"force_update\":true"; + "\"payload_not_available\":\"" D_OFFLINE "\""; // Offline + +const char HASS_DISCOVER_BUTTON[] PROGMEM = + "%s,\"force_update\":true"; + +const char HASS_DISCOVER_SWITCH[] PROGMEM = + "%s,\"payload_off\":\"%s\""; // OFF const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM = "%s,\"brightness_command_topic\":\"%s\"," // cmnd/led2/Dimmer @@ -92,7 +97,7 @@ const char HASS_DISCOVER_RELAY_SHORT[] PROGMEM = "\"pl_avail\":\"" D_ONLINE "\"," // Online "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline -const char HASS_DISCOVER_BUTTON_SHORT[] PROGMEM = +const char HASS_DISCOVER_BUTTON_SWITCH_SHORT[] PROGMEM = "{\"name\":\"%s\"," // dualr2 1 BTN "\"stat_t\":\"%s\"," // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",") // "\"value_template\":\"{{value_json.%s}}\"," // POWER2 @@ -100,8 +105,14 @@ const char HASS_DISCOVER_BUTTON_SHORT[] PROGMEM = // "\"optimistic\":\"false\"," // false is Hass default when state_topic is set "\"avty_t\":\"%s\"," // tele/dualr2/LWT "\"pl_avail\":\"" D_ONLINE "\"," // Online - "\"pl_not_avail\":\"" D_OFFLINE "\"," // Offline - "\"frc_upd\":true"; + "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline + +const char HASS_DISCOVER_BUTTON_SHORT[] PROGMEM = + "%s,\"frc_upd\":true"; + +const char HASS_DISCOVER_SWITCH_SHORT[] PROGMEM = + "%s,\"pl_off\":\"%s\""; // OFF + const char HASS_DISCOVER_LIGHT_DIMMER_SHORT[] PROGMEM = "%s,\"bri_cmd_t\":\"%s\"," // cmnd/led2/Dimmer @@ -266,9 +277,75 @@ void HAssAnnounceRelayLight(void) } } -void HAssAnnounceButton(void) +void HAssAnnounceButtonSwitch(byte device, char* topic, byte present, byte key) { + char stopic[TOPSZ]; char sidx[8]; + + mqtt_data[0] = '\0'; // Clear retained message + + // Clear or Set topic + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/binary_sensor/%s_%s_%d/config"), + topic, key?"BTN":"SW",device+1); + + if (Settings.flag.hass_discovery && present) { + char name[33]; + char value_template[33]; + char _state_topic[TOPSZ]; + char _availability_topic[TOPSZ]; + char prefix[TOPSZ]; + char *state_topic = _state_topic; + char *availability_topic = _availability_topic; + + if (device+1 > MAX_FRIENDLYNAMES) { + snprintf_P(name, sizeof(name), PSTR("%s %s %d"), Settings.friendlyname[0], key?"BTN":"SW", device+1); + } else { + snprintf_P(name, sizeof(name), PSTR("%s %s"), Settings.friendlyname[device], key?"BTN":"SW"); + } + GetPowerDevice(value_template, device+1, sizeof(value_template), Settings.flag.device_index_enable); + GetTopic_P(state_topic, CMND, topic, value_template); // State of button is sent as CMND TOGGLE, state of switch is sent as ON/OFF + GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + FindPrefix(state_topic, availability_topic, prefix); + if (Settings.flag3.hass_short_discovery_msg) { + Shorten(&state_topic, prefix); + Shorten(&availability_topic, prefix); + } + snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SWITCH_SHORT:HASS_DISCOVER_BUTTON_SWITCH, + name, state_topic, Settings.state_text[key?2:1], availability_topic); + if (key) snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SHORT:HASS_DISCOVER_BUTTON, + mqtt_data); + else snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SWITCH_SHORT:HASS_DISCOVER_SWITCH, + mqtt_data, Settings.state_text[0]); + + if (Settings.flag3.hass_short_discovery_msg) + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + } + MqttPublish(stopic, true); +} + +void HAssAnnounceSwitches(void) +{ + char sw_topic[sizeof(Settings.switch_topic)]; + + // Send info about buttons + char *tmp = Settings.switch_topic; + Format(sw_topic, tmp, sizeof(sw_topic)); + if ((strlen(sw_topic) != 0) && strcmp(sw_topic, "0")) { + for (byte switch_index = 0; switch_index < MAX_SWITCHES; switch_index++) { + uint8_t switch_present = 0; + + if ((pin[GPIO_SWT1 + switch_index] < 99) || (pin[GPIO_SWT1_NP + switch_index] < 99)) { + switch_present = 1; + } + + HAssAnnounceButtonSwitch(switch_index, sw_topic, switch_present, 0); + } + } +} + +void HAssAnnounceButtons(void) +{ char stopic[TOPSZ]; char key_topic[sizeof(Settings.button_topic)]; @@ -282,47 +359,12 @@ void HAssAnnounceButton(void) if (!button_index && ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module))) { button_present = 1; } else { - if (pin[GPIO_KEY1 + button_index] < 99) { + if ((pin[GPIO_KEY1 + button_index] < 99) || (pin[GPIO_KEY1_NP + button_index] < 99)) { button_present = 1; } } - mqtt_data[0] = '\0'; // Clear retained message - - // Clear or Set topic - snprintf_P(sidx, sizeof(sidx), PSTR("_%d"), button_index+1); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s%s/config"), "binary_sensor", key_topic, sidx); - - if (Settings.flag.hass_discovery && button_present) { - char name[33]; - char value_template[33]; - char _state_topic[TOPSZ]; - char _availability_topic[TOPSZ]; - char prefix[TOPSZ]; - char *state_topic = _state_topic; - char *availability_topic = _availability_topic; - - if (button_index+1 > MAX_FRIENDLYNAMES) { - snprintf_P(name, sizeof(name), PSTR("%s %d BTN"), Settings.friendlyname[0], button_index+1); - } else { - snprintf_P(name, sizeof(name), PSTR("%s BTN"), Settings.friendlyname[button_index]); - } - GetPowerDevice(value_template, button_index+1, sizeof(value_template), Settings.flag.device_index_enable); - GetTopic_P(state_topic, CMND, key_topic, value_template); // State of button is sent as CMND TOGGLE - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); - FindPrefix(state_topic, availability_topic, prefix); - if (Settings.flag3.hass_short_discovery_msg) { - Shorten(&state_topic, prefix); - Shorten(&availability_topic, prefix); - } - snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SHORT:HASS_DISCOVER_BUTTON, - name, state_topic, Settings.state_text[2], availability_topic); - - if (Settings.flag3.hass_short_discovery_msg) - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); - } - MqttPublish(stopic, true); + HAssAnnounceButtonSwitch(button_index, key_topic, button_present, 1); } } } @@ -440,9 +482,10 @@ void HAssDiscovery(uint8_t mode) HAssAnnounceRelayLight(); // Send info about buttons - HAssAnnounceButton(); + HAssAnnounceButtons(); - // TODO: Send info about switches + // Send info about switches + HAssAnnounceSwitches(); // Send info about sensors HAssAnnounceSensors(); From 94786d32177c62521489af25a1349a50350316d6 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 5 Dec 2018 20:20:36 +0100 Subject: [PATCH 2/3] Fix logic for ON/OFF vs TOGGLE --- sonoff/xdrv_12_home_assistant.ino | 41 ++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index b002049a2..b5d0c076c 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -43,10 +43,10 @@ const char HASS_DISCOVER_BUTTON_SWITCH[] PROGMEM = "\"payload_available\":\"" D_ONLINE "\"," // Online "\"payload_not_available\":\"" D_OFFLINE "\""; // Offline -const char HASS_DISCOVER_BUTTON[] PROGMEM = +const char HASS_DISCOVER_BUTTON_SWITCH_TOGGLE[] PROGMEM = "%s,\"force_update\":true"; -const char HASS_DISCOVER_SWITCH[] PROGMEM = +const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF[] PROGMEM = "%s,\"payload_off\":\"%s\""; // OFF const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM = @@ -107,10 +107,10 @@ const char HASS_DISCOVER_BUTTON_SWITCH_SHORT[] PROGMEM = "\"pl_avail\":\"" D_ONLINE "\"," // Online "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline -const char HASS_DISCOVER_BUTTON_SHORT[] PROGMEM = +const char HASS_DISCOVER_BUTTON_SWITCH_TOGGLE_SHORT[] PROGMEM = "%s,\"frc_upd\":true"; -const char HASS_DISCOVER_SWITCH_SHORT[] PROGMEM = +const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF_SHORT[] PROGMEM = "%s,\"pl_off\":\"%s\""; // OFF @@ -277,7 +277,7 @@ void HAssAnnounceRelayLight(void) } } -void HAssAnnounceButtonSwitch(byte device, char* topic, byte present, byte key) +void HAssAnnounceButtonSwitch(byte device, char* topic, byte present, byte key, byte toggle) { char stopic[TOPSZ]; char sidx[8]; @@ -311,10 +311,12 @@ void HAssAnnounceButtonSwitch(byte device, char* topic, byte present, byte key) Shorten(&availability_topic, prefix); } snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SWITCH_SHORT:HASS_DISCOVER_BUTTON_SWITCH, - name, state_topic, Settings.state_text[key?2:1], availability_topic); - if (key) snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SHORT:HASS_DISCOVER_BUTTON, + name, state_topic, Settings.state_text[toggle?2:1], availability_topic); + if (toggle) snprintf_P(mqtt_data, sizeof(mqtt_data), + Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SWITCH_TOGGLE_SHORT:HASS_DISCOVER_BUTTON_SWITCH_TOGGLE, mqtt_data); - else snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SWITCH_SHORT:HASS_DISCOVER_SWITCH, + else snprintf_P(mqtt_data, sizeof(mqtt_data), + Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SWITCH_ONOFF_SHORT:HASS_DISCOVER_BUTTON_SWITCH_ONOFF, mqtt_data, Settings.state_text[0]); if (Settings.flag3.hass_short_discovery_msg) @@ -333,13 +335,21 @@ void HAssAnnounceSwitches(void) Format(sw_topic, tmp, sizeof(sw_topic)); if ((strlen(sw_topic) != 0) && strcmp(sw_topic, "0")) { for (byte switch_index = 0; switch_index < MAX_SWITCHES; switch_index++) { - uint8_t switch_present = 0; + byte switch_present = 0; + byte toggle = 1; if ((pin[GPIO_SWT1 + switch_index] < 99) || (pin[GPIO_SWT1_NP + switch_index] < 99)) { switch_present = 1; } - HAssAnnounceButtonSwitch(switch_index, sw_topic, switch_present, 0); + // Check if MQTT message will be ON/OFF or TOGGLE + if (Settings.switchmode[switch_index] == FOLLOW || Settings.switchmode[switch_index] == FOLLOW_INV || + !strcmp(mqtt_topic, sw_topic) || !strcmp(Settings.mqtt_grptopic, sw_topic)) + { + toggle = 0; + } + + HAssAnnounceButtonSwitch(switch_index, sw_topic, switch_present, 0, toggle); } } } @@ -354,7 +364,8 @@ void HAssAnnounceButtons(void) Format(key_topic, tmp, sizeof(key_topic)); if ((strlen(key_topic) != 0) && strcmp(key_topic, "0")) { for (byte button_index = 0; button_index < MAX_KEYS; button_index++) { - uint8_t button_present = 0; + byte button_present = 0; + byte toggle = 1; if (!button_index && ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module))) { button_present = 1; @@ -364,7 +375,13 @@ void HAssAnnounceButtons(void) } } - HAssAnnounceButtonSwitch(button_index, key_topic, button_present, 1); + // Check if MQTT message will be ON/OFF or TOGGLE + if (!strcmp(mqtt_topic, key_topic) || !strcmp(Settings.mqtt_grptopic, key_topic)) + { + toggle = 0; + } + + HAssAnnounceButtonSwitch(button_index, key_topic, button_present, 1, toggle); } } } From e64c8d61c92d9fcd3e3963948fad040f3b607681 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 6 Dec 2018 11:01:57 +0100 Subject: [PATCH 3/3] Update sonoff.ino --- sonoff/sonoff.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 947f5d165..2132a09b2 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1311,7 +1311,7 @@ boolean SendKey(byte key, byte device, byte state) if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) { if (!key && (device > devices_present)) device = 1; // Only allow number of buttons up to number of devices GetTopic_P(stopic, CMND, key_topic, GetPowerDevice(scommand, device, sizeof(scommand), - Settings.flag.device_index_enable)); // cmnd/switchtopic/POWERx + (key + Settings.flag.device_index_enable))); // cmnd/switchtopic/POWERx if (9 == state) { mqtt_data[0] = '\0'; } else {