From 01224f25f7c2244fc88307a0391be3dc143bf66c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 19 Dec 2025 15:08:02 -1000 Subject: [PATCH] tweak --- esphome/components/web_server/web_server.cpp | 9 +++--- esphome/core/entity_base.cpp | 30 +++++++++++++++----- esphome/core/entity_base.h | 4 +++ 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index e6a7b48fbdd..a772034245e 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -404,10 +404,11 @@ void WebServer::handle_js_request(AsyncWebServerRequest *request) { // Helper functions to reduce code size by avoiding macro expansion static void set_json_id(JsonObject &root, EntityBase *obj, const char *prefix, JsonDetail start_config) { - char object_id_buf[OBJECT_ID_MAX_LEN]; - StringRef object_id = obj->get_object_id_to(object_id_buf); - char id_buf[160]; // object_id can be up to 128 chars + prefix + dash + null - snprintf(id_buf, sizeof(id_buf), "%s-%s", prefix, object_id.c_str()); + char id_buf[160]; // prefix + dash + object_id (up to 128) + null + size_t len = strlen(prefix); + memcpy(id_buf, prefix, len); + id_buf[len++] = '-'; + obj->write_object_id_to(id_buf + len, sizeof(id_buf) - len); root[ESPHOME_F("id")] = id_buf; if (start_config == DETAIL_ALL) { root[ESPHOME_F("name")] = obj->get_name(); diff --git a/esphome/core/entity_base.cpp b/esphome/core/entity_base.cpp index 98fb9579719..f83fc3b9d63 100644 --- a/esphome/core/entity_base.cpp +++ b/esphome/core/entity_base.cpp @@ -78,18 +78,34 @@ void EntityBase::calc_object_id_() { this->object_id_hash_ = fnv1_hash(object_id.c_str()); } +size_t EntityBase::write_object_id_to(char *buf, size_t buf_size) const { + if (!this->is_object_id_dynamic_()) { + // Static case: copy from stored c_str + const char *src = this->object_id_c_str_ == nullptr ? "" : this->object_id_c_str_; + size_t len = strlen(src); + if (len >= buf_size) + len = buf_size - 1; + memcpy(buf, src, len); + buf[len] = '\0'; + return len; + } + // Dynamic case: format into buffer + const std::string &name = App.get_friendly_name(); + size_t len = std::min(name.size(), buf_size - 1); + for (size_t i = 0; i < len; i++) { + buf[i] = to_sanitized_char(to_snake_case_char(name[i])); + } + buf[len] = '\0'; + return len; +} + StringRef EntityBase::get_object_id_to(std::span buf) const { if (!this->is_object_id_dynamic_()) { // Static case: return direct reference, buffer unused return this->object_id_c_str_ == nullptr ? StringRef() : StringRef(this->object_id_c_str_); } - // Dynamic case: format into buffer - const std::string &name = App.get_friendly_name(); - size_t len = std::min(name.size(), buf.size() - 1); - for (size_t i = 0; i < len; i++) { - buf[i] = to_sanitized_char(to_snake_case_char(name[i])); - } - buf[len] = '\0'; + // Dynamic case: write to buffer and return StringRef + size_t len = this->write_object_id_to(buf.data(), buf.size()); return StringRef(buf.data(), len); } diff --git a/esphome/core/entity_base.h b/esphome/core/entity_base.h index 17141948020..eb1ba46c94f 100644 --- a/esphome/core/entity_base.h +++ b/esphome/core/entity_base.h @@ -47,6 +47,10 @@ class EntityBase { /// For dynamic case: formats into buffer and returns StringRef to buffer StringRef get_object_id_to(std::span buf) const; + /// Write object_id directly to buffer, returns length written (excluding null) + /// Useful for building compound strings without intermediate buffer + size_t write_object_id_to(char *buf, size_t buf_size) const; + // Get/set whether this Entity should be hidden outside ESPHome bool is_internal() const { return this->flags_.internal; } void set_internal(bool internal) { this->flags_.internal = internal; }