From 932cddf2c3ccc3ef17babc03676500b26ef7bda4 Mon Sep 17 00:00:00 2001 From: Dusan Cervenka Date: Wed, 5 Feb 2025 17:00:44 +0100 Subject: [PATCH] Fixed topic when mac is used --- esphome/components/mqtt/__init__.py | 10 +++--- esphome/components/mqtt/mqtt_client.cpp | 42 ++++++++++++++++++++++--- esphome/components/mqtt/mqtt_client.h | 10 +++--- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index e1002478a1..eab8290e30 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -36,6 +36,7 @@ from esphome.const import ( CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, CONF_PORT, + CONF_PUBLISH_NAN_AS_NONE, CONF_QOS, CONF_REBOOT_TIMEOUT, CONF_RETAIN, @@ -49,7 +50,6 @@ from esphome.const import ( CONF_USE_ABBREVIATIONS, CONF_USERNAME, CONF_WILL_MESSAGE, - CONF_PUBLISH_NAN_AS_NONE, PLATFORM_BK72XX, PLATFORM_ESP32, PLATFORM_ESP8266, @@ -382,23 +382,23 @@ async def to_code(config): if not birth_message: cg.add(var.disable_birth_message()) else: - cg.add(var.set_birth_message(exp_mqtt_message(birth_message))) + cg.add(var.set_birth_message(exp_mqtt_message(birth_message), CORE.name)) will_message = config[CONF_WILL_MESSAGE] if not will_message: cg.add(var.disable_last_will()) else: - cg.add(var.set_last_will(exp_mqtt_message(will_message))) + cg.add(var.set_last_will(exp_mqtt_message(will_message), CORE.name)) shutdown_message = config[CONF_SHUTDOWN_MESSAGE] if not shutdown_message: cg.add(var.disable_shutdown_message()) else: - cg.add(var.set_shutdown_message(exp_mqtt_message(shutdown_message))) + cg.add(var.set_shutdown_message(exp_mqtt_message(shutdown_message), CORE.name)) log_topic = config[CONF_LOG_TOPIC] if not log_topic: cg.add(var.disable_log_message()) else: - cg.add(var.set_log_message_template(exp_mqtt_message(log_topic))) + cg.add(var.set_log_message_template(exp_mqtt_message(log_topic), CORE.name)) if CONF_LEVEL in log_topic: cg.add(var.set_log_level(logger.LOG_LEVELS[log_topic[CONF_LEVEL]])) diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index 9afa3a588d..3e841d61ba 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -22,6 +22,9 @@ #include "esphome/components/dashboard_import/dashboard_import.h" #endif +#include +#include + namespace esphome { namespace mqtt { @@ -84,6 +87,29 @@ void MQTTClientComponent::setup() { } } +void parse_topic(const std::string &topic, std::string &top_name, std::string &rest) { + std::stringstream ss(topic); + // Extract the first part + if (std::getline(ss, top_name, '/')) { + // Extract the rest of the string + std::getline(ss, rest); // Reads everything after the first '/' + rest = "/" + rest; + } else { + top_name = topic; // If no delimiter, the whole string is the first name + rest = ""; // No rest part + } +} + +void fix_topic(std::string &topic, const std::string &check_topic_prefix) { + if (App.is_name_add_mac_suffix_enabled()) { + std::string top_name(""), rest(""); + parse_topic(topic, top_name, rest); + if (top_name == check_topic_prefix) { + topic = str_sanitize(App.get_name()) + rest; + } + } +} + void MQTTClientComponent::send_device_info_() { if (!this->is_connected() or !this->is_discovery_ip_enabled()) { return; @@ -604,7 +630,10 @@ void MQTTClientComponent::set_reboot_timeout(uint32_t reboot_timeout) { this->re void MQTTClientComponent::register_mqtt_component(MQTTComponent *component) { this->children_.push_back(component); } void MQTTClientComponent::set_log_level(int level) { this->log_level_ = level; } void MQTTClientComponent::set_keep_alive(uint16_t keep_alive_s) { this->mqtt_backend_.set_keep_alive(keep_alive_s); } -void MQTTClientComponent::set_log_message_template(MQTTMessage &&message) { this->log_message_ = std::move(message); } +void MQTTClientComponent::set_log_message_template(MQTTMessage &&message, const std::string &check_topic_prefix) { + this->log_message_ = std::move(message); + fix_topic(this->log_message_.topic, check_topic_prefix); +} const MQTTDiscoveryInfo &MQTTClientComponent::get_discovery_info() const { return this->discovery_info_; } void MQTTClientComponent::set_topic_prefix(const std::string &topic_prefix, const std::string &check_topic_prefix) { if (App.is_name_add_mac_suffix_enabled() && (topic_prefix == check_topic_prefix)) { @@ -639,17 +668,22 @@ void MQTTClientComponent::recalculate_availability_() { this->availability_.payload_not_available = this->last_will_.payload; } -void MQTTClientComponent::set_last_will(MQTTMessage &&message) { +void MQTTClientComponent::set_last_will(MQTTMessage &&message, const std::string &check_topic_prefix) { this->last_will_ = std::move(message); + fix_topic(this->last_will_.topic, check_topic_prefix); this->recalculate_availability_(); } -void MQTTClientComponent::set_birth_message(MQTTMessage &&message) { +void MQTTClientComponent::set_birth_message(MQTTMessage &&message, const std::string &check_topic_prefix) { this->birth_message_ = std::move(message); + fix_topic(this->birth_message_.topic, check_topic_prefix); this->recalculate_availability_(); } -void MQTTClientComponent::set_shutdown_message(MQTTMessage &&message) { this->shutdown_message_ = std::move(message); } +void MQTTClientComponent::set_shutdown_message(MQTTMessage &&message, const std::string &check_topic_prefix) { + this->shutdown_message_ = std::move(message); + fix_topic(this->shutdown_message_.topic, check_topic_prefix); +} void MQTTClientComponent::set_discovery_info(std::string &&prefix, MQTTDiscoveryUniqueIdGenerator unique_id_generator, MQTTDiscoveryObjectIdGenerator object_id_generator, bool retain, diff --git a/esphome/components/mqtt/mqtt_client.h b/esphome/components/mqtt/mqtt_client.h index c68b3c62eb..73fee325f9 100644 --- a/esphome/components/mqtt/mqtt_client.h +++ b/esphome/components/mqtt/mqtt_client.h @@ -101,16 +101,16 @@ class MQTTClientComponent : public Component { MQTTClientComponent(); /// Set the last will testament message. - void set_last_will(MQTTMessage &&message); + void set_last_will(MQTTMessage &&message, const std::string &check_topic_prefix); /// Remove the last will testament message. void disable_last_will(); /// Set the birth message. - void set_birth_message(MQTTMessage &&message); + void set_birth_message(MQTTMessage &&message, const std::string &check_topic_prefix); /// Remove the birth message. void disable_birth_message(); - void set_shutdown_message(MQTTMessage &&message); + void set_shutdown_message(MQTTMessage &&message, const std::string &check_topic_prefix); void disable_shutdown_message(); /// Set the keep alive time in seconds, every 0.7*keep_alive a ping will be sent. @@ -170,7 +170,7 @@ class MQTTClientComponent : public Component { const std::string &get_topic_prefix() const; /// Manually set the topic used for logging. - void set_log_message_template(MQTTMessage &&message); + void set_log_message_template(MQTTMessage &&message, const std::string &check_topic_prefix); void set_log_level(int level); /// Get the topic used for logging. Defaults to "/debug" and the value is cached for speed. void disable_log_message(); @@ -268,6 +268,8 @@ class MQTTClientComponent : public Component { bool is_publish_nan_as_none() const; protected: + void parse_topic(const std::string &topic, std::string &top_name, std::string &rest); + void fix_topic(std::string &topic, const std::string &check_topic_prefix); void send_device_info_(); /// Reconnect to the MQTT broker if not already connected.