mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 16:29:51 +03:00
use add_ha_sections_to_doc(), add via_device, add check for domoticz
This commit is contained in:
@@ -615,13 +615,7 @@ void AnalogSensor::publish_values(const bool force) {
|
|||||||
config["stat_cla"] = "measurement";
|
config["stat_cla"] = "measurement";
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject dev = config.createNestedObject("dev");
|
Mqtt::add_ha_sections_to_doc("analog", stat_t, config.as<JsonObject>(), true, val_cond);
|
||||||
dev["name"] = Mqtt::basename() + " Analog";
|
|
||||||
JsonArray ids = dev.createNestedArray("ids");
|
|
||||||
ids.add(Mqtt::basename() + "-analog");
|
|
||||||
|
|
||||||
// add "availability" section
|
|
||||||
Mqtt::add_avty_to_doc(stat_t, config.as<JsonObject>(), val_cond);
|
|
||||||
|
|
||||||
sensor.ha_registered = Mqtt::queue_ha(topic, config.as<JsonObject>());
|
sensor.ha_registered = Mqtt::queue_ha(topic, config.as<JsonObject>());
|
||||||
}
|
}
|
||||||
|
|||||||
109
src/mqtt.cpp
109
src/mqtt.cpp
@@ -542,7 +542,7 @@ void Mqtt::ha_status() {
|
|||||||
JsonObject dev = doc.createNestedObject("dev");
|
JsonObject dev = doc.createNestedObject("dev");
|
||||||
dev["name"] = Mqtt::basename();
|
dev["name"] = Mqtt::basename();
|
||||||
dev["sw"] = "v" + std::string(EMSESP_APP_VERSION);
|
dev["sw"] = "v" + std::string(EMSESP_APP_VERSION);
|
||||||
dev["mf"] = "proddy";
|
dev["mf"] = "EMS-ESP";
|
||||||
dev["mdl"] = "EMS-ESP";
|
dev["mdl"] = "EMS-ESP";
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
dev["cu"] = "http://" + (EMSESP::system_.ethernet_connected() ? ETH.localIP().toString() : WiFi.localIP().toString());
|
dev["cu"] = "http://" + (EMSESP::system_.ethernet_connected() ? ETH.localIP().toString() : WiFi.localIP().toString());
|
||||||
@@ -739,10 +739,11 @@ bool Mqtt::publish_ha_sensor_config(DeviceValue & dv, const char * model, const
|
|||||||
dev_json["name"] = Mqtt::basename() + " " + cap_name;
|
dev_json["name"] = Mqtt::basename() + " " + cap_name;
|
||||||
free(cap_name);
|
free(cap_name);
|
||||||
|
|
||||||
|
// create only once per category
|
||||||
if (create_device_config) {
|
if (create_device_config) {
|
||||||
dev_json["mf"] = brand;
|
dev_json["mf"] = brand;
|
||||||
dev_json["mdl"] = model;
|
dev_json["mdl"] = model;
|
||||||
dev_json["via_device"] = "ems-esp";
|
dev_json["via_device"] = Mqtt::basename();
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate the min and max
|
// calculate the min and max
|
||||||
@@ -1136,8 +1137,8 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
doc["dev"] = dev_json; // add the dev json object to the end
|
doc["dev"] = dev_json; // add the dev json object to the end
|
||||||
add_avty_to_doc(stat_t, doc.as<JsonObject>(), val_cond); // add "availability" section
|
add_ha_sections_to_doc("", stat_t, doc.as<JsonObject>(), false, val_cond); // no name, since the "dev" has already been added
|
||||||
|
|
||||||
return queue_ha(topic, doc.as<JsonObject>());
|
return queue_ha(topic, doc.as<JsonObject>());
|
||||||
}
|
}
|
||||||
@@ -1245,18 +1246,8 @@ bool Mqtt::publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp,
|
|||||||
modes.add("heat");
|
modes.add("heat");
|
||||||
modes.add("off");
|
modes.add("off");
|
||||||
|
|
||||||
JsonObject dev = doc.createNestedObject("dev");
|
|
||||||
JsonArray ids = dev.createNestedArray("ids");
|
|
||||||
|
|
||||||
char ha_device[40];
|
|
||||||
snprintf(ha_device, sizeof(ha_device), "%s-thermostat", Mqtt::basename().c_str());
|
|
||||||
ids.add(ha_device);
|
|
||||||
|
|
||||||
// device name must be different to the entity name, take the ids value we just created
|
// device name must be different to the entity name, take the ids value we just created
|
||||||
dev["name"] = ha_device;
|
add_ha_sections_to_doc("thermostat", topic_t, doc.as<JsonObject>(), false, seltemp_cond, has_roomtemp ? currtemp_cond : nullptr, hc_mode_cond);
|
||||||
|
|
||||||
// add "availability" section
|
|
||||||
add_avty_to_doc(topic_t, doc.as<JsonObject>(), seltemp_cond, has_roomtemp ? currtemp_cond : nullptr, hc_mode_cond);
|
|
||||||
|
|
||||||
return queue_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
return queue_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
||||||
}
|
}
|
||||||
@@ -1280,42 +1271,68 @@ std::string Mqtt::tag_to_topic(uint8_t device_type, uint8_t tag) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// adds "availability" section to HA Discovery config
|
// adds availability, dev, ids to the config section to HA Discovery config
|
||||||
void Mqtt::add_avty_to_doc(const char * state_t, const JsonObject & doc, const char * cond1, const char * cond2, const char * negcond) {
|
void Mqtt::add_ha_sections_to_doc(const std::string & name,
|
||||||
const char * tpl_draft = "{{'online' if %s else 'offline'}}";
|
const char * state_t,
|
||||||
char tpl[150];
|
const JsonObject & config,
|
||||||
JsonArray avty = doc.createNestedArray("avty");
|
const bool is_first,
|
||||||
|
const char * cond1,
|
||||||
StaticJsonDocument<512> avty_json;
|
const char * cond2,
|
||||||
|
const char * negcond) {
|
||||||
snprintf(tpl, sizeof(tpl), "%s/status", Mqtt::base().c_str());
|
// adds dev section to HA Discovery config
|
||||||
avty_json["t"] = tpl;
|
if (!name.empty()) {
|
||||||
snprintf(tpl, sizeof(tpl), tpl_draft, "value == 'online'");
|
JsonObject dev = config.createNestedObject("dev");
|
||||||
avty_json["val_tpl"] = tpl;
|
auto cap_name = name;
|
||||||
avty.add(avty_json);
|
cap_name[0] = toupper(name[0]); // capitalize first letter
|
||||||
avty_json.clear();
|
dev["name"] = Mqtt::basename() + " " + cap_name;
|
||||||
avty_json["t"] = state_t;
|
// if it's the first in the category, attach the group to the main HA device
|
||||||
snprintf(tpl, sizeof(tpl), tpl_draft, cond1 == nullptr ? "value is defined" : cond1);
|
if (is_first) {
|
||||||
avty_json["val_tpl"] = tpl;
|
dev["mf"] = "EMS-ESP";
|
||||||
avty.add(avty_json);
|
dev["mdl"] = cap_name;
|
||||||
|
dev["via_device"] = Mqtt::basename();
|
||||||
if (cond2 != nullptr) {
|
}
|
||||||
avty_json.clear();
|
JsonArray ids = dev.createNestedArray("ids");
|
||||||
avty_json["t"] = state_t;
|
ids.add(Mqtt::basename() + "-" + Helpers::toLower(name));
|
||||||
snprintf(tpl, sizeof(tpl), tpl_draft, cond2);
|
|
||||||
avty_json["val_tpl"] = tpl;
|
|
||||||
avty.add(avty_json);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (negcond != nullptr) {
|
// adds "availability" section to HA Discovery config
|
||||||
avty_json.clear();
|
// but not for Domoticz
|
||||||
avty_json["t"] = state_t;
|
if (discovery_type() == discoveryType::HOMEASSISTANT) {
|
||||||
snprintf(tpl, sizeof(tpl), "{{'offline' if %s else 'online'}}", negcond);
|
const char * tpl_draft = "{{'online' if %s else 'offline'}}";
|
||||||
|
char tpl[150];
|
||||||
|
JsonArray avty = config.createNestedArray("avty");
|
||||||
|
|
||||||
|
StaticJsonDocument<512> avty_json;
|
||||||
|
|
||||||
|
snprintf(tpl, sizeof(tpl), "%s/status", Mqtt::base().c_str());
|
||||||
|
avty_json["t"] = tpl;
|
||||||
|
snprintf(tpl, sizeof(tpl), tpl_draft, "value == 'online'");
|
||||||
|
avty_json["val_tpl"] = tpl;
|
||||||
|
avty.add(avty_json);
|
||||||
|
avty_json.clear();
|
||||||
|
avty_json["t"] = state_t;
|
||||||
|
snprintf(tpl, sizeof(tpl), tpl_draft, cond1 == nullptr ? "value is defined" : cond1);
|
||||||
avty_json["val_tpl"] = tpl;
|
avty_json["val_tpl"] = tpl;
|
||||||
avty.add(avty_json);
|
avty.add(avty_json);
|
||||||
}
|
|
||||||
|
|
||||||
doc["avty_mode"] = "all";
|
if (cond2 != nullptr) {
|
||||||
|
avty_json.clear();
|
||||||
|
avty_json["t"] = state_t;
|
||||||
|
snprintf(tpl, sizeof(tpl), tpl_draft, cond2);
|
||||||
|
avty_json["val_tpl"] = tpl;
|
||||||
|
avty.add(avty_json);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (negcond != nullptr) {
|
||||||
|
avty_json.clear();
|
||||||
|
avty_json["t"] = state_t;
|
||||||
|
snprintf(tpl, sizeof(tpl), "{{'offline' if %s else 'online'}}", negcond);
|
||||||
|
avty_json["val_tpl"] = tpl;
|
||||||
|
avty.add(avty_json);
|
||||||
|
}
|
||||||
|
|
||||||
|
config["avty_mode"] = "all";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
@@ -217,8 +217,13 @@ class Mqtt {
|
|||||||
|
|
||||||
static std::string tag_to_topic(uint8_t device_type, uint8_t tag);
|
static std::string tag_to_topic(uint8_t device_type, uint8_t tag);
|
||||||
|
|
||||||
static void
|
static void add_ha_sections_to_doc(const std::string & name,
|
||||||
add_avty_to_doc(const char * state_t, const JsonObject & doc, const char * cond1 = nullptr, const char * cond2 = nullptr, const char * negcond = nullptr);
|
const char * state_t,
|
||||||
|
const JsonObject & doc,
|
||||||
|
const bool is_first = false,
|
||||||
|
const char * cond1 = nullptr,
|
||||||
|
const char * cond2 = nullptr,
|
||||||
|
const char * negcond = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static uuid::log::Logger logger_;
|
static uuid::log::Logger logger_;
|
||||||
|
|||||||
@@ -210,12 +210,7 @@ void Shower::set_shower_state(bool state, bool force) {
|
|||||||
doc["pl_off"] = Helpers::render_boolean(result, false);
|
doc["pl_off"] = Helpers::render_boolean(result, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject dev = doc.createNestedObject("dev");
|
Mqtt::add_ha_sections_to_doc("shower", stat_t, doc.as<JsonObject>(), true);
|
||||||
dev["name"] = "EMS-ESP Shower";
|
|
||||||
JsonArray ids = dev.createNestedArray("ids");
|
|
||||||
ids.add(Mqtt::basename() + "-shower");
|
|
||||||
|
|
||||||
Mqtt::add_avty_to_doc(stat_t, doc.as<JsonObject>()); // add "availability" section
|
|
||||||
|
|
||||||
snprintf(topic, sizeof(topic), "binary_sensor/%s/shower_active/config", Mqtt::basename().c_str());
|
snprintf(topic, sizeof(topic), "binary_sensor/%s/shower_active/config", Mqtt::basename().c_str());
|
||||||
ha_configdone_ = Mqtt::queue_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
ha_configdone_ = Mqtt::queue_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
||||||
@@ -240,12 +235,7 @@ void Shower::set_shower_state(bool state, bool force) {
|
|||||||
doc["dev_cla"] = "duration";
|
doc["dev_cla"] = "duration";
|
||||||
// doc["ent_cat"] = "diagnostic";
|
// doc["ent_cat"] = "diagnostic";
|
||||||
|
|
||||||
JsonObject dev2 = doc.createNestedObject("dev");
|
Mqtt::add_ha_sections_to_doc("shower", stat_t, doc.as<JsonObject>(), "value_json.duration is defined");
|
||||||
dev2["name"] = "EMS-ESP Shower";
|
|
||||||
JsonArray ids2 = dev2.createNestedArray("ids");
|
|
||||||
ids2.add(Mqtt::basename() + "-shower");
|
|
||||||
|
|
||||||
Mqtt::add_avty_to_doc(stat_t, doc.as<JsonObject>(), "value_json.duration is defined"); // add "availability" section
|
|
||||||
|
|
||||||
snprintf(topic, sizeof(topic), "sensor/%s/shower_duration/config", Mqtt::basename().c_str());
|
snprintf(topic, sizeof(topic), "sensor/%s/shower_duration/config", Mqtt::basename().c_str());
|
||||||
Mqtt::queue_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
Mqtt::queue_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
||||||
@@ -267,12 +257,7 @@ void Shower::set_shower_state(bool state, bool force) {
|
|||||||
doc["val_tpl"] = "{{value_json.timestamp if value_json.timestamp is defined else 0}}";
|
doc["val_tpl"] = "{{value_json.timestamp if value_json.timestamp is defined else 0}}";
|
||||||
// doc["ent_cat"] = "diagnostic";
|
// doc["ent_cat"] = "diagnostic";
|
||||||
|
|
||||||
JsonObject dev3 = doc.createNestedObject("dev");
|
Mqtt::add_ha_sections_to_doc("shower", stat_t, doc.as<JsonObject>(), "value_json.timestamp is defined");
|
||||||
dev3["name"] = "EMS-ESP Shower";
|
|
||||||
JsonArray ids3 = dev3.createNestedArray("ids");
|
|
||||||
ids3.add(Mqtt::basename() + "-shower");
|
|
||||||
|
|
||||||
Mqtt::add_avty_to_doc(stat_t, doc.as<JsonObject>(), "value_json.timestamp is defined"); // add "availability" section
|
|
||||||
|
|
||||||
snprintf(topic, sizeof(topic), "sensor/%s/shower_timestamp/config", Mqtt::basename().c_str());
|
snprintf(topic, sizeof(topic), "sensor/%s/shower_timestamp/config", Mqtt::basename().c_str());
|
||||||
Mqtt::queue_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
Mqtt::queue_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
||||||
|
|||||||
@@ -527,7 +527,14 @@ void TemperatureSensor::publish_values(const bool force) {
|
|||||||
snprintf(val_obj, sizeof(val_obj), "value_json['%s']", sensor.name().c_str());
|
snprintf(val_obj, sizeof(val_obj), "value_json['%s']", sensor.name().c_str());
|
||||||
snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj);
|
snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj);
|
||||||
}
|
}
|
||||||
config["val_tpl"] = (std::string) "{{" + val_obj + " if " + val_cond + " else -55}}";
|
|
||||||
|
// for the value template, there's a problem still with Domoticz probably due to the special characters.
|
||||||
|
// See https://github.com/emsesp/EMS-ESP32/issues/1360
|
||||||
|
if (Mqtt::discovery_type() == Mqtt::discoveryType::DOMOTICZ) {
|
||||||
|
config["val_tpl"] = (std::string) "{{" + val_obj + "}}";
|
||||||
|
} else {
|
||||||
|
config["val_tpl"] = (std::string) "{{" + val_obj + " if " + val_cond + " else -55}}";
|
||||||
|
}
|
||||||
|
|
||||||
char uniq_s[70];
|
char uniq_s[70];
|
||||||
if (Mqtt::entity_format() == Mqtt::entityFormat::MULTI_SHORT) {
|
if (Mqtt::entity_format() == Mqtt::entityFormat::MULTI_SHORT) {
|
||||||
@@ -543,13 +550,7 @@ void TemperatureSensor::publish_values(const bool force) {
|
|||||||
snprintf(name, sizeof(name), "%s", sensor.name().c_str());
|
snprintf(name, sizeof(name), "%s", sensor.name().c_str());
|
||||||
config["name"] = name;
|
config["name"] = name;
|
||||||
|
|
||||||
JsonObject dev = config.createNestedObject("dev");
|
Mqtt::add_ha_sections_to_doc("temperature", stat_t, config.as<JsonObject>(), true, val_cond);
|
||||||
dev["name"] = Mqtt::basename() + " Temperature";
|
|
||||||
JsonArray ids = dev.createNestedArray("ids");
|
|
||||||
ids.add(Mqtt::basename() + "-temperature");
|
|
||||||
|
|
||||||
// add "availability" section
|
|
||||||
Mqtt::add_avty_to_doc(stat_t, config.as<JsonObject>(), val_cond);
|
|
||||||
|
|
||||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
// use '_' as HA doesn't like '-' in the topic name
|
// use '_' as HA doesn't like '-' in the topic name
|
||||||
|
|||||||
@@ -426,13 +426,8 @@ void WebCustomEntityService::publish(const bool force) {
|
|||||||
config["pl_off"] = Helpers::render_boolean(result, false);
|
config["pl_off"] = Helpers::render_boolean(result, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
JsonObject dev = config.createNestedObject("dev");
|
Mqtt::add_ha_sections_to_doc("custom", stat_t, config.as<JsonObject>(), true, val_cond);
|
||||||
dev["name"] = Mqtt::basename() + " Custom";
|
|
||||||
JsonArray ids = dev.createNestedArray("ids");
|
|
||||||
ids.add(Mqtt::basename() + "-custom");
|
|
||||||
|
|
||||||
// add "availability" section
|
|
||||||
Mqtt::add_avty_to_doc(stat_t, config.as<JsonObject>(), val_cond);
|
|
||||||
ha_created |= Mqtt::queue_ha(topic, config.as<JsonObject>());
|
ha_created |= Mqtt::queue_ha(topic, config.as<JsonObject>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -287,13 +287,8 @@ void WebSchedulerService::publish(const bool force) {
|
|||||||
config["pl_off"] = Helpers::render_boolean(result, false);
|
config["pl_off"] = Helpers::render_boolean(result, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject dev = config.createNestedObject("dev");
|
Mqtt::add_ha_sections_to_doc("scheduler", stat_t, config.as<JsonObject>(), true, val_cond);
|
||||||
dev["name"] = Mqtt::basename() + " Scheduler";
|
|
||||||
JsonArray ids = dev.createNestedArray("ids");
|
|
||||||
ids.add(Mqtt::basename() + "-scheduler");
|
|
||||||
|
|
||||||
// add "availability" section
|
|
||||||
Mqtt::add_avty_to_doc(stat_t, config.as<JsonObject>(), val_cond);
|
|
||||||
ha_created |= Mqtt::queue_ha(topic, config.as<JsonObject>());
|
ha_created |= Mqtt::queue_ha(topic, config.as<JsonObject>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user