2018-01-18 15:19:28 +00:00
/*
2019-10-27 10:13:24 +00:00
xdrv_12_home_assistant . ino - home assistant support for Tasmota
2018-01-18 15:19:28 +00:00
2019-12-31 13:23:34 +00:00
Copyright ( C ) 2020 Theo Arends
2018-01-18 15:19:28 +00:00
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# ifdef USE_HOME_ASSISTANT
2018-11-07 09:30:03 +00:00
# define XDRV_12 12
2018-12-22 12:21:04 +00:00
const char HASS_DISCOVER_RELAY [ ] PROGMEM =
2018-01-18 15:19:28 +00:00
" { \" name \" : \" %s \" , " // dualr2 1
2018-11-13 19:52:12 +00:00
" \" cmd_t \" : \" %s \" , " // cmnd/dualr2/POWER2
" \" stat_t \" : \" %s \" , " // stat/dualr2/RESULT (implies "\"optimistic\":\"false\",")
" \" val_tpl \" : \" {{value_json.%s}} \" , " // POWER2
" \" pl_off \" : \" %s \" , " // OFF
" \" pl_on \" : \" %s \" , " // ON
" \" avty_t \" : \" %s \" , " // tele/dualr2/LWT
" \" pl_avail \" : \" " D_ONLINE " \" , " // Online
" \" pl_not_avail \" : \" " D_OFFLINE " \" " ; // Offline
2018-01-18 15:19:28 +00:00
2018-12-22 12:21:04 +00:00
const char HASS_DISCOVER_BUTTON_SWITCH [ ] PROGMEM =
2018-03-29 12:03:13 +01:00
" { \" name \" : \" %s \" , " // dualr2 1 BTN
2019-11-15 01:37:30 +00:00
" \" stat_t \" : \" %s \" , " // dualr2/stat/BUTTON1/ (implies "\"optimistic\":\"false\",")
2018-11-13 19:52:12 +00:00
" \" avty_t \" : \" %s \" , " // tele/dualr2/LWT
" \" pl_avail \" : \" " D_ONLINE " \" , " // Online
2018-12-04 20:31:23 +00:00
" \" pl_not_avail \" : \" " D_OFFLINE " \" " ; // Offline
2019-11-15 01:37:30 +00:00
const char HASS_DISCOVER_BUTTON_TOGGLE [ ] PROGMEM =
" , \" value_template \" : \" {{value_json.%s}} \" , " // STATE
" \" pl_on \" : \" %s \" , " // TOGGLE
" \" off_delay \" :1 " ; // Hass has no support for TOGGLE, fake it by resetting to OFF after 1s
2018-12-04 20:31:23 +00:00
2019-11-15 01:37:30 +00:00
const char HASS_DISCOVER_SWITCH_TOGGLE [ ] PROGMEM =
" , \" value_template \" : \" {%%if is_state(entity_id, \\ \" on \\ \" )-%%}OFF{%%-else-%%}ON{%%-endif%%} \" " ; // A switch must maintain his state until the next update
2019-12-16 14:13:57 +00:00
2018-12-22 12:21:04 +00:00
const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF [ ] PROGMEM =
2019-11-15 01:37:30 +00:00
" , \" value_template \" : \" {{value_json.%s}} \" , " // STATE
" \" frc_upd \" :true, " // In ON/OFF case, enable force_update to make automations work
" \" pl_on \" : \" %s \" , " // ON
2018-12-11 21:00:34 +00:00
" \" pl_off \" : \" %s \" " ; // OFF
2018-12-04 20:31:23 +00:00
2018-12-22 12:21:04 +00:00
const char HASS_DISCOVER_LIGHT_DIMMER [ ] PROGMEM =
2019-03-24 13:23:20 +00:00
" , \" bri_cmd_t \" : \" %s \" , " // cmnd/led2/Dimmer
2018-11-13 19:52:12 +00:00
" \" bri_stat_t \" : \" %s \" , " // stat/led2/RESULT
" \" bri_scl \" :100, " // 100%
2019-08-10 08:55:55 +01:00
" \" on_cmd_type \" : \" %s \" , " // power on (first), power on (last), no power on (brightness)
2018-11-13 19:52:12 +00:00
" \" bri_val_tpl \" : \" {{value_json. " D_CMND_DIMMER " }} \" " ;
2018-01-18 15:19:28 +00:00
2018-12-22 12:21:04 +00:00
const char HASS_DISCOVER_LIGHT_COLOR [ ] PROGMEM =
2019-03-24 13:23:20 +00:00
" , \" rgb_cmd_t \" : \" %s2 \" , " // cmnd/led2/Color2
2018-11-13 19:52:12 +00:00
" \" rgb_stat_t \" : \" %s \" , " // stat/led2/RESULT
2018-11-15 16:19:08 +00:00
" \" rgb_val_tpl \" : \" {{value_json. " D_CMND_COLOR " .split(',')[0:3]|join(',')}} \" " ;
2018-01-18 15:19:28 +00:00
2018-12-22 12:21:04 +00:00
const char HASS_DISCOVER_LIGHT_WHITE [ ] PROGMEM =
2019-03-24 13:23:20 +00:00
" , \" whit_val_cmd_t \" : \" %s \" , " // cmnd/led2/White
2018-12-07 20:32:01 +00:00
" \" whit_val_stat_t \" : \" %s \" , " // stat/led2/RESULT
" \" white_value_scale \" :100, " // (No abbreviation defined)
2019-01-30 13:33:20 +00:00
" \" whit_val_tpl \" : \" {{value_json.Channel[3]}} \" " ;
2018-12-07 20:32:01 +00:00
2018-12-22 12:21:04 +00:00
const char HASS_DISCOVER_LIGHT_CT [ ] PROGMEM =
2019-03-24 13:23:20 +00:00
" , \" clr_temp_cmd_t \" : \" %s \" , " // cmnd/led2/CT
2018-11-13 19:52:12 +00:00
" \" clr_temp_stat_t \" : \" %s \" , " // stat/led2/RESULT
" \" clr_temp_val_tpl \" : \" {{value_json. " D_CMND_COLORTEMPERATURE " }} \" " ;
2018-11-28 19:43:36 +00:00
2018-12-22 12:21:04 +00:00
const char HASS_DISCOVER_LIGHT_SCHEME [ ] PROGMEM =
2019-03-24 13:23:20 +00:00
" , \" fx_cmd_t \" : \" %s \" , " // cmnd/led2/Scheme
2018-11-28 19:43:36 +00:00
" \" fx_stat_t \" : \" %s \" , " // stat/led2/RESULT
" \" fx_val_tpl \" : \" {{value_json. " D_CMND_SCHEME " }} \" , "
" \" fx_list \" :[ \" 0 \" , \" 1 \" , \" 2 \" , \" 3 \" , \" 4 \" ] " ; // string list with reference to scheme parameter.
2018-11-18 14:33:13 +00:00
2018-12-22 12:21:04 +00:00
const char HASS_DISCOVER_SENSOR [ ] PROGMEM =
2018-11-18 14:33:13 +00:00
" { \" name \" : \" %s \" , " // dualr2 1 BTN
" \" stat_t \" : \" %s \" , " // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",")
" \" avty_t \" : \" %s \" , " // tele/dualr2/LWT
2019-12-16 14:13:57 +00:00
" \" frc_upd \" :true, " // force update for better graph representation
2018-11-18 14:33:13 +00:00
" \" pl_avail \" : \" " D_ONLINE " \" , " // Online
" \" pl_not_avail \" : \" " D_OFFLINE " \" " ; // Offline
2018-12-22 12:21:04 +00:00
const char HASS_DISCOVER_SENSOR_TEMP [ ] PROGMEM =
2019-03-24 13:23:20 +00:00
" , \" unit_of_meas \" : \" °%c \" , " // °C / °F
2019-09-09 19:29:05 +01:00
" \" val_tpl \" : \" {{value_json['%s'].Temperature}} \" , " // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Temperature }}
" \" dev_cla \" : \" temperature \" " ; // temperature
2018-11-18 14:33:13 +00:00
2018-12-22 12:21:04 +00:00
const char HASS_DISCOVER_SENSOR_HUM [ ] PROGMEM =
2019-03-24 13:23:20 +00:00
" , \" unit_of_meas \" : \" %% \" , " // %
2018-11-18 14:33:13 +00:00
" \" val_tpl \" : \" {{value_json['%s'].Humidity}} \" , " // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Humidity }}
" \" dev_cla \" : \" humidity \" " ; // humidity
2019-12-24 16:21:56 +00:00
const char HASS_DISCOVER_SENSOR_MOIST [ ] PROGMEM =
" , \" unit_of_meas \" : \" %% \" , " // %
" \" val_tpl \" : \" {{value_json['%s'].Moisture}} \" , " // "ANALOG":{"Moisture":78} -> {{ value_json['ANALOG'].Moisture }}
" \" dev_cla \" : \" humidity \" , " // humidity
" \" ic \" : \" mdi:cup-water \" " ; // cup-water icon
2018-12-22 12:21:04 +00:00
const char HASS_DISCOVER_SENSOR_PRESS [ ] PROGMEM =
2019-03-24 13:23:20 +00:00
" , \" unit_of_meas \" : \" %s \" , " // PressureUnit() setting
2019-11-08 23:22:17 +00:00
" \" val_tpl \" : \" {{value_json['%s'].%s}} \" , " // "BME280":{"Temperature":19.7,"Humidity":27.8,"Pressure":990.1} -> {{ value_json['BME280'].Pressure }}
2018-12-19 19:51:39 +00:00
" \" dev_cla \" : \" pressure \" " ; // pressure
2018-12-20 22:06:56 +00:00
//ENERGY
2018-12-22 12:21:04 +00:00
const char HASS_DISCOVER_SENSOR_KWH [ ] PROGMEM =
2019-10-10 19:00:26 +01:00
" , \" unit_of_meas \" : \" kWh \" , " // kWh
2019-09-09 19:29:05 +01:00
" \" val_tpl \" : \" {{value_json['%s'].%s}} \" , " // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Total/Yesterday/Today }}
" \" dev_cla \" : \" power \" " ; // power
2018-12-20 22:06:56 +00:00
2018-12-22 12:21:04 +00:00
const char HASS_DISCOVER_SENSOR_WATT [ ] PROGMEM =
2019-03-24 13:23:20 +00:00
" , \" unit_of_meas \" : \" W \" , " // W
2019-09-09 19:29:05 +01:00
" \" val_tpl \" : \" {{value_json['%s'].%s}} \" , " // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].POWER }}
" \" dev_cla \" : \" power \" " ;
2019-10-24 22:29:06 +01:00
2018-12-22 12:21:04 +00:00
const char HASS_DISCOVER_SENSOR_VOLTAGE [ ] PROGMEM =
2019-03-24 13:23:20 +00:00
" , \" unit_of_meas \" : \" V \" , " // V
2019-09-09 19:29:05 +01:00
" \" val_tpl \" : \" {{value_json['%s'].%s}} \" , " // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Voltage }}
" \" dev_cla \" : \" power \" " ;
2019-10-24 22:29:06 +01:00
2018-12-22 12:21:04 +00:00
const char HASS_DISCOVER_SENSOR_AMPERE [ ] PROGMEM =
2019-03-24 13:23:20 +00:00
" , \" unit_of_meas \" : \" A \" , " // A
2019-09-09 19:29:05 +01:00
" \" val_tpl \" : \" {{value_json['%s'].%s}} \" , " // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Current }}
" \" dev_cla \" : \" power \" " ;
//ILLUMINANCE
const char HASS_DISCOVER_SENSOR_ILLUMINANCE [ ] PROGMEM =
" , \" unit_of_meas \" : \" LX \" , " // LX by default
2019-10-24 22:29:06 +01:00
" \" val_tpl \" : \" {{value_json['%s'].Illuminance}} \" , " // "ANALOG":{"Illuminance":34}}
2019-09-09 19:29:05 +01:00
" \" dev_cla \" : \" illuminance \" " ; // illuminance
2018-12-20 22:06:56 +00:00
2018-12-22 12:21:04 +00:00
const char HASS_DISCOVER_SENSOR_ANY [ ] PROGMEM =
2019-10-17 15:57:54 +01:00
" , \" val_tpl \" : \" {{value_json['%s'].%s}} \" " ; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }}
2018-11-18 14:33:13 +00:00
2019-02-06 19:07:28 +00:00
const char HASS_DISCOVER_SENSOR_HASS_STATUS [ ] PROGMEM =
2019-03-24 13:23:20 +00:00
" , \" json_attributes_topic \" : \" %s \" , "
2019-10-24 22:29:06 +01:00
" \" unit_of_meas \" : \" \" , " // " " As unit of measurement to get a value graph in Hass
" \" val_tpl \" : \" {{value_json[' " D_JSON_RSSI " ']}} \" , " // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }}
2019-10-27 10:13:24 +00:00
" \" ic \" : \" mdi:information-outline \" " ;
2019-02-06 19:07:28 +00:00
2018-12-22 12:21:04 +00:00
const char HASS_DISCOVER_DEVICE_INFO [ ] PROGMEM =
2019-03-24 13:23:20 +00:00
" , \" uniq_id \" : \" %s \" , "
2018-12-10 18:51:47 +00:00
" \" device \" :{ \" identifiers \" :[ \" %06X \" ], "
2019-08-15 10:55:59 +01:00
" \" connections \" :[[ \" mac \" , \" %s \" ]], "
2018-12-10 18:51:47 +00:00
" \" name \" : \" %s \" , "
" \" model \" : \" %s \" , "
" \" sw_version \" : \" %s%s \" , "
2019-01-08 14:25:12 +00:00
" \" manufacturer \" : \" Tasmota \" } " ;
2018-12-10 18:51:47 +00:00
2019-02-06 19:07:28 +00:00
const char HASS_DISCOVER_DEVICE_INFO_SHORT [ ] PROGMEM =
2019-03-24 13:23:20 +00:00
" , \" uniq_id \" : \" %s \" , "
2019-08-15 10:55:59 +01:00
" \" device \" :{ \" identifiers \" :[ \" %06X \" ], "
" \" connections \" :[[ \" mac \" , \" %s \" ]]} " ;
2019-02-06 19:07:28 +00:00
2018-11-15 16:19:08 +00:00
const char HASS_DISCOVER_TOPIC_PREFIX [ ] PROGMEM =
2019-03-24 13:23:20 +00:00
" , \" ~ \" : \" %s \" " ;
2018-11-15 16:19:08 +00:00
2019-01-22 11:46:55 +00:00
uint8_t hass_init_step = 0 ;
uint8_t hass_mode = 0 ;
2019-02-06 19:07:28 +00:00
int hass_tele_period = 0 ;
2019-01-22 11:46:55 +00:00
2018-11-15 16:19:08 +00:00
static void FindPrefix ( char * s1 , char * s2 , char * out )
{
int prefixlen = 0 ;
while ( s1 [ prefixlen ] ! = ' \0 ' & & s2 [ prefixlen ] ! = ' \0 ' & & s1 [ prefixlen ] = = s2 [ prefixlen ] ) {
prefixlen + + ;
}
strlcpy ( out , s1 , prefixlen + 1 ) ;
}
static void Shorten ( char * * s , char * prefix )
{
size_t len = strlen ( * s ) ;
size_t prefixlen = strlen ( prefix ) ;
2019-01-06 18:26:42 +00:00
if ( len > prefixlen & & prefixlen ! = 0 & & ! strncmp ( * s , prefix , prefixlen ) ) {
2018-11-15 16:19:08 +00:00
* s + = prefixlen - 1 ;
* s [ 0 ] = ' ~ ' ;
}
}
2018-03-29 12:03:13 +01:00
2019-03-24 13:23:20 +00:00
void TryResponseAppend_P ( const char * format , . . . )
2019-02-06 19:07:28 +00:00
{
va_list args ;
va_start ( args , format ) ;
2019-03-11 14:41:06 +00:00
char dummy [ 2 ] ;
2019-03-24 13:23:20 +00:00
int dlen = vsnprintf_P ( dummy , 1 , format , args ) ;
int mlen = strlen ( mqtt_data ) ;
int slen = sizeof ( mqtt_data ) - 1 - mlen ;
if ( dlen > = slen ) {
AddLog_P2 ( LOG_LEVEL_ERROR , PSTR ( " HASS: MQTT discovery failed due to too long topic or friendly name. "
" Please shorten topic and friendly name. Failed to format(%u/%u): " ) , dlen , slen ) ;
2019-02-07 19:54:30 +00:00
va_start ( args , format ) ;
vsnprintf_P ( log_data , sizeof ( log_data ) , format , args ) ;
2019-02-06 19:07:28 +00:00
AddLog ( LOG_LEVEL_ERROR ) ;
} else {
va_start ( args , format ) ;
2019-03-24 13:23:20 +00:00
vsnprintf_P ( mqtt_data + mlen , slen , format , args ) ;
2019-02-06 19:07:28 +00:00
}
va_end ( args ) ;
}
2018-11-18 14:33:13 +00:00
void HAssAnnounceRelayLight ( void )
2018-01-18 15:19:28 +00:00
{
char stopic [ TOPSZ ] ;
2018-12-10 18:51:47 +00:00
char stemp1 [ TOPSZ ] ;
char stemp2 [ TOPSZ ] ;
char stemp3 [ TOPSZ ] ;
char unique_id [ 30 ] ;
2018-01-18 15:19:28 +00:00
bool is_light = false ;
2018-06-29 10:15:27 +01:00
bool is_topic_light = false ;
2018-01-18 15:19:28 +00:00
2019-06-30 15:44:36 +01:00
for ( uint32_t i = 1 ; i < = MAX_RELAYS ; i + + ) {
2018-01-18 15:19:28 +00:00
is_light = ( ( i = = devices_present ) & & ( light_type ) ) ;
2019-11-03 11:33:36 +00:00
is_topic_light = Settings . flag . hass_light | | is_light ; // SetOption30 - Enforce HAss autodiscovery as light
2018-01-18 15:19:28 +00:00
2018-03-29 12:03:13 +01:00
mqtt_data [ 0 ] = ' \0 ' ; // Clear retained message
2018-02-16 16:35:51 +00:00
2019-03-08 15:38:36 +00:00
// Clear "other" topic first in case the device has been reconfigured from light to switch or vice versa
2018-12-10 18:51:47 +00:00
snprintf_P ( unique_id , sizeof ( unique_id ) , PSTR ( " %06X_%s_%d " ) , ESP . getChipId ( ) , ( is_topic_light ) ? " RL " : " LI " , i ) ;
2019-02-06 19:07:28 +00:00
snprintf_P ( stopic , sizeof ( stopic ) , PSTR ( HOME_ASSISTANT_DISCOVERY_PREFIX " /%s/%s/config " ) ,
( is_topic_light ) ? " switch " : " light " , unique_id ) ;
2018-02-16 16:35:51 +00:00
MqttPublish ( stopic , true ) ;
2018-03-29 12:03:13 +01:00
// Clear or Set topic
2018-12-10 18:51:47 +00:00
snprintf_P ( unique_id , sizeof ( unique_id ) , PSTR ( " %06X_%s_%d " ) , ESP . getChipId ( ) , ( is_topic_light ) ? " LI " : " RL " , i ) ;
2019-02-06 19:07:28 +00:00
snprintf_P ( stopic , sizeof ( stopic ) , PSTR ( HOME_ASSISTANT_DISCOVERY_PREFIX " /%s/%s/config " ) ,
( is_topic_light ) ? " light " : " switch " , unique_id ) ;
2018-01-18 15:19:28 +00:00
2019-11-03 11:33:36 +00:00
if ( Settings . flag . hass_discovery & & ( i < = devices_present ) ) { // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59)
2019-02-07 19:54:30 +00:00
char name [ 33 + 2 ] ; // friendlyname(33) + " " + index
2018-01-18 15:19:28 +00:00
char value_template [ 33 ] ;
2018-11-15 16:19:08 +00:00
char prefix [ TOPSZ ] ;
2018-12-10 18:51:47 +00:00
char * command_topic = stemp1 ;
char * state_topic = stemp2 ;
char * availability_topic = stemp3 ;
2018-01-18 15:19:28 +00:00
if ( i > MAX_FRIENDLYNAMES ) {
2019-12-16 14:13:57 +00:00
snprintf_P ( name , sizeof ( name ) , PSTR ( " %s %d " ) , SettingsText ( SET_FRIENDLYNAME1 ) , i ) ;
2018-01-18 15:19:28 +00:00
} else {
2019-12-16 14:13:57 +00:00
snprintf_P ( name , sizeof ( name ) , SettingsText ( SET_FRIENDLYNAME1 + i - 1 ) ) ;
2018-01-18 15:19:28 +00:00
}
2019-11-03 11:33:36 +00:00
GetPowerDevice ( value_template , i , sizeof ( value_template ) , Settings . flag . device_index_enable ) ; // SetOption26 - Switch between POWER or POWER1
2018-02-13 13:30:30 +00:00
GetTopic_P ( command_topic , CMND , mqtt_topic , value_template ) ;
2018-12-02 14:23:25 +00:00
//GetTopic_P(state_topic, STAT, mqtt_topic, S_RSLT_RESULT);
GetTopic_P ( state_topic , TELE , mqtt_topic , D_RSLT_STATE ) ;
2018-02-13 13:30:30 +00:00
GetTopic_P ( availability_topic , TELE , mqtt_topic , S_LWT ) ;
2018-11-15 16:19:08 +00:00
FindPrefix ( command_topic , state_topic , prefix ) ;
2018-12-22 12:15:55 +00:00
Shorten ( & command_topic , prefix ) ;
Shorten ( & state_topic , prefix ) ;
Shorten ( & availability_topic , prefix ) ;
2019-03-11 14:41:06 +00:00
2019-12-16 14:13:57 +00:00
Response_P ( HASS_DISCOVER_RELAY , name , command_topic , state_topic , value_template , SettingsText ( SET_STATE_TXT1 ) , SettingsText ( SET_STATE_TXT2 ) , availability_topic ) ;
2019-08-15 10:55:59 +01:00
TryResponseAppend_P ( HASS_DISCOVER_DEVICE_INFO_SHORT , unique_id , ESP . getChipId ( ) , WiFi . macAddress ( ) . c_str ( ) ) ;
2019-03-24 13:23:20 +00:00
TryResponseAppend_P ( HASS_DISCOVER_TOPIC_PREFIX , prefix ) ;
2018-01-18 15:19:28 +00:00
2019-08-27 09:02:25 +01:00
# ifdef USE_LIGHT
2018-01-18 15:19:28 +00:00
if ( is_light ) {
2018-12-10 18:51:47 +00:00
char * brightness_command_topic = stemp1 ;
2018-01-18 15:19:28 +00:00
2018-02-13 13:30:30 +00:00
GetTopic_P ( brightness_command_topic , CMND , mqtt_topic , D_CMND_DIMMER ) ;
2018-12-22 12:15:55 +00:00
Shorten ( & brightness_command_topic , prefix ) ;
2019-11-03 11:33:36 +00:00
strncpy_P ( stemp3 , Settings . flag . not_power_linked ? PSTR ( " last " ) : PSTR ( " brightness " ) , sizeof ( stemp3 ) ) ; // SetOption20 - Control power in relation to Dimmer/Color/Ct changes
2019-08-10 08:55:55 +01:00
TryResponseAppend_P ( HASS_DISCOVER_LIGHT_DIMMER , brightness_command_topic , state_topic , stemp3 ) ;
2018-01-18 15:19:28 +00:00
2019-08-17 12:17:30 +01:00
if ( Light . subtype > = LST_RGB ) {
2018-12-10 18:51:47 +00:00
char * rgb_command_topic = stemp1 ;
2018-01-18 15:19:28 +00:00
2018-02-13 13:30:30 +00:00
GetTopic_P ( rgb_command_topic , CMND , mqtt_topic , D_CMND_COLOR ) ;
2018-12-22 12:15:55 +00:00
Shorten ( & rgb_command_topic , prefix ) ;
2019-03-24 13:23:20 +00:00
TryResponseAppend_P ( HASS_DISCOVER_LIGHT_COLOR , rgb_command_topic , state_topic ) ;
2018-01-18 15:19:28 +00:00
2018-12-10 18:51:47 +00:00
char * effect_command_topic = stemp1 ;
2018-02-13 13:30:30 +00:00
GetTopic_P ( effect_command_topic , CMND , mqtt_topic , D_CMND_SCHEME ) ;
2018-12-22 12:15:55 +00:00
Shorten ( & effect_command_topic , prefix ) ;
2019-03-24 13:23:20 +00:00
TryResponseAppend_P ( HASS_DISCOVER_LIGHT_SCHEME , effect_command_topic , state_topic ) ;
2018-11-28 19:43:36 +00:00
2018-01-18 15:19:28 +00:00
}
2019-08-17 12:17:30 +01:00
if ( LST_RGBW = = Light . subtype ) {
2018-12-10 18:51:47 +00:00
char * white_temp_command_topic = stemp1 ;
2018-12-07 20:32:01 +00:00
GetTopic_P ( white_temp_command_topic , CMND , mqtt_topic , D_CMND_WHITE ) ;
2018-12-22 12:15:55 +00:00
Shorten ( & white_temp_command_topic , prefix ) ;
2019-03-24 13:23:20 +00:00
TryResponseAppend_P ( HASS_DISCOVER_LIGHT_WHITE , white_temp_command_topic , state_topic ) ;
2018-12-07 20:32:01 +00:00
}
2020-01-04 10:01:44 +00:00
if ( ( LST_COLDWARM = = Light . subtype ) | | ( LST_RGBCW = = Light . subtype ) ) {
2018-12-10 18:51:47 +00:00
char * color_temp_command_topic = stemp1 ;
2018-01-18 15:19:28 +00:00
2018-02-13 13:30:30 +00:00
GetTopic_P ( color_temp_command_topic , CMND , mqtt_topic , D_CMND_COLORTEMPERATURE ) ;
2018-12-22 12:15:55 +00:00
Shorten ( & color_temp_command_topic , prefix ) ;
2019-03-24 13:23:20 +00:00
TryResponseAppend_P ( HASS_DISCOVER_LIGHT_CT , color_temp_command_topic , state_topic ) ;
2018-01-18 15:19:28 +00:00
}
}
2019-08-27 09:02:25 +01:00
# endif // USE_LIGHT
2019-03-24 13:23:20 +00:00
TryResponseAppend_P ( PSTR ( " } " ) ) ;
2018-01-18 15:19:28 +00:00
}
MqttPublish ( stopic , true ) ;
}
}
2019-01-28 13:08:33 +00:00
void HAssAnnounceButtonSwitch ( uint8_t device , char * topic , uint8_t present , uint8_t key , uint8_t toggle )
2018-03-29 12:03:13 +01:00
{
2018-12-08 14:24:16 +00:00
// key 0 = button
// key 1 = switch
2018-12-04 20:31:23 +00:00
char stopic [ TOPSZ ] ;
2018-12-10 18:51:47 +00:00
char stemp1 [ TOPSZ ] ;
char stemp2 [ TOPSZ ] ;
char unique_id [ 30 ] ;
2018-12-04 20:31:23 +00:00
mqtt_data [ 0 ] = ' \0 ' ; // Clear retained message
// Clear or Set topic
2018-12-10 18:51:47 +00:00
snprintf_P ( unique_id , sizeof ( unique_id ) , PSTR ( " %06X_%s_%d " ) , ESP . getChipId ( ) , key ? " SW " : " BTN " , device + 1 ) ;
snprintf_P ( stopic , sizeof ( stopic ) , PSTR ( HOME_ASSISTANT_DISCOVERY_PREFIX " /binary_sensor/%s/config " ) , unique_id ) ;
2018-12-04 20:31:23 +00:00
2019-11-03 11:33:36 +00:00
if ( Settings . flag . hass_discovery & & present ) { // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59)
2019-02-07 19:54:30 +00:00
char name [ 33 + 6 ] ; // friendlyname(33) + " " + "BTN" + " " + index
2018-12-04 20:31:23 +00:00
char value_template [ 33 ] ;
char prefix [ TOPSZ ] ;
2018-12-10 18:51:47 +00:00
char * state_topic = stemp1 ;
char * availability_topic = stemp2 ;
2019-10-24 22:29:06 +01:00
char jsoname [ 8 ] ;
2018-12-04 20:31:23 +00:00
2019-12-16 14:13:57 +00:00
snprintf_P ( name , sizeof ( name ) , PSTR ( " %s %s%d " ) , SettingsText ( SET_FRIENDLYNAME1 ) , key ? " Switch " : " Button " , device + 1 ) ;
2019-11-15 01:37:30 +00:00
snprintf_P ( jsoname , sizeof ( jsoname ) , PSTR ( " %s%d " ) , key ? " SWITCH " : " BUTTON " , device + 1 ) ;
2018-12-07 16:19:14 +00:00
GetPowerDevice ( value_template , device + 1 , sizeof ( value_template ) ,
2019-11-03 11:33:36 +00:00
key + Settings . flag . device_index_enable ) ; // Force index for Switch 1, Index on Button1 is controlled by SetOption26 - Switch between POWER or POWER1
2019-10-24 22:29:06 +01:00
//GetTopic_P(state_topic, CMND, topic, value_template); // State of button is sent as CMND TOGGLE, state of switch is sent as ON/OFF
2019-11-15 01:37:30 +00:00
GetTopic_P ( state_topic , STAT , mqtt_topic , ( PSTR ( " /'%s' " ) , jsoname ) ) ;
2018-12-04 20:31:23 +00:00
GetTopic_P ( availability_topic , TELE , mqtt_topic , S_LWT ) ;
FindPrefix ( state_topic , availability_topic , prefix ) ;
2019-10-24 22:29:06 +01:00
2018-12-22 12:15:55 +00:00
Shorten ( & state_topic , prefix ) ;
Shorten ( & availability_topic , prefix ) ;
2019-11-15 01:37:30 +00:00
Response_P ( HASS_DISCOVER_BUTTON_SWITCH , name , state_topic , availability_topic ) ;
2019-08-15 10:55:59 +01:00
TryResponseAppend_P ( HASS_DISCOVER_DEVICE_INFO_SHORT , unique_id , ESP . getChipId ( ) , WiFi . macAddress ( ) . c_str ( ) ) ;
2019-03-24 13:23:20 +00:00
if ( strlen ( prefix ) > 0 ) TryResponseAppend_P ( HASS_DISCOVER_TOPIC_PREFIX , prefix ) ;
2019-11-15 01:37:30 +00:00
if ( toggle ) {
2019-12-16 14:13:57 +00:00
if ( ! key ) {
2019-12-19 01:00:05 +00:00
TryResponseAppend_P ( HASS_DISCOVER_BUTTON_TOGGLE , PSTR ( D_RSLT_STATE ) , SettingsText ( SET_STATE_TXT3 ) ) ;
2019-11-15 01:37:30 +00:00
} else { TryResponseAppend_P ( HASS_DISCOVER_SWITCH_TOGGLE ) ; }
}
2019-12-19 01:00:05 +00:00
else TryResponseAppend_P ( HASS_DISCOVER_BUTTON_SWITCH_ONOFF , PSTR ( D_RSLT_STATE ) , SettingsText ( SET_STATE_TXT2 ) , SettingsText ( SET_STATE_TXT1 ) ) ;
2019-03-24 13:23:20 +00:00
TryResponseAppend_P ( PSTR ( " } " ) ) ;
2018-12-04 20:31:23 +00:00
}
MqttPublish ( stopic , true ) ;
}
void HAssAnnounceSwitches ( void )
{
2019-12-16 14:13:57 +00:00
char sw_topic [ TOPSZ ] ;
2018-12-04 20:31:23 +00:00
// Send info about buttons
2019-12-16 14:13:57 +00:00
char * tmp = SettingsText ( SET_MQTT_SWITCH_TOPIC ) ;
2018-12-04 20:31:23 +00:00
Format ( sw_topic , tmp , sizeof ( sw_topic ) ) ;
2019-10-24 22:29:06 +01:00
if ( ! strcmp_P ( sw_topic , " 0 " ) | | strlen ( sw_topic ) = = 0 ) {
2019-06-30 15:44:36 +01:00
for ( uint32_t switch_index = 0 ; switch_index < MAX_SWITCHES ; switch_index + + ) {
2019-01-28 13:08:33 +00:00
uint8_t switch_present = 0 ;
uint8_t toggle = 1 ;
2018-12-04 20:31:23 +00:00
2019-01-08 14:25:12 +00:00
if ( pin [ GPIO_SWT1 + switch_index ] < 99 ) {
2018-12-04 20:31:23 +00:00
switch_present = 1 ;
}
2018-12-05 19:20:36 +00:00
// Check if MQTT message will be ON/OFF or TOGGLE
if ( Settings . switchmode [ switch_index ] = = FOLLOW | | Settings . switchmode [ switch_index ] = = FOLLOW_INV | |
2019-11-03 12:51:22 +00:00
Settings . flag3 . button_switch_force_local | | // SetOption61 - Force local operation when button/switch topic is set
2019-12-16 14:13:57 +00:00
! strcmp ( mqtt_topic , sw_topic ) | | ! strcmp ( SettingsText ( SET_MQTT_GRP_TOPIC ) , sw_topic ) )
2018-12-05 19:20:36 +00:00
{
2018-12-08 08:43:48 +00:00
toggle = 0 ; // MQTT message will be ON/OFF
2018-12-05 19:20:36 +00:00
}
2018-12-08 14:24:16 +00:00
HAssAnnounceButtonSwitch ( switch_index , sw_topic , switch_present , 1 , toggle ) ;
2018-12-04 20:31:23 +00:00
}
}
}
void HAssAnnounceButtons ( void )
{
2019-12-16 14:13:57 +00:00
char key_topic [ TOPSZ ] ;
2018-03-29 12:03:13 +01:00
// Send info about buttons
2019-12-16 14:13:57 +00:00
char * tmp = SettingsText ( SET_MQTT_BUTTON_TOPIC ) ;
2018-03-29 12:03:13 +01:00
Format ( key_topic , tmp , sizeof ( key_topic ) ) ;
2019-10-24 22:29:06 +01:00
if ( ! strcmp_P ( key_topic , " 0 " ) | | strlen ( key_topic ) = = 0 ) {
2019-06-30 15:44:36 +01:00
for ( uint32_t button_index = 0 ; button_index < MAX_KEYS ; button_index + + ) {
2019-01-28 13:08:33 +00:00
uint8_t button_present = 0 ;
uint8_t toggle = 1 ;
2018-03-29 12:03:13 +01:00
2019-02-11 18:21:49 +00:00
if ( ! button_index & & ( ( SONOFF_DUAL = = my_module_type ) | | ( CH4 = = my_module_type ) ) ) {
2018-03-29 12:03:13 +01:00
button_present = 1 ;
} else {
2019-01-08 14:25:12 +00:00
if ( pin [ GPIO_KEY1 + button_index ] < 99 ) {
2018-03-29 12:03:13 +01:00
button_present = 1 ;
}
}
2018-12-05 19:20:36 +00:00
// Check if MQTT message will be ON/OFF or TOGGLE
2019-11-03 12:51:22 +00:00
if ( Settings . flag3 . button_switch_force_local | | // SetOption61 - Force local operation when button/switch topic is set
2019-12-16 14:13:57 +00:00
! strcmp ( mqtt_topic , key_topic ) | | ! strcmp ( SettingsText ( SET_MQTT_GRP_TOPIC ) , key_topic ) )
2018-12-05 19:20:36 +00:00
{
2018-12-08 08:43:48 +00:00
toggle = 0 ; // MQTT message will be ON/OFF
2018-12-05 19:20:36 +00:00
}
2018-12-08 14:24:16 +00:00
HAssAnnounceButtonSwitch ( button_index , key_topic , button_present , 0 , toggle ) ;
2018-03-29 12:03:13 +01:00
}
}
}
2019-10-24 08:47:28 +01:00
void HAssAnnounceSensor ( const char * sensorname , const char * subsensortype )
2018-11-18 14:33:13 +00:00
{
char stopic [ TOPSZ ] ;
2018-12-10 18:51:47 +00:00
char stemp1 [ TOPSZ ] ;
char stemp2 [ TOPSZ ] ;
char unique_id [ 30 ] ;
2019-10-24 08:47:28 +01:00
bool is_sensor = true ;
2018-11-18 14:33:13 +00:00
// Announce sensor, special handling of temperature and humidity sensors
mqtt_data [ 0 ] = ' \0 ' ; // Clear retained message
// Clear or Set topic
2018-12-10 18:51:47 +00:00
snprintf_P ( unique_id , sizeof ( unique_id ) , PSTR ( " %06X_%s_%s " ) , ESP . getChipId ( ) , sensorname , subsensortype ) ;
2019-10-17 15:57:54 +01:00
if ( ! strncmp_P ( sensorname , " MPR121 " , 6 ) ) { // Add more exceptions here. Perhaps MCP230XX?
snprintf_P ( stopic , sizeof ( stopic ) , PSTR ( HOME_ASSISTANT_DISCOVERY_PREFIX " /binary_sensor/%s/config " ) , unique_id ) ;
is_sensor = false ;
} else {
snprintf_P ( stopic , sizeof ( stopic ) , PSTR ( HOME_ASSISTANT_DISCOVERY_PREFIX " /sensor/%s/config " ) , unique_id ) ;
}
2019-11-03 11:33:36 +00:00
if ( Settings . flag . hass_discovery ) { // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59)
2019-02-07 19:54:30 +00:00
char name [ 33 + 42 ] ; // friendlyname(33) + " " + sensorname(20?) + " " + sensortype(20?)
2018-11-18 14:33:13 +00:00
char prefix [ TOPSZ ] ;
2018-12-10 18:51:47 +00:00
char * state_topic = stemp1 ;
char * availability_topic = stemp2 ;
2018-11-18 14:33:13 +00:00
2019-10-17 15:57:54 +01:00
// sensor or binary_sensor? //
if ( ! is_sensor ) {
snprintf_P ( stopic , sizeof ( stopic ) , PSTR ( HOME_ASSISTANT_DISCOVERY_PREFIX " /binary_sensor/%s/config " ) , unique_id ) ;
GetTopic_P ( state_topic , STAT , mqtt_topic , PSTR ( D_RSLT_RESULT ) ) ;
} else {
snprintf_P ( stopic , sizeof ( stopic ) , PSTR ( HOME_ASSISTANT_DISCOVERY_PREFIX " /sensor/%s/config " ) , unique_id ) ;
GetTopic_P ( state_topic , TELE , mqtt_topic , PSTR ( D_RSLT_SENSOR ) ) ;
}
2019-12-16 14:13:57 +00:00
snprintf_P ( name , sizeof ( name ) , PSTR ( " %s %s %s " ) , SettingsText ( SET_FRIENDLYNAME1 ) , sensorname , subsensortype ) ;
2018-11-18 14:33:13 +00:00
GetTopic_P ( availability_topic , TELE , mqtt_topic , S_LWT ) ;
FindPrefix ( state_topic , availability_topic , prefix ) ;
2018-12-22 12:15:55 +00:00
Shorten ( & state_topic , prefix ) ;
Shorten ( & availability_topic , prefix ) ;
2019-03-24 13:23:20 +00:00
Response_P ( HASS_DISCOVER_SENSOR , name , state_topic , availability_topic ) ;
2019-08-15 10:55:59 +01:00
TryResponseAppend_P ( HASS_DISCOVER_DEVICE_INFO_SHORT , unique_id , ESP . getChipId ( ) , WiFi . macAddress ( ) . c_str ( ) ) ;
2019-03-24 13:23:20 +00:00
TryResponseAppend_P ( HASS_DISCOVER_TOPIC_PREFIX , prefix ) ;
2018-12-15 02:57:12 +00:00
if ( ! strcmp_P ( subsensortype , PSTR ( D_JSON_TEMPERATURE ) ) ) {
2019-03-24 13:23:20 +00:00
TryResponseAppend_P ( HASS_DISCOVER_SENSOR_TEMP , TempUnit ( ) , sensorname ) ;
2018-12-10 18:51:47 +00:00
} else if ( ! strcmp_P ( subsensortype , PSTR ( D_JSON_HUMIDITY ) ) ) {
2019-03-24 13:23:20 +00:00
TryResponseAppend_P ( HASS_DISCOVER_SENSOR_HUM , sensorname ) ;
2019-12-16 14:13:57 +00:00
} else if ( ! strcmp_P ( subsensortype , PSTR ( D_JSON_PRESSURE ) )
2019-11-09 00:00:24 +00:00
| | ! strcmp_P ( subsensortype , PSTR ( D_JSON_PRESSUREATSEALEVEL ) ) ) {
2019-11-08 23:22:17 +00:00
TryResponseAppend_P ( HASS_DISCOVER_SENSOR_PRESS , PressureUnit ( ) . c_str ( ) , sensorname , subsensortype ) ;
2019-02-06 19:07:28 +00:00
} else if ( ! strcmp_P ( subsensortype , PSTR ( D_JSON_TOTAL ) )
| | ! strcmp_P ( subsensortype , PSTR ( D_JSON_TODAY ) )
| | ! strcmp_P ( subsensortype , PSTR ( D_JSON_YESTERDAY ) ) ) {
2019-03-24 13:23:20 +00:00
TryResponseAppend_P ( HASS_DISCOVER_SENSOR_KWH , sensorname , subsensortype ) ;
2018-12-20 22:06:56 +00:00
} else if ( ! strcmp_P ( subsensortype , PSTR ( D_JSON_POWERUSAGE ) ) ) {
2019-03-24 13:23:20 +00:00
TryResponseAppend_P ( HASS_DISCOVER_SENSOR_WATT , sensorname , subsensortype ) ;
2018-12-20 22:06:56 +00:00
} else if ( ! strcmp_P ( subsensortype , PSTR ( D_JSON_VOLTAGE ) ) ) {
2019-03-24 13:23:20 +00:00
TryResponseAppend_P ( HASS_DISCOVER_SENSOR_VOLTAGE , sensorname , subsensortype ) ;
2018-12-20 22:06:56 +00:00
} else if ( ! strcmp_P ( subsensortype , PSTR ( D_JSON_CURRENT ) ) ) {
2019-03-24 13:23:20 +00:00
TryResponseAppend_P ( HASS_DISCOVER_SENSOR_AMPERE , sensorname , subsensortype ) ;
2019-09-09 19:29:05 +01:00
} else if ( ! strcmp_P ( subsensortype , PSTR ( D_JSON_ILLUMINANCE ) ) ) {
TryResponseAppend_P ( HASS_DISCOVER_SENSOR_ILLUMINANCE , sensorname , subsensortype ) ;
2019-12-24 16:21:56 +00:00
} else if ( ! strcmp_P ( subsensortype , PSTR ( D_JSON_MOISTURE ) ) ) {
TryResponseAppend_P ( HASS_DISCOVER_SENSOR_MOIST , sensorname , subsensortype ) ;
2019-10-10 19:00:26 +01:00
} else {
2019-10-24 08:47:28 +01:00
if ( is_sensor ) {
TryResponseAppend_P ( PSTR ( " , \" unit_of_meas \" : \" \" " ) ) ; // " " As unit of measurement to get a value graph (not available for binary sensors)
}
TryResponseAppend_P ( HASS_DISCOVER_SENSOR_ANY , sensorname , subsensortype ) ;
2018-11-18 14:33:13 +00:00
}
2019-03-24 13:23:20 +00:00
TryResponseAppend_P ( PSTR ( " } " ) ) ;
2018-11-18 14:33:13 +00:00
}
MqttPublish ( stopic , true ) ;
}
void HAssAnnounceSensors ( void )
{
uint8_t hass_xsns_index = 0 ;
2019-01-22 11:46:55 +00:00
2018-11-18 14:33:13 +00:00
do {
mqtt_data [ 0 ] = ' \0 ' ;
int tele_period_save = tele_period ;
tele_period = 2 ; // Do not allow HA updates during next function call
XsnsNextCall ( FUNC_JSON_APPEND , hass_xsns_index ) ; // ,"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089}
tele_period = tele_period_save ;
2019-10-10 19:00:26 +01:00
char sensordata [ 512 ] ; // Copy because we need to write to mqtt_data
2018-11-18 14:33:13 +00:00
strlcpy ( sensordata , mqtt_data , sizeof ( sensordata ) ) ;
if ( strlen ( sensordata ) ) {
sensordata [ 0 ] = ' { ' ; // {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089}
2019-01-22 11:46:55 +00:00
snprintf_P ( sensordata , sizeof ( sensordata ) , PSTR ( " %s} " ) , sensordata ) ; // {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089}}
2018-11-18 14:33:13 +00:00
2019-01-22 11:46:55 +00:00
// JsonBuffer size calculation (https://arduinojson.org/v5/assistant/)
// 383 = {"MCP230XX":{"D0":0,"D1":0,"D2":0,"D3":0,"D4":0,"D5":0,"D6":0,"D7":0,"D8":0,"D9":0,"D10":0,"D11":0,"D12":0,"D13":0,"D14":0,"D15":0}}
// 381 = {"MPR121A":{"Button0":0,"Button1":0,"Button2":0,"Button3":0,"Button4":0,"Button5":0,"Button6":0,"Button7":0,"Button8":0,"Button9":0,"Button10":0,"Button11":0,"Button12":0}}
// 420 = {"ENERGY":{"TotalStartTime":"2018-10-30T17:09:47","Total":2.684,"Yesterday":0.020,"Today":0.006,"Period":0.04,"Power":0.49,"ApparentPower":4.71,"ReactivePower":4.70,"Factor":0.10,"Frequency":50.04,"Voltage":226.3,"Current":0.021}}
StaticJsonBuffer < 500 > jsonBuffer ;
2018-11-18 14:33:13 +00:00
JsonObject & root = jsonBuffer . parseObject ( sensordata ) ;
if ( ! root . success ( ) ) {
2019-10-17 15:57:54 +01:00
AddLog_P2 ( LOG_LEVEL_ERROR , PSTR ( " HASS: jsonBuffer failed to parse '%s' " ) , sensordata ) ;
2018-11-18 14:33:13 +00:00
continue ;
}
for ( auto sensor : root ) {
const char * sensorname = sensor . key ;
JsonObject & sensors = sensor . value . as < JsonObject > ( ) ;
if ( ! sensors . success ( ) ) {
2019-10-17 15:57:54 +01:00
AddLog_P2 ( LOG_LEVEL_ERROR , PSTR ( " HASS: JsonObject failed to parse '%s' " ) , sensordata ) ;
2018-11-18 14:33:13 +00:00
continue ;
}
for ( auto subsensor : sensors ) {
HAssAnnounceSensor ( sensorname , subsensor . key ) ;
}
}
}
2019-01-08 14:25:12 +00:00
yield ( ) ;
2018-11-18 14:33:13 +00:00
} while ( hass_xsns_index ! = 0 ) ;
}
2019-02-06 19:07:28 +00:00
void HAssAnnounceStatusSensor ( void )
{
char stopic [ TOPSZ ] ;
char stemp1 [ TOPSZ ] ;
char stemp2 [ TOPSZ ] ;
char unique_id [ 30 ] ;
// Announce sensor
mqtt_data [ 0 ] = ' \0 ' ; // Clear retained message
// Clear or Set topic
2019-03-24 13:23:20 +00:00
snprintf_P ( unique_id , sizeof ( unique_id ) , PSTR ( " %06X_status " ) , ESP . getChipId ( ) ) ;
2019-02-06 19:07:28 +00:00
snprintf_P ( stopic , sizeof ( stopic ) , PSTR ( HOME_ASSISTANT_DISCOVERY_PREFIX " /sensor/%s/config " ) , unique_id ) ;
2019-11-03 11:33:36 +00:00
if ( Settings . flag . hass_discovery ) { // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59)
2019-02-07 19:54:30 +00:00
char name [ 33 + 7 ] ; // friendlyname(33) + " " + "status"
2019-02-06 19:07:28 +00:00
char prefix [ TOPSZ ] ;
char * state_topic = stemp1 ;
char * availability_topic = stemp2 ;
2019-12-16 14:13:57 +00:00
snprintf_P ( name , sizeof ( name ) , PSTR ( " %s status " ) , SettingsText ( SET_FRIENDLYNAME1 ) ) ;
2019-02-06 19:07:28 +00:00
GetTopic_P ( state_topic , TELE , mqtt_topic , PSTR ( D_RSLT_HASS_STATE ) ) ;
GetTopic_P ( availability_topic , TELE , mqtt_topic , S_LWT ) ;
FindPrefix ( state_topic , availability_topic , prefix ) ;
Shorten ( & state_topic , prefix ) ;
Shorten ( & availability_topic , prefix ) ;
2019-03-24 13:23:20 +00:00
Response_P ( HASS_DISCOVER_SENSOR , name , state_topic , availability_topic ) ;
TryResponseAppend_P ( HASS_DISCOVER_SENSOR_HASS_STATUS , state_topic ) ;
2019-08-15 10:55:59 +01:00
TryResponseAppend_P ( HASS_DISCOVER_DEVICE_INFO , unique_id , ESP . getChipId ( ) , WiFi . macAddress ( ) . c_str ( ) ,
2019-12-16 14:13:57 +00:00
SettingsText ( SET_FRIENDLYNAME1 ) , ModuleName ( ) . c_str ( ) , my_version , my_image ) ;
2019-03-24 13:23:20 +00:00
TryResponseAppend_P ( HASS_DISCOVER_TOPIC_PREFIX , prefix ) ;
TryResponseAppend_P ( PSTR ( " } " ) ) ;
2019-02-06 19:07:28 +00:00
}
MqttPublish ( stopic , true ) ;
}
void HAssPublishStatus ( void )
{
2019-03-23 16:00:59 +00:00
Response_P ( PSTR ( " { \" " D_JSON_VERSION " \" : \" %s%s \" , \" " D_JSON_BUILDDATETIME " \" : \" %s \" , "
2019-03-08 15:38:36 +00:00
" \" " D_JSON_COREVERSION " \" : \" " ARDUINO_ESP8266_RELEASE " \" , \" " D_JSON_SDKVERSION " \" : \" %s \" , "
" \" " D_CMND_MODULE " \" : \" %s \" , \" " D_JSON_RESTARTREASON " \" : \" %s \" , \" " D_JSON_UPTIME " \" : \" %s \" , "
2019-03-11 17:29:39 +00:00
" \" WiFi " D_JSON_LINK_COUNT " \" :%d, \" WiFi " D_JSON_DOWNTIME " \" : \" %s \" , \" " D_JSON_MQTT_COUNT " \" :%d, "
2019-03-08 15:38:36 +00:00
" \" " D_JSON_BOOTCOUNT " \" :%d, \" " D_JSON_SAVECOUNT " \" :%d, \" " D_CMND_IPADDRESS " \" : \" %s \" , "
" \" " D_JSON_RSSI " \" : \" %d \" , \" LoadAvg \" :%lu} " ) ,
my_version , my_image , GetBuildDateAndTime ( ) . c_str ( ) , ESP . getSdkVersion ( ) , ModuleName ( ) . c_str ( ) ,
2019-03-11 17:29:39 +00:00
GetResetReason ( ) . c_str ( ) , GetUptime ( ) . c_str ( ) , WifiLinkCount ( ) , WifiDowntime ( ) . c_str ( ) , MqttConnectCount ( ) ,
2019-03-08 15:38:36 +00:00
Settings . bootcount , Settings . save_flag , WiFi . localIP ( ) . toString ( ) . c_str ( ) ,
WifiGetRssiAsQuality ( WiFi . RSSI ( ) ) , loop_load_avg ) ;
2019-02-06 19:07:28 +00:00
MqttPublishPrefixTopic_P ( TELE , PSTR ( D_RSLT_HASS_STATE ) ) ;
}
2019-01-22 11:46:55 +00:00
void HAssDiscovery ( void )
2018-03-29 12:03:13 +01:00
{
// Configure Tasmota for default Home Assistant parameters to keep discovery message as short as possible
2019-11-03 11:33:36 +00:00
if ( Settings . flag . hass_discovery ) { // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59)
Settings . flag . mqtt_response = 0 ; // SetOption4 - Switch between MQTT RESULT or COMMAND - Response always as RESULT and not as uppercase command
Settings . flag . decimal_text = 1 ; // SetOption17 - Switch between decimal or hexadecimal output - Respond with decimal color values
2019-11-03 12:51:22 +00:00
Settings . flag3 . hass_tele_on_power = 1 ; // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT - send tele/STATE message as stat/RESULT
2019-01-22 11:46:55 +00:00
// Settings.light_scheme = 0; // To just control color it needs to be Scheme 0
2019-12-16 14:13:57 +00:00
if ( strcmp_P ( SettingsText ( SET_MQTT_FULLTOPIC ) , PSTR ( " %topic%/%prefix%/ " ) ) ) {
SettingsUpdateText ( SET_MQTT_FULLTOPIC , " %topic%/%prefix%/ " ) ;
2018-11-27 18:31:45 +00:00
restart_flag = 2 ;
2019-01-22 11:46:55 +00:00
return ; // As full topic has changed do restart first before sending discovery data
2018-11-27 18:31:45 +00:00
}
2018-03-29 12:03:13 +01:00
}
2019-11-03 11:33:36 +00:00
if ( Settings . flag . hass_discovery | | ( 1 = = hass_mode ) ) { // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59)
2018-03-29 13:01:38 +01:00
// Send info about relays and lights
2018-11-18 14:33:13 +00:00
HAssAnnounceRelayLight ( ) ;
2018-03-29 13:01:38 +01:00
// Send info about buttons
2018-12-04 20:31:23 +00:00
HAssAnnounceButtons ( ) ;
2018-11-18 14:33:13 +00:00
2018-12-04 20:31:23 +00:00
// Send info about switches
HAssAnnounceSwitches ( ) ;
2018-03-29 12:03:13 +01:00
2018-11-18 14:33:13 +00:00
// Send info about sensors
HAssAnnounceSensors ( ) ;
2019-02-06 19:07:28 +00:00
// Send info about status sensor
HAssAnnounceStatusSensor ( ) ;
2018-03-29 13:01:38 +01:00
}
2018-03-29 12:03:13 +01:00
}
2019-01-22 11:46:55 +00:00
void HAssDiscover ( void )
2018-08-23 15:05:51 +01:00
{
2019-01-22 11:46:55 +00:00
hass_mode = 1 ; // Force discovery
hass_init_step = 1 ; // Delayed discovery
2018-08-23 15:05:51 +01:00
}
2019-10-24 08:47:28 +01:00
void HAssAnyKey ( void )
{
2019-11-03 11:33:36 +00:00
if ( ! Settings . flag . hass_discovery ) { return ; } // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59)
2019-10-24 08:47:28 +01:00
uint32_t key = ( XdrvMailbox . payload > > 16 ) & 0xFF ;
uint32_t device = XdrvMailbox . payload & 0xFF ;
uint32_t state = ( XdrvMailbox . payload > > 8 ) & 0xFF ;
char scommand [ CMDSZ ] ;
snprintf_P ( scommand , sizeof ( scommand ) , PSTR ( " %s%d " ) , ( key ) ? " SWITCH " : " BUTTON " , device ) ;
char stopic [ TOPSZ ] ;
2019-11-15 01:37:30 +00:00
//GetTopic_P(stopic, STAT, mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT); // SetOption4 - Switch between MQTT RESULT or COMMAND
//Response_P(S_JSON_COMMAND_SVALUE, scommand, GetStateText(state));
GetTopic_P ( stopic , STAT , mqtt_topic , scommand ) ;
Response_P ( S_JSON_COMMAND_SVALUE , PSTR ( D_RSLT_STATE ) , GetStateText ( state ) ) ;
2019-10-27 10:13:24 +00:00
MqttPublish ( stopic ) ;
2019-10-24 08:47:28 +01:00
}
2018-01-18 15:19:28 +00:00
/*********************************************************************************************\
* Interface
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019-01-28 13:08:33 +00:00
bool Xdrv12 ( uint8_t function )
2018-01-18 15:19:28 +00:00
{
2019-01-28 13:08:33 +00:00
bool result = false ;
2018-01-18 15:19:28 +00:00
2019-11-03 11:33:36 +00:00
if ( Settings . flag . mqtt_enabled ) { // SetOption3 - Enable MQTT
2018-01-18 15:19:28 +00:00
switch ( function ) {
2019-01-22 11:46:55 +00:00
case FUNC_EVERY_SECOND :
if ( hass_init_step ) {
hass_init_step - - ;
if ( ! hass_init_step ) {
HAssDiscovery ( ) ; // Scheduled discovery using available resources
}
2019-11-03 11:33:36 +00:00
} else if ( Settings . flag . hass_discovery & & Settings . tele_period ) { // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59)
2019-02-06 19:07:28 +00:00
hass_tele_period + + ;
if ( hass_tele_period > = Settings . tele_period ) {
hass_tele_period = 0 ;
mqtt_data [ 0 ] = ' \0 ' ;
HAssPublishStatus ( ) ;
}
2019-01-22 11:46:55 +00:00
}
2018-08-23 15:05:51 +01:00
break ;
2019-10-24 08:47:28 +01:00
case FUNC_ANY_KEY :
HAssAnyKey ( ) ;
break ;
case FUNC_MQTT_INIT :
hass_mode = 0 ; // Discovery only if Settings.flag.hass_discovery is set
hass_init_step = 2 ; // Delayed discovery
break ;
2018-01-18 15:19:28 +00:00
}
}
return result ;
}
# endif // USE_HOME_ASSISTANT