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.
This commit is contained in:
Jesse Hills
2025-06-24 19:56:30 +12:00
parent 8d5d7f5237
commit d4e978369a
3 changed files with 37 additions and 26 deletions

View File

@@ -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_; }

View File

@@ -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)

View File

@@ -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(