From 9826726a72624f78bfb77fec7656e1474ef2158b Mon Sep 17 00:00:00 2001 From: Andrej Komelj Date: Tue, 8 Feb 2022 10:58:38 +0100 Subject: [PATCH] Implement MQTT discovery object_id generator (#3114) --- esphome/components/mqtt/__init__.py | 22 ++++++++++++++++++++-- esphome/components/mqtt/mqtt_client.cpp | 4 +++- esphome/components/mqtt/mqtt_client.h | 12 ++++++++++-- esphome/components/mqtt/mqtt_component.cpp | 7 +++++-- esphome/components/mqtt/mqtt_const.h | 2 ++ esphome/const.py | 1 + 6 files changed, 41 insertions(+), 7 deletions(-) diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index 88e5d43509..901b77474d 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -16,6 +16,7 @@ from esphome.const import ( CONF_DISCOVERY_PREFIX, CONF_DISCOVERY_RETAIN, CONF_DISCOVERY_UNIQUE_ID_GENERATOR, + CONF_DISCOVERY_OBJECT_ID_GENERATOR, CONF_ID, CONF_KEEPALIVE, CONF_LEVEL, @@ -105,6 +106,12 @@ MQTT_DISCOVERY_UNIQUE_ID_GENERATOR_OPTIONS = { "mac": MQTTDiscoveryUniqueIdGenerator.MQTT_MAC_ADDRESS_UNIQUE_ID_GENERATOR, } +MQTTDiscoveryObjectIdGenerator = mqtt_ns.enum("MQTTDiscoveryObjectIdGenerator") +MQTT_DISCOVERY_OBJECT_ID_GENERATOR_OPTIONS = { + "none": MQTTDiscoveryObjectIdGenerator.MQTT_NONE_OBJECT_ID_GENERATOR, + "device_name": MQTTDiscoveryObjectIdGenerator.MQTT_DEVICE_NAME_OBJECT_ID_GENERATOR, +} + def validate_config(value): # Populate default fields @@ -166,6 +173,9 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_DISCOVERY_UNIQUE_ID_GENERATOR, default="legacy"): cv.enum( MQTT_DISCOVERY_UNIQUE_ID_GENERATOR_OPTIONS ), + cv.Optional(CONF_DISCOVERY_OBJECT_ID_GENERATOR, default="none"): cv.enum( + MQTT_DISCOVERY_OBJECT_ID_GENERATOR_OPTIONS + ), cv.Optional(CONF_USE_ABBREVIATIONS, default=True): cv.boolean, cv.Optional(CONF_BIRTH_MESSAGE): MQTT_MESSAGE_SCHEMA, cv.Optional(CONF_WILL_MESSAGE): MQTT_MESSAGE_SCHEMA, @@ -245,19 +255,27 @@ async def to_code(config): discovery_retain = config[CONF_DISCOVERY_RETAIN] discovery_prefix = config[CONF_DISCOVERY_PREFIX] discovery_unique_id_generator = config[CONF_DISCOVERY_UNIQUE_ID_GENERATOR] + discovery_object_id_generator = config[CONF_DISCOVERY_OBJECT_ID_GENERATOR] if not discovery: cg.add(var.disable_discovery()) elif discovery == "CLEAN": cg.add( var.set_discovery_info( - discovery_prefix, discovery_unique_id_generator, discovery_retain, True + discovery_prefix, + discovery_unique_id_generator, + discovery_object_id_generator, + discovery_retain, + True, ) ) elif CONF_DISCOVERY_RETAIN in config or CONF_DISCOVERY_PREFIX in config: cg.add( var.set_discovery_info( - discovery_prefix, discovery_unique_id_generator, discovery_retain + discovery_prefix, + discovery_unique_id_generator, + discovery_object_id_generator, + discovery_retain, ) ) diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index 67063d4c72..148316672a 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -538,9 +538,11 @@ void MQTTClientComponent::set_birth_message(MQTTMessage &&message) { void MQTTClientComponent::set_shutdown_message(MQTTMessage &&message) { this->shutdown_message_ = std::move(message); } void MQTTClientComponent::set_discovery_info(std::string &&prefix, MQTTDiscoveryUniqueIdGenerator unique_id_generator, - bool retain, bool clean) { + MQTTDiscoveryObjectIdGenerator object_id_generator, bool retain, + bool clean) { this->discovery_info_.prefix = std::move(prefix); this->discovery_info_.unique_id_generator = unique_id_generator; + this->discovery_info_.object_id_generator = object_id_generator; this->discovery_info_.retain = retain; this->discovery_info_.clean = clean; } diff --git a/esphome/components/mqtt/mqtt_client.h b/esphome/components/mqtt/mqtt_client.h index a6a7025c6f..58a4fbe166 100644 --- a/esphome/components/mqtt/mqtt_client.h +++ b/esphome/components/mqtt/mqtt_client.h @@ -61,6 +61,12 @@ enum MQTTDiscoveryUniqueIdGenerator { MQTT_MAC_ADDRESS_UNIQUE_ID_GENERATOR, }; +/// available discovery object_id generators +enum MQTTDiscoveryObjectIdGenerator { + MQTT_NONE_OBJECT_ID_GENERATOR = 0, + MQTT_DEVICE_NAME_OBJECT_ID_GENERATOR, +}; + /** Internal struct for MQTT Home Assistant discovery * * See MQTT Discovery. @@ -70,6 +76,7 @@ struct MQTTDiscoveryInfo { bool retain; ///< Whether to retain discovery messages. bool clean; MQTTDiscoveryUniqueIdGenerator unique_id_generator; + MQTTDiscoveryObjectIdGenerator object_id_generator; }; enum MQTTClientState { @@ -106,10 +113,11 @@ class MQTTClientComponent : public Component { * See MQTT Discovery. * @param prefix The Home Assistant discovery prefix. * @param unique_id_generator Controls how UniqueId is generated. + * @param object_id_generator Controls how ObjectId is generated. * @param retain Whether to retain discovery messages. */ - void set_discovery_info(std::string &&prefix, MQTTDiscoveryUniqueIdGenerator unique_id_generator, bool retain, - bool clean = false); + void set_discovery_info(std::string &&prefix, MQTTDiscoveryUniqueIdGenerator unique_id_generator, + MQTTDiscoveryObjectIdGenerator object_id_generator, bool retain, bool clean = false); /// Get Home Assistant discovery info. const MQTTDiscoveryInfo &get_discovery_info() const; /// Globally disable Home Assistant discovery. diff --git a/esphome/components/mqtt/mqtt_component.cpp b/esphome/components/mqtt/mqtt_component.cpp index 341ac50e37..cf228efd1b 100644 --- a/esphome/components/mqtt/mqtt_component.cpp +++ b/esphome/components/mqtt/mqtt_component.cpp @@ -111,12 +111,11 @@ bool MQTTComponent::send_discovery_() { root[MQTT_PAYLOAD_NOT_AVAILABLE] = this->availability_->payload_not_available; } - const std::string &node_name = App.get_name(); std::string unique_id = this->unique_id(); + const MQTTDiscoveryInfo &discovery_info = global_mqtt_client->get_discovery_info(); if (!unique_id.empty()) { root[MQTT_UNIQUE_ID] = unique_id; } else { - const MQTTDiscoveryInfo &discovery_info = global_mqtt_client->get_discovery_info(); if (discovery_info.unique_id_generator == MQTT_MAC_ADDRESS_UNIQUE_ID_GENERATOR) { char friendly_name_hash[9]; sprintf(friendly_name_hash, "%08x", fnv1_hash(this->friendly_name())); @@ -129,6 +128,10 @@ bool MQTTComponent::send_discovery_() { } } + const std::string &node_name = App.get_name(); + if (discovery_info.object_id_generator == MQTT_DEVICE_NAME_OBJECT_ID_GENERATOR) + root[MQTT_OBJECT_ID] = node_name + "_" + this->get_default_object_id_(); + JsonObject device_info = root.createNestedObject(MQTT_DEVICE); device_info[MQTT_DEVICE_IDENTIFIERS] = get_mac_address(); device_info[MQTT_DEVICE_NAME] = node_name; diff --git a/esphome/components/mqtt/mqtt_const.h b/esphome/components/mqtt/mqtt_const.h index 52ca0ed7c0..7f74197ab4 100644 --- a/esphome/components/mqtt/mqtt_const.h +++ b/esphome/components/mqtt/mqtt_const.h @@ -107,6 +107,7 @@ constexpr const char *const MQTT_MODE_STATE_TOPIC = "mode_stat_t"; constexpr const char *const MQTT_MODE_STATE_TEMPLATE = "mode_stat_tpl"; constexpr const char *const MQTT_MODES = "modes"; constexpr const char *const MQTT_NAME = "name"; +constexpr const char *const MQTT_OBJECT_ID = "obj_id"; constexpr const char *const MQTT_OFF_DELAY = "off_dly"; constexpr const char *const MQTT_ON_COMMAND_TYPE = "on_cmd_type"; constexpr const char *const MQTT_OPTIONS = "ops"; @@ -360,6 +361,7 @@ constexpr const char *const MQTT_MODE_STATE_TOPIC = "mode_state_topic"; constexpr const char *const MQTT_MODE_STATE_TEMPLATE = "mode_state_template"; constexpr const char *const MQTT_MODES = "modes"; constexpr const char *const MQTT_NAME = "name"; +constexpr const char *const MQTT_OBJECT_ID = "object_id"; constexpr const char *const MQTT_OFF_DELAY = "off_delay"; constexpr const char *const MQTT_ON_COMMAND_TYPE = "on_command_type"; constexpr const char *const MQTT_OPTIONS = "options"; diff --git a/esphome/const.py b/esphome/const.py index 61b152654a..dcd6fea31f 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -168,6 +168,7 @@ CONF_DIRECTION = "direction" CONF_DIRECTION_OUTPUT = "direction_output" CONF_DISABLED_BY_DEFAULT = "disabled_by_default" CONF_DISCOVERY = "discovery" +CONF_DISCOVERY_OBJECT_ID_GENERATOR = "discovery_object_id_generator" CONF_DISCOVERY_PREFIX = "discovery_prefix" CONF_DISCOVERY_RETAIN = "discovery_retain" CONF_DISCOVERY_UNIQUE_ID_GENERATOR = "discovery_unique_id_generator"