From 33b7dc6023b60a4c2fc996858a0c66d152a6ea0d Mon Sep 17 00:00:00 2001 From: Aleksey Zinchenko Date: Mon, 24 Aug 2026 17:31:01 +0300 Subject: [PATCH] [mqtt] Let Home Assistant discovery be switched at run time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MQTTDiscoveryInfo keeps no separate "enabled" flag — the prefix is the flag (`is_discovery_enabled()` is `!prefix.empty()`), so blanking it to disable discovery throws away the only copy of the configured prefix and nothing can ever turn discovery back on. set_discovery_enabled() closes that gap: set_discovery_info() now also records the prefix it was configured with, and the toggle swaps discovery_info_.prefix between that and "". Nothing else has to change for it to take effect — every publish path re-reads the flag through MQTTComponent::is_discovery_enabled(), called from call_setup() and call_loop(), so the switch lands on the next publish with no reconnect, and resend_discovery() re-announces everything at once when it goes back on. disable_discovery() clears the recorded prefix as well. That is the build-time `discovery: false, discover_ip: false` path, and a firmware that compiled discovery out should stay out — a run-time setting must not resurrect it. No YAML key, like set_enable_on_boot() before it: the only caller is the workspace's jxd_config, which applies the value the user stored in the web UI. Co-Authored-By: Claude Opus 5 (1M context) --- esphome/components/mqtt/mqtt_client.cpp | 6 ++++++ esphome/components/mqtt/mqtt_client.h | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index 6a7d91a02ab3..1cdf704d8394 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -723,6 +723,11 @@ void MQTTClientComponent::set_discovery_info(std::string &&prefix, MQTTDiscovery this->discovery_info_.object_id_generator = object_id_generator; this->discovery_info_.retain = retain; this->discovery_info_.clean = clean; + this->discovery_prefix_configured_ = this->discovery_info_.prefix; +} + +void MQTTClientComponent::set_discovery_enabled(bool enabled) { + this->discovery_info_.prefix = enabled ? this->discovery_prefix_configured_ : ""; } void MQTTClientComponent::disable_last_will() { @@ -739,6 +744,7 @@ void MQTTClientComponent::disable_discovery() { .unique_id_generator = MQTT_LEGACY_UNIQUE_ID_GENERATOR, .object_id_generator = MQTT_NONE_OBJECT_ID_GENERATOR, }; + this->discovery_prefix_configured_ = ""; } void MQTTClientComponent::on_shutdown() { if (!this->shutdown_message_.topic.empty()) { diff --git a/esphome/components/mqtt/mqtt_client.h b/esphome/components/mqtt/mqtt_client.h index fe8f42b0cdec..88d8acb5dc5a 100644 --- a/esphome/components/mqtt/mqtt_client.h +++ b/esphome/components/mqtt/mqtt_client.h @@ -132,6 +132,8 @@ class MQTTClientComponent : public Component { const MQTTDiscoveryInfo &get_discovery_info() const; /// Globally disable Home Assistant discovery. void disable_discovery(); + /// Flip discovery at run time; off keeps the configured prefix so a later on can restore it. + void set_discovery_enabled(bool enabled); bool is_discovery_enabled() const; bool is_discovery_ip_enabled() const; @@ -314,6 +316,8 @@ class MQTTClientComponent : public Component { .unique_id_generator = MQTT_LEGACY_UNIQUE_ID_GENERATOR, .object_id_generator = MQTT_NONE_OBJECT_ID_GENERATOR, }; + /// What set_discovery_enabled(true) restores; empty once discovery is off at build time. + std::string discovery_prefix_configured_{"homeassistant"}; std::string topic_prefix_{}; bool topic_prefix_auto_{true}; bool birth_message_auto_{true};