Compute the object id hash when an external caller passes 0

This commit is contained in:
J. Nick Koston
2026-10-12 16:53:49 -10:00
parent 0e8a3dfb6f
commit 12c35c1545
3 changed files with 37 additions and 1 deletions
+8 -1
View File
@@ -68,7 +68,14 @@ void EntityBase::configure_entity_(const char *name, uint32_t object_id_hash, ui
this->object_id_hash_ = fnv1_hash_object_id(fallback.c_str(), fallback.size());
} else {
this->flags_.has_own_name = true;
// Static name - codegen precomputes the hash
// Static name - codegen precomputes the hash; external register_* callers may pass 0
if (object_id_hash == 0) {
#ifdef USE_ESP8266
object_id_hash = fnv1_hash_object_id_P(this->name_.progmem_ptr(), this->name_.size());
#else
object_id_hash = fnv1_hash_object_id(this->name_.progmem_ptr(), this->name_.size());
#endif
}
this->object_id_hash_ = object_id_hash;
}
// Unpack entity string table indices and flags from entity_fields.
+12
View File
@@ -1145,6 +1145,18 @@ inline uint32_t fnv1_hash_object_id(const char *str, size_t len) {
return hash;
}
#ifdef USE_ESP8266
/// fnv1_hash_object_id() for a string in flash (PROGMEM).
inline uint32_t fnv1_hash_object_id_P(PGM_P str, size_t len) {
uint32_t hash = FNV1_OFFSET_BASIS;
for (size_t i = 0; i < len; i++) {
hash *= FNV1_PRIME;
hash ^= static_cast<uint8_t>(to_sanitized_char(to_snake_case_char(static_cast<char>(pgm_read_byte(str + i)))));
}
return hash;
}
#endif
#ifdef USE_ESP8266
// ESP8266: Use vsnprintf_P to keep format strings in flash (PROGMEM)
// Format strings must be wrapped with PSTR() macro
@@ -13,4 +13,21 @@ namespace esphome::core::testing {
static_assert(std::is_same_v<decltype(std::declval<const EntityBase &>().get_name()), const StringRef &>);
#pragma GCC diagnostic pop
class TestEntity : public EntityBase {
public:
void configure(const char *name, uint32_t object_id_hash) { this->configure_entity_(name, object_id_hash, 0); }
};
TEST(EntityBaseName, ZeroHashIsComputedFromTheName) {
TestEntity entity;
entity.configure("Living Room Temp", 0);
EXPECT_EQ(entity.get_object_id_hash(), fnv1_hash_object_id("Living Room Temp", 16));
}
TEST(EntityBaseName, PrecomputedHashIsKept) {
TestEntity entity;
entity.configure("Living Room Temp", 0x1234);
EXPECT_EQ(entity.get_object_id_hash(), 0x1234u);
}
} // namespace esphome::core::testing