From d4e978369a9f376b5e072431aba356f778139e52 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 24 Jun 2025 19:56:30 +1200 Subject: [PATCH] Store reference to device on EntityBase This is so we can get the name of the device to use as part of the object id and to internally set the name for logging. --- esphome/core/entity_base.cpp | 38 ++++++++++++++++++------------------ esphome/core/entity_base.h | 15 +++++++++++--- esphome/cpp_helpers.py | 10 ++++++---- 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/esphome/core/entity_base.cpp b/esphome/core/entity_base.cpp index 791b6615a1..cf91e17a6a 100644 --- a/esphome/core/entity_base.cpp +++ b/esphome/core/entity_base.cpp @@ -11,7 +11,14 @@ const StringRef &EntityBase::get_name() const { return this->name_; } void EntityBase::set_name(const char *name) { this->name_ = StringRef(name); if (this->name_.empty()) { - this->name_ = StringRef(App.get_friendly_name()); +#ifdef USE_DEVICES + if (this->device_ != nullptr) { + this->name_ = StringRef(this->device_->get_name()); + } else +#endif + { + this->name_ = StringRef(App.get_friendly_name()); + } this->flags_.has_own_name = false; } else { this->flags_.has_own_name = true; @@ -29,16 +36,21 @@ void EntityBase::set_icon(const char *icon) { this->icon_c_str_ = icon; } // Entity Object ID std::string EntityBase::get_object_id() const { + std::string suffix = ""; +#ifdef USE_DEVICES + if (this->device_ != nullptr) { + suffix = "@" + str_sanitize(str_snake_case(this->device_->get_name())); + } +#endif // Check if `App.get_friendly_name()` is constant or dynamic. if (!this->flags_.has_own_name && App.is_name_add_mac_suffix_enabled()) { // `App.get_friendly_name()` is dynamic. - return str_sanitize(str_snake_case(App.get_friendly_name())); - } else { - // `App.get_friendly_name()` is constant. + return str_sanitize(str_snake_case(App.get_friendly_name())) + suffix; + } else { // `App.get_friendly_name()` is constant. if (this->object_id_c_str_ == nullptr) { - return ""; + return suffix; } - return this->object_id_c_str_; + return this->object_id_c_str_ + suffix; } } void EntityBase::set_object_id(const char *object_id) { @@ -47,19 +59,7 @@ void EntityBase::set_object_id(const char *object_id) { } // Calculate Object ID Hash from Entity Name -void EntityBase::calc_object_id_() { - // Check if `App.get_friendly_name()` is constant or dynamic. - if (!this->flags_.has_own_name && App.is_name_add_mac_suffix_enabled()) { - // `App.get_friendly_name()` is dynamic. - const auto object_id = str_sanitize(str_snake_case(App.get_friendly_name())); - // FNV-1 hash - this->object_id_hash_ = fnv1_hash(object_id); - } else { - // `App.get_friendly_name()` is constant. - // FNV-1 hash - this->object_id_hash_ = fnv1_hash(this->object_id_c_str_); - } -} +void EntityBase::calc_object_id_() { this->object_id_hash_ = fnv1_hash(this->get_object_id()); } uint32_t EntityBase::get_object_id_hash() { return this->object_id_hash_; } diff --git a/esphome/core/entity_base.h b/esphome/core/entity_base.h index 4bd04a9b1c..4819b66108 100644 --- a/esphome/core/entity_base.h +++ b/esphome/core/entity_base.h @@ -6,6 +6,10 @@ #include "helpers.h" #include "log.h" +#ifdef USE_DEVICES +#include "device.h" +#endif + namespace esphome { enum EntityCategory : uint8_t { @@ -53,8 +57,13 @@ class EntityBase { #ifdef USE_DEVICES // Get/set this entity's device id - uint32_t get_device_id() const { return this->device_id_; } - void set_device_id(const uint32_t device_id) { this->device_id_ = device_id; } + uint32_t get_device_id() const { + if (this->device_ == nullptr) { + return 0; // No device set, return 0 + } + return this->device_->get_device_id(); + } + void set_device(Device *device) { this->device_ = device; } #endif // Check if this entity has state @@ -74,7 +83,7 @@ class EntityBase { const char *icon_c_str_{nullptr}; uint32_t object_id_hash_{}; #ifdef USE_DEVICES - uint32_t device_id_{}; + Device *device_{}; #endif // Bit-packed flags to save memory (1 byte instead of 5) diff --git a/esphome/cpp_helpers.py b/esphome/cpp_helpers.py index 8d5440f591..e50be56092 100644 --- a/esphome/cpp_helpers.py +++ b/esphome/cpp_helpers.py @@ -17,7 +17,7 @@ from esphome.core import CORE, ID, coroutine from esphome.coroutine import FakeAwaitable from esphome.cpp_generator import add, get_variable from esphome.cpp_types import App -from esphome.helpers import fnv1a_32bit_hash, sanitize, snake_case +from esphome.helpers import sanitize, snake_case from esphome.types import ConfigFragmentType, ConfigType from esphome.util import Registry, RegistryEntry @@ -99,6 +99,11 @@ async def register_parented(var, value): async def setup_entity(var, config): """Set up generic properties of an Entity""" + if CONF_DEVICE_ID in config: + device_id: ID = config[CONF_DEVICE_ID] + device = await get_variable(device_id) + add(var.set_device(device)) + add(var.set_name(config[CONF_NAME])) if not config[CONF_NAME]: add(var.set_object_id(sanitize(snake_case(CORE.friendly_name)))) @@ -111,9 +116,6 @@ async def setup_entity(var, config): add(var.set_icon(config[CONF_ICON])) if CONF_ENTITY_CATEGORY in config: add(var.set_entity_category(config[CONF_ENTITY_CATEGORY])) - if CONF_DEVICE_ID in config: - device_id: ID = config[CONF_DEVICE_ID] - add(var.set_device_id(fnv1a_32bit_hash(device_id.id))) def extract_registry_entry_config(