This commit is contained in:
MichaelDvP
2025-12-19 16:53:36 +01:00
14 changed files with 70 additions and 77 deletions

View File

@@ -806,7 +806,7 @@ void AnalogSensor::publish_values(const bool force) {
Mqtt::add_ha_classes(config.as<JsonObject>(), EMSdevice::DeviceType::ANALOGSENSOR, valueType, sensor.uom());
// dev section with model is only created on the 1st sensor
Mqtt::add_ha_dev_section(config.as<JsonObject>(), "Analog Sensors", nullptr, "EMS-ESP", EMSESP_APP_VERSION, !ha_dev_created);
Mqtt::add_ha_dev_section(config.as<JsonObject>(), "Analog Sensors", !ha_dev_created);
Mqtt::add_ha_avty_section(config.as<JsonObject>(), stat_t, val_cond);
sensor.ha_registered = Mqtt::queue_ha(topic, config.as<JsonObject>());

View File

@@ -646,6 +646,8 @@ void EMSESP::reset_mqtt_ha() {
// force the re-creating of the temperature and analog sensor topics (for HA)
temperaturesensor_.reload();
analogsensor_.reload();
// rebuild MQTT HA config topics for shower, custom entities and scheduler
shower_.ha_reset();
webSchedulerService.ha_reset();
webCustomEntityService.ha_reset();

View File

@@ -1106,14 +1106,14 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
// add origin
JsonObject origin_json = doc["o"].to<JsonObject>();
origin_json["name"] = "EMS-ESP";
origin_json["sw"] = EMSESP_APP_VERSION;
origin_json["sw"] = "v" + std::string(EMSESP_APP_VERSION);
origin_json["url"] = "https://emsesp.org";
// add dev section
if (device_type == EMSdevice::DeviceType::SYSTEM) {
add_ha_dev_section(doc.as<JsonObject>(), nullptr, nullptr, nullptr, nullptr, false);
add_ha_dev_section(doc.as<JsonObject>());
} else {
add_ha_dev_section(doc.as<JsonObject>(), EMSdevice::device_type_2_device_name(device_type), model, brand, version, create_device_config);
add_ha_dev_section(doc.as<JsonObject>(), EMSdevice::device_type_2_device_name(device_type), create_device_config, model, brand, version);
}
return queue_ha(topic, doc.as<JsonObject>());
@@ -1414,8 +1414,8 @@ bool Mqtt::publish_ha_climate_config(const DeviceValue & dv, const bool has_room
doc["ic"] = icon;
}
add_ha_dev_section(doc.as<JsonObject>(), devicename, nullptr, nullptr, nullptr, false); // add dev section
add_ha_avty_section(doc.as<JsonObject>(), topic_t, seltemp_cond, has_roomtemp ? currtemp_cond : nullptr, hc_mode_cond); // add availability section
add_ha_dev_section(doc.as<JsonObject>(), devicename);
add_ha_avty_section(doc.as<JsonObject>(), topic_t, seltemp_cond, has_roomtemp ? currtemp_cond : nullptr, hc_mode_cond);
return queue_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
}
@@ -1442,40 +1442,42 @@ std::string Mqtt::tag_to_topic(uint8_t device_type, int8_t tag) {
// add devs section to an existing doc, only for HA
// under devs node it will create ids and name and optional mf, mdl, via_device
// name could be EMSdevice::device_type_2_device_name(dv.device_type));
void Mqtt::add_ha_dev_section(JsonObject doc, const char * name, const char * model, const char * brand, const char * version, const bool create_model) {
void Mqtt::add_ha_dev_section(JsonObject doc, const char * name, const bool create_model, const char * model, const char * brand, const char * version) {
// only works for HA
if (discovery_type() != discoveryType::HOMEASSISTANT) {
return;
}
// create dev section
JsonObject dev_json = doc["dev"].to<JsonObject>();
JsonObject dev_json = doc["dev"].to<JsonObject>(); // create dev section
// add ids and name - capitalize first letter of the name
// add ids - capitalize first letter of the name if there is one
JsonArray ids = dev_json["ids"].to<JsonArray>(); // ids, it is an array with a single element
if (name != nullptr) {
// for ids, replace all spaces with -
// for ids, replace all spaces with - and add to the basename
std::string lower_name_str(name);
std::replace(lower_name_str.begin(), lower_name_str.end(), ' ', '-');
ids.add(Mqtt::basename() + "-" + Helpers::toLower(lower_name_str));
auto cap_name = strdup(name);
Helpers::CharToUpperUTF8(cap_name); // capitalize first letter
dev_json["name"] = Mqtt::basename() + " " + cap_name;
free(cap_name);
} else {
ids.add(Mqtt::basename()); // no name, assign it to the main EMS-ESP device in HA
}
// create the model, manufacturer and version
// create the name, model, manufacturer and version
if (create_model) {
if (name != nullptr) {
auto cap_name = strdup(name);
Helpers::CharToUpperUTF8(cap_name); // capitalize first letter
dev_json["name"] = Mqtt::basename() + " " + cap_name;
free(cap_name);
} else {
dev_json["name"] = Mqtt::basename();
}
// add mf (manufacturer/brand), mdl (model), sw (software version) and via_device
dev_json["mf"] = brand != nullptr ? brand : "EMS-ESP";
if (model != nullptr) {
dev_json["mdl"] = model;
}
if (version != nullptr) {
dev_json["sw"] = version;
}
dev_json["sw"] = version != nullptr ? version : "v" + std::string(EMSESP_APP_VERSION);
dev_json["via_device"] = Mqtt::basename();
}
}

View File

@@ -259,7 +259,12 @@ class Mqtt {
static void
add_ha_classes(JsonObject doc, const uint8_t device_type, const uint8_t type, const uint8_t uom, const char * entity = nullptr, bool is_discovery = true);
static void add_ha_dev_section(JsonObject doc, const char * name, const char * model, const char * brand, const char * version, const bool create_model);
static void add_ha_dev_section(JsonObject doc,
const char * name = nullptr,
const bool create_model = false,
const char * model = nullptr,
const char * brand = nullptr,
const char * version = nullptr);
static void add_ha_avty_section(JsonObject doc,
const char * state_t = nullptr,
const char * cond1 = nullptr,

View File

@@ -210,7 +210,7 @@ void Shower::create_ha_discovery() {
doc["stat_t"] = "~/shower_active";
Mqtt::add_ha_bool(doc.as<JsonObject>());
Mqtt::add_ha_dev_section(doc.as<JsonObject>(), "Shower Sensors", nullptr, nullptr, nullptr, false);
Mqtt::add_ha_dev_section(doc.as<JsonObject>(), "Shower Sensors", true);
Mqtt::add_ha_avty_section(doc.as<JsonObject>()); // no conditions
snprintf(topic, sizeof(topic), "binary_sensor/%s/shower_active/config", Mqtt::basename().c_str());
@@ -239,7 +239,7 @@ void Shower::create_ha_discovery() {
doc["dev_cla"] = "duration";
// doc["ent_cat"] = "diagnostic";
Mqtt::add_ha_dev_section(doc.as<JsonObject>(), "Shower Sensors", nullptr, "EMS-ESP", EMSESP_APP_VERSION, true);
Mqtt::add_ha_dev_section(doc.as<JsonObject>(), "Shower Sensors");
Mqtt::add_ha_avty_section(doc.as<JsonObject>(), "~/shower_data", "value_json.duration is defined");
snprintf(topic, sizeof(topic), "sensor/%s/shower_duration/config", Mqtt::basename().c_str());

View File

@@ -547,7 +547,7 @@ void TemperatureSensor::publish_values(const bool force) {
config["dev_cla"] = "temperature";
// dev section with model is only created on the 1st sensor
Mqtt::add_ha_dev_section(config.as<JsonObject>(), "Temperature Sensors", nullptr, "EMS-ESP", EMSESP_APP_VERSION, !ha_dev_created);
Mqtt::add_ha_dev_section(config.as<JsonObject>(), "Temperature Sensors", !ha_dev_created);
Mqtt::add_ha_avty_section(config.as<JsonObject>(), stat_t, val_cond);
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];