[api] Add max_data_length = 63 for unit_of_measurement fields

Add UNIT_OF_MEASUREMENT_MAX_LENGTH = 63 constant in core/config.py
and enforce it in sensor and number component validators.

Annotate unit_of_measurement proto fields with (max_data_length) = 63
so the codegen emits constant-size length varint calculations.
This commit is contained in:
J. Nick Koston
2026-04-03 14:10:25 -10:00
parent 4ce24389b7
commit f0622b7624
5 changed files with 18 additions and 4 deletions
+2 -1
View File
@@ -312,6 +312,7 @@ enum EntityCategory {
// name/object_id = 120 (NAME_MAX_LENGTH)
// icon = 63 (ICON_MAX_LENGTH)
// device_class = 47 (DEVICE_CLASS_MAX_LENGTH)
// unit_of_measurement = 63 (UNIT_OF_MEASUREMENT_MAX_LENGTH)
// ==================== BINARY SENSOR ====================
message ListEntitiesBinarySensorResponse {
@@ -637,7 +638,7 @@ message ListEntitiesSensorResponse {
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string unit_of_measurement = 6;
string unit_of_measurement = 6 [(max_data_length) = 63];
int32 accuracy_decimals = 7;
bool force_update = 8;
string device_class = 9 [(max_data_length) = 47];
+1 -1
View File
@@ -707,7 +707,7 @@ uint32_t ListEntitiesSensorResponse::calculate_size() const {
#ifdef USE_ENTITY_ICON
size += !this->icon.empty() ? 2 + this->icon.size() : 0;
#endif
size += ProtoSize::calc_length(1, this->unit_of_measurement.size());
size += !this->unit_of_measurement.empty() ? 2 + this->unit_of_measurement.size() : 0;
size += ProtoSize::calc_int32(1, this->accuracy_decimals);
size += ProtoSize::calc_bool(1, this->force_update);
size += !this->device_class.empty() ? 2 + this->device_class.size() : 0;
+6 -1
View File
@@ -79,6 +79,7 @@ from esphome.const import (
DEVICE_CLASS_WIND_SPEED,
)
from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.core.config import UNIT_OF_MEASUREMENT_MAX_LENGTH
from esphome.core.entity_helpers import (
entity_duplicate_validator,
setup_device_class,
@@ -186,7 +187,11 @@ NUMBER_OPERATION_OPTIONS = {
}
validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_")
validate_unit_of_measurement = cv.string_strict
validate_unit_of_measurement = cv.All(
cv.string_strict,
# Keep in sync with max_data_length in api.proto
cv.Length(max=UNIT_OF_MEASUREMENT_MAX_LENGTH),
)
_NUMBER_SCHEMA = (
cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA)
+6 -1
View File
@@ -106,6 +106,7 @@ from esphome.const import (
ENTITY_CATEGORY_CONFIG,
)
from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.core.config import UNIT_OF_MEASUREMENT_MAX_LENGTH
from esphome.core.entity_helpers import (
entity_duplicate_validator,
setup_device_class,
@@ -290,7 +291,11 @@ ClampFilter = sensor_ns.class_("ClampFilter", Filter)
RoundFilter = sensor_ns.class_("RoundFilter", Filter)
RoundMultipleFilter = sensor_ns.class_("RoundMultipleFilter", Filter)
validate_unit_of_measurement = cv.string_strict
validate_unit_of_measurement = cv.All(
cv.string_strict,
# Keep in sync with max_data_length in api.proto
cv.Length(max=UNIT_OF_MEASUREMENT_MAX_LENGTH),
)
validate_accuracy_decimals = cv.int_
validate_icon = cv.icon
validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_")
+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),