diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 8e3b5a1ffb1..0a49a76c115 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -225,6 +225,8 @@ message SerialProxyInfo { // esphome_version = 32 (ESPHOME_VERSION string literal) // compilation_time = 25 (Application::BUILD_TIME_STR_SIZE - 1, constexpr) // manufacturer = 20 (longest hardcoded literal: "Nordic Semiconductor") +// model = 127 (core/config.BOARD_MAX_LENGTH, validated in platform schemas) +// project_name/project_version = 127 (core/config.PROJECT_MAX_LENGTH) message DeviceInfoResponse { option (id) = 10; option (source) = SOURCE_SERVER; @@ -248,13 +250,15 @@ message DeviceInfoResponse { string compilation_time = 5 [(max_data_length) = 25, (force) = true]; // The model of the board. For example NodeMCU - string model = 6; + // max_data_length matches core/config.BOARD_MAX_LENGTH (validated in platform schemas) + string model = 6 [(max_data_length) = 127, (force) = true]; bool has_deep_sleep = 7 [(field_ifdef) = "USE_DEEP_SLEEP"]; // The esphome project details if set - string project_name = 8 [(field_ifdef) = "ESPHOME_PROJECT_NAME"]; - string project_version = 9 [(field_ifdef) = "ESPHOME_PROJECT_NAME"]; + // max_data_length matches core/config.PROJECT_MAX_LENGTH + string project_name = 8 [(max_data_length) = 127, (force) = true, (field_ifdef) = "ESPHOME_PROJECT_NAME"]; + string project_version = 9 [(max_data_length) = 127, (force) = true, (field_ifdef) = "ESPHOME_PROJECT_NAME"]; uint32 webserver_port = 10 [(field_ifdef) = "USE_WEBSERVER"]; diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 66996452fab..64adc8bc9e7 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -97,15 +97,15 @@ uint8_t *DeviceInfoResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_ ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->mac_address); ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 34, this->esphome_version); ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 42, this->compilation_time); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 6, this->model); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 50, this->model); #ifdef USE_DEEP_SLEEP ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->has_deep_sleep); #endif #ifdef ESPHOME_PROJECT_NAME - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->project_name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 66, this->project_name); #endif #ifdef ESPHOME_PROJECT_NAME - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 9, this->project_version); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 74, this->project_version); #endif #ifdef USE_WEBSERVER ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, this->webserver_port); @@ -159,15 +159,15 @@ uint32_t DeviceInfoResponse::calculate_size() const { size += 2 + this->mac_address.size(); size += 2 + this->esphome_version.size(); size += 2 + this->compilation_time.size(); - size += ProtoSize::calc_length(1, this->model.size()); + size += 2 + this->model.size(); #ifdef USE_DEEP_SLEEP size += ProtoSize::calc_bool(1, this->has_deep_sleep); #endif #ifdef ESPHOME_PROJECT_NAME - size += ProtoSize::calc_length(1, this->project_name.size()); + size += 2 + this->project_name.size(); #endif #ifdef ESPHOME_PROJECT_NAME - size += ProtoSize::calc_length(1, this->project_version.size()); + size += 2 + this->project_version.size(); #endif #ifdef USE_WEBSERVER size += ProtoSize::calc_uint32(1, this->webserver_port); diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 0d8a2215245..54eecb5ad1f 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -44,6 +44,7 @@ from esphome.const import ( __version__, ) from esphome.core import CORE, HexInt +from esphome.core.config import BOARD_MAX_LENGTH from esphome.coroutine import CoroPriority, coroutine_with_priority import esphome.final_validate as fv from esphome.helpers import copy_file_if_changed, rmtree, write_file_if_changed @@ -1403,7 +1404,9 @@ CONF_PARTITIONS = "partitions" CONFIG_SCHEMA = cv.All( cv.Schema( { - cv.Optional(CONF_BOARD): cv.string_strict, + cv.Optional(CONF_BOARD): cv.All( + cv.string_strict, cv.Length(max=BOARD_MAX_LENGTH) + ), cv.Optional(CONF_CPU_FREQUENCY): cv.one_of( *FULL_CPU_FREQUENCIES, upper=True ), diff --git a/esphome/components/esp8266/__init__.py b/esphome/components/esp8266/__init__.py index fcd3499b151..76c8b1e870a 100644 --- a/esphome/components/esp8266/__init__.py +++ b/esphome/components/esp8266/__init__.py @@ -20,6 +20,7 @@ from esphome.const import ( ThreadModel, ) from esphome.core import CORE, CoroPriority, Lambda, coroutine_with_priority +from esphome.core.config import BOARD_MAX_LENGTH from esphome.helpers import copy_file_if_changed from esphome.types import ConfigType @@ -203,7 +204,9 @@ BUILD_FLASH_MODES = ["qio", "qout", "dio", "dout"] CONFIG_SCHEMA = cv.All( cv.Schema( { - cv.Required(CONF_BOARD): cv.string_strict, + cv.Required(CONF_BOARD): cv.All( + cv.string_strict, cv.Length(max=BOARD_MAX_LENGTH) + ), cv.Optional(CONF_FRAMEWORK, default={}): ARDUINO_FRAMEWORK_SCHEMA, cv.Optional(CONF_RESTORE_FROM_FLASH, default=False): cv.boolean, cv.Optional(CONF_EARLY_PIN_INIT, default=True): cv.boolean, diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index 8f991246040..00be620831b 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -23,6 +23,7 @@ from esphome.const import ( __version__, ) from esphome.core import CORE +from esphome.core.config import BOARD_MAX_LENGTH from esphome.storage_json import StorageJSON from . import gpio # noqa @@ -266,7 +267,9 @@ CONFIG_SCHEMA = cv.All(_notify_old_style) BASE_SCHEMA = cv.Schema( { cv.GenerateID(): cv.declare_id(LTComponent), - cv.Required(CONF_BOARD): cv.string_strict, + cv.Required(CONF_BOARD): cv.All( + cv.string_strict, cv.Length(max=BOARD_MAX_LENGTH) + ), cv.Optional(CONF_FAMILY): cv.one_of(*FAMILIES, upper=True), cv.Optional(CONF_FRAMEWORK, default={}): FRAMEWORK_SCHEMA, }, diff --git a/esphome/components/nrf52/__init__.py b/esphome/components/nrf52/__init__.py index 5054e5e0df4..566aefb2090 100644 --- a/esphome/components/nrf52/__init__.py +++ b/esphome/components/nrf52/__init__.py @@ -46,6 +46,7 @@ from esphome.const import ( ThreadModel, ) from esphome.core import CORE, CoroPriority, EsphomeError, coroutine_with_priority +from esphome.core.config import BOARD_MAX_LENGTH import esphome.final_validate as fv from esphome.storage_json import StorageJSON from esphome.types import ConfigType @@ -145,7 +146,9 @@ CONFIG_SCHEMA = cv.All( set_core_data, cv.Schema( { - cv.Required(CONF_BOARD): cv.string_strict, + cv.Required(CONF_BOARD): cv.All( + cv.string_strict, cv.Length(max=BOARD_MAX_LENGTH) + ), cv.Optional(KEY_BOOTLOADER): cv.one_of(*BOOTLOADERS, lower=True), cv.Optional(CONF_DFU): cv.Schema( { diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index 0bb18110693..628cdf370a0 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -22,6 +22,7 @@ from esphome.const import ( ThreadModel, ) from esphome.core import CORE, CoroPriority, EsphomeError, coroutine_with_priority +from esphome.core.config import BOARD_MAX_LENGTH from esphome.helpers import copy_file_if_changed, read_file, write_file_if_changed from . import boards @@ -168,7 +169,9 @@ ARDUINO_FRAMEWORK_SCHEMA = cv.All( CONFIG_SCHEMA = cv.All( cv.Schema( { - cv.Required(CONF_BOARD): cv.string_strict, + cv.Required(CONF_BOARD): cv.All( + cv.string_strict, cv.Length(max=BOARD_MAX_LENGTH) + ), cv.Optional(CONF_FRAMEWORK, default={}): ARDUINO_FRAMEWORK_SCHEMA, cv.Optional(CONF_WATCHDOG_TIMEOUT, default="8388ms"): cv.All( cv.positive_time_period_milliseconds, diff --git a/esphome/core/config.py b/esphome/core/config.py index 31cfd00ef7a..efc6d62f481 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -236,6 +236,12 @@ ICON_MAX_LENGTH = 63 # Max unit of measurement string length UNIT_OF_MEASUREMENT_MAX_LENGTH = 63 +# Max project name/version string length (must fit in single-byte varint for proto encoding) +PROJECT_MAX_LENGTH = 127 + +# Max board/model string length (must fit in single-byte varint for proto encoding) +BOARD_MAX_LENGTH = 127 + AREA_SCHEMA = cv.Schema( { cv.GenerateID(CONF_ID): cv.declare_id(Area), @@ -306,9 +312,13 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_PROJECT): cv.Schema( { cv.Required(CONF_NAME): cv.All( - cv.string_strict, valid_project_name + cv.string_strict, + valid_project_name, + cv.Length(max=PROJECT_MAX_LENGTH), + ), + cv.Required(CONF_VERSION): cv.All( + cv.string_strict, cv.Length(max=PROJECT_MAX_LENGTH) ), - cv.Required(CONF_VERSION): cv.string_strict, cv.Optional(CONF_ON_UPDATE): automation.validate_automation( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(