diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 379cc1d12..c9882902a 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1308,7 +1308,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), + (key + 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..b5d0c076c 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_SWITCH_TOGGLE[] PROGMEM = + "%s,\"force_update\":true"; + +const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF[] 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_SWITCH_TOGGLE_SHORT[] PROGMEM = + "%s,\"frc_upd\":true"; + +const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF_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,85 @@ void HAssAnnounceRelayLight(void) } } -void HAssAnnounceButton(void) +void HAssAnnounceButtonSwitch(byte device, char* topic, byte present, byte key, byte toggle) { + 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[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_BUTTON_SWITCH_ONOFF_SHORT:HASS_DISCOVER_BUTTON_SWITCH_ONOFF, + 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++) { + byte switch_present = 0; + byte toggle = 1; + + if ((pin[GPIO_SWT1 + switch_index] < 99) || (pin[GPIO_SWT1_NP + switch_index] < 99)) { + switch_present = 1; + } + + // 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); + } + } +} + +void HAssAnnounceButtons(void) +{ char stopic[TOPSZ]; char key_topic[sizeof(Settings.button_topic)]; @@ -277,52 +364,24 @@ void HAssAnnounceButton(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; } 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); + // Check if MQTT message will be ON/OFF or TOGGLE + if (!strcmp(mqtt_topic, key_topic) || !strcmp(Settings.mqtt_grptopic, key_topic)) + { + toggle = 0; } - MqttPublish(stopic, true); + + HAssAnnounceButtonSwitch(button_index, key_topic, button_present, 1, toggle); } } } @@ -440,9 +499,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();