[api] Add max_data_length proto option and optimize entity string encoding

Add a max_data_length field option to api_options.proto for string/bytes
fields. When max_data_length < 128 and force = true, the code generator
uses encode_short_string_force() — a single call that writes the tag
byte, 1-byte length varint, and raw string data with no branching. Size
calculation simplifies from calc_length(1, size) to 2 + size.

Annotate entity fields across all 25 ListEntities*Response messages:
- name and object_id: max_data_length = 120, force = true (50 fields)
- icon: max_data_length = 63 (25 fields)

The 120 and 63 values match NAME_MAX_LENGTH and ICON_MAX_LENGTH in
esphome/core/config.py, validated at config time.
This commit is contained in:
J. Nick Koston
2026-04-06 13:28:50 -10:00
parent ce0d360790
commit 87622c9a74
10 changed files with 318 additions and 231 deletions
+3
View File
@@ -233,6 +233,9 @@ DEVICE_CLASS_MAX_LENGTH = 47
# Keep in sync with MAX_ICON_LENGTH in esphome/core/entity_base.h
ICON_MAX_LENGTH = 63
# Max unit of measurement string length
UNIT_OF_MEASUREMENT_MAX_LENGTH = 63
AREA_SCHEMA = cv.Schema(
{
cv.GenerateID(CONF_ID): cv.declare_id(Area),
+10 -1
View File
@@ -17,7 +17,11 @@ from esphome.const import (
CONF_UNIT_OF_MEASUREMENT,
)
from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority
from esphome.core.config import DEVICE_CLASS_MAX_LENGTH, ICON_MAX_LENGTH
from esphome.core.config import (
DEVICE_CLASS_MAX_LENGTH,
ICON_MAX_LENGTH,
UNIT_OF_MEASUREMENT_MAX_LENGTH,
)
from esphome.cpp_generator import MockObj, RawStatement, add, get_variable
import esphome.final_validate as fv
from esphome.helpers import cpp_string_escape, fnv1_hash_object_id, sanitize, snake_case
@@ -200,6 +204,11 @@ def register_device_class(value: str) -> int:
def register_unit_of_measurement(value: str) -> int:
"""Register a unit_of_measurement string and return its 1-based index."""
if value and len(value) > UNIT_OF_MEASUREMENT_MAX_LENGTH:
raise ValueError(
f"Unit of measurement string too long ({len(value)} chars, "
f"max {UNIT_OF_MEASUREMENT_MAX_LENGTH}): '{value}'"
)
return _register_string(value, _get_pool().units, _MAX_UNITS, "unit_of_measurement")