From ae07f77ab9d1d794c88ad708f621e0b5a3501fda Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Thu, 29 Mar 2018 10:13:44 +0200 Subject: [PATCH 1/4] Update Spanish language file Update Spanish language file (#2283) --- sonoff/language/es-AR.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 5ad7d344c..bf35cc807 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -359,14 +359,14 @@ #define D_DOMOTICZ_UPDATE_TIMER "Intervalo de refresco" // xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Configure Timer" -#define D_TIMER_PARAMETERS "Timer parameters" -#define D_TIMER_ARM "Arm" -#define D_TIMER_TIME "Time" -#define D_TIMER_DAYS "Days" -#define D_TIMER_REPEAT "Repeat" -#define D_TIMER_DEVICE "Device" -#define D_TIMER_POWER "Power" +#define D_CONFIGURE_TIMER "Configuración Temporizadores" +#define D_TIMER_PARAMETERS "Parámetros de Temporizadores" +#define D_TIMER_ARM "Activo" +#define D_TIMER_TIME "Hora" +#define D_TIMER_DAYS "Días" +#define D_TIMER_REPEAT "Repetir" +#define D_TIMER_DEVICE "Salida" +#define D_TIMER_POWER "Estado" // xdrv_03_energy.ino #define D_ENERGY_TODAY "Energía Hoy" From a935f92998b0510fb8f7d310aa541447862f59f7 Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Thu, 29 Mar 2018 13:03:13 +0200 Subject: [PATCH 2/4] v5.12.0i - Add HAss Button discovery 5.12.0i * Add Home Assistant MQTT Discovery for Buttons (#2277) --- sonoff/_releasenotes.ino | 1 + sonoff/settings.ino | 6 +- sonoff/sonoff.ino | 10 ++-- sonoff/user_config.h | 2 + sonoff/webserver.ino | 2 +- sonoff/xdrv_00_mqtt.ino | 4 +- sonoff/xdrv_07_home_assistant.ino | 99 +++++++++++++++++++++++++++---- 7 files changed, 102 insertions(+), 22 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 5583d95fc..5a9ad3773 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -2,6 +2,7 @@ * Add 16 timers using commands Timer and Timers (#1091) * Add commands Timer 0 to clear timer and Timer 1..16 to copy timer * Add optional Timer configuration webpage to be enabled in user_config.h with define USE_TIMERS_WEB + * Add Home Assistant MQTT Discovery for Buttons (#2277) * Change webpage parameter communication * * 5.12.0h diff --git a/sonoff/settings.ino b/sonoff/settings.ino index d17f33d35..e1b0a7dcd 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -494,7 +494,7 @@ void SettingsDefaultSet2() strlcpy(Settings.mqtt_user, MQTT_USER, sizeof(Settings.mqtt_user)); strlcpy(Settings.mqtt_pwd, MQTT_PASS, sizeof(Settings.mqtt_pwd)); strlcpy(Settings.mqtt_topic, MQTT_TOPIC, sizeof(Settings.mqtt_topic)); - strlcpy(Settings.button_topic, "0", sizeof(Settings.button_topic)); + strlcpy(Settings.button_topic, MQTT_BUTTON_TOPIC, sizeof(Settings.button_topic)); strlcpy(Settings.mqtt_grptopic, MQTT_GRPTOPIC, sizeof(Settings.mqtt_grptopic)); Settings.tele_period = TELE_PERIOD; @@ -544,7 +544,7 @@ void SettingsDefaultSet2() SettingsDefaultSet_3_9_3(); - strlcpy(Settings.switch_topic, "0", sizeof(Settings.switch_topic)); + strlcpy(Settings.switch_topic, MQTT_SWITCH_TOPIC, sizeof(Settings.switch_topic)); strlcpy(Settings.web_password, WEB_PASSWORD, sizeof(Settings.web_password)); @@ -744,7 +744,7 @@ void SettingsDelta() SettingsDefaultSet_3_2_4(); } if (Settings.version < 0x03020500) { // 3.2.5 - Add parameter - GetMqttClient(Settings.friendlyname[0], Settings.mqtt_client, sizeof(Settings.friendlyname[0])); + Format(Settings.friendlyname[0], Settings.mqtt_client, sizeof(Settings.friendlyname[0])); strlcpy(Settings.friendlyname[1], FRIENDLY_NAME"2", sizeof(Settings.friendlyname[1])); strlcpy(Settings.friendlyname[2], FRIENDLY_NAME"3", sizeof(Settings.friendlyname[2])); strlcpy(Settings.friendlyname[3], FRIENDLY_NAME"4", sizeof(Settings.friendlyname[3])); diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 96ade5005..47ee15b9d 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -196,7 +196,7 @@ String backlog[MAX_BACKLOG]; // Command backlog /********************************************************************************************/ -char* GetMqttClient(char* output, const char* input, int size) +char* Format(char* output, const char* input, int size) { char *token; uint8_t digits = 0; @@ -1107,9 +1107,11 @@ boolean send_button_power(byte key, byte device, byte state) char stopic[TOPSZ]; char scommand[CMDSZ]; + char key_topic[sizeof(Settings.button_topic)]; boolean result = false; - char *key_topic = (key) ? Settings.switch_topic : Settings.button_topic; + char *tmp = (key) ? Settings.switch_topic : Settings.button_topic; + 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; GetTopic_P(stopic, CMND, key_topic, GetPowerDevice(scommand, device, sizeof(scommand), key)); @@ -2328,8 +2330,8 @@ void setup() SetSerialBaudrate(baudrate); - GetMqttClient(mqtt_client, Settings.mqtt_client, sizeof(mqtt_client)); - GetMqttClient(mqtt_topic, Settings.mqtt_topic, sizeof(mqtt_topic)); + Format(mqtt_client, Settings.mqtt_client, sizeof(mqtt_client)); + Format(mqtt_topic, Settings.mqtt_topic, sizeof(mqtt_topic)); if (strstr(Settings.hostname, "%")) { strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); diff --git a/sonoff/user_config.h b/sonoff/user_config.h index d49373f67..178f414f6 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -126,6 +126,8 @@ // %topic% token options (also ButtonTopic and SwitchTopic) #define MQTT_TOPIC PROJECT // [Topic] (unique) MQTT device topic #define MQTT_GRPTOPIC "sonoffs" // [GroupTopic] MQTT Group topic +#define MQTT_BUTTON_TOPIC "0" // [ButtonTopic] MQTT button topic +#define MQTT_SWITCH_TOPIC "0" // [SwitchTopic] MQTT switch topic #define MQTT_CLIENT_ID "DVES_%06X" // [MqttClient] Also fall back topic using Chip Id = last 6 characters of MAC address // -- MQTT - Telemetry ---------------------------- diff --git a/sonoff/webserver.ino b/sonoff/webserver.ino index d314d09e4..45bde262f 100644 --- a/sonoff/webserver.ino +++ b/sonoff/webserver.ino @@ -879,7 +879,7 @@ void HandleMqttConfiguration() page += FPSTR(HTTP_HEAD_STYLE); page += FPSTR(HTTP_FORM_MQTT); char str[sizeof(Settings.mqtt_client)]; - page.replace(F("{m0"), GetMqttClient(str, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client))); + page.replace(F("{m0"), Format(str, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client))); page.replace(F("{m1"), Settings.mqtt_host); page.replace(F("{m2"), String(Settings.mqtt_port)); page.replace(F("{m3"), Settings.mqtt_client); diff --git a/sonoff/xdrv_00_mqtt.ino b/sonoff/xdrv_00_mqtt.ino index 6a87f1f25..c1f2867da 100644 --- a/sonoff/xdrv_00_mqtt.ino +++ b/sonoff/xdrv_00_mqtt.ino @@ -637,7 +637,7 @@ bool MqttCommand() if ((data_len > 0) && (data_len < sizeof(Settings.button_topic))) { MakeValidMqtt(0, dataBuf); if (!strcmp(dataBuf, mqtt_client)) payload = 1; - strlcpy(Settings.button_topic, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? mqtt_topic : dataBuf, sizeof(Settings.button_topic)); + strlcpy(Settings.button_topic, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? MQTT_BUTTON_TOPIC : dataBuf, sizeof(Settings.button_topic)); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.button_topic); } @@ -645,7 +645,7 @@ bool MqttCommand() if ((data_len > 0) && (data_len < sizeof(Settings.switch_topic))) { MakeValidMqtt(0, dataBuf); if (!strcmp(dataBuf, mqtt_client)) payload = 1; - strlcpy(Settings.switch_topic, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? mqtt_topic : dataBuf, sizeof(Settings.switch_topic)); + strlcpy(Settings.switch_topic, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? MQTT_SWITCH_TOPIC : dataBuf, sizeof(Settings.switch_topic)); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.switch_topic); } diff --git a/sonoff/xdrv_07_home_assistant.ino b/sonoff/xdrv_07_home_assistant.ino index eaec8686e..87a07a6f6 100644 --- a/sonoff/xdrv_07_home_assistant.ino +++ b/sonoff/xdrv_07_home_assistant.ino @@ -31,6 +31,16 @@ const char HASS_DISCOVER_SWITCH[] PROGMEM = "\"payload_available\":\"" D_ONLINE "\"," // Online "\"payload_not_available\":\"" D_OFFLINE "\""; // Offline +const char HASS_DISCOVER_BUTTON[] 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 +// "\"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 + const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM = "%s,\"brightness_command_topic\":\"%s\"," // cmnd/led2/Dimmer "\"brightness_state_topic\":\"%s\"," // stat/led2/RESULT @@ -55,32 +65,26 @@ const char HASS_DISCOVER_LIGHT_SCHEME[] PROGMEM = "\"effect_value_template\":\"{{value_json." D_CMND_SCHEME "}}\"," "\"effect_list\":[\"0\",\"1\",\"2\",\"3\",\"4\"]"; // string list with reference to scheme parameter. Currently only supports numbers 0 to 11 as it make the mqtt string too long */ -void HAssDiscovery() + +void HAssDiscoverRelay() { char sidx[8]; char stopic[TOPSZ]; bool is_light = false; - // Configure Tasmota for default Home Assistant parameters to keep discovery message as short as possible - if (Settings.flag.hass_discovery) { - Settings.flag.mqtt_response = 0; // Response always as RESULT and not as uppercase command - Settings.flag.decimal_text = 1; // Respond with decimal color values -// Settings.light_scheme = 0; // To just control color it needs to be Scheme 0 -// strncpy_P(Settings.mqtt_fulltopic, PSTR("%prefix%/%topic%/"), sizeof(Settings.mqtt_fulltopic)); // Make MQTT topic as short as possible to make this process posible within MQTT_MAX_PACKET_SIZE - } - - for (int i = 1; i <= devices_present; i++) { + for (int i = 1; i <= MAX_RELAYS; i++) { is_light = ((i == devices_present) && (light_type)); - mqtt_data[0] = '\0'; + mqtt_data[0] = '\0'; // Clear retained message snprintf_P(sidx, sizeof(sidx), PSTR("_%d"), i); // Clear "other" topic first in case the device has been reconfigured snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s%s/config"), (is_light) ? "switch" : "light", mqtt_topic, sidx); MqttPublish(stopic, true); + // Clear or Set topic snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s%s/config"), (is_light) ? "light" : "switch", mqtt_topic, sidx); - if (Settings.flag.hass_discovery) { + if (Settings.flag.hass_discovery && (i <= devices_present)) { char name[33]; char value_template[33]; char command_topic[TOPSZ]; @@ -129,6 +133,77 @@ void HAssDiscovery() } } +void HAssDiscoverButton() +{ + char sidx[8]; + char stopic[TOPSZ]; + char key_topic[sizeof(Settings.button_topic)]; + + // Send info about buttons + char *tmp = Settings.button_topic; + 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; + + if (!button_index && ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module))) { + button_present = 1; + } else { + if (pin[GPIO_KEY1 + 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]; + + 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)); + 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); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_BUTTON, name, state_topic, Settings.state_text[2], availability_topic); + + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + } + MqttPublish(stopic, true); + } + } +} + +void HAssDiscovery() +{ + // Configure Tasmota for default Home Assistant parameters to keep discovery message as short as possible + if (Settings.flag.hass_discovery) { + Settings.flag.mqtt_response = 0; // Response always as RESULT and not as uppercase command + Settings.flag.decimal_text = 1; // Respond with decimal color values +// Settings.light_scheme = 0; // To just control color it needs to be Scheme 0 +// strncpy_P(Settings.mqtt_fulltopic, PSTR("%prefix%/%topic%/"), sizeof(Settings.mqtt_fulltopic)); // Make MQTT topic as short as possible to make this process posible within MQTT_MAX_PACKET_SIZE + } + + // Send info about relays and lights + HAssDiscoverRelay(); + + // Send info about buttons + HAssDiscoverButton(); + + // TODO: Send info about switches + + // TODO: Send info about sensors +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/ From dabb4deefc1bed9748b165744dc3e3bac412d973 Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Thu, 29 Mar 2018 14:01:38 +0200 Subject: [PATCH 3/4] Cleanup restart for non-HAss users Cleanup restart for non-HAss users --- sonoff/sonoff.ino | 8 +++++++- sonoff/xdrv_07_home_assistant.ino | 20 ++++++++++---------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 47ee15b9d..9703b62e8 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -572,7 +572,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) switch (index) { case 3: // mqtt case 15: // pwm_control - case 19: // hass_discovery +// case 19: // hass_discovery restart_flag = 2; case 0: // save_state case 1: // button_restrict @@ -587,6 +587,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) case 16: // ws_clock_reverse case 17: // decimal_text case 18: // light_signal + case 19: // hass_discovery case 20: // not_power_linked case 21: // no_power_on_check bitWrite(Settings.flag.data, index, payload); @@ -595,6 +596,11 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) stop_flash_rotate = payload; SettingsSave(2); } +#ifdef USE_HOME_ASSISTANT + if (19 == index) { // hass_discovery + HAssDiscovery(1); + } +#endif // USE_HOME_ASSISTANT } } else { // SetOption32 .. diff --git a/sonoff/xdrv_07_home_assistant.ino b/sonoff/xdrv_07_home_assistant.ino index 87a07a6f6..3f8e001be 100644 --- a/sonoff/xdrv_07_home_assistant.ino +++ b/sonoff/xdrv_07_home_assistant.ino @@ -183,7 +183,7 @@ void HAssDiscoverButton() } } -void HAssDiscovery() +void HAssDiscovery(uint8_t mode) { // Configure Tasmota for default Home Assistant parameters to keep discovery message as short as possible if (Settings.flag.hass_discovery) { @@ -193,15 +193,15 @@ void HAssDiscovery() // strncpy_P(Settings.mqtt_fulltopic, PSTR("%prefix%/%topic%/"), sizeof(Settings.mqtt_fulltopic)); // Make MQTT topic as short as possible to make this process posible within MQTT_MAX_PACKET_SIZE } - // Send info about relays and lights - HAssDiscoverRelay(); + if (Settings.flag.hass_discovery || (1 == mode)) { + // Send info about relays and lights + HAssDiscoverRelay(); + // Send info about buttons + HAssDiscoverButton(); + // TODO: Send info about switches - // Send info about buttons - HAssDiscoverButton(); - - // TODO: Send info about switches - - // TODO: Send info about sensors + // TODO: Send info about sensors + } } /*********************************************************************************************\ @@ -217,7 +217,7 @@ boolean Xdrv07(byte function) if (Settings.flag.mqtt_enabled) { switch (function) { case FUNC_MQTT_INIT: - HAssDiscovery(); + HAssDiscovery(0); break; } } From c85edf15aca858e5395b74a66e084d4975c3ae9d Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Thu, 29 Mar 2018 14:51:34 +0200 Subject: [PATCH 4/4] Change MQTT Energy response topic to SENSOR 5.12.0i * Change MQTT response topic for Energy changes from ENERGY to SENSOR (#2229, #2251) --- sonoff/_releasenotes.ino | 3 ++- sonoff/xdrv_03_energy.ino | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 5a9ad3773..4b0a6d335 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -2,7 +2,8 @@ * Add 16 timers using commands Timer and Timers (#1091) * Add commands Timer 0 to clear timer and Timer 1..16 to copy timer * Add optional Timer configuration webpage to be enabled in user_config.h with define USE_TIMERS_WEB - * Add Home Assistant MQTT Discovery for Buttons (#2277) + * Change MQTT response topic for Energy changes from ENERGY to SENSOR (#2229, #2251) + * Add Home Assistant MQTT Discovery for Buttons and change SetOption19 response (#2277) * Change webpage parameter communication * * 5.12.0h diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 8867ed298..a1052a077 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -778,7 +778,7 @@ void EnergyMqttShow() snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); EnergyShow(1); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_ENERGY), Settings.flag.mqtt_sensor_retain); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); energy_power_delta = 0; }