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(