From 0a18add4479333b25e19666ee2d3d3f4b478bd50 Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 8 Jul 2025 22:05:45 +0200 Subject: [PATCH] show ems device details in MQTT HA screen --- src/core/analogsensor.cpp | 2 +- src/core/emsdevice.cpp | 9 +++++++-- src/core/emsdevice.h | 1 + src/core/mqtt.cpp | 20 +++++++++++++++----- src/core/mqtt.h | 11 +++++++++-- src/core/shower.cpp | 4 ++-- src/core/temperaturesensor.cpp | 2 +- src/web/WebCustomEntityService.cpp | 2 +- src/web/WebSchedulerService.cpp | 2 +- 9 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/core/analogsensor.cpp b/src/core/analogsensor.cpp index 1a6f01ed4..281cfe1a6 100644 --- a/src/core/analogsensor.cpp +++ b/src/core/analogsensor.cpp @@ -685,7 +685,7 @@ void AnalogSensor::publish_values(const bool force) { } } - Mqtt::add_ha_dev_section(config.as(), "Analog Sensors", nullptr, nullptr, false); + Mqtt::add_ha_dev_section(config.as(), "Analog Sensors", nullptr, nullptr, nullptr, false); Mqtt::add_ha_avail_section(config.as(), stat_t, !is_ha_device_created, val_cond); sensor.ha_registered = Mqtt::queue_ha(topic, config.as()); diff --git a/src/core/emsdevice.cpp b/src/core/emsdevice.cpp index 57f3ef4b8..fe6b8de0a 100644 --- a/src/core/emsdevice.cpp +++ b/src/core/emsdevice.cpp @@ -321,6 +321,11 @@ std::string EMSdevice::to_string() { + ", Version:" + version_ + ")"; } +// returns string of EMS device version and productID +std::string EMSdevice::to_string_version() { + return "DeviceID:" + Helpers::hextoa(device_id_) + " ProductID:" + Helpers::itoa(product_id_) + " Version:" + version_; +} + // returns out brand + device name // translated std::string EMSdevice::to_string_short() { @@ -1221,7 +1226,7 @@ void EMSdevice::setCustomizationEntity(const std::string & entity_id) { if (Mqtt::ha_enabled() && (has_custom_name || ((current_mask ^ new_mask) & (DeviceValueState::DV_READONLY >> 4)))) { // remove ha config on change of dv_readonly flag dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED); - Mqtt::publish_ha_sensor_config_dv(dv, "", "", true); // delete topic (remove = true) + Mqtt::publish_ha_sensor_config_dv(dv, "", "", "", true); // delete topic (remove = true) } // always write the mask @@ -1886,7 +1891,7 @@ void EMSdevice::mqtt_ha_entity_config_create() { if (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) && dv.has_state(DeviceValueState::DV_ACTIVE) && !dv.has_state(DeviceValueState::DV_API_MQTT_EXCLUDE)) { // create_device_config is only done once for the EMS device. It can added to any entity, so we take the first - if (Mqtt::publish_ha_sensor_config_dv(dv, name().c_str(), brand_to_char(), false, create_device_config)) { + if (Mqtt::publish_ha_sensor_config_dv(dv, name().c_str(), brand_to_char(), to_string_version().c_str(), false, create_device_config)) { dv.add_state(DeviceValueState::DV_HA_CONFIG_CREATED); create_device_config = false; // only create the main config once count++; diff --git a/src/core/emsdevice.h b/src/core/emsdevice.h index 74b0dd1aa..f3d7dd0b5 100644 --- a/src/core/emsdevice.h +++ b/src/core/emsdevice.h @@ -62,6 +62,7 @@ class EMSdevice { const char * brand_to_char(); std::string to_string(); std::string to_string_short(); + std::string to_string_version(); std::string name(); // returns either default or custom name of a device (if defined) bool is_device_id(uint8_t device_id) const { diff --git a/src/core/mqtt.cpp b/src/core/mqtt.cpp index 7b2e4701c..54a5262df 100644 --- a/src/core/mqtt.cpp +++ b/src/core/mqtt.cpp @@ -747,7 +747,12 @@ bool Mqtt::queue_ha(const char * topic, const JsonObjectConst payload) { // create's a ha sensor config topic from a device value object (dev) // adds ids, name, mf, mdl, via_device // and also takes a flag (create_device_config) used to also create the main HA device config. This is only needed for one entity -bool Mqtt::publish_ha_sensor_config_dv(DeviceValue & dv, const char * model, const char * brand, const bool remove, const bool create_device_config) { +bool Mqtt::publish_ha_sensor_config_dv(DeviceValue & dv, + const char * model, + const char * brand, + const char * version, + const bool remove, + const bool create_device_config) { // calculate the min and max int16_t dv_set_min; uint32_t dv_set_max; @@ -774,6 +779,7 @@ bool Mqtt::publish_ha_sensor_config_dv(DeviceValue & dv, const char * model, con dv.numeric_operator, model, brand, + version, create_device_config); } @@ -801,6 +807,7 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev const int8_t num_op, const char * const model, const char * const brand, + const char * const version, const bool create_device_config) { // ignore if name (fullname) is empty if (!fullname || !en_name) { @@ -1096,9 +1103,9 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev // add dev section if (device_type == EMSdevice::DeviceType::SYSTEM) { - add_ha_dev_section(doc.as(), nullptr, nullptr, nullptr, false); + add_ha_dev_section(doc.as(), nullptr, nullptr, nullptr, nullptr, false); } else { - add_ha_dev_section(doc.as(), EMSdevice::device_type_2_device_name(device_type), model, brand, create_device_config); + add_ha_dev_section(doc.as(), EMSdevice::device_type_2_device_name(device_type), model, brand, version, create_device_config); } return queue_ha(topic, doc.as()); @@ -1334,7 +1341,7 @@ bool Mqtt::publish_ha_climate_config(const int8_t tag, const bool has_roomtemp, modes.add("heat"); modes.add("off"); - add_ha_dev_section(doc.as(), "thermostat", nullptr, nullptr, false); // add dev section + add_ha_dev_section(doc.as(), "thermostat", nullptr, nullptr, nullptr, false); // add dev section add_ha_avail_section(doc.as(), topic_t, false, seltemp_cond, has_roomtemp ? currtemp_cond : nullptr, hc_mode_cond); // add availability section return queue_ha(topic, doc.as()); // publish the config payload with retain flag @@ -1362,7 +1369,7 @@ 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 bool create_model) { +void Mqtt::add_ha_dev_section(JsonObject doc, const char * name, const char * model, const char * brand, const char * version, const bool create_model) { // only works for HA if (discovery_type() != discoveryType::HOMEASSISTANT) { return; @@ -1394,6 +1401,9 @@ void Mqtt::add_ha_dev_section(JsonObject doc, const char * name, const char * mo if (model != nullptr) { dev_json["mdl"] = model; } + if (version != nullptr) { + dev_json["sw"] = version; + } dev_json["via_device"] = Mqtt::basename(); } } diff --git a/src/core/mqtt.h b/src/core/mqtt.h index 9d936a802..421d38a3d 100644 --- a/src/core/mqtt.h +++ b/src/core/mqtt.h @@ -85,7 +85,13 @@ class Mqtt { static bool queue_ha(const char * topic, const JsonObjectConst payload); static bool queue_remove_topic(const char * topic); - static bool publish_ha_sensor_config_dv(DeviceValue & dv, const char * model, const char * brand, const bool remove, const bool create_device_config = false); + static bool publish_ha_sensor_config_dv(DeviceValue & dv, + const char * model, + const char * brand, + const char * version, + const bool remove, + const bool create_device_config = false); + static bool publish_ha_sensor_config(uint8_t type, int8_t tag, const char * const fullname, @@ -102,6 +108,7 @@ class Mqtt { const int8_t num_op, const char * const model = nullptr, const char * const brand = nullptr, + const char * const version = nullptr, const bool create_device_config = false); static bool publish_system_ha_sensor_config(uint8_t type, const char * name, const char * entity, const uint8_t uom); @@ -247,7 +254,7 @@ 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 bool create_model); + 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_avail_section(JsonObject doc, const char * state_t, const bool is_first, diff --git a/src/core/shower.cpp b/src/core/shower.cpp index 912a6b786..78e9651bf 100644 --- a/src/core/shower.cpp +++ b/src/core/shower.cpp @@ -212,7 +212,7 @@ void Shower::create_ha_discovery() { doc["stat_t"] = stat_t; Mqtt::add_ha_bool(doc.as()); - Mqtt::add_ha_dev_section(doc.as(), "Shower Sensor", nullptr, nullptr, false); + Mqtt::add_ha_dev_section(doc.as(), "Shower Sensor", nullptr, nullptr, nullptr, false); Mqtt::add_ha_avail_section(doc.as(), stat_t, true); // no conditions snprintf(topic, sizeof(topic), "binary_sensor/%s/shower_active/config", Mqtt::basename().c_str()); @@ -243,7 +243,7 @@ void Shower::create_ha_discovery() { doc["dev_cla"] = "duration"; // doc["ent_cat"] = "diagnostic"; - Mqtt::add_ha_dev_section(doc.as(), "Shower Sensor", nullptr, nullptr, false); + Mqtt::add_ha_dev_section(doc.as(), "Shower Sensor", nullptr, nullptr, nullptr, false); Mqtt::add_ha_avail_section(doc.as(), stat_t, false, "value_json.duration is defined"); snprintf(topic, sizeof(topic), "sensor/%s/shower_duration/config", Mqtt::basename().c_str()); diff --git a/src/core/temperaturesensor.cpp b/src/core/temperaturesensor.cpp index 305639786..e7664a1d1 100644 --- a/src/core/temperaturesensor.cpp +++ b/src/core/temperaturesensor.cpp @@ -520,7 +520,7 @@ void TemperatureSensor::publish_values(const bool force) { } } - Mqtt::add_ha_dev_section(config.as(), "Temperature Sensors", nullptr, nullptr, false); + Mqtt::add_ha_dev_section(config.as(), "Temperature Sensors", nullptr, nullptr, nullptr, false); Mqtt::add_ha_avail_section(config.as(), stat_t, !is_ha_device_created, val_cond); char topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; diff --git a/src/web/WebCustomEntityService.cpp b/src/web/WebCustomEntityService.cpp index 2bd4ed86e..4e5aaec4b 100644 --- a/src/web/WebCustomEntityService.cpp +++ b/src/web/WebCustomEntityService.cpp @@ -452,7 +452,7 @@ void WebCustomEntityService::publish(const bool force) { } Mqtt::add_ha_classes(config.as(), EMSdevice::DeviceType::SYSTEM, entityItem.value_type, entityItem.uom); - Mqtt::add_ha_dev_section(config.as(), "Custom Entities", nullptr, nullptr, false); + Mqtt::add_ha_dev_section(config.as(), "Custom Entities", nullptr, nullptr, nullptr, false); Mqtt::add_ha_avail_section(config.as(), stat_t, !ha_created, val_cond); ha_created |= Mqtt::queue_ha(topic, config.as()); diff --git a/src/web/WebSchedulerService.cpp b/src/web/WebSchedulerService.cpp index ef519cc31..d4b923006 100644 --- a/src/web/WebSchedulerService.cpp +++ b/src/web/WebSchedulerService.cpp @@ -288,7 +288,7 @@ void WebSchedulerService::publish(const bool force) { config["cmd_t"] = command_topic; Mqtt::add_ha_bool(config.as()); - Mqtt::add_ha_dev_section(config.as(), F_(scheduler), nullptr, nullptr, false); + Mqtt::add_ha_dev_section(config.as(), F_(scheduler), nullptr, nullptr, nullptr, false); Mqtt::add_ha_avail_section(config.as(), stat_t, !ha_created, val_cond); ha_created |= Mqtt::queue_ha(topic, config.as());