mirror of https://github.com/arendst/Tasmota.git
Merge pull request #4380 from emontnemery/hass_announce_dht_sensor
Add support for sensor discovery
This commit is contained in:
commit
29f46c5804
|
@ -455,13 +455,15 @@ void RulesEvery50ms(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t rules_xsns_index = 0;
|
||||||
|
|
||||||
void RulesEvery100ms(void)
|
void RulesEvery100ms(void)
|
||||||
{
|
{
|
||||||
if (Settings.rule_enabled && (uptime > 4)) { // Any rule enabled and allow 4 seconds start-up time for sensors (#3811)
|
if (Settings.rule_enabled && (uptime > 4)) { // Any rule enabled and allow 4 seconds start-up time for sensors (#3811)
|
||||||
mqtt_data[0] = '\0';
|
mqtt_data[0] = '\0';
|
||||||
int tele_period_save = tele_period;
|
int tele_period_save = tele_period;
|
||||||
tele_period = 2; // Do not allow HA updates during next function call
|
tele_period = 2; // Do not allow HA updates during next function call
|
||||||
XsnsNextCall(FUNC_JSON_APPEND); // ,"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089}
|
XsnsNextCall(FUNC_JSON_APPEND, rules_xsns_index); // ,"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089}
|
||||||
tele_period = tele_period_save;
|
tele_period = tele_period_save;
|
||||||
if (strlen(mqtt_data)) {
|
if (strlen(mqtt_data)) {
|
||||||
mqtt_data[0] = '{'; // {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089}
|
mqtt_data[0] = '{'; // {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089}
|
||||||
|
|
|
@ -62,6 +62,25 @@ const char HASS_DISCOVER_LIGHT_CT[] PROGMEM =
|
||||||
"\"color_temp_state_topic\":\"%s\"," // stat/led2/RESULT
|
"\"color_temp_state_topic\":\"%s\"," // stat/led2/RESULT
|
||||||
"\"color_temp_value_template\":\"{{value_json." D_CMND_COLORTEMPERATURE "}}\"";
|
"\"color_temp_value_template\":\"{{value_json." D_CMND_COLORTEMPERATURE "}}\"";
|
||||||
|
|
||||||
|
const char HASS_DISCOVER_SENSOR[] PROGMEM =
|
||||||
|
"{\"name\":\"%s\"," // dualr2 1 BTN
|
||||||
|
"\"state_topic\":\"%s\"," // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",")
|
||||||
|
"\"availability_topic\":\"%s\"," // tele/dualr2/LWT
|
||||||
|
"\"payload_available\":\"" D_ONLINE "\"," // Online
|
||||||
|
"\"payload_not_available\":\"" D_OFFLINE "\""; // Offline
|
||||||
|
|
||||||
|
const char HASS_DISCOVER_SENSOR_TEMP[] PROGMEM =
|
||||||
|
"%s,\"unit_of_measurement\":\"°%c\"," // °C / °F
|
||||||
|
"\"value_template\":\"{{value_json['%s'].Temperature}}\""; // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Temperature }}
|
||||||
|
|
||||||
|
const char HASS_DISCOVER_SENSOR_HUM[] PROGMEM =
|
||||||
|
"%s,\"unit_of_measurement\":\"%%\"," // %
|
||||||
|
"\"value_template\":\"{{value_json['%s'].Humidity}}\"," // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Humidity }}
|
||||||
|
"\"device_class\":\"humidity\""; // temperature / humidity
|
||||||
|
|
||||||
|
const char HASS_DISCOVER_SENSOR_ANY[] PROGMEM =
|
||||||
|
"%s,\"value_template\":\"{{value_json['%s'].%s}}\""; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }}
|
||||||
|
|
||||||
const char HASS_DISCOVER_RELAY_SHORT[] PROGMEM =
|
const char HASS_DISCOVER_RELAY_SHORT[] PROGMEM =
|
||||||
"{\"name\":\"%s\"," // dualr2 1
|
"{\"name\":\"%s\"," // dualr2 1
|
||||||
"\"cmd_t\":\"%s\"," // cmnd/dualr2/POWER2
|
"\"cmd_t\":\"%s\"," // cmnd/dualr2/POWER2
|
||||||
|
@ -109,6 +128,26 @@ const char HASS_DISCOVER_LIGHT_SCHEME[] PROGMEM =
|
||||||
"\"effect_value_template\":\"{{value_json." D_CMND_SCHEME "}}\","
|
"\"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
|
"\"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
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const char HASS_DISCOVER_SENSOR_SHORT[] PROGMEM =
|
||||||
|
"{\"name\":\"%s\"," // dualr2 1 BTN
|
||||||
|
"\"stat_t\":\"%s\"," // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",")
|
||||||
|
"\"avty_t\":\"%s\"," // tele/dualr2/LWT
|
||||||
|
"\"pl_avail\":\"" D_ONLINE "\"," // Online
|
||||||
|
"\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline
|
||||||
|
|
||||||
|
const char HASS_DISCOVER_SENSOR_TEMP_SHORT[] PROGMEM =
|
||||||
|
"%s,\"unit_of_meas\":\"°%c\"," // °C / °F
|
||||||
|
"\"val_tpl\":\"{{value_json['%s'].Temperature}}\""; // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Temperature }}
|
||||||
|
|
||||||
|
const char HASS_DISCOVER_SENSOR_HUM_SHORT[] PROGMEM =
|
||||||
|
"%s,\"unit_of_meas\":\"%%\"," // %
|
||||||
|
"\"val_tpl\":\"{{value_json['%s'].Humidity}}\"," // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Humidity }}
|
||||||
|
"\"dev_cla\":\"humidity\""; // humidity
|
||||||
|
|
||||||
|
const char HASS_DISCOVER_SENSOR_ANY_SHORT[] PROGMEM =
|
||||||
|
"%s,\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }}
|
||||||
|
|
||||||
const char HASS_DISCOVER_TOPIC_PREFIX[] PROGMEM =
|
const char HASS_DISCOVER_TOPIC_PREFIX[] PROGMEM =
|
||||||
"%s, \"~\":\"%s\"";
|
"%s, \"~\":\"%s\"";
|
||||||
|
|
||||||
|
@ -132,7 +171,7 @@ static void Shorten(char** s, char *prefix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HAssDiscoverRelay(void)
|
void HAssAnnounceRelayLight(void)
|
||||||
{
|
{
|
||||||
char sidx[8];
|
char sidx[8];
|
||||||
char stopic[TOPSZ];
|
char stopic[TOPSZ];
|
||||||
|
@ -226,7 +265,7 @@ void HAssDiscoverRelay(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HAssDiscoverButton(void)
|
void HAssAnnounceButton(void)
|
||||||
{
|
{
|
||||||
char sidx[8];
|
char sidx[8];
|
||||||
char stopic[TOPSZ];
|
char stopic[TOPSZ];
|
||||||
|
@ -287,6 +326,92 @@ void HAssDiscoverButton(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HAssAnnounceSensor(const char* sensorname, const char* subsensortype)
|
||||||
|
{
|
||||||
|
char stopic[TOPSZ];
|
||||||
|
|
||||||
|
// Announce sensor, special handling of temperature and humidity sensors
|
||||||
|
mqtt_data[0] = '\0'; // Clear retained message
|
||||||
|
|
||||||
|
// Clear or Set topic
|
||||||
|
snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s_%s_%s/config"),
|
||||||
|
mqtt_topic, sensorname, subsensortype);
|
||||||
|
|
||||||
|
if (Settings.flag.hass_discovery) {
|
||||||
|
char name[33];
|
||||||
|
char _state_topic[TOPSZ];
|
||||||
|
char _availability_topic[TOPSZ];
|
||||||
|
char prefix[TOPSZ];
|
||||||
|
char *state_topic = _state_topic;
|
||||||
|
char *availability_topic = _availability_topic;
|
||||||
|
|
||||||
|
snprintf_P(name, sizeof(name), PSTR("%s %s %s"), Settings.friendlyname[0], sensorname, subsensortype);
|
||||||
|
GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_SENSOR));
|
||||||
|
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_SENSOR_SHORT:HASS_DISCOVER_SENSOR,
|
||||||
|
name, state_topic, availability_topic);
|
||||||
|
if (!strcmp(subsensortype, "Temperature")) {
|
||||||
|
snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_TEMP_SHORT:HASS_DISCOVER_SENSOR_TEMP,
|
||||||
|
mqtt_data, TempUnit(), sensorname);
|
||||||
|
} else if (!strcmp(subsensortype, "Humidity")) {
|
||||||
|
snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_HUM_SHORT:HASS_DISCOVER_SENSOR_HUM,
|
||||||
|
mqtt_data, sensorname);
|
||||||
|
} else {
|
||||||
|
snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_ANY_SHORT:HASS_DISCOVER_SENSOR_ANY,
|
||||||
|
mqtt_data, sensorname, subsensortype);
|
||||||
|
}
|
||||||
|
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 HAssAnnounceSensors(void)
|
||||||
|
{
|
||||||
|
uint8_t hass_xsns_index = 0;
|
||||||
|
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;
|
||||||
|
|
||||||
|
char sensordata[256]; // Copy because we need to write to mqtt_data
|
||||||
|
strlcpy(sensordata, mqtt_data, sizeof(sensordata));
|
||||||
|
|
||||||
|
if (strlen(sensordata)) {
|
||||||
|
sensordata[0] = '{'; // {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089}
|
||||||
|
snprintf_P(sensordata, sizeof(sensordata), PSTR("%s}"), sensordata);
|
||||||
|
|
||||||
|
StaticJsonBuffer<256> jsonBuffer;
|
||||||
|
JsonObject& root = jsonBuffer.parseObject(sensordata);
|
||||||
|
if (!root.success()) {
|
||||||
|
snprintf_P(log_data, sizeof(log_data), PSTR("HASS: failed to parse '%s'"), sensordata);
|
||||||
|
AddLog(LOG_LEVEL_ERROR);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (auto sensor : root) {
|
||||||
|
const char* sensorname = sensor.key;
|
||||||
|
JsonObject& sensors = sensor.value.as<JsonObject>();
|
||||||
|
if (!sensors.success()) {
|
||||||
|
snprintf_P(log_data, sizeof(log_data), PSTR("HASS: failed to parse '%s'"), sensordata);
|
||||||
|
AddLog(LOG_LEVEL_ERROR);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (auto subsensor : sensors) {
|
||||||
|
HAssAnnounceSensor(sensorname, subsensor.key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (hass_xsns_index != 0);
|
||||||
|
}
|
||||||
|
|
||||||
static int string_ends_with(const char * str, const char * suffix)
|
static int string_ends_with(const char * str, const char * suffix)
|
||||||
{
|
{
|
||||||
int str_len = strlen(str);
|
int str_len = strlen(str);
|
||||||
|
@ -308,12 +433,15 @@ void HAssDiscovery(uint8_t mode)
|
||||||
|
|
||||||
if (Settings.flag.hass_discovery || (1 == mode)) {
|
if (Settings.flag.hass_discovery || (1 == mode)) {
|
||||||
// Send info about relays and lights
|
// Send info about relays and lights
|
||||||
HAssDiscoverRelay();
|
HAssAnnounceRelayLight();
|
||||||
|
|
||||||
// Send info about buttons
|
// Send info about buttons
|
||||||
HAssDiscoverButton();
|
HAssAnnounceButton();
|
||||||
|
|
||||||
// TODO: Send info about switches
|
// TODO: Send info about switches
|
||||||
|
|
||||||
// TODO: Send info about sensors
|
// Send info about sensors
|
||||||
|
HAssAnnounceSensors();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -263,13 +263,12 @@ boolean (* const xsns_func_ptr[])(byte) = { // Sensor Function Pointers for sim
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint8_t xsns_present = sizeof(xsns_func_ptr) / sizeof(xsns_func_ptr[0]); // Number of External Sensors found
|
const uint8_t xsns_present = sizeof(xsns_func_ptr) / sizeof(xsns_func_ptr[0]); // Number of External Sensors found
|
||||||
uint8_t xsns_index = 0;
|
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Function call to all xsns
|
* Function call to all xsns
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
boolean XsnsNextCall(byte Function)
|
boolean XsnsNextCall(byte Function, uint8_t &xsns_index)
|
||||||
{
|
{
|
||||||
|
|
||||||
xsns_index++;
|
xsns_index++;
|
||||||
|
|
Loading…
Reference in New Issue