From c9793f374192dfa575a6ee34ec9475b1dd12bca3 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 22 Jul 2025 22:57:42 -0400 Subject: [PATCH 01/28] [remote_receiver] Fix idle validation (#9819) --- esphome/components/remote_receiver/__init__.py | 18 +++++++++++++++++- .../remote_receiver/remote_receiver_esp32.cpp | 3 +-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/esphome/components/remote_receiver/__init__.py b/esphome/components/remote_receiver/__init__.py index dffc088085..9095016b55 100644 --- a/esphome/components/remote_receiver/__init__.py +++ b/esphome/components/remote_receiver/__init__.py @@ -60,6 +60,20 @@ RemoteReceiverComponent = remote_receiver_ns.class_( ) +def validate_config(config): + if CORE.is_esp32: + variant = esp32.get_esp32_variant() + if variant in (esp32.const.VARIANT_ESP32, esp32.const.VARIANT_ESP32S2): + max_idle = 65535 + else: + max_idle = 32767 + if CONF_CLOCK_RESOLUTION in config: + max_idle = int(max_idle * 1000000 / config[CONF_CLOCK_RESOLUTION]) + if config[CONF_IDLE].total_microseconds > max_idle: + raise cv.Invalid(f"config 'idle' exceeds the maximum value of {max_idle}us") + return config + + def validate_tolerance(value): if isinstance(value, dict): return TOLERANCE_SCHEMA(value) @@ -136,7 +150,9 @@ CONFIG_SCHEMA = remote_base.validate_triggers( cv.boolean, ), } - ).extend(cv.COMPONENT_SCHEMA) + ) + .extend(cv.COMPONENT_SCHEMA) + .add_extra(validate_config) ) diff --git a/esphome/components/remote_receiver/remote_receiver_esp32.cpp b/esphome/components/remote_receiver/remote_receiver_esp32.cpp index 3d6346baec..3e6172c6d6 100644 --- a/esphome/components/remote_receiver/remote_receiver_esp32.cpp +++ b/esphome/components/remote_receiver/remote_receiver_esp32.cpp @@ -86,10 +86,9 @@ void RemoteReceiverComponent::setup() { uint32_t event_size = sizeof(rmt_rx_done_event_data_t); uint32_t max_filter_ns = 255u * 1000 / (RMT_CLK_FREQ / 1000000); - uint32_t max_idle_ns = 65535u * 1000; memset(&this->store_.config, 0, sizeof(this->store_.config)); this->store_.config.signal_range_min_ns = std::min(this->filter_us_ * 1000, max_filter_ns); - this->store_.config.signal_range_max_ns = std::min(this->idle_us_ * 1000, max_idle_ns); + this->store_.config.signal_range_max_ns = this->idle_us_ * 1000; this->store_.filter_symbols = this->filter_symbols_; this->store_.receive_size = this->receive_symbols_ * sizeof(rmt_symbol_word_t); this->store_.buffer_size = std::max((event_size + this->store_.receive_size) * 2, this->buffer_size_); From 93028a4d908b08e62fb206848c0dc42fdfe3eb77 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 24 Jul 2025 07:52:07 +1000 Subject: [PATCH 02/28] [gt911] i2c fixes (#9822) --- .../gt911/touchscreen/gt911_touchscreen.cpp | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/esphome/components/gt911/touchscreen/gt911_touchscreen.cpp b/esphome/components/gt911/touchscreen/gt911_touchscreen.cpp index 1cead70181..5c540effd0 100644 --- a/esphome/components/gt911/touchscreen/gt911_touchscreen.cpp +++ b/esphome/components/gt911/touchscreen/gt911_touchscreen.cpp @@ -8,6 +8,8 @@ namespace gt911 { static const char *const TAG = "gt911.touchscreen"; +static const uint8_t PRIMARY_ADDRESS = 0x5D; // default I2C address for GT911 +static const uint8_t SECONDARY_ADDRESS = 0x14; // secondary I2C address for GT911 static const uint8_t GET_TOUCH_STATE[2] = {0x81, 0x4E}; static const uint8_t CLEAR_TOUCH_STATE[3] = {0x81, 0x4E, 0x00}; static const uint8_t GET_TOUCHES[2] = {0x81, 0x4F}; @@ -18,8 +20,7 @@ static const size_t MAX_BUTTONS = 4; // max number of buttons scanned #define ERROR_CHECK(err) \ if ((err) != i2c::ERROR_OK) { \ - ESP_LOGE(TAG, "Failed to communicate!"); \ - this->status_set_warning(); \ + this->status_set_warning("Communication failure"); \ return; \ } @@ -30,31 +31,31 @@ void GT911Touchscreen::setup() { this->reset_pin_->setup(); this->reset_pin_->digital_write(false); if (this->interrupt_pin_ != nullptr) { - // The interrupt pin is used as an input during reset to select the I2C address. + // temporarily set the interrupt pin to output to control address selection this->interrupt_pin_->pin_mode(gpio::FLAG_OUTPUT); - this->interrupt_pin_->setup(); this->interrupt_pin_->digital_write(false); } delay(2); this->reset_pin_->digital_write(true); delay(50); // NOLINT - if (this->interrupt_pin_ != nullptr) { - this->interrupt_pin_->pin_mode(gpio::FLAG_INPUT); - this->interrupt_pin_->setup(); - } + } + if (this->interrupt_pin_ != nullptr) { + // set pre-configured input mode + this->interrupt_pin_->setup(); } // check the configuration of the int line. uint8_t data[4]; - err = this->write(GET_SWITCHES, 2); + err = this->write(GET_SWITCHES, sizeof(GET_SWITCHES)); + if (err != i2c::ERROR_OK && this->address_ == PRIMARY_ADDRESS) { + this->address_ = SECONDARY_ADDRESS; + err = this->write(GET_SWITCHES, sizeof(GET_SWITCHES)); + } if (err == i2c::ERROR_OK) { err = this->read(data, 1); if (err == i2c::ERROR_OK) { - ESP_LOGD(TAG, "Read from switches: 0x%02X", data[0]); + ESP_LOGD(TAG, "Read from switches at address 0x%02X: 0x%02X", this->address_, data[0]); if (this->interrupt_pin_ != nullptr) { - // datasheet says NOT to use pullup/down on the int line. - this->interrupt_pin_->pin_mode(gpio::FLAG_INPUT); - this->interrupt_pin_->setup(); this->attach_interrupt_(this->interrupt_pin_, (data[0] & 1) ? gpio::INTERRUPT_FALLING_EDGE : gpio::INTERRUPT_RISING_EDGE); } @@ -63,7 +64,7 @@ void GT911Touchscreen::setup() { if (this->x_raw_max_ == 0 || this->y_raw_max_ == 0) { // no calibration? Attempt to read the max values from the touchscreen. if (err == i2c::ERROR_OK) { - err = this->write(GET_MAX_VALUES, 2); + err = this->write(GET_MAX_VALUES, sizeof(GET_MAX_VALUES)); if (err == i2c::ERROR_OK) { err = this->read(data, sizeof(data)); if (err == i2c::ERROR_OK) { @@ -75,15 +76,12 @@ void GT911Touchscreen::setup() { } } if (err != i2c::ERROR_OK) { - ESP_LOGE(TAG, "Failed to read calibration values from touchscreen!"); - this->mark_failed(); + this->mark_failed("Failed to read calibration"); return; } } if (err != i2c::ERROR_OK) { - ESP_LOGE(TAG, "Failed to communicate!"); - this->mark_failed(); - return; + this->mark_failed("Failed to communicate"); } ESP_LOGCONFIG(TAG, "GT911 Touchscreen setup complete"); @@ -94,7 +92,7 @@ void GT911Touchscreen::update_touches() { uint8_t touch_state = 0; uint8_t data[MAX_TOUCHES + 1][8]; // 8 bytes each for each point, plus extra space for the key byte - err = this->write(GET_TOUCH_STATE, sizeof(GET_TOUCH_STATE), false); + err = this->write(GET_TOUCH_STATE, sizeof(GET_TOUCH_STATE)); ERROR_CHECK(err); err = this->read(&touch_state, 1); ERROR_CHECK(err); @@ -106,7 +104,7 @@ void GT911Touchscreen::update_touches() { return; } - err = this->write(GET_TOUCHES, sizeof(GET_TOUCHES), false); + err = this->write(GET_TOUCHES, sizeof(GET_TOUCHES)); ERROR_CHECK(err); // num_of_touches is guaranteed to be 0..5. Also read the key data err = this->read(data[0], sizeof(data[0]) * num_of_touches + 1); @@ -132,6 +130,7 @@ void GT911Touchscreen::dump_config() { ESP_LOGCONFIG(TAG, "GT911 Touchscreen:"); LOG_I2C_DEVICE(this); LOG_PIN(" Interrupt Pin: ", this->interrupt_pin_); + LOG_PIN(" Reset Pin: ", this->reset_pin_); } } // namespace gt911 From 8b0ad3072f94b7614eed2c63217fd8a3f993087a Mon Sep 17 00:00:00 2001 From: Eric Hoffmann Date: Wed, 23 Jul 2025 23:55:31 +0200 Subject: [PATCH 03/28] fix: non-optional x/y target calculation for ld2450 (#9849) --- esphome/components/ld2450/ld2450.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index 8f3b3a3f21..09761b2937 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -477,10 +477,11 @@ void LD2450Component::handle_periodic_data_() { // X start = TARGET_X + index * 8; is_moving = false; + // tx is used for further calculations, so always needs to be populated + val = ld2450::decode_coordinate(this->buffer_data_[start], this->buffer_data_[start + 1]); + tx = val; sensor::Sensor *sx = this->move_x_sensors_[index]; if (sx != nullptr) { - val = ld2450::decode_coordinate(this->buffer_data_[start], this->buffer_data_[start + 1]); - tx = val; if (this->cached_target_data_[index].x != val) { sx->publish_state(val); this->cached_target_data_[index].x = val; @@ -488,10 +489,11 @@ void LD2450Component::handle_periodic_data_() { } // Y start = TARGET_Y + index * 8; + // ty is used for further calculations, so always needs to be populated + val = ld2450::decode_coordinate(this->buffer_data_[start], this->buffer_data_[start + 1]); + ty = val; sensor::Sensor *sy = this->move_y_sensors_[index]; if (sy != nullptr) { - val = ld2450::decode_coordinate(this->buffer_data_[start], this->buffer_data_[start + 1]); - ty = val; if (this->cached_target_data_[index].y != val) { sy->publish_state(val); this->cached_target_data_[index].y = val; From 8dce7b0905640aa448aa50bc47132733d9cf6844 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Sat, 26 Jul 2025 16:23:36 +1200 Subject: [PATCH 04/28] [logger] Don't allow ``logger.log`` actions without configuring the ``logger`` (#9821) --- esphome/components/logger/__init__.py | 1 + tests/component_tests/text/test_text.yaml | 2 ++ 2 files changed, 3 insertions(+) diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index cf2af17677..618f5bcc7a 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -400,6 +400,7 @@ CONF_LOGGER_LOG = "logger.log" LOGGER_LOG_ACTION_SCHEMA = cv.All( cv.maybe_simple_value( { + cv.GenerateID(CONF_LOGGER_ID): cv.use_id(Logger), cv.Required(CONF_FORMAT): cv.string, cv.Optional(CONF_ARGS, default=list): cv.ensure_list(cv.lambda_), cv.Optional(CONF_LEVEL, default="DEBUG"): cv.one_of( diff --git a/tests/component_tests/text/test_text.yaml b/tests/component_tests/text/test_text.yaml index d81c909f9d..9b05d59349 100644 --- a/tests/component_tests/text/test_text.yaml +++ b/tests/component_tests/text/test_text.yaml @@ -4,6 +4,8 @@ esphome: esp32: board: esp32dev +logger: + text: - platform: template name: "test 1 text" From 2f9475a9275a2a7a4db5091d5fb466d6eea76510 Mon Sep 17 00:00:00 2001 From: cryptk <421501+cryptk@users.noreply.github.com> Date: Sun, 27 Jul 2025 21:20:51 -0500 Subject: [PATCH 05/28] Add seed flag when running setup with uv present (#9932) --- script/setup | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/setup b/script/setup index b17d3235a7..1bd7c44575 100755 --- a/script/setup +++ b/script/setup @@ -6,7 +6,7 @@ set -e cd "$(dirname "$0")/.." if [ ! -n "$VIRTUAL_ENV" ]; then if [ -x "$(command -v uv)" ]; then - uv venv venv + uv venv --seed venv else python3 -m venv venv fi From 3a6cc0ea3d95a3c4fce5e56c0f75ad086878dc20 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Mon, 28 Jul 2025 05:19:17 +0200 Subject: [PATCH 06/28] Fail with old lerp (#9914) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/core/helpers.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 53b79a00b7..4a4c52bb06 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -67,7 +67,10 @@ To bit_cast(const From &src) { return dst; } #endif -using std::lerp; + +// clang-format off +inline float lerp(float completion, float start, float end) = delete; // Please use std::lerp. Notice that it has different order on arguments! +// clang-format on // std::byteswap from C++23 template constexpr T byteswap(T n) { From 573dad17365746b8053087b3047bbfbaa13f5c8a Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 28 Jul 2025 15:55:07 +1200 Subject: [PATCH 07/28] Bump version to 2025.7.4 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index ae1e519030..afd3b582e5 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2025.7.3 +PROJECT_NUMBER = 2025.7.4 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 476059af62..6ed0119411 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2025.7.3" +__version__ = "2025.7.4" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 4933ef780b7d921bd5ddb18853de8611586d5fec Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 27 Jul 2025 18:50:17 -1000 Subject: [PATCH 08/28] [bluetooth_proxy] Fix service discovery cache pollution and descriptor count parameter bug (#9902) --- .../bluetooth_proxy/bluetooth_connection.cpp | 52 ++++++++++--------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/esphome/components/bluetooth_proxy/bluetooth_connection.cpp b/esphome/components/bluetooth_proxy/bluetooth_connection.cpp index 4b84257e27..b3484032b2 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_connection.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_connection.cpp @@ -80,15 +80,10 @@ void BluetoothConnection::send_service_for_discovery_() { &service_result, &service_count, this->send_service_); this->send_service_++; - if (service_status != ESP_GATT_OK) { - ESP_LOGE(TAG, "[%d] [%s] esp_ble_gattc_get_service error at offset=%d, status=%d", this->connection_index_, - this->address_str().c_str(), this->send_service_ - 1, service_status); - return; - } - - if (service_count == 0) { - ESP_LOGE(TAG, "[%d] [%s] esp_ble_gattc_get_service missing, service_count=%d", this->connection_index_, - this->address_str().c_str(), service_count); + if (service_status != ESP_GATT_OK || service_count == 0) { + ESP_LOGE(TAG, "[%d] [%s] esp_ble_gattc_get_service %s, status=%d, service_count=%d, offset=%d", + this->connection_index_, this->address_str().c_str(), service_status != ESP_GATT_OK ? "error" : "missing", + service_status, service_count, this->send_service_ - 1); return; } @@ -104,15 +99,20 @@ void BluetoothConnection::send_service_for_discovery_() { esp_ble_gattc_get_attr_count(this->gattc_if_, this->conn_id_, ESP_GATT_DB_CHARACTERISTIC, service_result.start_handle, service_result.end_handle, 0, &total_char_count); - if (char_count_status == ESP_GATT_OK && total_char_count > 0) { - // Only reserve if we successfully got a count - service_resp.characteristics.reserve(total_char_count); - } else if (char_count_status != ESP_GATT_OK) { + if (char_count_status != ESP_GATT_OK) { ESP_LOGW(TAG, "[%d] [%s] Error getting characteristic count, status=%d", this->connection_index_, this->address_str().c_str(), char_count_status); + return; } - // Now process characteristics + if (total_char_count == 0) { + // No characteristics, just send the service response + api_conn->send_message(resp, api::BluetoothGATTGetServicesResponse::MESSAGE_TYPE); + return; + } + + // Reserve space and process characteristics + service_resp.characteristics.reserve(total_char_count); uint16_t char_offset = 0; esp_gattc_char_elem_t char_result; while (true) { // characteristics @@ -126,7 +126,7 @@ void BluetoothConnection::send_service_for_discovery_() { if (char_status != ESP_GATT_OK) { ESP_LOGE(TAG, "[%d] [%s] esp_ble_gattc_get_all_char error, status=%d", this->connection_index_, this->address_str().c_str(), char_status); - break; + return; } if (char_count == 0) { break; @@ -141,19 +141,21 @@ void BluetoothConnection::send_service_for_discovery_() { // Get the number of descriptors directly with one call uint16_t total_desc_count = 0; - esp_gatt_status_t desc_count_status = - esp_ble_gattc_get_attr_count(this->gattc_if_, this->conn_id_, ESP_GATT_DB_DESCRIPTOR, char_result.char_handle, - service_result.end_handle, 0, &total_desc_count); + esp_gatt_status_t desc_count_status = esp_ble_gattc_get_attr_count( + this->gattc_if_, this->conn_id_, ESP_GATT_DB_DESCRIPTOR, 0, 0, char_result.char_handle, &total_desc_count); - if (desc_count_status == ESP_GATT_OK && total_desc_count > 0) { - // Only reserve if we successfully got a count - characteristic_resp.descriptors.reserve(total_desc_count); - } else if (desc_count_status != ESP_GATT_OK) { + if (desc_count_status != ESP_GATT_OK) { ESP_LOGW(TAG, "[%d] [%s] Error getting descriptor count for char handle %d, status=%d", this->connection_index_, this->address_str().c_str(), char_result.char_handle, desc_count_status); + return; + } + if (total_desc_count == 0) { + // No descriptors, continue to next characteristic + continue; } - // Now process descriptors + // Reserve space and process descriptors + characteristic_resp.descriptors.reserve(total_desc_count); uint16_t desc_offset = 0; esp_gattc_descr_elem_t desc_result; while (true) { // descriptors @@ -166,10 +168,10 @@ void BluetoothConnection::send_service_for_discovery_() { if (desc_status != ESP_GATT_OK) { ESP_LOGE(TAG, "[%d] [%s] esp_ble_gattc_get_all_descr error, status=%d", this->connection_index_, this->address_str().c_str(), desc_status); - break; + return; } if (desc_count == 0) { - break; + break; // No more descriptors } characteristic_resp.descriptors.emplace_back(); From eecdaa516315544092d93bbec96207648d7ec359 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 28 Jul 2025 17:23:35 +1000 Subject: [PATCH 09/28] [config_validation] extend should combine extra validations (#9939) --- esphome/voluptuous_schema.py | 7 +-- .../config_validation/test_config.py | 51 +++++++++++++++++++ 2 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 tests/component_tests/config_validation/test_config.py diff --git a/esphome/voluptuous_schema.py b/esphome/voluptuous_schema.py index 8fb966e3b2..7220fb307f 100644 --- a/esphome/voluptuous_schema.py +++ b/esphome/voluptuous_schema.py @@ -225,9 +225,10 @@ class _Schema(vol.Schema): return ret schema = schemas[0] + extra_schemas = self._extra_schemas.copy() + if isinstance(schema, _Schema): + extra_schemas.extend(schema._extra_schemas) if isinstance(schema, vol.Schema): schema = schema.schema ret = super().extend(schema, extra=extra) - return _Schema( - ret.schema, extra=ret.extra, extra_schemas=self._extra_schemas.copy() - ) + return _Schema(ret.schema, extra=ret.extra, extra_schemas=extra_schemas) diff --git a/tests/component_tests/config_validation/test_config.py b/tests/component_tests/config_validation/test_config.py new file mode 100644 index 0000000000..1a9b9bc1f3 --- /dev/null +++ b/tests/component_tests/config_validation/test_config.py @@ -0,0 +1,51 @@ +""" +Test schema.extend functionality in esphome.config_validation. +""" + +from typing import Any + +import esphome.config_validation as cv + + +def test_config_extend() -> None: + """Test that schema.extend correctly merges schemas with extras.""" + + def func1(data: dict[str, Any]) -> dict[str, Any]: + data["extra_1"] = "value1" + return data + + def func2(data: dict[str, Any]) -> dict[str, Any]: + data["extra_2"] = "value2" + return data + + schema1 = cv.Schema( + { + cv.Required("key1"): cv.string, + } + ) + schema1.add_extra(func1) + schema2 = cv.Schema( + { + cv.Required("key2"): cv.string, + } + ) + schema2.add_extra(func2) + extended_schema = schema1.extend(schema2) + config = { + "key1": "initial_value1", + "key2": "initial_value2", + } + validated = extended_schema(config) + assert validated["key1"] == "initial_value1" + assert validated["key2"] == "initial_value2" + assert validated["extra_1"] == "value1" + assert validated["extra_2"] == "value2" + + # Check the opposite order of extension + extended_schema = schema2.extend(schema1) + + validated = extended_schema(config) + assert validated["key1"] == "initial_value1" + assert validated["key2"] == "initial_value2" + assert validated["extra_1"] == "value1" + assert validated["extra_2"] == "value2" From f9453f96421ab0493fa824d36a3d0342398d7a35 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 29 Jul 2025 06:43:22 +1000 Subject: [PATCH 10/28] [lvgl] Bugfix for tileview (#9938) --- esphome/components/lvgl/widgets/tileview.py | 22 ++++++++++++++------- tests/components/lvgl/lvgl-package.yaml | 2 +- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/esphome/components/lvgl/widgets/tileview.py b/esphome/components/lvgl/widgets/tileview.py index 3865d404e2..5e3a95f017 100644 --- a/esphome/components/lvgl/widgets/tileview.py +++ b/esphome/components/lvgl/widgets/tileview.py @@ -15,7 +15,7 @@ from ..defines import ( TILE_DIRECTIONS, literal, ) -from ..lv_validation import animated, lv_int +from ..lv_validation import animated, lv_int, lv_pct from ..lvcode import lv, lv_assign, lv_expr, lv_obj, lv_Pvariable from ..schemas import container_schema from ..types import LV_EVENT, LvType, ObjUpdateAction, lv_obj_t, lv_obj_t_ptr @@ -41,8 +41,8 @@ TILEVIEW_SCHEMA = cv.Schema( container_schema( obj_spec, { - cv.Required(CONF_ROW): lv_int, - cv.Required(CONF_COLUMN): lv_int, + cv.Required(CONF_ROW): cv.positive_int, + cv.Required(CONF_COLUMN): cv.positive_int, cv.GenerateID(): cv.declare_id(lv_tile_t), cv.Optional(CONF_DIR, default="ALL"): TILE_DIRECTIONS.several_of, }, @@ -63,21 +63,29 @@ class TileviewType(WidgetType): ) async def to_code(self, w: Widget, config: dict): - for tile_conf in config.get(CONF_TILES, ()): + tiles = config[CONF_TILES] + for tile_conf in tiles: w_id = tile_conf[CONF_ID] tile_obj = lv_Pvariable(lv_obj_t, w_id) tile = Widget.create(w_id, tile_obj, tile_spec, tile_conf) dirs = tile_conf[CONF_DIR] if isinstance(dirs, list): dirs = "|".join(dirs) + row_pos = tile_conf[CONF_ROW] + col_pos = tile_conf[CONF_COLUMN] lv_assign( tile_obj, - lv_expr.tileview_add_tile( - w.obj, tile_conf[CONF_COLUMN], tile_conf[CONF_ROW], literal(dirs) - ), + lv_expr.tileview_add_tile(w.obj, col_pos, row_pos, literal(dirs)), ) + # Bugfix for LVGL 8.x + lv_obj.set_pos(tile_obj, lv_pct(col_pos * 100), lv_pct(row_pos * 100)) await set_obj_properties(tile, tile_conf) await add_widgets(tile, tile_conf) + if tiles: + # Set the first tile as active + lv_obj.set_tile_id( + w.obj, tiles[0][CONF_COLUMN], tiles[0][CONF_ROW], literal("LV_ANIM_OFF") + ) tileview_spec = TileviewType() diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 46341c266d..853466c9cc 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -738,7 +738,7 @@ lvgl: id: bar_id value: !lambda return (int)((float)rand() / RAND_MAX * 100); start_value: !lambda return (int)((float)rand() / RAND_MAX * 100); - mode: symmetrical + mode: range - logger.log: format: "bar value %f" args: [x] From 85435e6b5f695b37a0efd688c1848373762f191e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 28 Jul 2025 10:54:16 -1000 Subject: [PATCH 11/28] [scheduler] Eliminate more runtime string allocations from retry (#9930) --- esphome/core/scheduler.cpp | 61 ++++++++++++------ esphome/core/scheduler.h | 32 +++++++--- .../fixtures/scheduler_retry_test.yaml | 62 ++++++++++++++++++ .../integration/test_scheduler_retry_test.py | 64 ++++++++++++++++++- 4 files changed, 192 insertions(+), 27 deletions(-) diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index a2c16c41fb..6269a66543 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -83,6 +83,7 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type item->type = type; item->callback = std::move(func); item->remove = false; + item->is_retry = is_retry; #ifndef ESPHOME_THREAD_SINGLE // Special handling for defer() (delay = 0, type = TIMEOUT) @@ -134,8 +135,8 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type // For retries, check if there's a cancelled timeout first if (is_retry && name_cstr != nullptr && type == SchedulerItem::TIMEOUT && - (has_cancelled_timeout_in_container_(this->items_, component, name_cstr) || - has_cancelled_timeout_in_container_(this->to_add_, component, name_cstr))) { + (has_cancelled_timeout_in_container_(this->items_, component, name_cstr, /* match_retry= */ true) || + has_cancelled_timeout_in_container_(this->to_add_, component, name_cstr, /* match_retry= */ true))) { // Skip scheduling - the retry was cancelled #ifdef ESPHOME_DEBUG_SCHEDULER ESP_LOGD(TAG, "Skipping retry '%s' - found cancelled item", name_cstr); @@ -198,25 +199,27 @@ void retry_handler(const std::shared_ptr &args) { // second execution of `func` happens after `initial_wait_time` args->scheduler->set_timer_common_( args->component, Scheduler::SchedulerItem::TIMEOUT, false, &args->name, args->current_interval, - [args]() { retry_handler(args); }, true); + [args]() { retry_handler(args); }, /* is_retry= */ true); // backoff_increase_factor applied to third & later executions args->current_interval *= args->backoff_increase_factor; } -void HOT Scheduler::set_retry(Component *component, const std::string &name, uint32_t initial_wait_time, - uint8_t max_attempts, std::function func, - float backoff_increase_factor) { - if (!name.empty()) - this->cancel_retry(component, name); +void HOT Scheduler::set_retry_common_(Component *component, bool is_static_string, const void *name_ptr, + uint32_t initial_wait_time, uint8_t max_attempts, + std::function func, float backoff_increase_factor) { + const char *name_cstr = this->get_name_cstr_(is_static_string, name_ptr); + + if (name_cstr != nullptr) + this->cancel_retry(component, name_cstr); if (initial_wait_time == SCHEDULER_DONT_RUN) return; ESP_LOGVV(TAG, "set_retry(name='%s', initial_wait_time=%" PRIu32 ", max_attempts=%u, backoff_factor=%0.1f)", - name.c_str(), initial_wait_time, max_attempts, backoff_increase_factor); + name_cstr ? name_cstr : "", initial_wait_time, max_attempts, backoff_increase_factor); if (backoff_increase_factor < 0.0001) { - ESP_LOGE(TAG, "backoff_factor %0.1f too small, using 1.0: %s", backoff_increase_factor, name.c_str()); + ESP_LOGE(TAG, "backoff_factor %0.1f too small, using 1.0: %s", backoff_increase_factor, name_cstr ? name_cstr : ""); backoff_increase_factor = 1; } @@ -225,15 +228,36 @@ void HOT Scheduler::set_retry(Component *component, const std::string &name, uin args->retry_countdown = max_attempts; args->current_interval = initial_wait_time; args->component = component; - args->name = "retry$" + name; + args->name = name_cstr ? name_cstr : ""; // Convert to std::string for RetryArgs args->backoff_increase_factor = backoff_increase_factor; args->scheduler = this; - // First execution of `func` immediately - this->set_timeout(component, args->name, 0, [args]() { retry_handler(args); }); + // First execution of `func` immediately - use set_timer_common_ with is_retry=true + this->set_timer_common_( + component, SchedulerItem::TIMEOUT, false, &args->name, 0, [args]() { retry_handler(args); }, + /* is_retry= */ true); +} + +void HOT Scheduler::set_retry(Component *component, const std::string &name, uint32_t initial_wait_time, + uint8_t max_attempts, std::function func, + float backoff_increase_factor) { + this->set_retry_common_(component, false, &name, initial_wait_time, max_attempts, std::move(func), + backoff_increase_factor); +} + +void HOT Scheduler::set_retry(Component *component, const char *name, uint32_t initial_wait_time, uint8_t max_attempts, + std::function func, float backoff_increase_factor) { + this->set_retry_common_(component, true, name, initial_wait_time, max_attempts, std::move(func), + backoff_increase_factor); } bool HOT Scheduler::cancel_retry(Component *component, const std::string &name) { - return this->cancel_timeout(component, "retry$" + name); + return this->cancel_retry(component, name.c_str()); +} + +bool HOT Scheduler::cancel_retry(Component *component, const char *name) { + // Cancel timeouts that have is_retry flag set + LockGuard guard{this->lock_}; + return this->cancel_item_locked_(component, name, SchedulerItem::TIMEOUT, /* match_retry= */ true); } optional HOT Scheduler::next_schedule_in(uint32_t now) { @@ -479,7 +503,8 @@ bool HOT Scheduler::cancel_item_(Component *component, bool is_static_string, co } // Helper to cancel items by name - must be called with lock held -bool HOT Scheduler::cancel_item_locked_(Component *component, const char *name_cstr, SchedulerItem::Type type) { +bool HOT Scheduler::cancel_item_locked_(Component *component, const char *name_cstr, SchedulerItem::Type type, + bool match_retry) { // Early return if name is invalid - no items to cancel if (name_cstr == nullptr) { return false; @@ -492,7 +517,7 @@ bool HOT Scheduler::cancel_item_locked_(Component *component, const char *name_c // Only check defer queue for timeouts (intervals never go there) if (type == SchedulerItem::TIMEOUT) { for (auto &item : this->defer_queue_) { - if (this->matches_item_(item, component, name_cstr, type)) { + if (this->matches_item_(item, component, name_cstr, type, match_retry)) { item->remove = true; total_cancelled++; } @@ -502,7 +527,7 @@ bool HOT Scheduler::cancel_item_locked_(Component *component, const char *name_c // Cancel items in the main heap for (auto &item : this->items_) { - if (this->matches_item_(item, component, name_cstr, type)) { + if (this->matches_item_(item, component, name_cstr, type, match_retry)) { item->remove = true; total_cancelled++; this->to_remove_++; // Track removals for heap items @@ -511,7 +536,7 @@ bool HOT Scheduler::cancel_item_locked_(Component *component, const char *name_c // Cancel items in to_add_ for (auto &item : this->to_add_) { - if (this->matches_item_(item, component, name_cstr, type)) { + if (this->matches_item_(item, component, name_cstr, type, match_retry)) { item->remove = true; total_cancelled++; // Don't track removals for to_add_ items diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index fa189bacf7..a6092e1b1e 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -61,7 +61,10 @@ class Scheduler { bool cancel_interval(Component *component, const char *name); void set_retry(Component *component, const std::string &name, uint32_t initial_wait_time, uint8_t max_attempts, std::function func, float backoff_increase_factor = 1.0f); + void set_retry(Component *component, const char *name, uint32_t initial_wait_time, uint8_t max_attempts, + std::function func, float backoff_increase_factor = 1.0f); bool cancel_retry(Component *component, const std::string &name); + bool cancel_retry(Component *component, const char *name); // Calculate when the next scheduled item should run // @param now Fresh timestamp from millis() - must not be stale/cached @@ -98,11 +101,18 @@ class Scheduler { enum Type : uint8_t { TIMEOUT, INTERVAL } type : 1; bool remove : 1; bool name_is_dynamic : 1; // True if name was dynamically allocated (needs delete[]) - // 5 bits padding + bool is_retry : 1; // True if this is a retry timeout + // 4 bits padding // Constructor SchedulerItem() - : component(nullptr), interval(0), next_execution_(0), type(TIMEOUT), remove(false), name_is_dynamic(false) { + : component(nullptr), + interval(0), + next_execution_(0), + type(TIMEOUT), + remove(false), + name_is_dynamic(false), + is_retry(false) { name_.static_name = nullptr; } @@ -156,6 +166,10 @@ class Scheduler { void set_timer_common_(Component *component, SchedulerItem::Type type, bool is_static_string, const void *name_ptr, uint32_t delay, std::function func, bool is_retry = false); + // Common implementation for retry + void set_retry_common_(Component *component, bool is_static_string, const void *name_ptr, uint32_t initial_wait_time, + uint8_t max_attempts, std::function func, float backoff_increase_factor); + uint64_t millis_64_(uint32_t now); // Cleanup logically deleted items from the scheduler // Returns the number of items remaining after cleanup @@ -165,7 +179,7 @@ class Scheduler { private: // Helper to cancel items by name - must be called with lock held - bool cancel_item_locked_(Component *component, const char *name, SchedulerItem::Type type); + bool cancel_item_locked_(Component *component, const char *name, SchedulerItem::Type type, bool match_retry = false); // Helper to extract name as const char* from either static string or std::string inline const char *get_name_cstr_(bool is_static_string, const void *name_ptr) { @@ -177,8 +191,9 @@ class Scheduler { // Helper function to check if item matches criteria for cancellation inline bool HOT matches_item_(const std::unique_ptr &item, Component *component, const char *name_cstr, - SchedulerItem::Type type, bool skip_removed = true) const { - if (item->component != component || item->type != type || (skip_removed && item->remove)) { + SchedulerItem::Type type, bool match_retry, bool skip_removed = true) const { + if (item->component != component || item->type != type || (skip_removed && item->remove) || + (match_retry && !item->is_retry)) { return false; } const char *item_name = item->get_name(); @@ -206,10 +221,11 @@ class Scheduler { // Template helper to check if any item in a container matches our criteria template - bool has_cancelled_timeout_in_container_(const Container &container, Component *component, - const char *name_cstr) const { + bool has_cancelled_timeout_in_container_(const Container &container, Component *component, const char *name_cstr, + bool match_retry) const { for (const auto &item : container) { - if (item->remove && this->matches_item_(item, component, name_cstr, SchedulerItem::TIMEOUT, false)) { + if (item->remove && this->matches_item_(item, component, name_cstr, SchedulerItem::TIMEOUT, match_retry, + /* skip_removed= */ false)) { return true; } } diff --git a/tests/integration/fixtures/scheduler_retry_test.yaml b/tests/integration/fixtures/scheduler_retry_test.yaml index c6fcc53f8c..11fff6c395 100644 --- a/tests/integration/fixtures/scheduler_retry_test.yaml +++ b/tests/integration/fixtures/scheduler_retry_test.yaml @@ -37,6 +37,15 @@ globals: - id: multiple_same_name_counter type: int initial_value: '0' + - id: const_char_retry_counter + type: int + initial_value: '0' + - id: static_char_retry_counter + type: int + initial_value: '0' + - id: mixed_cancel_result + type: bool + initial_value: 'false' # Using different component types for each test to ensure isolation sensor: @@ -229,6 +238,56 @@ script: return RetryResult::RETRY; }); + # Test 8: Const char* overloads + - logger.log: "=== Test 8: Const char* overloads ===" + - lambda: |- + auto *component = id(simple_retry_sensor); + + // Test 8a: Direct string literal + App.scheduler.set_retry(component, "const_char_test", 30, 2, + [](uint8_t retry_countdown) { + id(const_char_retry_counter)++; + ESP_LOGI("test", "Const char retry %d", id(const_char_retry_counter)); + return RetryResult::DONE; + }); + + # Test 9: Static const char* variable + - logger.log: "=== Test 9: Static const char* ===" + - lambda: |- + auto *component = id(backoff_retry_sensor); + + static const char* STATIC_NAME = "static_retry_test"; + App.scheduler.set_retry(component, STATIC_NAME, 20, 1, + [](uint8_t retry_countdown) { + id(static_char_retry_counter)++; + ESP_LOGI("test", "Static const char retry %d", id(static_char_retry_counter)); + return RetryResult::DONE; + }); + + // Cancel with same static const char* + App.scheduler.set_timeout(component, "static_cancel", 10, []() { + static const char* STATIC_NAME = "static_retry_test"; + bool result = App.scheduler.cancel_retry(id(backoff_retry_sensor), STATIC_NAME); + ESP_LOGI("test", "Static cancel result: %s", result ? "true" : "false"); + }); + + # Test 10: Mix string and const char* cancel + - logger.log: "=== Test 10: Mixed string/const char* ===" + - lambda: |- + auto *component = id(immediate_done_sensor); + + // Set with std::string + std::string str_name = "mixed_retry"; + App.scheduler.set_retry(component, str_name, 40, 3, + [](uint8_t retry_countdown) { + ESP_LOGI("test", "Mixed retry - should be cancelled"); + return RetryResult::RETRY; + }); + + // Cancel with const char* + id(mixed_cancel_result) = App.scheduler.cancel_retry(component, "mixed_retry"); + ESP_LOGI("test", "Mixed cancel result: %s", id(mixed_cancel_result) ? "true" : "false"); + # Wait for all tests to complete before reporting - delay: 500ms @@ -242,4 +301,7 @@ script: ESP_LOGI("test", "Empty name retry counter: %d (expected 1-2)", id(empty_name_retry_counter)); ESP_LOGI("test", "Component retry counter: %d (expected 2)", id(script_retry_counter)); ESP_LOGI("test", "Multiple same name counter: %d (expected 20+)", id(multiple_same_name_counter)); + ESP_LOGI("test", "Const char retry counter: %d (expected 1)", id(const_char_retry_counter)); + ESP_LOGI("test", "Static char retry counter: %d (expected 1)", id(static_char_retry_counter)); + ESP_LOGI("test", "Mixed cancel result: %s (expected true)", id(mixed_cancel_result) ? "true" : "false"); ESP_LOGI("test", "All retry tests completed"); diff --git a/tests/integration/test_scheduler_retry_test.py b/tests/integration/test_scheduler_retry_test.py index 1a469fcff1..c04b7197c9 100644 --- a/tests/integration/test_scheduler_retry_test.py +++ b/tests/integration/test_scheduler_retry_test.py @@ -23,6 +23,9 @@ async def test_scheduler_retry_test( empty_name_retry_done = asyncio.Event() component_retry_done = asyncio.Event() multiple_name_done = asyncio.Event() + const_char_done = asyncio.Event() + static_char_done = asyncio.Event() + mixed_cancel_done = asyncio.Event() test_complete = asyncio.Event() # Track retry counts @@ -33,16 +36,20 @@ async def test_scheduler_retry_test( empty_name_retry_count = 0 component_retry_count = 0 multiple_name_count = 0 + const_char_retry_count = 0 + static_char_retry_count = 0 # Track specific test results cancel_result = None empty_cancel_result = None + mixed_cancel_result = None backoff_intervals = [] def on_log_line(line: str) -> None: nonlocal simple_retry_count, backoff_retry_count, immediate_done_count nonlocal cancel_retry_count, empty_name_retry_count, component_retry_count - nonlocal multiple_name_count, cancel_result, empty_cancel_result + nonlocal multiple_name_count, const_char_retry_count, static_char_retry_count + nonlocal cancel_result, empty_cancel_result, mixed_cancel_result # Strip ANSI color codes clean_line = re.sub(r"\x1b\[[0-9;]*m", "", line) @@ -106,6 +113,27 @@ async def test_scheduler_retry_test( if multiple_name_count >= 20: multiple_name_done.set() + # Const char retry test + elif "Const char retry" in clean_line: + if match := re.search(r"Const char retry (\d+)", clean_line): + const_char_retry_count = int(match.group(1)) + const_char_done.set() + + # Static const char retry test + elif "Static const char retry" in clean_line: + if match := re.search(r"Static const char retry (\d+)", clean_line): + static_char_retry_count = int(match.group(1)) + static_char_done.set() + + elif "Static cancel result:" in clean_line: + # This is part of test 9, but we don't track it separately + pass + + # Mixed cancel test + elif "Mixed cancel result:" in clean_line: + mixed_cancel_result = "true" in clean_line + mixed_cancel_done.set() + # Test completion elif "All retry tests completed" in clean_line: test_complete.set() @@ -227,6 +255,40 @@ async def test_scheduler_retry_test( f"Expected multiple name count >= 20 (second retry only), got {multiple_name_count}" ) + # Wait for const char retry test + try: + await asyncio.wait_for(const_char_done.wait(), timeout=1.0) + except TimeoutError: + pytest.fail( + f"Const char retry test did not complete. Count: {const_char_retry_count}" + ) + + assert const_char_retry_count == 1, ( + f"Expected 1 const char retry call, got {const_char_retry_count}" + ) + + # Wait for static char retry test + try: + await asyncio.wait_for(static_char_done.wait(), timeout=1.0) + except TimeoutError: + pytest.fail( + f"Static char retry test did not complete. Count: {static_char_retry_count}" + ) + + assert static_char_retry_count == 1, ( + f"Expected 1 static char retry call, got {static_char_retry_count}" + ) + + # Wait for mixed cancel test + try: + await asyncio.wait_for(mixed_cancel_done.wait(), timeout=1.0) + except TimeoutError: + pytest.fail("Mixed cancel test did not complete") + + assert mixed_cancel_result is True, ( + "Mixed string/const char cancel should have succeeded" + ) + # Wait for test completion try: await asyncio.wait_for(test_complete.wait(), timeout=1.0) From 59d466a6c8f88a470e24dbde4c8e7b797e75e5e9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 28 Jul 2025 10:55:41 -1000 Subject: [PATCH 12/28] [api] Remove unnecessary string copies from optional access (#9897) --- esphome/components/api/api_connection.cpp | 46 ++++++++-------- esphome/components/api/api_connection.h | 4 ++ esphome/components/api/proto.h | 5 +- .../fixtures/host_mode_many_entities.yaml | 53 +++++++++++++++++++ .../test_host_mode_many_entities.py | 21 +++++++- 5 files changed, 104 insertions(+), 25 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index e0d4ec0cc8..d5e9f61427 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -244,21 +244,7 @@ void APIConnection::loop() { #ifdef USE_API_HOMEASSISTANT_STATES if (state_subs_at_ >= 0) { - const auto &subs = this->parent_->get_state_subs(); - if (state_subs_at_ < static_cast(subs.size())) { - auto &it = subs[state_subs_at_]; - SubscribeHomeAssistantStateResponse resp; - resp.set_entity_id(StringRef(it.entity_id)); - // attribute.value() returns temporary - must store it - std::string attribute_value = it.attribute.value(); - resp.set_attribute(StringRef(attribute_value)); - resp.once = it.once; - if (this->send_message(resp, SubscribeHomeAssistantStateResponse::MESSAGE_TYPE)) { - state_subs_at_++; - } - } else { - state_subs_at_ = -1; - } + this->process_state_subscriptions_(); } #endif } @@ -644,17 +630,13 @@ uint16_t APIConnection::try_send_climate_state(EntityBase *entity, APIConnection if (traits.get_supports_fan_modes() && climate->fan_mode.has_value()) resp.fan_mode = static_cast(climate->fan_mode.value()); if (!traits.get_supported_custom_fan_modes().empty() && climate->custom_fan_mode.has_value()) { - // custom_fan_mode.value() returns temporary - must store it - std::string custom_fan_mode = climate->custom_fan_mode.value(); - resp.set_custom_fan_mode(StringRef(custom_fan_mode)); + resp.set_custom_fan_mode(StringRef(climate->custom_fan_mode.value())); } if (traits.get_supports_presets() && climate->preset.has_value()) { resp.preset = static_cast(climate->preset.value()); } if (!traits.get_supported_custom_presets().empty() && climate->custom_preset.has_value()) { - // custom_preset.value() returns temporary - must store it - std::string custom_preset = climate->custom_preset.value(); - resp.set_custom_preset(StringRef(custom_preset)); + resp.set_custom_preset(StringRef(climate->custom_preset.value())); } if (traits.get_supports_swing_modes()) resp.swing_mode = static_cast(climate->swing_mode); @@ -1843,5 +1825,27 @@ uint16_t APIConnection::try_send_ping_request(EntityBase *entity, APIConnection return encode_message_to_buffer(req, PingRequest::MESSAGE_TYPE, conn, remaining_size, is_single); } +#ifdef USE_API_HOMEASSISTANT_STATES +void APIConnection::process_state_subscriptions_() { + const auto &subs = this->parent_->get_state_subs(); + if (this->state_subs_at_ >= static_cast(subs.size())) { + this->state_subs_at_ = -1; + return; + } + + const auto &it = subs[this->state_subs_at_]; + SubscribeHomeAssistantStateResponse resp; + resp.set_entity_id(StringRef(it.entity_id)); + + // Avoid string copy by directly using the optional's value if it exists + resp.set_attribute(it.attribute.has_value() ? StringRef(it.attribute.value()) : StringRef("")); + + resp.once = it.once; + if (this->send_message(resp, SubscribeHomeAssistantStateResponse::MESSAGE_TYPE)) { + this->state_subs_at_++; + } +} +#endif // USE_API_HOMEASSISTANT_STATES + } // namespace esphome::api #endif diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 3c446c431b..f57d37f5a5 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -298,6 +298,10 @@ class APIConnection : public APIServerConnection { // Helper function to handle authentication completion void complete_authentication_(); +#ifdef USE_API_HOMEASSISTANT_STATES + void process_state_subscriptions_(); +#endif + // Non-template helper to encode any ProtoMessage static uint16_t encode_message_to_buffer(ProtoMessage &msg, uint8_t message_type, APIConnection *conn, uint32_t remaining_size, bool is_single); diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 771eaa98d1..cea93f928f 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -35,11 +35,10 @@ namespace esphome::api { * * Unsafe Patterns (WILL cause crashes/corruption): * 1. Temporaries: msg.set_field(StringRef(obj.get_string())) // get_string() returns by value - * 2. Optional values: msg.set_field(StringRef(optional.value())) // value() returns a copy - * 3. Concatenation: msg.set_field(StringRef(str1 + str2)) // Result is temporary + * 2. Concatenation: msg.set_field(StringRef(str1 + str2)) // Result is temporary * * For unsafe patterns, store in a local variable first: - * std::string temp = optional.value(); // or get_string() or str1 + str2 + * std::string temp = get_string(); // or str1 + str2 * msg.set_field(StringRef(temp)); * * The send_*_response pattern ensures proper lifetime management by encoding diff --git a/tests/integration/fixtures/host_mode_many_entities.yaml b/tests/integration/fixtures/host_mode_many_entities.yaml index 3d1aa36196..5e085a15c9 100644 --- a/tests/integration/fixtures/host_mode_many_entities.yaml +++ b/tests/integration/fixtures/host_mode_many_entities.yaml @@ -210,6 +210,15 @@ sensor: name: "Test Sensor 50" lambda: return 50.0; update_interval: 0.1s + # Temperature sensor for the thermostat + - platform: template + name: "Temperature Sensor" + id: temp_sensor + lambda: return 22.5; + unit_of_measurement: "°C" + device_class: temperature + state_class: measurement + update_interval: 5s # Mixed entity types for comprehensive batching test binary_sensor: @@ -285,6 +294,50 @@ valve: stop_action: - logger.log: "Valve stopping" +output: + - platform: template + id: heater_output + type: binary + write_action: + - logger.log: "Heater output changed" + - platform: template + id: cooler_output + type: binary + write_action: + - logger.log: "Cooler output changed" + +climate: + - platform: thermostat + name: "Test Thermostat" + sensor: temp_sensor + default_preset: Home + on_boot_restore_from: default_preset + min_heating_off_time: 1s + min_heating_run_time: 1s + min_cooling_off_time: 1s + min_cooling_run_time: 1s + min_idle_time: 1s + heat_action: + - output.turn_on: heater_output + cool_action: + - output.turn_on: cooler_output + idle_action: + - output.turn_off: heater_output + - output.turn_off: cooler_output + preset: + - name: Home + default_target_temperature_low: 20 + default_target_temperature_high: 24 + mode: heat_cool + - name: Away + default_target_temperature_low: 16 + default_target_temperature_high: 26 + mode: heat_cool + - name: Sleep + default_target_temperature_low: 18 + default_target_temperature_high: 22 + mode: heat_cool + alarm_control_panel: - platform: template name: "Test Alarm" diff --git a/tests/integration/test_host_mode_many_entities.py b/tests/integration/test_host_mode_many_entities.py index ce9e157a88..aaca4555f6 100644 --- a/tests/integration/test_host_mode_many_entities.py +++ b/tests/integration/test_host_mode_many_entities.py @@ -4,7 +4,7 @@ from __future__ import annotations import asyncio -from aioesphomeapi import EntityState, SensorState +from aioesphomeapi import ClimateInfo, EntityState, SensorState import pytest from .types import APIClientConnectedFactory, RunCompiledFunction @@ -70,3 +70,22 @@ async def test_host_mode_many_entities( assert len(sensor_states) >= 50, ( f"Expected at least 50 sensor states, got {len(sensor_states)}" ) + + # Get entity info to verify climate entity details + entities = await client.list_entities_services() + climate_infos = [e for e in entities[0] if isinstance(e, ClimateInfo)] + assert len(climate_infos) >= 1, "Expected at least 1 climate entity" + + climate_info = climate_infos[0] + # Verify the thermostat has presets + assert len(climate_info.supported_presets) > 0, ( + "Expected climate to have presets" + ) + # The thermostat platform uses standard presets (Home, Away, Sleep) + # which should be transmitted properly without string copies + + # Verify specific presets exist + preset_names = [p.name for p in climate_info.supported_presets] + assert "HOME" in preset_names, f"Expected 'HOME' preset, got {preset_names}" + assert "AWAY" in preset_names, f"Expected 'AWAY' preset, got {preset_names}" + assert "SLEEP" in preset_names, f"Expected 'SLEEP' preset, got {preset_names}" From 08defd7360e21ccb2acc6a3d46b061e3c67ca017 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Jul 2025 11:02:53 -1000 Subject: [PATCH 13/28] Bump aioesphomeapi from 37.1.2 to 37.1.3 (#9943) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 80bd470f02..9889e83910 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.18 # When updating platformio, also update /docker/Dockerfile esptool==4.9.0 click==8.1.7 esphome-dashboard==20250514.0 -aioesphomeapi==37.1.2 +aioesphomeapi==37.1.3 zeroconf==0.147.0 puremagic==1.30 ruamel.yaml==0.18.14 # dashboard_import From 189d20a822e782495c572ea0bf47dd32b322b799 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 29 Jul 2025 09:21:53 +1200 Subject: [PATCH 14/28] [heatpumpir] Bump library to 1.0.37 (#9944) --- .clang-tidy.hash | 2 +- esphome/components/heatpumpir/climate.py | 2 +- platformio.ini | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index 316f43e706..02b528b0d6 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -32b0db73b3ae01ba18c9cbb1dabbd8156bc14dded500471919bd0a3dc33916e0 +b7056e39f1484500ca2d237068670b789fe9241786b48da0681d646b25af05d5 diff --git a/esphome/components/heatpumpir/climate.py b/esphome/components/heatpumpir/climate.py index 0f9f146ae9..d2b907d437 100644 --- a/esphome/components/heatpumpir/climate.py +++ b/esphome/components/heatpumpir/climate.py @@ -126,6 +126,6 @@ async def to_code(config): cg.add(var.set_max_temperature(config[CONF_MAX_TEMPERATURE])) cg.add(var.set_min_temperature(config[CONF_MIN_TEMPERATURE])) - cg.add_library("tonia/HeatpumpIR", "1.0.35") + cg.add_library("tonia/HeatpumpIR", "1.0.37") if CORE.is_libretiny: CORE.add_platformio_option("lib_ignore", "IRremoteESP8266") diff --git a/platformio.ini b/platformio.ini index bf0754ead3..5956ae8117 100644 --- a/platformio.ini +++ b/platformio.ini @@ -78,7 +78,7 @@ lib_deps = glmnet/Dsmr@0.7 ; dsmr rweather/Crypto@0.4.0 ; dsmr dudanov/MideaUART@1.1.9 ; midea - tonia/HeatpumpIR@1.0.35 ; heatpumpir + tonia/HeatpumpIR@1.0.37 ; heatpumpir build_flags = ${common.build_flags} -DUSE_ARDUINO From 68f388f78e14d9374156caa37b858fba2cbf90c7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 28 Jul 2025 12:25:07 -1000 Subject: [PATCH 15/28] [api] Optimize protobuf empty message handling to reduce flash and runtime overhead (#9908) --- esphome/components/api/api_pb2.h | 26 +++++++++++----------- esphome/components/api/api_pb2_service.cpp | 26 +++++++++++----------- script/api_protobuf/api_protobuf.py | 18 ++++++++++++--- 3 files changed, 41 insertions(+), 29 deletions(-) diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index fb8174f988..47bdaead23 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -378,7 +378,7 @@ class ConnectResponse : public ProtoMessage { protected: }; -class DisconnectRequest : public ProtoDecodableMessage { +class DisconnectRequest : public ProtoMessage { public: static constexpr uint8_t MESSAGE_TYPE = 5; static constexpr uint8_t ESTIMATED_SIZE = 0; @@ -391,7 +391,7 @@ class DisconnectRequest : public ProtoDecodableMessage { protected: }; -class DisconnectResponse : public ProtoDecodableMessage { +class DisconnectResponse : public ProtoMessage { public: static constexpr uint8_t MESSAGE_TYPE = 6; static constexpr uint8_t ESTIMATED_SIZE = 0; @@ -404,7 +404,7 @@ class DisconnectResponse : public ProtoDecodableMessage { protected: }; -class PingRequest : public ProtoDecodableMessage { +class PingRequest : public ProtoMessage { public: static constexpr uint8_t MESSAGE_TYPE = 7; static constexpr uint8_t ESTIMATED_SIZE = 0; @@ -417,7 +417,7 @@ class PingRequest : public ProtoDecodableMessage { protected: }; -class PingResponse : public ProtoDecodableMessage { +class PingResponse : public ProtoMessage { public: static constexpr uint8_t MESSAGE_TYPE = 8; static constexpr uint8_t ESTIMATED_SIZE = 0; @@ -430,7 +430,7 @@ class PingResponse : public ProtoDecodableMessage { protected: }; -class DeviceInfoRequest : public ProtoDecodableMessage { +class DeviceInfoRequest : public ProtoMessage { public: static constexpr uint8_t MESSAGE_TYPE = 9; static constexpr uint8_t ESTIMATED_SIZE = 0; @@ -546,7 +546,7 @@ class DeviceInfoResponse : public ProtoMessage { protected: }; -class ListEntitiesRequest : public ProtoDecodableMessage { +class ListEntitiesRequest : public ProtoMessage { public: static constexpr uint8_t MESSAGE_TYPE = 11; static constexpr uint8_t ESTIMATED_SIZE = 0; @@ -572,7 +572,7 @@ class ListEntitiesDoneResponse : public ProtoMessage { protected: }; -class SubscribeStatesRequest : public ProtoDecodableMessage { +class SubscribeStatesRequest : public ProtoMessage { public: static constexpr uint8_t MESSAGE_TYPE = 20; static constexpr uint8_t ESTIMATED_SIZE = 0; @@ -1045,7 +1045,7 @@ class NoiseEncryptionSetKeyResponse : public ProtoMessage { }; #endif #ifdef USE_API_HOMEASSISTANT_SERVICES -class SubscribeHomeassistantServicesRequest : public ProtoDecodableMessage { +class SubscribeHomeassistantServicesRequest : public ProtoMessage { public: static constexpr uint8_t MESSAGE_TYPE = 34; static constexpr uint8_t ESTIMATED_SIZE = 0; @@ -1094,7 +1094,7 @@ class HomeassistantServiceResponse : public ProtoMessage { }; #endif #ifdef USE_API_HOMEASSISTANT_STATES -class SubscribeHomeAssistantStatesRequest : public ProtoDecodableMessage { +class SubscribeHomeAssistantStatesRequest : public ProtoMessage { public: static constexpr uint8_t MESSAGE_TYPE = 38; static constexpr uint8_t ESTIMATED_SIZE = 0; @@ -1145,7 +1145,7 @@ class HomeAssistantStateResponse : public ProtoDecodableMessage { bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; }; #endif -class GetTimeRequest : public ProtoDecodableMessage { +class GetTimeRequest : public ProtoMessage { public: static constexpr uint8_t MESSAGE_TYPE = 36; static constexpr uint8_t ESTIMATED_SIZE = 0; @@ -2043,7 +2043,7 @@ class BluetoothGATTNotifyDataResponse : public ProtoMessage { protected: }; -class SubscribeBluetoothConnectionsFreeRequest : public ProtoDecodableMessage { +class SubscribeBluetoothConnectionsFreeRequest : public ProtoMessage { public: static constexpr uint8_t MESSAGE_TYPE = 80; static constexpr uint8_t ESTIMATED_SIZE = 0; @@ -2162,7 +2162,7 @@ class BluetoothDeviceUnpairingResponse : public ProtoMessage { protected: }; -class UnsubscribeBluetoothLEAdvertisementsRequest : public ProtoDecodableMessage { +class UnsubscribeBluetoothLEAdvertisementsRequest : public ProtoMessage { public: static constexpr uint8_t MESSAGE_TYPE = 87; static constexpr uint8_t ESTIMATED_SIZE = 0; @@ -2418,7 +2418,7 @@ class VoiceAssistantWakeWord : public ProtoMessage { protected: }; -class VoiceAssistantConfigurationRequest : public ProtoDecodableMessage { +class VoiceAssistantConfigurationRequest : public ProtoMessage { public: static constexpr uint8_t MESSAGE_TYPE = 121; static constexpr uint8_t ESTIMATED_SIZE = 0; diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index 26d5b12d00..6b7b8b9ebd 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -35,7 +35,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, } case DisconnectRequest::MESSAGE_TYPE: { DisconnectRequest msg; - msg.decode(msg_data, msg_size); + // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP ESP_LOGVV(TAG, "on_disconnect_request: %s", msg.dump().c_str()); #endif @@ -44,7 +44,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, } case DisconnectResponse::MESSAGE_TYPE: { DisconnectResponse msg; - msg.decode(msg_data, msg_size); + // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP ESP_LOGVV(TAG, "on_disconnect_response: %s", msg.dump().c_str()); #endif @@ -53,7 +53,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, } case PingRequest::MESSAGE_TYPE: { PingRequest msg; - msg.decode(msg_data, msg_size); + // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP ESP_LOGVV(TAG, "on_ping_request: %s", msg.dump().c_str()); #endif @@ -62,7 +62,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, } case PingResponse::MESSAGE_TYPE: { PingResponse msg; - msg.decode(msg_data, msg_size); + // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP ESP_LOGVV(TAG, "on_ping_response: %s", msg.dump().c_str()); #endif @@ -71,7 +71,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, } case DeviceInfoRequest::MESSAGE_TYPE: { DeviceInfoRequest msg; - msg.decode(msg_data, msg_size); + // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP ESP_LOGVV(TAG, "on_device_info_request: %s", msg.dump().c_str()); #endif @@ -80,7 +80,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, } case ListEntitiesRequest::MESSAGE_TYPE: { ListEntitiesRequest msg; - msg.decode(msg_data, msg_size); + // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP ESP_LOGVV(TAG, "on_list_entities_request: %s", msg.dump().c_str()); #endif @@ -89,7 +89,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, } case SubscribeStatesRequest::MESSAGE_TYPE: { SubscribeStatesRequest msg; - msg.decode(msg_data, msg_size); + // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP ESP_LOGVV(TAG, "on_subscribe_states_request: %s", msg.dump().c_str()); #endif @@ -152,7 +152,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, #ifdef USE_API_HOMEASSISTANT_SERVICES case SubscribeHomeassistantServicesRequest::MESSAGE_TYPE: { SubscribeHomeassistantServicesRequest msg; - msg.decode(msg_data, msg_size); + // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP ESP_LOGVV(TAG, "on_subscribe_homeassistant_services_request: %s", msg.dump().c_str()); #endif @@ -162,7 +162,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, #endif case GetTimeRequest::MESSAGE_TYPE: { GetTimeRequest msg; - msg.decode(msg_data, msg_size); + // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP ESP_LOGVV(TAG, "on_get_time_request: %s", msg.dump().c_str()); #endif @@ -181,7 +181,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, #ifdef USE_API_HOMEASSISTANT_STATES case SubscribeHomeAssistantStatesRequest::MESSAGE_TYPE: { SubscribeHomeAssistantStatesRequest msg; - msg.decode(msg_data, msg_size); + // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP ESP_LOGVV(TAG, "on_subscribe_home_assistant_states_request: %s", msg.dump().c_str()); #endif @@ -390,7 +390,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, #ifdef USE_BLUETOOTH_PROXY case SubscribeBluetoothConnectionsFreeRequest::MESSAGE_TYPE: { SubscribeBluetoothConnectionsFreeRequest msg; - msg.decode(msg_data, msg_size); + // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP ESP_LOGVV(TAG, "on_subscribe_bluetooth_connections_free_request: %s", msg.dump().c_str()); #endif @@ -401,7 +401,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, #ifdef USE_BLUETOOTH_PROXY case UnsubscribeBluetoothLEAdvertisementsRequest::MESSAGE_TYPE: { UnsubscribeBluetoothLEAdvertisementsRequest msg; - msg.decode(msg_data, msg_size); + // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP ESP_LOGVV(TAG, "on_unsubscribe_bluetooth_le_advertisements_request: %s", msg.dump().c_str()); #endif @@ -555,7 +555,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, #ifdef USE_VOICE_ASSISTANT case VoiceAssistantConfigurationRequest::MESSAGE_TYPE: { VoiceAssistantConfigurationRequest msg; - msg.decode(msg_data, msg_size); + // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP ESP_LOGVV(TAG, "on_voice_assistant_configuration_request: %s", msg.dump().c_str()); #endif diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 4b9a61383d..d346b66aef 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -1772,8 +1772,13 @@ def build_message_type( if base_class: out = f"class {desc.name} : public {base_class} {{\n" else: - # Determine inheritance based on whether the message needs decoding - base_class = "ProtoDecodableMessage" if needs_decode else "ProtoMessage" + # Check if message has any non-deprecated fields + has_fields = any(not field.options.deprecated for field in desc.field) + # Determine inheritance based on whether the message needs decoding and has fields + if needs_decode and has_fields: + base_class = "ProtoDecodableMessage" + else: + base_class = "ProtoMessage" out = f"class {desc.name} : public {base_class} {{\n" out += " public:\n" out += indent("\n".join(public_content)) + "\n" @@ -2039,7 +2044,14 @@ def build_service_message_type( hout += f"virtual void {func}(const {mt.name} &value){{}};\n" case = "" case += f"{mt.name} msg;\n" - case += "msg.decode(msg_data, msg_size);\n" + # Check if this message has any fields (excluding deprecated ones) + has_fields = any(not field.options.deprecated for field in mt.field) + if has_fields: + # Normal case: decode the message + case += "msg.decode(msg_data, msg_size);\n" + else: + # Empty message optimization: skip decode since there are no fields + case += "// Empty message: no decode needed\n" if log: case += "#ifdef HAS_PROTO_MESSAGE_DUMP\n" case += f'ESP_LOGVV(TAG, "{func}: %s", msg.dump().c_str());\n' From 2c9987869e6533dc3f47936368b3dcac822d82fd Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 28 Jul 2025 12:28:32 -1000 Subject: [PATCH 16/28] [api] Align ProtoSize API design with ProtoWriteBuffer pattern (#9920) --- esphome/components/api/api_connection.cpp | 5 +- esphome/components/api/api_pb2.cpp | 1118 ++++++++++----------- esphome/components/api/api_pb2.h | 166 +-- esphome/components/api/proto.h | 293 +++--- script/api_protobuf/api_protobuf.py | 78 +- 5 files changed, 795 insertions(+), 865 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index d5e9f61427..cd27087fe8 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -276,8 +276,9 @@ uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint8_t mess #endif // Calculate size - uint32_t calculated_size = 0; - msg.calculate_size(calculated_size); + ProtoSize size_calc; + msg.calculate_size(size_calc); + uint32_t calculated_size = size_calc.get_size(); // Cache frame sizes to avoid repeated virtual calls const uint8_t header_padding = conn->helper_->frame_header_padding(); diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index b587ee5f03..f6f39f901f 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -36,11 +36,11 @@ void HelloResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_string(3, this->server_info_ref_); buffer.encode_string(4, this->name_ref_); } -void HelloResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_uint32_field(total_size, 1, this->api_version_major); - ProtoSize::add_uint32_field(total_size, 1, this->api_version_minor); - ProtoSize::add_string_field(total_size, 1, this->server_info_ref_.size()); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); +void HelloResponse::calculate_size(ProtoSize &size) const { + size.add_uint32(1, this->api_version_major); + size.add_uint32(1, this->api_version_minor); + size.add_length(1, this->server_info_ref_.size()); + size.add_length(1, this->name_ref_.size()); } bool ConnectRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { switch (field_id) { @@ -53,17 +53,15 @@ bool ConnectRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value return true; } void ConnectResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_bool(1, this->invalid_password); } -void ConnectResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_bool_field(total_size, 1, this->invalid_password); -} +void ConnectResponse::calculate_size(ProtoSize &size) const { size.add_bool(1, this->invalid_password); } #ifdef USE_AREAS void AreaInfo::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(1, this->area_id); buffer.encode_string(2, this->name_ref_); } -void AreaInfo::calculate_size(uint32_t &total_size) const { - ProtoSize::add_uint32_field(total_size, 1, this->area_id); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); +void AreaInfo::calculate_size(ProtoSize &size) const { + size.add_uint32(1, this->area_id); + size.add_length(1, this->name_ref_.size()); } #endif #ifdef USE_DEVICES @@ -72,10 +70,10 @@ void DeviceInfo::encode(ProtoWriteBuffer buffer) const { buffer.encode_string(2, this->name_ref_); buffer.encode_uint32(3, this->area_id); } -void DeviceInfo::calculate_size(uint32_t &total_size) const { - ProtoSize::add_uint32_field(total_size, 1, this->device_id); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); - ProtoSize::add_uint32_field(total_size, 1, this->area_id); +void DeviceInfo::calculate_size(ProtoSize &size) const { + size.add_uint32(1, this->device_id); + size.add_length(1, this->name_ref_.size()); + size.add_uint32(1, this->area_id); } #endif void DeviceInfoResponse::encode(ProtoWriteBuffer buffer) const { @@ -130,52 +128,52 @@ void DeviceInfoResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_message(22, this->area); #endif } -void DeviceInfoResponse::calculate_size(uint32_t &total_size) const { +void DeviceInfoResponse::calculate_size(ProtoSize &size) const { #ifdef USE_API_PASSWORD - ProtoSize::add_bool_field(total_size, 1, this->uses_password); + size.add_bool(1, this->uses_password); #endif - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); - ProtoSize::add_string_field(total_size, 1, this->mac_address_ref_.size()); - ProtoSize::add_string_field(total_size, 1, this->esphome_version_ref_.size()); - ProtoSize::add_string_field(total_size, 1, this->compilation_time_ref_.size()); - ProtoSize::add_string_field(total_size, 1, this->model_ref_.size()); + size.add_length(1, this->name_ref_.size()); + size.add_length(1, this->mac_address_ref_.size()); + size.add_length(1, this->esphome_version_ref_.size()); + size.add_length(1, this->compilation_time_ref_.size()); + size.add_length(1, this->model_ref_.size()); #ifdef USE_DEEP_SLEEP - ProtoSize::add_bool_field(total_size, 1, this->has_deep_sleep); + size.add_bool(1, this->has_deep_sleep); #endif #ifdef ESPHOME_PROJECT_NAME - ProtoSize::add_string_field(total_size, 1, this->project_name_ref_.size()); + size.add_length(1, this->project_name_ref_.size()); #endif #ifdef ESPHOME_PROJECT_NAME - ProtoSize::add_string_field(total_size, 1, this->project_version_ref_.size()); + size.add_length(1, this->project_version_ref_.size()); #endif #ifdef USE_WEBSERVER - ProtoSize::add_uint32_field(total_size, 1, this->webserver_port); + size.add_uint32(1, this->webserver_port); #endif #ifdef USE_BLUETOOTH_PROXY - ProtoSize::add_uint32_field(total_size, 1, this->bluetooth_proxy_feature_flags); + size.add_uint32(1, this->bluetooth_proxy_feature_flags); #endif - ProtoSize::add_string_field(total_size, 1, this->manufacturer_ref_.size()); - ProtoSize::add_string_field(total_size, 1, this->friendly_name_ref_.size()); + size.add_length(1, this->manufacturer_ref_.size()); + size.add_length(1, this->friendly_name_ref_.size()); #ifdef USE_VOICE_ASSISTANT - ProtoSize::add_uint32_field(total_size, 2, this->voice_assistant_feature_flags); + size.add_uint32(2, this->voice_assistant_feature_flags); #endif #ifdef USE_AREAS - ProtoSize::add_string_field(total_size, 2, this->suggested_area_ref_.size()); + size.add_length(2, this->suggested_area_ref_.size()); #endif #ifdef USE_BLUETOOTH_PROXY - ProtoSize::add_string_field(total_size, 2, this->bluetooth_mac_address_ref_.size()); + size.add_length(2, this->bluetooth_mac_address_ref_.size()); #endif #ifdef USE_API_NOISE - ProtoSize::add_bool_field(total_size, 2, this->api_encryption_supported); + size.add_bool(2, this->api_encryption_supported); #endif #ifdef USE_DEVICES - ProtoSize::add_repeated_message(total_size, 2, this->devices); + size.add_repeated_message(2, this->devices); #endif #ifdef USE_AREAS - ProtoSize::add_repeated_message(total_size, 2, this->areas); + size.add_repeated_message(2, this->areas); #endif #ifdef USE_AREAS - ProtoSize::add_message_object(total_size, 2, this->area); + size.add_message_object(2, this->area); #endif } #ifdef USE_BINARY_SENSOR @@ -194,19 +192,19 @@ void ListEntitiesBinarySensorResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(10, this->device_id); #endif } -void ListEntitiesBinarySensorResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); - ProtoSize::add_string_field(total_size, 1, this->device_class_ref_.size()); - ProtoSize::add_bool_field(total_size, 1, this->is_status_binary_sensor); - ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default); +void ListEntitiesBinarySensorResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); + size.add_length(1, this->device_class_ref_.size()); + size.add_bool(1, this->is_status_binary_sensor); + size.add_bool(1, this->disabled_by_default); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 1, this->icon_ref_.size()); + size.add_length(1, this->icon_ref_.size()); #endif - ProtoSize::add_enum_field(total_size, 1, static_cast(this->entity_category)); + size.add_uint32(1, static_cast(this->entity_category)); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } void BinarySensorStateResponse::encode(ProtoWriteBuffer buffer) const { @@ -217,12 +215,12 @@ void BinarySensorStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(4, this->device_id); #endif } -void BinarySensorStateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_bool_field(total_size, 1, this->state); - ProtoSize::add_bool_field(total_size, 1, this->missing_state); +void BinarySensorStateResponse::calculate_size(ProtoSize &size) const { + size.add_fixed32(1, this->key); + size.add_bool(1, this->state); + size.add_bool(1, this->missing_state); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } #endif @@ -245,22 +243,22 @@ void ListEntitiesCoverResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(13, this->device_id); #endif } -void ListEntitiesCoverResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); - ProtoSize::add_bool_field(total_size, 1, this->assumed_state); - ProtoSize::add_bool_field(total_size, 1, this->supports_position); - ProtoSize::add_bool_field(total_size, 1, this->supports_tilt); - ProtoSize::add_string_field(total_size, 1, this->device_class_ref_.size()); - ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default); +void ListEntitiesCoverResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); + size.add_bool(1, this->assumed_state); + size.add_bool(1, this->supports_position); + size.add_bool(1, this->supports_tilt); + size.add_length(1, this->device_class_ref_.size()); + size.add_bool(1, this->disabled_by_default); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 1, this->icon_ref_.size()); + size.add_length(1, this->icon_ref_.size()); #endif - ProtoSize::add_enum_field(total_size, 1, static_cast(this->entity_category)); - ProtoSize::add_bool_field(total_size, 1, this->supports_stop); + size.add_uint32(1, static_cast(this->entity_category)); + size.add_bool(1, this->supports_stop); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } void CoverStateResponse::encode(ProtoWriteBuffer buffer) const { @@ -272,13 +270,13 @@ void CoverStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(6, this->device_id); #endif } -void CoverStateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_float_field(total_size, 1, this->position); - ProtoSize::add_float_field(total_size, 1, this->tilt); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->current_operation)); +void CoverStateResponse::calculate_size(ProtoSize &size) const { + size.add_fixed32(1, this->key); + size.add_float(1, this->position); + size.add_float(1, this->tilt); + size.add_uint32(1, static_cast(this->current_operation)); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } bool CoverCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { @@ -340,26 +338,26 @@ void ListEntitiesFanResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(13, this->device_id); #endif } -void ListEntitiesFanResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); - ProtoSize::add_bool_field(total_size, 1, this->supports_oscillation); - ProtoSize::add_bool_field(total_size, 1, this->supports_speed); - ProtoSize::add_bool_field(total_size, 1, this->supports_direction); - ProtoSize::add_int32_field(total_size, 1, this->supported_speed_count); - ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default); +void ListEntitiesFanResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); + size.add_bool(1, this->supports_oscillation); + size.add_bool(1, this->supports_speed); + size.add_bool(1, this->supports_direction); + size.add_int32(1, this->supported_speed_count); + size.add_bool(1, this->disabled_by_default); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 1, this->icon_ref_.size()); + size.add_length(1, this->icon_ref_.size()); #endif - ProtoSize::add_enum_field(total_size, 1, static_cast(this->entity_category)); + size.add_uint32(1, static_cast(this->entity_category)); if (!this->supported_preset_modes.empty()) { for (const auto &it : this->supported_preset_modes) { - ProtoSize::add_string_field_repeated(total_size, 1, it); + size.add_length_force(1, it.size()); } } #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } void FanStateResponse::encode(ProtoWriteBuffer buffer) const { @@ -373,15 +371,15 @@ void FanStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(8, this->device_id); #endif } -void FanStateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_bool_field(total_size, 1, this->state); - ProtoSize::add_bool_field(total_size, 1, this->oscillating); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->direction)); - ProtoSize::add_int32_field(total_size, 1, this->speed_level); - ProtoSize::add_string_field(total_size, 1, this->preset_mode_ref_.size()); +void FanStateResponse::calculate_size(ProtoSize &size) const { + size.add_fixed32(1, this->key); + size.add_bool(1, this->state); + size.add_bool(1, this->oscillating); + size.add_uint32(1, static_cast(this->direction)); + size.add_int32(1, this->speed_level); + size.add_length(1, this->preset_mode_ref_.size()); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } bool FanCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { @@ -466,29 +464,29 @@ void ListEntitiesLightResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(16, this->device_id); #endif } -void ListEntitiesLightResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); +void ListEntitiesLightResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); if (!this->supported_color_modes.empty()) { for (const auto &it : this->supported_color_modes) { - ProtoSize::add_enum_field_repeated(total_size, 1, static_cast(it)); + size.add_uint32_force(1, static_cast(it)); } } - ProtoSize::add_float_field(total_size, 1, this->min_mireds); - ProtoSize::add_float_field(total_size, 1, this->max_mireds); + size.add_float(1, this->min_mireds); + size.add_float(1, this->max_mireds); if (!this->effects.empty()) { for (const auto &it : this->effects) { - ProtoSize::add_string_field_repeated(total_size, 1, it); + size.add_length_force(1, it.size()); } } - ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default); + size.add_bool(1, this->disabled_by_default); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 1, this->icon_ref_.size()); + size.add_length(1, this->icon_ref_.size()); #endif - ProtoSize::add_enum_field(total_size, 1, static_cast(this->entity_category)); + size.add_uint32(1, static_cast(this->entity_category)); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 2, this->device_id); + size.add_uint32(2, this->device_id); #endif } void LightStateResponse::encode(ProtoWriteBuffer buffer) const { @@ -509,22 +507,22 @@ void LightStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(14, this->device_id); #endif } -void LightStateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_bool_field(total_size, 1, this->state); - ProtoSize::add_float_field(total_size, 1, this->brightness); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->color_mode)); - ProtoSize::add_float_field(total_size, 1, this->color_brightness); - ProtoSize::add_float_field(total_size, 1, this->red); - ProtoSize::add_float_field(total_size, 1, this->green); - ProtoSize::add_float_field(total_size, 1, this->blue); - ProtoSize::add_float_field(total_size, 1, this->white); - ProtoSize::add_float_field(total_size, 1, this->color_temperature); - ProtoSize::add_float_field(total_size, 1, this->cold_white); - ProtoSize::add_float_field(total_size, 1, this->warm_white); - ProtoSize::add_string_field(total_size, 1, this->effect_ref_.size()); +void LightStateResponse::calculate_size(ProtoSize &size) const { + size.add_fixed32(1, this->key); + size.add_bool(1, this->state); + size.add_float(1, this->brightness); + size.add_uint32(1, static_cast(this->color_mode)); + size.add_float(1, this->color_brightness); + size.add_float(1, this->red); + size.add_float(1, this->green); + size.add_float(1, this->blue); + size.add_float(1, this->white); + size.add_float(1, this->color_temperature); + size.add_float(1, this->cold_white); + size.add_float(1, this->warm_white); + size.add_length(1, this->effect_ref_.size()); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } bool LightCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { @@ -654,22 +652,22 @@ void ListEntitiesSensorResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(14, this->device_id); #endif } -void ListEntitiesSensorResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); +void ListEntitiesSensorResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 1, this->icon_ref_.size()); + size.add_length(1, this->icon_ref_.size()); #endif - ProtoSize::add_string_field(total_size, 1, this->unit_of_measurement_ref_.size()); - ProtoSize::add_int32_field(total_size, 1, this->accuracy_decimals); - ProtoSize::add_bool_field(total_size, 1, this->force_update); - ProtoSize::add_string_field(total_size, 1, this->device_class_ref_.size()); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->state_class)); - ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->entity_category)); + size.add_length(1, this->unit_of_measurement_ref_.size()); + size.add_int32(1, this->accuracy_decimals); + size.add_bool(1, this->force_update); + size.add_length(1, this->device_class_ref_.size()); + size.add_uint32(1, static_cast(this->state_class)); + size.add_bool(1, this->disabled_by_default); + size.add_uint32(1, static_cast(this->entity_category)); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } void SensorStateResponse::encode(ProtoWriteBuffer buffer) const { @@ -680,12 +678,12 @@ void SensorStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(4, this->device_id); #endif } -void SensorStateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_float_field(total_size, 1, this->state); - ProtoSize::add_bool_field(total_size, 1, this->missing_state); +void SensorStateResponse::calculate_size(ProtoSize &size) const { + size.add_fixed32(1, this->key); + size.add_float(1, this->state); + size.add_bool(1, this->missing_state); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } #endif @@ -705,19 +703,19 @@ void ListEntitiesSwitchResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(10, this->device_id); #endif } -void ListEntitiesSwitchResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); +void ListEntitiesSwitchResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 1, this->icon_ref_.size()); + size.add_length(1, this->icon_ref_.size()); #endif - ProtoSize::add_bool_field(total_size, 1, this->assumed_state); - ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->entity_category)); - ProtoSize::add_string_field(total_size, 1, this->device_class_ref_.size()); + size.add_bool(1, this->assumed_state); + size.add_bool(1, this->disabled_by_default); + size.add_uint32(1, static_cast(this->entity_category)); + size.add_length(1, this->device_class_ref_.size()); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } void SwitchStateResponse::encode(ProtoWriteBuffer buffer) const { @@ -727,11 +725,11 @@ void SwitchStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(3, this->device_id); #endif } -void SwitchStateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_bool_field(total_size, 1, this->state); +void SwitchStateResponse::calculate_size(ProtoSize &size) const { + size.add_fixed32(1, this->key); + size.add_bool(1, this->state); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } bool SwitchCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { @@ -775,18 +773,18 @@ void ListEntitiesTextSensorResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(9, this->device_id); #endif } -void ListEntitiesTextSensorResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); +void ListEntitiesTextSensorResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 1, this->icon_ref_.size()); + size.add_length(1, this->icon_ref_.size()); #endif - ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->entity_category)); - ProtoSize::add_string_field(total_size, 1, this->device_class_ref_.size()); + size.add_bool(1, this->disabled_by_default); + size.add_uint32(1, static_cast(this->entity_category)); + size.add_length(1, this->device_class_ref_.size()); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } void TextSensorStateResponse::encode(ProtoWriteBuffer buffer) const { @@ -797,12 +795,12 @@ void TextSensorStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(4, this->device_id); #endif } -void TextSensorStateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->state_ref_.size()); - ProtoSize::add_bool_field(total_size, 1, this->missing_state); +void TextSensorStateResponse::calculate_size(ProtoSize &size) const { + size.add_fixed32(1, this->key); + size.add_length(1, this->state_ref_.size()); + size.add_bool(1, this->missing_state); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } #endif @@ -823,9 +821,9 @@ void SubscribeLogsResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(1, static_cast(this->level)); buffer.encode_bytes(3, this->message_ptr_, this->message_len_); } -void SubscribeLogsResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_enum_field(total_size, 1, static_cast(this->level)); - ProtoSize::add_bytes_field(total_size, 1, this->message_len_); +void SubscribeLogsResponse::calculate_size(ProtoSize &size) const { + size.add_uint32(1, static_cast(this->level)); + size.add_length(1, this->message_len_); } #ifdef USE_API_NOISE bool NoiseEncryptionSetKeyRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { @@ -839,18 +837,16 @@ bool NoiseEncryptionSetKeyRequest::decode_length(uint32_t field_id, ProtoLengthD return true; } void NoiseEncryptionSetKeyResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_bool(1, this->success); } -void NoiseEncryptionSetKeyResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_bool_field(total_size, 1, this->success); -} +void NoiseEncryptionSetKeyResponse::calculate_size(ProtoSize &size) const { size.add_bool(1, this->success); } #endif #ifdef USE_API_HOMEASSISTANT_SERVICES void HomeassistantServiceMap::encode(ProtoWriteBuffer buffer) const { buffer.encode_string(1, this->key_ref_); buffer.encode_string(2, this->value); } -void HomeassistantServiceMap::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->key_ref_.size()); - ProtoSize::add_string_field(total_size, 1, this->value.size()); +void HomeassistantServiceMap::calculate_size(ProtoSize &size) const { + size.add_length(1, this->key_ref_.size()); + size.add_length(1, this->value.size()); } void HomeassistantServiceResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_string(1, this->service_ref_); @@ -865,12 +861,12 @@ void HomeassistantServiceResponse::encode(ProtoWriteBuffer buffer) const { } buffer.encode_bool(5, this->is_event); } -void HomeassistantServiceResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->service_ref_.size()); - ProtoSize::add_repeated_message(total_size, 1, this->data); - ProtoSize::add_repeated_message(total_size, 1, this->data_template); - ProtoSize::add_repeated_message(total_size, 1, this->variables); - ProtoSize::add_bool_field(total_size, 1, this->is_event); +void HomeassistantServiceResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->service_ref_.size()); + size.add_repeated_message(1, this->data); + size.add_repeated_message(1, this->data_template); + size.add_repeated_message(1, this->variables); + size.add_bool(1, this->is_event); } #endif #ifdef USE_API_HOMEASSISTANT_STATES @@ -879,10 +875,10 @@ void SubscribeHomeAssistantStateResponse::encode(ProtoWriteBuffer buffer) const buffer.encode_string(2, this->attribute_ref_); buffer.encode_bool(3, this->once); } -void SubscribeHomeAssistantStateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->entity_id_ref_.size()); - ProtoSize::add_string_field(total_size, 1, this->attribute_ref_.size()); - ProtoSize::add_bool_field(total_size, 1, this->once); +void SubscribeHomeAssistantStateResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->entity_id_ref_.size()); + size.add_length(1, this->attribute_ref_.size()); + size.add_bool(1, this->once); } bool HomeAssistantStateResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) { switch (field_id) { @@ -912,17 +908,15 @@ bool GetTimeResponse::decode_32bit(uint32_t field_id, Proto32Bit value) { return true; } void GetTimeResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_fixed32(1, this->epoch_seconds); } -void GetTimeResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->epoch_seconds); -} +void GetTimeResponse::calculate_size(ProtoSize &size) const { size.add_fixed32(1, this->epoch_seconds); } #ifdef USE_API_SERVICES void ListEntitiesServicesArgument::encode(ProtoWriteBuffer buffer) const { buffer.encode_string(1, this->name_ref_); buffer.encode_uint32(2, static_cast(this->type)); } -void ListEntitiesServicesArgument::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->type)); +void ListEntitiesServicesArgument::calculate_size(ProtoSize &size) const { + size.add_length(1, this->name_ref_.size()); + size.add_uint32(1, static_cast(this->type)); } void ListEntitiesServicesResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_string(1, this->name_ref_); @@ -931,10 +925,10 @@ void ListEntitiesServicesResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_message(3, it, true); } } -void ListEntitiesServicesResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_repeated_message(total_size, 1, this->args); +void ListEntitiesServicesResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->name_ref_.size()); + size.add_fixed32(1, this->key); + size.add_repeated_message(1, this->args); } bool ExecuteServiceArgument::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -1020,17 +1014,17 @@ void ListEntitiesCameraResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(8, this->device_id); #endif } -void ListEntitiesCameraResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); - ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default); +void ListEntitiesCameraResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); + size.add_bool(1, this->disabled_by_default); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 1, this->icon_ref_.size()); + size.add_length(1, this->icon_ref_.size()); #endif - ProtoSize::add_enum_field(total_size, 1, static_cast(this->entity_category)); + size.add_uint32(1, static_cast(this->entity_category)); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } void CameraImageResponse::encode(ProtoWriteBuffer buffer) const { @@ -1041,12 +1035,12 @@ void CameraImageResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(4, this->device_id); #endif } -void CameraImageResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_bytes_field(total_size, 1, this->data_len_); - ProtoSize::add_bool_field(total_size, 1, this->done); +void CameraImageResponse::calculate_size(ProtoSize &size) const { + size.add_fixed32(1, this->key); + size.add_length(1, this->data_len_); + size.add_bool(1, this->done); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } bool CameraImageRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { @@ -1106,58 +1100,58 @@ void ListEntitiesClimateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(26, this->device_id); #endif } -void ListEntitiesClimateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); - ProtoSize::add_bool_field(total_size, 1, this->supports_current_temperature); - ProtoSize::add_bool_field(total_size, 1, this->supports_two_point_target_temperature); +void ListEntitiesClimateResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); + size.add_bool(1, this->supports_current_temperature); + size.add_bool(1, this->supports_two_point_target_temperature); if (!this->supported_modes.empty()) { for (const auto &it : this->supported_modes) { - ProtoSize::add_enum_field_repeated(total_size, 1, static_cast(it)); + size.add_uint32_force(1, static_cast(it)); } } - ProtoSize::add_float_field(total_size, 1, this->visual_min_temperature); - ProtoSize::add_float_field(total_size, 1, this->visual_max_temperature); - ProtoSize::add_float_field(total_size, 1, this->visual_target_temperature_step); - ProtoSize::add_bool_field(total_size, 1, this->supports_action); + size.add_float(1, this->visual_min_temperature); + size.add_float(1, this->visual_max_temperature); + size.add_float(1, this->visual_target_temperature_step); + size.add_bool(1, this->supports_action); if (!this->supported_fan_modes.empty()) { for (const auto &it : this->supported_fan_modes) { - ProtoSize::add_enum_field_repeated(total_size, 1, static_cast(it)); + size.add_uint32_force(1, static_cast(it)); } } if (!this->supported_swing_modes.empty()) { for (const auto &it : this->supported_swing_modes) { - ProtoSize::add_enum_field_repeated(total_size, 1, static_cast(it)); + size.add_uint32_force(1, static_cast(it)); } } if (!this->supported_custom_fan_modes.empty()) { for (const auto &it : this->supported_custom_fan_modes) { - ProtoSize::add_string_field_repeated(total_size, 1, it); + size.add_length_force(1, it.size()); } } if (!this->supported_presets.empty()) { for (const auto &it : this->supported_presets) { - ProtoSize::add_enum_field_repeated(total_size, 2, static_cast(it)); + size.add_uint32_force(2, static_cast(it)); } } if (!this->supported_custom_presets.empty()) { for (const auto &it : this->supported_custom_presets) { - ProtoSize::add_string_field_repeated(total_size, 2, it); + size.add_length_force(2, it.size()); } } - ProtoSize::add_bool_field(total_size, 2, this->disabled_by_default); + size.add_bool(2, this->disabled_by_default); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 2, this->icon_ref_.size()); + size.add_length(2, this->icon_ref_.size()); #endif - ProtoSize::add_enum_field(total_size, 2, static_cast(this->entity_category)); - ProtoSize::add_float_field(total_size, 2, this->visual_current_temperature_step); - ProtoSize::add_bool_field(total_size, 2, this->supports_current_humidity); - ProtoSize::add_bool_field(total_size, 2, this->supports_target_humidity); - ProtoSize::add_float_field(total_size, 2, this->visual_min_humidity); - ProtoSize::add_float_field(total_size, 2, this->visual_max_humidity); + size.add_uint32(2, static_cast(this->entity_category)); + size.add_float(2, this->visual_current_temperature_step); + size.add_bool(2, this->supports_current_humidity); + size.add_bool(2, this->supports_target_humidity); + size.add_float(2, this->visual_min_humidity); + size.add_float(2, this->visual_max_humidity); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 2, this->device_id); + size.add_uint32(2, this->device_id); #endif } void ClimateStateResponse::encode(ProtoWriteBuffer buffer) const { @@ -1179,23 +1173,23 @@ void ClimateStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(16, this->device_id); #endif } -void ClimateStateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->mode)); - ProtoSize::add_float_field(total_size, 1, this->current_temperature); - ProtoSize::add_float_field(total_size, 1, this->target_temperature); - ProtoSize::add_float_field(total_size, 1, this->target_temperature_low); - ProtoSize::add_float_field(total_size, 1, this->target_temperature_high); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->action)); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->fan_mode)); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->swing_mode)); - ProtoSize::add_string_field(total_size, 1, this->custom_fan_mode_ref_.size()); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->preset)); - ProtoSize::add_string_field(total_size, 1, this->custom_preset_ref_.size()); - ProtoSize::add_float_field(total_size, 1, this->current_humidity); - ProtoSize::add_float_field(total_size, 1, this->target_humidity); +void ClimateStateResponse::calculate_size(ProtoSize &size) const { + size.add_fixed32(1, this->key); + size.add_uint32(1, static_cast(this->mode)); + size.add_float(1, this->current_temperature); + size.add_float(1, this->target_temperature); + size.add_float(1, this->target_temperature_low); + size.add_float(1, this->target_temperature_high); + size.add_uint32(1, static_cast(this->action)); + size.add_uint32(1, static_cast(this->fan_mode)); + size.add_uint32(1, static_cast(this->swing_mode)); + size.add_length(1, this->custom_fan_mode_ref_.size()); + size.add_uint32(1, static_cast(this->preset)); + size.add_length(1, this->custom_preset_ref_.size()); + size.add_float(1, this->current_humidity); + size.add_float(1, this->target_humidity); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 2, this->device_id); + size.add_uint32(2, this->device_id); #endif } bool ClimateCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { @@ -1308,23 +1302,23 @@ void ListEntitiesNumberResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(14, this->device_id); #endif } -void ListEntitiesNumberResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); +void ListEntitiesNumberResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 1, this->icon_ref_.size()); + size.add_length(1, this->icon_ref_.size()); #endif - ProtoSize::add_float_field(total_size, 1, this->min_value); - ProtoSize::add_float_field(total_size, 1, this->max_value); - ProtoSize::add_float_field(total_size, 1, this->step); - ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->entity_category)); - ProtoSize::add_string_field(total_size, 1, this->unit_of_measurement_ref_.size()); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->mode)); - ProtoSize::add_string_field(total_size, 1, this->device_class_ref_.size()); + size.add_float(1, this->min_value); + size.add_float(1, this->max_value); + size.add_float(1, this->step); + size.add_bool(1, this->disabled_by_default); + size.add_uint32(1, static_cast(this->entity_category)); + size.add_length(1, this->unit_of_measurement_ref_.size()); + size.add_uint32(1, static_cast(this->mode)); + size.add_length(1, this->device_class_ref_.size()); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } void NumberStateResponse::encode(ProtoWriteBuffer buffer) const { @@ -1335,12 +1329,12 @@ void NumberStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(4, this->device_id); #endif } -void NumberStateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_float_field(total_size, 1, this->state); - ProtoSize::add_bool_field(total_size, 1, this->missing_state); +void NumberStateResponse::calculate_size(ProtoSize &size) const { + size.add_fixed32(1, this->key); + size.add_float(1, this->state); + size.add_bool(1, this->missing_state); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } bool NumberCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { @@ -1386,22 +1380,22 @@ void ListEntitiesSelectResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(9, this->device_id); #endif } -void ListEntitiesSelectResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); +void ListEntitiesSelectResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 1, this->icon_ref_.size()); + size.add_length(1, this->icon_ref_.size()); #endif if (!this->options.empty()) { for (const auto &it : this->options) { - ProtoSize::add_string_field_repeated(total_size, 1, it); + size.add_length_force(1, it.size()); } } - ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->entity_category)); + size.add_bool(1, this->disabled_by_default); + size.add_uint32(1, static_cast(this->entity_category)); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } void SelectStateResponse::encode(ProtoWriteBuffer buffer) const { @@ -1412,12 +1406,12 @@ void SelectStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(4, this->device_id); #endif } -void SelectStateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->state_ref_.size()); - ProtoSize::add_bool_field(total_size, 1, this->missing_state); +void SelectStateResponse::calculate_size(ProtoSize &size) const { + size.add_fixed32(1, this->key); + size.add_length(1, this->state_ref_.size()); + size.add_bool(1, this->missing_state); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } bool SelectCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { @@ -1472,24 +1466,24 @@ void ListEntitiesSirenResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(11, this->device_id); #endif } -void ListEntitiesSirenResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); +void ListEntitiesSirenResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 1, this->icon_ref_.size()); + size.add_length(1, this->icon_ref_.size()); #endif - ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default); + size.add_bool(1, this->disabled_by_default); if (!this->tones.empty()) { for (const auto &it : this->tones) { - ProtoSize::add_string_field_repeated(total_size, 1, it); + size.add_length_force(1, it.size()); } } - ProtoSize::add_bool_field(total_size, 1, this->supports_duration); - ProtoSize::add_bool_field(total_size, 1, this->supports_volume); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->entity_category)); + size.add_bool(1, this->supports_duration); + size.add_bool(1, this->supports_volume); + size.add_uint32(1, static_cast(this->entity_category)); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } void SirenStateResponse::encode(ProtoWriteBuffer buffer) const { @@ -1499,11 +1493,11 @@ void SirenStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(3, this->device_id); #endif } -void SirenStateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_bool_field(total_size, 1, this->state); +void SirenStateResponse::calculate_size(ProtoSize &size) const { + size.add_fixed32(1, this->key); + size.add_bool(1, this->state); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } bool SirenCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { @@ -1578,21 +1572,21 @@ void ListEntitiesLockResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(12, this->device_id); #endif } -void ListEntitiesLockResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); +void ListEntitiesLockResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 1, this->icon_ref_.size()); + size.add_length(1, this->icon_ref_.size()); #endif - ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->entity_category)); - ProtoSize::add_bool_field(total_size, 1, this->assumed_state); - ProtoSize::add_bool_field(total_size, 1, this->supports_open); - ProtoSize::add_bool_field(total_size, 1, this->requires_code); - ProtoSize::add_string_field(total_size, 1, this->code_format_ref_.size()); + size.add_bool(1, this->disabled_by_default); + size.add_uint32(1, static_cast(this->entity_category)); + size.add_bool(1, this->assumed_state); + size.add_bool(1, this->supports_open); + size.add_bool(1, this->requires_code); + size.add_length(1, this->code_format_ref_.size()); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } void LockStateResponse::encode(ProtoWriteBuffer buffer) const { @@ -1602,11 +1596,11 @@ void LockStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(3, this->device_id); #endif } -void LockStateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->state)); +void LockStateResponse::calculate_size(ProtoSize &size) const { + size.add_fixed32(1, this->key); + size.add_uint32(1, static_cast(this->state)); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } bool LockCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { @@ -1663,18 +1657,18 @@ void ListEntitiesButtonResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(9, this->device_id); #endif } -void ListEntitiesButtonResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); +void ListEntitiesButtonResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 1, this->icon_ref_.size()); + size.add_length(1, this->icon_ref_.size()); #endif - ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->entity_category)); - ProtoSize::add_string_field(total_size, 1, this->device_class_ref_.size()); + size.add_bool(1, this->disabled_by_default); + size.add_uint32(1, static_cast(this->entity_category)); + size.add_length(1, this->device_class_ref_.size()); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } bool ButtonCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { @@ -1708,12 +1702,12 @@ void MediaPlayerSupportedFormat::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(4, static_cast(this->purpose)); buffer.encode_uint32(5, this->sample_bytes); } -void MediaPlayerSupportedFormat::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->format_ref_.size()); - ProtoSize::add_uint32_field(total_size, 1, this->sample_rate); - ProtoSize::add_uint32_field(total_size, 1, this->num_channels); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->purpose)); - ProtoSize::add_uint32_field(total_size, 1, this->sample_bytes); +void MediaPlayerSupportedFormat::calculate_size(ProtoSize &size) const { + size.add_length(1, this->format_ref_.size()); + size.add_uint32(1, this->sample_rate); + size.add_uint32(1, this->num_channels); + size.add_uint32(1, static_cast(this->purpose)); + size.add_uint32(1, this->sample_bytes); } void ListEntitiesMediaPlayerResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_string(1, this->object_id_ref_); @@ -1732,19 +1726,19 @@ void ListEntitiesMediaPlayerResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(10, this->device_id); #endif } -void ListEntitiesMediaPlayerResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); +void ListEntitiesMediaPlayerResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 1, this->icon_ref_.size()); + size.add_length(1, this->icon_ref_.size()); #endif - ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->entity_category)); - ProtoSize::add_bool_field(total_size, 1, this->supports_pause); - ProtoSize::add_repeated_message(total_size, 1, this->supported_formats); + size.add_bool(1, this->disabled_by_default); + size.add_uint32(1, static_cast(this->entity_category)); + size.add_bool(1, this->supports_pause); + size.add_repeated_message(1, this->supported_formats); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } void MediaPlayerStateResponse::encode(ProtoWriteBuffer buffer) const { @@ -1756,13 +1750,13 @@ void MediaPlayerStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(5, this->device_id); #endif } -void MediaPlayerStateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->state)); - ProtoSize::add_float_field(total_size, 1, this->volume); - ProtoSize::add_bool_field(total_size, 1, this->muted); +void MediaPlayerStateResponse::calculate_size(ProtoSize &size) const { + size.add_fixed32(1, this->key); + size.add_uint32(1, static_cast(this->state)); + size.add_float(1, this->volume); + size.add_bool(1, this->muted); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } bool MediaPlayerCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { @@ -1836,21 +1830,19 @@ void BluetoothLERawAdvertisement::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(3, this->address_type); buffer.encode_bytes(4, this->data, this->data_len); } -void BluetoothLERawAdvertisement::calculate_size(uint32_t &total_size) const { - ProtoSize::add_uint64_field(total_size, 1, this->address); - ProtoSize::add_sint32_field(total_size, 1, this->rssi); - ProtoSize::add_uint32_field(total_size, 1, this->address_type); - if (this->data_len != 0) { - total_size += 1 + ProtoSize::varint(static_cast(this->data_len)) + this->data_len; - } +void BluetoothLERawAdvertisement::calculate_size(ProtoSize &size) const { + size.add_uint64(1, this->address); + size.add_sint32(1, this->rssi); + size.add_uint32(1, this->address_type); + size.add_length(1, this->data_len); } void BluetoothLERawAdvertisementsResponse::encode(ProtoWriteBuffer buffer) const { for (auto &it : this->advertisements) { buffer.encode_message(1, it, true); } } -void BluetoothLERawAdvertisementsResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_repeated_message(total_size, 1, this->advertisements); +void BluetoothLERawAdvertisementsResponse::calculate_size(ProtoSize &size) const { + size.add_repeated_message(1, this->advertisements); } bool BluetoothDeviceRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -1877,11 +1869,11 @@ void BluetoothDeviceConnectionResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(3, this->mtu); buffer.encode_int32(4, this->error); } -void BluetoothDeviceConnectionResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_uint64_field(total_size, 1, this->address); - ProtoSize::add_bool_field(total_size, 1, this->connected); - ProtoSize::add_uint32_field(total_size, 1, this->mtu); - ProtoSize::add_int32_field(total_size, 1, this->error); +void BluetoothDeviceConnectionResponse::calculate_size(ProtoSize &size) const { + size.add_uint64(1, this->address); + size.add_bool(1, this->connected); + size.add_uint32(1, this->mtu); + size.add_int32(1, this->error); } bool BluetoothGATTGetServicesRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -1898,10 +1890,10 @@ void BluetoothGATTDescriptor::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint64(1, this->uuid[1], true); buffer.encode_uint32(2, this->handle); } -void BluetoothGATTDescriptor::calculate_size(uint32_t &total_size) const { - ProtoSize::add_uint64_field_repeated(total_size, 1, this->uuid[0]); - ProtoSize::add_uint64_field_repeated(total_size, 1, this->uuid[1]); - ProtoSize::add_uint32_field(total_size, 1, this->handle); +void BluetoothGATTDescriptor::calculate_size(ProtoSize &size) const { + size.add_uint64_force(1, this->uuid[0]); + size.add_uint64_force(1, this->uuid[1]); + size.add_uint32(1, this->handle); } void BluetoothGATTCharacteristic::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint64(1, this->uuid[0], true); @@ -1912,12 +1904,12 @@ void BluetoothGATTCharacteristic::encode(ProtoWriteBuffer buffer) const { buffer.encode_message(4, it, true); } } -void BluetoothGATTCharacteristic::calculate_size(uint32_t &total_size) const { - ProtoSize::add_uint64_field_repeated(total_size, 1, this->uuid[0]); - ProtoSize::add_uint64_field_repeated(total_size, 1, this->uuid[1]); - ProtoSize::add_uint32_field(total_size, 1, this->handle); - ProtoSize::add_uint32_field(total_size, 1, this->properties); - ProtoSize::add_repeated_message(total_size, 1, this->descriptors); +void BluetoothGATTCharacteristic::calculate_size(ProtoSize &size) const { + size.add_uint64_force(1, this->uuid[0]); + size.add_uint64_force(1, this->uuid[1]); + size.add_uint32(1, this->handle); + size.add_uint32(1, this->properties); + size.add_repeated_message(1, this->descriptors); } void BluetoothGATTService::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint64(1, this->uuid[0], true); @@ -1927,26 +1919,24 @@ void BluetoothGATTService::encode(ProtoWriteBuffer buffer) const { buffer.encode_message(3, it, true); } } -void BluetoothGATTService::calculate_size(uint32_t &total_size) const { - ProtoSize::add_uint64_field_repeated(total_size, 1, this->uuid[0]); - ProtoSize::add_uint64_field_repeated(total_size, 1, this->uuid[1]); - ProtoSize::add_uint32_field(total_size, 1, this->handle); - ProtoSize::add_repeated_message(total_size, 1, this->characteristics); +void BluetoothGATTService::calculate_size(ProtoSize &size) const { + size.add_uint64_force(1, this->uuid[0]); + size.add_uint64_force(1, this->uuid[1]); + size.add_uint32(1, this->handle); + size.add_repeated_message(1, this->characteristics); } void BluetoothGATTGetServicesResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint64(1, this->address); buffer.encode_message(2, this->services[0], true); } -void BluetoothGATTGetServicesResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_uint64_field(total_size, 1, this->address); - ProtoSize::add_message_object_repeated(total_size, 1, this->services[0]); +void BluetoothGATTGetServicesResponse::calculate_size(ProtoSize &size) const { + size.add_uint64(1, this->address); + size.add_message_object_force(1, this->services[0]); } void BluetoothGATTGetServicesDoneResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint64(1, this->address); } -void BluetoothGATTGetServicesDoneResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_uint64_field(total_size, 1, this->address); -} +void BluetoothGATTGetServicesDoneResponse::calculate_size(ProtoSize &size) const { size.add_uint64(1, this->address); } bool BluetoothGATTReadRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { case 1: @@ -1965,10 +1955,10 @@ void BluetoothGATTReadResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(2, this->handle); buffer.encode_bytes(3, this->data_ptr_, this->data_len_); } -void BluetoothGATTReadResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_uint64_field(total_size, 1, this->address); - ProtoSize::add_uint32_field(total_size, 1, this->handle); - ProtoSize::add_bytes_field(total_size, 1, this->data_len_); +void BluetoothGATTReadResponse::calculate_size(ProtoSize &size) const { + size.add_uint64(1, this->address); + size.add_uint32(1, this->handle); + size.add_length(1, this->data_len_); } bool BluetoothGATTWriteRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -2053,10 +2043,10 @@ void BluetoothGATTNotifyDataResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(2, this->handle); buffer.encode_bytes(3, this->data_ptr_, this->data_len_); } -void BluetoothGATTNotifyDataResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_uint64_field(total_size, 1, this->address); - ProtoSize::add_uint32_field(total_size, 1, this->handle); - ProtoSize::add_bytes_field(total_size, 1, this->data_len_); +void BluetoothGATTNotifyDataResponse::calculate_size(ProtoSize &size) const { + size.add_uint64(1, this->address); + size.add_uint32(1, this->handle); + size.add_length(1, this->data_len_); } void BluetoothConnectionsFreeResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(1, this->free); @@ -2065,12 +2055,12 @@ void BluetoothConnectionsFreeResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint64(3, it, true); } } -void BluetoothConnectionsFreeResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_uint32_field(total_size, 1, this->free); - ProtoSize::add_uint32_field(total_size, 1, this->limit); +void BluetoothConnectionsFreeResponse::calculate_size(ProtoSize &size) const { + size.add_uint32(1, this->free); + size.add_uint32(1, this->limit); if (!this->allocated.empty()) { for (const auto &it : this->allocated) { - ProtoSize::add_uint64_field_repeated(total_size, 1, it); + size.add_uint64_force(1, it); } } } @@ -2079,64 +2069,64 @@ void BluetoothGATTErrorResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(2, this->handle); buffer.encode_int32(3, this->error); } -void BluetoothGATTErrorResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_uint64_field(total_size, 1, this->address); - ProtoSize::add_uint32_field(total_size, 1, this->handle); - ProtoSize::add_int32_field(total_size, 1, this->error); +void BluetoothGATTErrorResponse::calculate_size(ProtoSize &size) const { + size.add_uint64(1, this->address); + size.add_uint32(1, this->handle); + size.add_int32(1, this->error); } void BluetoothGATTWriteResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint64(1, this->address); buffer.encode_uint32(2, this->handle); } -void BluetoothGATTWriteResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_uint64_field(total_size, 1, this->address); - ProtoSize::add_uint32_field(total_size, 1, this->handle); +void BluetoothGATTWriteResponse::calculate_size(ProtoSize &size) const { + size.add_uint64(1, this->address); + size.add_uint32(1, this->handle); } void BluetoothGATTNotifyResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint64(1, this->address); buffer.encode_uint32(2, this->handle); } -void BluetoothGATTNotifyResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_uint64_field(total_size, 1, this->address); - ProtoSize::add_uint32_field(total_size, 1, this->handle); +void BluetoothGATTNotifyResponse::calculate_size(ProtoSize &size) const { + size.add_uint64(1, this->address); + size.add_uint32(1, this->handle); } void BluetoothDevicePairingResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint64(1, this->address); buffer.encode_bool(2, this->paired); buffer.encode_int32(3, this->error); } -void BluetoothDevicePairingResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_uint64_field(total_size, 1, this->address); - ProtoSize::add_bool_field(total_size, 1, this->paired); - ProtoSize::add_int32_field(total_size, 1, this->error); +void BluetoothDevicePairingResponse::calculate_size(ProtoSize &size) const { + size.add_uint64(1, this->address); + size.add_bool(1, this->paired); + size.add_int32(1, this->error); } void BluetoothDeviceUnpairingResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint64(1, this->address); buffer.encode_bool(2, this->success); buffer.encode_int32(3, this->error); } -void BluetoothDeviceUnpairingResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_uint64_field(total_size, 1, this->address); - ProtoSize::add_bool_field(total_size, 1, this->success); - ProtoSize::add_int32_field(total_size, 1, this->error); +void BluetoothDeviceUnpairingResponse::calculate_size(ProtoSize &size) const { + size.add_uint64(1, this->address); + size.add_bool(1, this->success); + size.add_int32(1, this->error); } void BluetoothDeviceClearCacheResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint64(1, this->address); buffer.encode_bool(2, this->success); buffer.encode_int32(3, this->error); } -void BluetoothDeviceClearCacheResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_uint64_field(total_size, 1, this->address); - ProtoSize::add_bool_field(total_size, 1, this->success); - ProtoSize::add_int32_field(total_size, 1, this->error); +void BluetoothDeviceClearCacheResponse::calculate_size(ProtoSize &size) const { + size.add_uint64(1, this->address); + size.add_bool(1, this->success); + size.add_int32(1, this->error); } void BluetoothScannerStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(1, static_cast(this->state)); buffer.encode_uint32(2, static_cast(this->mode)); } -void BluetoothScannerStateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_enum_field(total_size, 1, static_cast(this->state)); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->mode)); +void BluetoothScannerStateResponse::calculate_size(ProtoSize &size) const { + size.add_uint32(1, static_cast(this->state)); + size.add_uint32(1, static_cast(this->mode)); } bool BluetoothScannerSetModeRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -2168,10 +2158,10 @@ void VoiceAssistantAudioSettings::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(2, this->auto_gain); buffer.encode_float(3, this->volume_multiplier); } -void VoiceAssistantAudioSettings::calculate_size(uint32_t &total_size) const { - ProtoSize::add_uint32_field(total_size, 1, this->noise_suppression_level); - ProtoSize::add_uint32_field(total_size, 1, this->auto_gain); - ProtoSize::add_float_field(total_size, 1, this->volume_multiplier); +void VoiceAssistantAudioSettings::calculate_size(ProtoSize &size) const { + size.add_uint32(1, this->noise_suppression_level); + size.add_uint32(1, this->auto_gain); + size.add_float(1, this->volume_multiplier); } void VoiceAssistantRequest::encode(ProtoWriteBuffer buffer) const { buffer.encode_bool(1, this->start); @@ -2180,12 +2170,12 @@ void VoiceAssistantRequest::encode(ProtoWriteBuffer buffer) const { buffer.encode_message(4, this->audio_settings); buffer.encode_string(5, this->wake_word_phrase_ref_); } -void VoiceAssistantRequest::calculate_size(uint32_t &total_size) const { - ProtoSize::add_bool_field(total_size, 1, this->start); - ProtoSize::add_string_field(total_size, 1, this->conversation_id_ref_.size()); - ProtoSize::add_uint32_field(total_size, 1, this->flags); - ProtoSize::add_message_object(total_size, 1, this->audio_settings); - ProtoSize::add_string_field(total_size, 1, this->wake_word_phrase_ref_.size()); +void VoiceAssistantRequest::calculate_size(ProtoSize &size) const { + size.add_bool(1, this->start); + size.add_length(1, this->conversation_id_ref_.size()); + size.add_uint32(1, this->flags); + size.add_message_object(1, this->audio_settings); + size.add_length(1, this->wake_word_phrase_ref_.size()); } bool VoiceAssistantResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -2258,9 +2248,9 @@ void VoiceAssistantAudio::encode(ProtoWriteBuffer buffer) const { buffer.encode_bytes(1, this->data_ptr_, this->data_len_); buffer.encode_bool(2, this->end); } -void VoiceAssistantAudio::calculate_size(uint32_t &total_size) const { - ProtoSize::add_bytes_field(total_size, 1, this->data_len_); - ProtoSize::add_bool_field(total_size, 1, this->end); +void VoiceAssistantAudio::calculate_size(ProtoSize &size) const { + size.add_length(1, this->data_len_); + size.add_bool(1, this->end); } bool VoiceAssistantTimerEventResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -2321,9 +2311,7 @@ bool VoiceAssistantAnnounceRequest::decode_length(uint32_t field_id, ProtoLength return true; } void VoiceAssistantAnnounceFinished::encode(ProtoWriteBuffer buffer) const { buffer.encode_bool(1, this->success); } -void VoiceAssistantAnnounceFinished::calculate_size(uint32_t &total_size) const { - ProtoSize::add_bool_field(total_size, 1, this->success); -} +void VoiceAssistantAnnounceFinished::calculate_size(ProtoSize &size) const { size.add_bool(1, this->success); } void VoiceAssistantWakeWord::encode(ProtoWriteBuffer buffer) const { buffer.encode_string(1, this->id_ref_); buffer.encode_string(2, this->wake_word_ref_); @@ -2331,12 +2319,12 @@ void VoiceAssistantWakeWord::encode(ProtoWriteBuffer buffer) const { buffer.encode_string(3, it, true); } } -void VoiceAssistantWakeWord::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->id_ref_.size()); - ProtoSize::add_string_field(total_size, 1, this->wake_word_ref_.size()); +void VoiceAssistantWakeWord::calculate_size(ProtoSize &size) const { + size.add_length(1, this->id_ref_.size()); + size.add_length(1, this->wake_word_ref_.size()); if (!this->trained_languages.empty()) { for (const auto &it : this->trained_languages) { - ProtoSize::add_string_field_repeated(total_size, 1, it); + size.add_length_force(1, it.size()); } } } @@ -2349,14 +2337,14 @@ void VoiceAssistantConfigurationResponse::encode(ProtoWriteBuffer buffer) const } buffer.encode_uint32(3, this->max_active_wake_words); } -void VoiceAssistantConfigurationResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_repeated_message(total_size, 1, this->available_wake_words); +void VoiceAssistantConfigurationResponse::calculate_size(ProtoSize &size) const { + size.add_repeated_message(1, this->available_wake_words); if (!this->active_wake_words.empty()) { for (const auto &it : this->active_wake_words) { - ProtoSize::add_string_field_repeated(total_size, 1, it); + size.add_length_force(1, it.size()); } } - ProtoSize::add_uint32_field(total_size, 1, this->max_active_wake_words); + size.add_uint32(1, this->max_active_wake_words); } bool VoiceAssistantSetConfiguration::decode_length(uint32_t field_id, ProtoLengthDelimited value) { switch (field_id) { @@ -2386,20 +2374,20 @@ void ListEntitiesAlarmControlPanelResponse::encode(ProtoWriteBuffer buffer) cons buffer.encode_uint32(11, this->device_id); #endif } -void ListEntitiesAlarmControlPanelResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); +void ListEntitiesAlarmControlPanelResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 1, this->icon_ref_.size()); + size.add_length(1, this->icon_ref_.size()); #endif - ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->entity_category)); - ProtoSize::add_uint32_field(total_size, 1, this->supported_features); - ProtoSize::add_bool_field(total_size, 1, this->requires_code); - ProtoSize::add_bool_field(total_size, 1, this->requires_code_to_arm); + size.add_bool(1, this->disabled_by_default); + size.add_uint32(1, static_cast(this->entity_category)); + size.add_uint32(1, this->supported_features); + size.add_bool(1, this->requires_code); + size.add_bool(1, this->requires_code_to_arm); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } void AlarmControlPanelStateResponse::encode(ProtoWriteBuffer buffer) const { @@ -2409,11 +2397,11 @@ void AlarmControlPanelStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(3, this->device_id); #endif } -void AlarmControlPanelStateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->state)); +void AlarmControlPanelStateResponse::calculate_size(ProtoSize &size) const { + size.add_fixed32(1, this->key); + size.add_uint32(1, static_cast(this->state)); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } bool AlarmControlPanelCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { @@ -2470,21 +2458,21 @@ void ListEntitiesTextResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(12, this->device_id); #endif } -void ListEntitiesTextResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); +void ListEntitiesTextResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 1, this->icon_ref_.size()); + size.add_length(1, this->icon_ref_.size()); #endif - ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->entity_category)); - ProtoSize::add_uint32_field(total_size, 1, this->min_length); - ProtoSize::add_uint32_field(total_size, 1, this->max_length); - ProtoSize::add_string_field(total_size, 1, this->pattern_ref_.size()); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->mode)); + size.add_bool(1, this->disabled_by_default); + size.add_uint32(1, static_cast(this->entity_category)); + size.add_uint32(1, this->min_length); + size.add_uint32(1, this->max_length); + size.add_length(1, this->pattern_ref_.size()); + size.add_uint32(1, static_cast(this->mode)); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } void TextStateResponse::encode(ProtoWriteBuffer buffer) const { @@ -2495,12 +2483,12 @@ void TextStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(4, this->device_id); #endif } -void TextStateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->state_ref_.size()); - ProtoSize::add_bool_field(total_size, 1, this->missing_state); +void TextStateResponse::calculate_size(ProtoSize &size) const { + size.add_fixed32(1, this->key); + size.add_length(1, this->state_ref_.size()); + size.add_bool(1, this->missing_state); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } bool TextCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { @@ -2550,17 +2538,17 @@ void ListEntitiesDateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(8, this->device_id); #endif } -void ListEntitiesDateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); +void ListEntitiesDateResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 1, this->icon_ref_.size()); + size.add_length(1, this->icon_ref_.size()); #endif - ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->entity_category)); + size.add_bool(1, this->disabled_by_default); + size.add_uint32(1, static_cast(this->entity_category)); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } void DateStateResponse::encode(ProtoWriteBuffer buffer) const { @@ -2573,14 +2561,14 @@ void DateStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(6, this->device_id); #endif } -void DateStateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_bool_field(total_size, 1, this->missing_state); - ProtoSize::add_uint32_field(total_size, 1, this->year); - ProtoSize::add_uint32_field(total_size, 1, this->month); - ProtoSize::add_uint32_field(total_size, 1, this->day); +void DateStateResponse::calculate_size(ProtoSize &size) const { + size.add_fixed32(1, this->key); + size.add_bool(1, this->missing_state); + size.add_uint32(1, this->year); + size.add_uint32(1, this->month); + size.add_uint32(1, this->day); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } bool DateCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { @@ -2629,17 +2617,17 @@ void ListEntitiesTimeResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(8, this->device_id); #endif } -void ListEntitiesTimeResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); +void ListEntitiesTimeResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 1, this->icon_ref_.size()); + size.add_length(1, this->icon_ref_.size()); #endif - ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->entity_category)); + size.add_bool(1, this->disabled_by_default); + size.add_uint32(1, static_cast(this->entity_category)); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } void TimeStateResponse::encode(ProtoWriteBuffer buffer) const { @@ -2652,14 +2640,14 @@ void TimeStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(6, this->device_id); #endif } -void TimeStateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_bool_field(total_size, 1, this->missing_state); - ProtoSize::add_uint32_field(total_size, 1, this->hour); - ProtoSize::add_uint32_field(total_size, 1, this->minute); - ProtoSize::add_uint32_field(total_size, 1, this->second); +void TimeStateResponse::calculate_size(ProtoSize &size) const { + size.add_fixed32(1, this->key); + size.add_bool(1, this->missing_state); + size.add_uint32(1, this->hour); + size.add_uint32(1, this->minute); + size.add_uint32(1, this->second); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } bool TimeCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { @@ -2712,23 +2700,23 @@ void ListEntitiesEventResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(10, this->device_id); #endif } -void ListEntitiesEventResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); +void ListEntitiesEventResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 1, this->icon_ref_.size()); + size.add_length(1, this->icon_ref_.size()); #endif - ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->entity_category)); - ProtoSize::add_string_field(total_size, 1, this->device_class_ref_.size()); + size.add_bool(1, this->disabled_by_default); + size.add_uint32(1, static_cast(this->entity_category)); + size.add_length(1, this->device_class_ref_.size()); if (!this->event_types.empty()) { for (const auto &it : this->event_types) { - ProtoSize::add_string_field_repeated(total_size, 1, it); + size.add_length_force(1, it.size()); } } #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } void EventResponse::encode(ProtoWriteBuffer buffer) const { @@ -2738,11 +2726,11 @@ void EventResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(3, this->device_id); #endif } -void EventResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->event_type_ref_.size()); +void EventResponse::calculate_size(ProtoSize &size) const { + size.add_fixed32(1, this->key); + size.add_length(1, this->event_type_ref_.size()); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } #endif @@ -2764,21 +2752,21 @@ void ListEntitiesValveResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(12, this->device_id); #endif } -void ListEntitiesValveResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); +void ListEntitiesValveResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 1, this->icon_ref_.size()); + size.add_length(1, this->icon_ref_.size()); #endif - ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->entity_category)); - ProtoSize::add_string_field(total_size, 1, this->device_class_ref_.size()); - ProtoSize::add_bool_field(total_size, 1, this->assumed_state); - ProtoSize::add_bool_field(total_size, 1, this->supports_position); - ProtoSize::add_bool_field(total_size, 1, this->supports_stop); + size.add_bool(1, this->disabled_by_default); + size.add_uint32(1, static_cast(this->entity_category)); + size.add_length(1, this->device_class_ref_.size()); + size.add_bool(1, this->assumed_state); + size.add_bool(1, this->supports_position); + size.add_bool(1, this->supports_stop); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } void ValveStateResponse::encode(ProtoWriteBuffer buffer) const { @@ -2789,12 +2777,12 @@ void ValveStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(4, this->device_id); #endif } -void ValveStateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_float_field(total_size, 1, this->position); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->current_operation)); +void ValveStateResponse::calculate_size(ProtoSize &size) const { + size.add_fixed32(1, this->key); + size.add_float(1, this->position); + size.add_uint32(1, static_cast(this->current_operation)); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } bool ValveCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { @@ -2843,17 +2831,17 @@ void ListEntitiesDateTimeResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(8, this->device_id); #endif } -void ListEntitiesDateTimeResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); +void ListEntitiesDateTimeResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 1, this->icon_ref_.size()); + size.add_length(1, this->icon_ref_.size()); #endif - ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->entity_category)); + size.add_bool(1, this->disabled_by_default); + size.add_uint32(1, static_cast(this->entity_category)); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } void DateTimeStateResponse::encode(ProtoWriteBuffer buffer) const { @@ -2864,12 +2852,12 @@ void DateTimeStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(4, this->device_id); #endif } -void DateTimeStateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_bool_field(total_size, 1, this->missing_state); - ProtoSize::add_fixed32_field(total_size, 1, this->epoch_seconds); +void DateTimeStateResponse::calculate_size(ProtoSize &size) const { + size.add_fixed32(1, this->key); + size.add_bool(1, this->missing_state); + size.add_fixed32(1, this->epoch_seconds); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } bool DateTimeCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { @@ -2913,18 +2901,18 @@ void ListEntitiesUpdateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(9, this->device_id); #endif } -void ListEntitiesUpdateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_string_field(total_size, 1, this->object_id_ref_.size()); - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_string_field(total_size, 1, this->name_ref_.size()); +void ListEntitiesUpdateResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id_ref_.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name_ref_.size()); #ifdef USE_ENTITY_ICON - ProtoSize::add_string_field(total_size, 1, this->icon_ref_.size()); + size.add_length(1, this->icon_ref_.size()); #endif - ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default); - ProtoSize::add_enum_field(total_size, 1, static_cast(this->entity_category)); - ProtoSize::add_string_field(total_size, 1, this->device_class_ref_.size()); + size.add_bool(1, this->disabled_by_default); + size.add_uint32(1, static_cast(this->entity_category)); + size.add_length(1, this->device_class_ref_.size()); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } void UpdateStateResponse::encode(ProtoWriteBuffer buffer) const { @@ -2942,19 +2930,19 @@ void UpdateStateResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_uint32(11, this->device_id); #endif } -void UpdateStateResponse::calculate_size(uint32_t &total_size) const { - ProtoSize::add_fixed32_field(total_size, 1, this->key); - ProtoSize::add_bool_field(total_size, 1, this->missing_state); - ProtoSize::add_bool_field(total_size, 1, this->in_progress); - ProtoSize::add_bool_field(total_size, 1, this->has_progress); - ProtoSize::add_float_field(total_size, 1, this->progress); - ProtoSize::add_string_field(total_size, 1, this->current_version_ref_.size()); - ProtoSize::add_string_field(total_size, 1, this->latest_version_ref_.size()); - ProtoSize::add_string_field(total_size, 1, this->title_ref_.size()); - ProtoSize::add_string_field(total_size, 1, this->release_summary_ref_.size()); - ProtoSize::add_string_field(total_size, 1, this->release_url_ref_.size()); +void UpdateStateResponse::calculate_size(ProtoSize &size) const { + size.add_fixed32(1, this->key); + size.add_bool(1, this->missing_state); + size.add_bool(1, this->in_progress); + size.add_bool(1, this->has_progress); + size.add_float(1, this->progress); + size.add_length(1, this->current_version_ref_.size()); + size.add_length(1, this->latest_version_ref_.size()); + size.add_length(1, this->title_ref_.size()); + size.add_length(1, this->release_summary_ref_.size()); + size.add_length(1, this->release_url_ref_.size()); #ifdef USE_DEVICES - ProtoSize::add_uint32_field(total_size, 1, this->device_id); + size.add_uint32(1, this->device_id); #endif } bool UpdateCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 47bdaead23..f637e44df3 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -340,7 +340,7 @@ class HelloResponse : public ProtoMessage { StringRef name_ref_{}; void set_name(const StringRef &ref) { this->name_ref_ = ref; } void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -371,7 +371,7 @@ class ConnectResponse : public ProtoMessage { #endif bool invalid_password{false}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -450,7 +450,7 @@ class AreaInfo : public ProtoMessage { StringRef name_ref_{}; void set_name(const StringRef &ref) { this->name_ref_ = ref; } void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -466,7 +466,7 @@ class DeviceInfo : public ProtoMessage { void set_name(const StringRef &ref) { this->name_ref_ = ref; } uint32_t area_id{0}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -539,7 +539,7 @@ class DeviceInfoResponse : public ProtoMessage { AreaInfo area{}; #endif void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -597,7 +597,7 @@ class ListEntitiesBinarySensorResponse : public InfoResponseProtoMessage { void set_device_class(const StringRef &ref) { this->device_class_ref_ = ref; } bool is_status_binary_sensor{false}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -614,7 +614,7 @@ class BinarySensorStateResponse : public StateResponseProtoMessage { bool state{false}; bool missing_state{false}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -637,7 +637,7 @@ class ListEntitiesCoverResponse : public InfoResponseProtoMessage { void set_device_class(const StringRef &ref) { this->device_class_ref_ = ref; } bool supports_stop{false}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -655,7 +655,7 @@ class CoverStateResponse : public StateResponseProtoMessage { float tilt{0.0f}; enums::CoverOperation current_operation{}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -697,7 +697,7 @@ class ListEntitiesFanResponse : public InfoResponseProtoMessage { int32_t supported_speed_count{0}; std::vector supported_preset_modes{}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -718,7 +718,7 @@ class FanStateResponse : public StateResponseProtoMessage { StringRef preset_mode_ref_{}; void set_preset_mode(const StringRef &ref) { this->preset_mode_ref_ = ref; } void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -765,7 +765,7 @@ class ListEntitiesLightResponse : public InfoResponseProtoMessage { float max_mireds{0.0f}; std::vector effects{}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -793,7 +793,7 @@ class LightStateResponse : public StateResponseProtoMessage { StringRef effect_ref_{}; void set_effect(const StringRef &ref) { this->effect_ref_ = ref; } void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -859,7 +859,7 @@ class ListEntitiesSensorResponse : public InfoResponseProtoMessage { void set_device_class(const StringRef &ref) { this->device_class_ref_ = ref; } enums::SensorStateClass state_class{}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -876,7 +876,7 @@ class SensorStateResponse : public StateResponseProtoMessage { float state{0.0f}; bool missing_state{false}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -896,7 +896,7 @@ class ListEntitiesSwitchResponse : public InfoResponseProtoMessage { StringRef device_class_ref_{}; void set_device_class(const StringRef &ref) { this->device_class_ref_ = ref; } void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -912,7 +912,7 @@ class SwitchStateResponse : public StateResponseProtoMessage { #endif bool state{false}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -947,7 +947,7 @@ class ListEntitiesTextSensorResponse : public InfoResponseProtoMessage { StringRef device_class_ref_{}; void set_device_class(const StringRef &ref) { this->device_class_ref_ = ref; } void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -965,7 +965,7 @@ class TextSensorStateResponse : public StateResponseProtoMessage { void set_state(const StringRef &ref) { this->state_ref_ = ref; } bool missing_state{false}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1004,7 +1004,7 @@ class SubscribeLogsResponse : public ProtoMessage { this->message_len_ = len; } void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1036,7 +1036,7 @@ class NoiseEncryptionSetKeyResponse : public ProtoMessage { #endif bool success{false}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1064,7 +1064,7 @@ class HomeassistantServiceMap : public ProtoMessage { void set_key(const StringRef &ref) { this->key_ref_ = ref; } std::string value{}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1085,7 +1085,7 @@ class HomeassistantServiceResponse : public ProtoMessage { std::vector variables{}; bool is_event{false}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1120,7 +1120,7 @@ class SubscribeHomeAssistantStateResponse : public ProtoMessage { void set_attribute(const StringRef &ref) { this->attribute_ref_ = ref; } bool once{false}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1167,7 +1167,7 @@ class GetTimeResponse : public ProtoDecodableMessage { #endif uint32_t epoch_seconds{0}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1182,7 +1182,7 @@ class ListEntitiesServicesArgument : public ProtoMessage { void set_name(const StringRef &ref) { this->name_ref_ = ref; } enums::ServiceArgType type{}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1201,7 +1201,7 @@ class ListEntitiesServicesResponse : public ProtoMessage { uint32_t key{0}; std::vector args{}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1255,7 +1255,7 @@ class ListEntitiesCameraResponse : public InfoResponseProtoMessage { const char *message_name() const override { return "list_entities_camera_response"; } #endif void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1277,7 +1277,7 @@ class CameraImageResponse : public StateResponseProtoMessage { } bool done{false}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1327,7 +1327,7 @@ class ListEntitiesClimateResponse : public InfoResponseProtoMessage { float visual_min_humidity{0.0f}; float visual_max_humidity{0.0f}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1357,7 +1357,7 @@ class ClimateStateResponse : public StateResponseProtoMessage { float current_humidity{0.0f}; float target_humidity{0.0f}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1418,7 +1418,7 @@ class ListEntitiesNumberResponse : public InfoResponseProtoMessage { StringRef device_class_ref_{}; void set_device_class(const StringRef &ref) { this->device_class_ref_ = ref; } void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1435,7 +1435,7 @@ class NumberStateResponse : public StateResponseProtoMessage { float state{0.0f}; bool missing_state{false}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1469,7 +1469,7 @@ class ListEntitiesSelectResponse : public InfoResponseProtoMessage { #endif std::vector options{}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1487,7 +1487,7 @@ class SelectStateResponse : public StateResponseProtoMessage { void set_state(const StringRef &ref) { this->state_ref_ = ref; } bool missing_state{false}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1524,7 +1524,7 @@ class ListEntitiesSirenResponse : public InfoResponseProtoMessage { bool supports_duration{false}; bool supports_volume{false}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1540,7 +1540,7 @@ class SirenStateResponse : public StateResponseProtoMessage { #endif bool state{false}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1586,7 +1586,7 @@ class ListEntitiesLockResponse : public InfoResponseProtoMessage { StringRef code_format_ref_{}; void set_code_format(const StringRef &ref) { this->code_format_ref_ = ref; } void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1602,7 +1602,7 @@ class LockStateResponse : public StateResponseProtoMessage { #endif enums::LockState state{}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1640,7 +1640,7 @@ class ListEntitiesButtonResponse : public InfoResponseProtoMessage { StringRef device_class_ref_{}; void set_device_class(const StringRef &ref) { this->device_class_ref_ = ref; } void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1673,7 +1673,7 @@ class MediaPlayerSupportedFormat : public ProtoMessage { enums::MediaPlayerFormatPurpose purpose{}; uint32_t sample_bytes{0}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1690,7 +1690,7 @@ class ListEntitiesMediaPlayerResponse : public InfoResponseProtoMessage { bool supports_pause{false}; std::vector supported_formats{}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1708,7 +1708,7 @@ class MediaPlayerStateResponse : public StateResponseProtoMessage { float volume{0.0f}; bool muted{false}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1764,7 +1764,7 @@ class BluetoothLERawAdvertisement : public ProtoMessage { uint8_t data[62]{}; uint8_t data_len{0}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1780,7 +1780,7 @@ class BluetoothLERawAdvertisementsResponse : public ProtoMessage { #endif std::vector advertisements{}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1817,7 +1817,7 @@ class BluetoothDeviceConnectionResponse : public ProtoMessage { uint32_t mtu{0}; int32_t error{0}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1844,7 +1844,7 @@ class BluetoothGATTDescriptor : public ProtoMessage { std::array uuid{}; uint32_t handle{0}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1858,7 +1858,7 @@ class BluetoothGATTCharacteristic : public ProtoMessage { uint32_t properties{0}; std::vector descriptors{}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1871,7 +1871,7 @@ class BluetoothGATTService : public ProtoMessage { uint32_t handle{0}; std::vector characteristics{}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1888,7 +1888,7 @@ class BluetoothGATTGetServicesResponse : public ProtoMessage { uint64_t address{0}; std::array services{}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1904,7 +1904,7 @@ class BluetoothGATTGetServicesDoneResponse : public ProtoMessage { #endif uint64_t address{0}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -1943,7 +1943,7 @@ class BluetoothGATTReadResponse : public ProtoMessage { this->data_len_ = len; } void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2036,7 +2036,7 @@ class BluetoothGATTNotifyDataResponse : public ProtoMessage { this->data_len_ = len; } void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2067,7 +2067,7 @@ class BluetoothConnectionsFreeResponse : public ProtoMessage { uint32_t limit{0}; std::vector allocated{}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2085,7 +2085,7 @@ class BluetoothGATTErrorResponse : public ProtoMessage { uint32_t handle{0}; int32_t error{0}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2102,7 +2102,7 @@ class BluetoothGATTWriteResponse : public ProtoMessage { uint64_t address{0}; uint32_t handle{0}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2119,7 +2119,7 @@ class BluetoothGATTNotifyResponse : public ProtoMessage { uint64_t address{0}; uint32_t handle{0}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2137,7 +2137,7 @@ class BluetoothDevicePairingResponse : public ProtoMessage { bool paired{false}; int32_t error{0}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2155,7 +2155,7 @@ class BluetoothDeviceUnpairingResponse : public ProtoMessage { bool success{false}; int32_t error{0}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2186,7 +2186,7 @@ class BluetoothDeviceClearCacheResponse : public ProtoMessage { bool success{false}; int32_t error{0}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2203,7 +2203,7 @@ class BluetoothScannerStateResponse : public ProtoMessage { enums::BluetoothScannerState state{}; enums::BluetoothScannerMode mode{}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2249,7 +2249,7 @@ class VoiceAssistantAudioSettings : public ProtoMessage { uint32_t auto_gain{0}; float volume_multiplier{0.0f}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2271,7 +2271,7 @@ class VoiceAssistantRequest : public ProtoMessage { StringRef wake_word_phrase_ref_{}; void set_wake_word_phrase(const StringRef &ref) { this->wake_word_phrase_ref_ = ref; } void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2338,7 +2338,7 @@ class VoiceAssistantAudio : public ProtoDecodableMessage { } bool end{false}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2396,7 +2396,7 @@ class VoiceAssistantAnnounceFinished : public ProtoMessage { #endif bool success{false}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2411,7 +2411,7 @@ class VoiceAssistantWakeWord : public ProtoMessage { void set_wake_word(const StringRef &ref) { this->wake_word_ref_ = ref; } std::vector trained_languages{}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2442,7 +2442,7 @@ class VoiceAssistantConfigurationResponse : public ProtoMessage { std::vector active_wake_words{}; uint32_t max_active_wake_words{0}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2477,7 +2477,7 @@ class ListEntitiesAlarmControlPanelResponse : public InfoResponseProtoMessage { bool requires_code{false}; bool requires_code_to_arm{false}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2493,7 +2493,7 @@ class AlarmControlPanelStateResponse : public StateResponseProtoMessage { #endif enums::AlarmControlPanelState state{}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2533,7 +2533,7 @@ class ListEntitiesTextResponse : public InfoResponseProtoMessage { void set_pattern(const StringRef &ref) { this->pattern_ref_ = ref; } enums::TextMode mode{}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2551,7 +2551,7 @@ class TextStateResponse : public StateResponseProtoMessage { void set_state(const StringRef &ref) { this->state_ref_ = ref; } bool missing_state{false}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2585,7 +2585,7 @@ class ListEntitiesDateResponse : public InfoResponseProtoMessage { const char *message_name() const override { return "list_entities_date_response"; } #endif void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2604,7 +2604,7 @@ class DateStateResponse : public StateResponseProtoMessage { uint32_t month{0}; uint32_t day{0}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2639,7 +2639,7 @@ class ListEntitiesTimeResponse : public InfoResponseProtoMessage { const char *message_name() const override { return "list_entities_time_response"; } #endif void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2658,7 +2658,7 @@ class TimeStateResponse : public StateResponseProtoMessage { uint32_t minute{0}; uint32_t second{0}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2696,7 +2696,7 @@ class ListEntitiesEventResponse : public InfoResponseProtoMessage { void set_device_class(const StringRef &ref) { this->device_class_ref_ = ref; } std::vector event_types{}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2713,7 +2713,7 @@ class EventResponse : public StateResponseProtoMessage { StringRef event_type_ref_{}; void set_event_type(const StringRef &ref) { this->event_type_ref_ = ref; } void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2735,7 +2735,7 @@ class ListEntitiesValveResponse : public InfoResponseProtoMessage { bool supports_position{false}; bool supports_stop{false}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2752,7 +2752,7 @@ class ValveStateResponse : public StateResponseProtoMessage { float position{0.0f}; enums::ValveOperation current_operation{}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2787,7 +2787,7 @@ class ListEntitiesDateTimeResponse : public InfoResponseProtoMessage { const char *message_name() const override { return "list_entities_date_time_response"; } #endif void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2804,7 +2804,7 @@ class DateTimeStateResponse : public StateResponseProtoMessage { bool missing_state{false}; uint32_t epoch_seconds{0}; void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2839,7 +2839,7 @@ class ListEntitiesUpdateResponse : public InfoResponseProtoMessage { StringRef device_class_ref_{}; void set_device_class(const StringRef &ref) { this->device_class_ref_ = ref; } void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif @@ -2868,7 +2868,7 @@ class UpdateStateResponse : public StateResponseProtoMessage { StringRef release_url_ref_{}; void set_release_url(const StringRef &ref) { this->release_url_ref_ = ref; } void encode(ProtoWriteBuffer buffer) const override; - void calculate_size(uint32_t &total_size) const override; + void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; #endif diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index cea93f928f..5c174b679c 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -333,13 +333,16 @@ class ProtoWriteBuffer { std::vector *buffer_; }; +// Forward declaration +class ProtoSize; + class ProtoMessage { public: virtual ~ProtoMessage() = default; // Default implementation for messages with no fields virtual void encode(ProtoWriteBuffer buffer) const {} // Default implementation for messages with no fields - virtual void calculate_size(uint32_t &total_size) const {} + virtual void calculate_size(ProtoSize &size) const {} #ifdef HAS_PROTO_MESSAGE_DUMP std::string dump() const; virtual void dump_to(std::string &out) const = 0; @@ -360,24 +363,32 @@ class ProtoDecodableMessage : public ProtoMessage { }; class ProtoSize { + private: + uint32_t total_size_ = 0; + public: /** * @brief ProtoSize class for Protocol Buffer serialization size calculation * - * This class provides static methods to calculate the exact byte counts needed - * for encoding various Protocol Buffer field types. All methods are designed to be - * efficient for the common case where many fields have default values. + * This class provides methods to calculate the exact byte counts needed + * for encoding various Protocol Buffer field types. The class now uses an + * object-based approach to reduce parameter passing overhead while keeping + * varint calculation methods static for external use. * * Implements Protocol Buffer encoding size calculation according to: * https://protobuf.dev/programming-guides/encoding/ * * Key features: + * - Object-based approach reduces flash usage by eliminating parameter passing * - Early-return optimization for zero/default values - * - Direct total_size updates to avoid unnecessary additions + * - Static varint methods for external callers * - Specialized handling for different field types according to protobuf spec - * - Templated helpers for repeated fields and messages */ + ProtoSize() = default; + + uint32_t get_size() const { return total_size_; } + /** * @brief Calculates the size in bytes needed to encode a uint32_t value as a varint * @@ -478,9 +489,7 @@ class ProtoSize { * @brief Common parameters for all add_*_field methods * * All add_*_field methods follow these common patterns: - * - * @param total_size Reference to the total message size to update - * @param field_id_size Pre-calculated size of the field ID in bytes + * * @param field_id_size Pre-calculated size of the field ID in bytes * @param value The value to calculate size for (type varies) * @param force Whether to calculate size even if the value is default/zero/empty * @@ -493,85 +502,63 @@ class ProtoSize { /** * @brief Calculates and adds the size of an int32 field to the total message size */ - static inline void add_int32_field(uint32_t &total_size, uint32_t field_id_size, int32_t value) { - // Skip calculation if value is zero - if (value == 0) { - return; // No need to update total_size - } - - // Calculate and directly add to total_size - if (value < 0) { - // Negative values are encoded as 10-byte varints in protobuf - total_size += field_id_size + 10; - } else { - // For non-negative values, use the standard varint size - total_size += field_id_size + varint(static_cast(value)); + inline void add_int32(uint32_t field_id_size, int32_t value) { + if (value != 0) { + add_int32_force(field_id_size, value); } } /** - * @brief Calculates and adds the size of an int32 field to the total message size (repeated field version) + * @brief Calculates and adds the size of an int32 field to the total message size (force version) */ - static inline void add_int32_field_repeated(uint32_t &total_size, uint32_t field_id_size, int32_t value) { - // Always calculate size for repeated fields - if (value < 0) { - // Negative values are encoded as 10-byte varints in protobuf - total_size += field_id_size + 10; - } else { - // For non-negative values, use the standard varint size - total_size += field_id_size + varint(static_cast(value)); - } + inline void add_int32_force(uint32_t field_id_size, int32_t value) { + // Always calculate size when forced + // Negative values are encoded as 10-byte varints in protobuf + total_size_ += field_id_size + (value < 0 ? 10 : varint(static_cast(value))); } /** * @brief Calculates and adds the size of a uint32 field to the total message size */ - static inline void add_uint32_field(uint32_t &total_size, uint32_t field_id_size, uint32_t value) { - // Skip calculation if value is zero - if (value == 0) { - return; // No need to update total_size + inline void add_uint32(uint32_t field_id_size, uint32_t value) { + if (value != 0) { + add_uint32_force(field_id_size, value); } - - // Calculate and directly add to total_size - total_size += field_id_size + varint(value); } /** - * @brief Calculates and adds the size of a uint32 field to the total message size (repeated field version) + * @brief Calculates and adds the size of a uint32 field to the total message size (force version) */ - static inline void add_uint32_field_repeated(uint32_t &total_size, uint32_t field_id_size, uint32_t value) { - // Always calculate size for repeated fields - total_size += field_id_size + varint(value); + inline void add_uint32_force(uint32_t field_id_size, uint32_t value) { + // Always calculate size when force is true + total_size_ += field_id_size + varint(value); } /** * @brief Calculates and adds the size of a boolean field to the total message size */ - static inline void add_bool_field(uint32_t &total_size, uint32_t field_id_size, bool value) { - // Skip calculation if value is false - if (!value) { - return; // No need to update total_size + inline void add_bool(uint32_t field_id_size, bool value) { + if (value) { + // Boolean fields always use 1 byte when true + total_size_ += field_id_size + 1; } - - // Boolean fields always use 1 byte when true - total_size += field_id_size + 1; } /** - * @brief Calculates and adds the size of a boolean field to the total message size (repeated field version) + * @brief Calculates and adds the size of a boolean field to the total message size (force version) */ - static inline void add_bool_field_repeated(uint32_t &total_size, uint32_t field_id_size, bool value) { - // Always calculate size for repeated fields + inline void add_bool_force(uint32_t field_id_size, bool value) { + // Always calculate size when force is true // Boolean fields always use 1 byte - total_size += field_id_size + 1; + total_size_ += field_id_size + 1; } /** * @brief Calculates and adds the size of a float field to the total message size */ - static inline void add_float_field(uint32_t &total_size, uint32_t field_id_size, float value) { + inline void add_float(uint32_t field_id_size, float value) { if (value != 0.0f) { - total_size += field_id_size + 4; + total_size_ += field_id_size + 4; } } @@ -581,9 +568,9 @@ class ProtoSize { /** * @brief Calculates and adds the size of a fixed32 field to the total message size */ - static inline void add_fixed32_field(uint32_t &total_size, uint32_t field_id_size, uint32_t value) { + inline void add_fixed32(uint32_t field_id_size, uint32_t value) { if (value != 0) { - total_size += field_id_size + 4; + total_size_ += field_id_size + 4; } } @@ -593,149 +580,104 @@ class ProtoSize { /** * @brief Calculates and adds the size of a sfixed32 field to the total message size */ - static inline void add_sfixed32_field(uint32_t &total_size, uint32_t field_id_size, int32_t value) { + inline void add_sfixed32(uint32_t field_id_size, int32_t value) { if (value != 0) { - total_size += field_id_size + 4; + total_size_ += field_id_size + 4; } } // NOTE: add_sfixed64_field removed - wire type 1 (64-bit: sfixed64) not supported // to reduce overhead on embedded systems - /** - * @brief Calculates and adds the size of an enum field to the total message size - * - * Enum fields are encoded as uint32 varints. - */ - static inline void add_enum_field(uint32_t &total_size, uint32_t field_id_size, uint32_t value) { - // Skip calculation if value is zero - if (value == 0) { - return; // No need to update total_size - } - - // Enums are encoded as uint32 - total_size += field_id_size + varint(value); - } - - /** - * @brief Calculates and adds the size of an enum field to the total message size (repeated field version) - * - * Enum fields are encoded as uint32 varints. - */ - static inline void add_enum_field_repeated(uint32_t &total_size, uint32_t field_id_size, uint32_t value) { - // Always calculate size for repeated fields - // Enums are encoded as uint32 - total_size += field_id_size + varint(value); - } - /** * @brief Calculates and adds the size of a sint32 field to the total message size * * Sint32 fields use ZigZag encoding, which is more efficient for negative values. */ - static inline void add_sint32_field(uint32_t &total_size, uint32_t field_id_size, int32_t value) { - // Skip calculation if value is zero - if (value == 0) { - return; // No need to update total_size + inline void add_sint32(uint32_t field_id_size, int32_t value) { + if (value != 0) { + add_sint32_force(field_id_size, value); } - - // ZigZag encoding for sint32: (n << 1) ^ (n >> 31) - uint32_t zigzag = (static_cast(value) << 1) ^ (static_cast(value >> 31)); - total_size += field_id_size + varint(zigzag); } /** - * @brief Calculates and adds the size of a sint32 field to the total message size (repeated field version) + * @brief Calculates and adds the size of a sint32 field to the total message size (force version) * * Sint32 fields use ZigZag encoding, which is more efficient for negative values. */ - static inline void add_sint32_field_repeated(uint32_t &total_size, uint32_t field_id_size, int32_t value) { - // Always calculate size for repeated fields + inline void add_sint32_force(uint32_t field_id_size, int32_t value) { + // Always calculate size when force is true // ZigZag encoding for sint32: (n << 1) ^ (n >> 31) uint32_t zigzag = (static_cast(value) << 1) ^ (static_cast(value >> 31)); - total_size += field_id_size + varint(zigzag); + total_size_ += field_id_size + varint(zigzag); } /** * @brief Calculates and adds the size of an int64 field to the total message size */ - static inline void add_int64_field(uint32_t &total_size, uint32_t field_id_size, int64_t value) { - // Skip calculation if value is zero - if (value == 0) { - return; // No need to update total_size + inline void add_int64(uint32_t field_id_size, int64_t value) { + if (value != 0) { + add_int64_force(field_id_size, value); } - - // Calculate and directly add to total_size - total_size += field_id_size + varint(value); } /** - * @brief Calculates and adds the size of an int64 field to the total message size (repeated field version) + * @brief Calculates and adds the size of an int64 field to the total message size (force version) */ - static inline void add_int64_field_repeated(uint32_t &total_size, uint32_t field_id_size, int64_t value) { - // Always calculate size for repeated fields - total_size += field_id_size + varint(value); + inline void add_int64_force(uint32_t field_id_size, int64_t value) { + // Always calculate size when force is true + total_size_ += field_id_size + varint(value); } /** * @brief Calculates and adds the size of a uint64 field to the total message size */ - static inline void add_uint64_field(uint32_t &total_size, uint32_t field_id_size, uint64_t value) { - // Skip calculation if value is zero - if (value == 0) { - return; // No need to update total_size + inline void add_uint64(uint32_t field_id_size, uint64_t value) { + if (value != 0) { + add_uint64_force(field_id_size, value); } - - // Calculate and directly add to total_size - total_size += field_id_size + varint(value); } /** - * @brief Calculates and adds the size of a uint64 field to the total message size (repeated field version) + * @brief Calculates and adds the size of a uint64 field to the total message size (force version) */ - static inline void add_uint64_field_repeated(uint32_t &total_size, uint32_t field_id_size, uint64_t value) { - // Always calculate size for repeated fields - total_size += field_id_size + varint(value); + inline void add_uint64_force(uint32_t field_id_size, uint64_t value) { + // Always calculate size when force is true + total_size_ += field_id_size + varint(value); } - // NOTE: sint64 support functions (add_sint64_field, add_sint64_field_repeated) removed + // NOTE: sint64 support functions (add_sint64_field, add_sint64_field_force) removed // sint64 type is not supported by ESPHome API to reduce overhead on embedded systems /** - * @brief Calculates and adds the size of a string field using length + * @brief Calculates and adds the size of a length-delimited field (string/bytes) to the total message size */ - static inline void add_string_field(uint32_t &total_size, uint32_t field_id_size, size_t len) { - // Skip calculation if string is empty - if (len == 0) { - return; // No need to update total_size + inline void add_length(uint32_t field_id_size, size_t len) { + if (len != 0) { + add_length_force(field_id_size, len); } - - // Field ID + length varint + string bytes - total_size += field_id_size + varint(static_cast(len)) + static_cast(len); } /** - * @brief Calculates and adds the size of a string/bytes field to the total message size (repeated field version) + * @brief Calculates and adds the size of a length-delimited field (string/bytes) to the total message size (repeated + * field version) */ - static inline void add_string_field_repeated(uint32_t &total_size, uint32_t field_id_size, const std::string &str) { - // Always calculate size for repeated fields - const uint32_t str_size = static_cast(str.size()); - total_size += field_id_size + varint(str_size) + str_size; - } - - /** - * @brief Calculates and adds the size of a bytes field to the total message size - */ - static inline void add_bytes_field(uint32_t &total_size, uint32_t field_id_size, size_t len) { - // Skip calculation if bytes is empty - if (len == 0) { - return; // No need to update total_size - } - + inline void add_length_force(uint32_t field_id_size, size_t len) { + // Always calculate size when force is true // Field ID + length varint + data bytes - total_size += field_id_size + varint(static_cast(len)) + static_cast(len); + total_size_ += field_id_size + varint(static_cast(len)) + static_cast(len); } + /** + * @brief Adds a pre-calculated size directly to the total + * + * This is used when we can calculate the total size by multiplying the number + * of elements by the bytes per element (for repeated fixed-size types like float, fixed32, etc.) + * + * @param size The pre-calculated total size to add + */ + inline void add_precalculated_size(uint32_t size) { total_size_ += size; } + /** * @brief Calculates and adds the size of a nested message field to the total message size * @@ -744,26 +686,21 @@ class ProtoSize { * * @param nested_size The pre-calculated size of the nested message */ - static inline void add_message_field(uint32_t &total_size, uint32_t field_id_size, uint32_t nested_size) { - // Skip calculation if nested message is empty - if (nested_size == 0) { - return; // No need to update total_size + inline void add_message_field(uint32_t field_id_size, uint32_t nested_size) { + if (nested_size != 0) { + add_message_field_force(field_id_size, nested_size); } - - // Calculate and directly add to total_size - // Field ID + length varint + nested message content - total_size += field_id_size + varint(nested_size) + nested_size; } /** - * @brief Calculates and adds the size of a nested message field to the total message size (repeated field version) + * @brief Calculates and adds the size of a nested message field to the total message size (force version) * * @param nested_size The pre-calculated size of the nested message */ - static inline void add_message_field_repeated(uint32_t &total_size, uint32_t field_id_size, uint32_t nested_size) { - // Always calculate size for repeated fields + inline void add_message_field_force(uint32_t field_id_size, uint32_t nested_size) { + // Always calculate size when force is true // Field ID + length varint + nested message content - total_size += field_id_size + varint(nested_size) + nested_size; + total_size_ += field_id_size + varint(nested_size) + nested_size; } /** @@ -775,26 +712,29 @@ class ProtoSize { * * @param message The nested message object */ - static inline void add_message_object(uint32_t &total_size, uint32_t field_id_size, const ProtoMessage &message) { - uint32_t nested_size = 0; - message.calculate_size(nested_size); + inline void add_message_object(uint32_t field_id_size, const ProtoMessage &message) { + // Calculate nested message size by creating a temporary ProtoSize + ProtoSize nested_calc; + message.calculate_size(nested_calc); + uint32_t nested_size = nested_calc.get_size(); // Use the base implementation with the calculated nested_size - add_message_field(total_size, field_id_size, nested_size); + add_message_field(field_id_size, nested_size); } /** - * @brief Calculates and adds the size of a nested message field to the total message size (repeated field version) + * @brief Calculates and adds the size of a nested message field to the total message size (force version) * * @param message The nested message object */ - static inline void add_message_object_repeated(uint32_t &total_size, uint32_t field_id_size, - const ProtoMessage &message) { - uint32_t nested_size = 0; - message.calculate_size(nested_size); + inline void add_message_object_force(uint32_t field_id_size, const ProtoMessage &message) { + // Calculate nested message size by creating a temporary ProtoSize + ProtoSize nested_calc; + message.calculate_size(nested_calc); + uint32_t nested_size = nested_calc.get_size(); // Use the base implementation with the calculated nested_size - add_message_field_repeated(total_size, field_id_size, nested_size); + add_message_field_force(field_id_size, nested_size); } /** @@ -807,16 +747,15 @@ class ProtoSize { * @param messages Vector of message objects */ template - static inline void add_repeated_message(uint32_t &total_size, uint32_t field_id_size, - const std::vector &messages) { + inline void add_repeated_message(uint32_t field_id_size, const std::vector &messages) { // Skip if the vector is empty if (messages.empty()) { return; } - // Use the repeated field version for all messages + // Use the force version for all messages in the repeated field for (const auto &message : messages) { - add_message_object_repeated(total_size, field_id_size, message); + add_message_object_force(field_id_size, message); } } }; @@ -826,8 +765,9 @@ inline void ProtoWriteBuffer::encode_message(uint32_t field_id, const ProtoMessa this->encode_field_raw(field_id, 2); // type 2: Length-delimited message // Calculate the message size first - uint32_t msg_length_bytes = 0; - value.calculate_size(msg_length_bytes); + ProtoSize msg_size; + value.calculate_size(msg_size); + uint32_t msg_length_bytes = msg_size.get_size(); // Calculate how many bytes the length varint needs uint32_t varint_length_bytes = ProtoSize::varint(msg_length_bytes); @@ -876,8 +816,9 @@ class ProtoService { // Optimized method that pre-allocates buffer based on message size bool send_message_(const ProtoMessage &msg, uint8_t message_type) { - uint32_t msg_size = 0; - msg.calculate_size(msg_size); + ProtoSize size; + msg.calculate_size(size); + uint32_t msg_size = size.get_size(); // Create a pre-sized buffer auto buffer = this->create_buffer(msg_size); diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index d346b66aef..275c7ffc9e 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -275,13 +275,13 @@ class TypeInfo(ABC): Args: name: Field name force: Whether this is for a repeated field - base_method: Base method name (e.g., "add_int32_field") + base_method: Base method name (e.g., "add_int32") value_expr: Optional value expression (defaults to name) """ field_id_size = self.calculate_field_id_size() - method = f"{base_method}_repeated" if force else base_method + method = f"{base_method}_force" if force else base_method value = value_expr if value_expr else name - return f"ProtoSize::{method}(total_size, {field_id_size}, {value});" + return f"size.{method}({field_id_size}, {value});" @abstractmethod def get_size_calculation(self, name: str, force: bool = False) -> str: @@ -389,7 +389,7 @@ class DoubleType(TypeInfo): def get_size_calculation(self, name: str, force: bool = False) -> str: field_id_size = self.calculate_field_id_size() - return f"ProtoSize::add_double_field(total_size, {field_id_size}, {name});" + return f"size.add_double({field_id_size}, {name});" def get_fixed_size_bytes(self) -> int: return 8 @@ -413,7 +413,7 @@ class FloatType(TypeInfo): def get_size_calculation(self, name: str, force: bool = False) -> str: field_id_size = self.calculate_field_id_size() - return f"ProtoSize::add_float_field(total_size, {field_id_size}, {name});" + return f"size.add_float({field_id_size}, {name});" def get_fixed_size_bytes(self) -> int: return 4 @@ -436,7 +436,7 @@ class Int64Type(TypeInfo): return o def get_size_calculation(self, name: str, force: bool = False) -> str: - return self._get_simple_size_calculation(name, force, "add_int64_field") + return self._get_simple_size_calculation(name, force, "add_int64") def get_estimated_size(self) -> int: return self.calculate_field_id_size() + 3 # field ID + 3 bytes typical varint @@ -456,7 +456,7 @@ class UInt64Type(TypeInfo): return o def get_size_calculation(self, name: str, force: bool = False) -> str: - return self._get_simple_size_calculation(name, force, "add_uint64_field") + return self._get_simple_size_calculation(name, force, "add_uint64") def get_estimated_size(self) -> int: return self.calculate_field_id_size() + 3 # field ID + 3 bytes typical varint @@ -476,7 +476,7 @@ class Int32Type(TypeInfo): return o def get_size_calculation(self, name: str, force: bool = False) -> str: - return self._get_simple_size_calculation(name, force, "add_int32_field") + return self._get_simple_size_calculation(name, force, "add_int32") def get_estimated_size(self) -> int: return self.calculate_field_id_size() + 3 # field ID + 3 bytes typical varint @@ -497,7 +497,7 @@ class Fixed64Type(TypeInfo): def get_size_calculation(self, name: str, force: bool = False) -> str: field_id_size = self.calculate_field_id_size() - return f"ProtoSize::add_fixed64_field(total_size, {field_id_size}, {name});" + return f"size.add_fixed64({field_id_size}, {name});" def get_fixed_size_bytes(self) -> int: return 8 @@ -521,7 +521,7 @@ class Fixed32Type(TypeInfo): def get_size_calculation(self, name: str, force: bool = False) -> str: field_id_size = self.calculate_field_id_size() - return f"ProtoSize::add_fixed32_field(total_size, {field_id_size}, {name});" + return f"size.add_fixed32({field_id_size}, {name});" def get_fixed_size_bytes(self) -> int: return 4 @@ -543,7 +543,7 @@ class BoolType(TypeInfo): return o def get_size_calculation(self, name: str, force: bool = False) -> str: - return self._get_simple_size_calculation(name, force, "add_bool_field") + return self._get_simple_size_calculation(name, force, "add_bool") def get_estimated_size(self) -> int: return self.calculate_field_id_size() + 1 # field ID + 1 byte @@ -657,19 +657,21 @@ class StringType(TypeInfo): # For no_zero_copy, we need to use .size() on the string if no_zero_copy and name != "it": field_id_size = self.calculate_field_id_size() - return f"ProtoSize::add_string_field(total_size, {field_id_size}, this->{self.field_name}.size());" - return self._get_simple_size_calculation(name, force, "add_string_field") + return ( + f"size.add_length({field_id_size}, this->{self.field_name}.size());" + ) + return self._get_simple_size_calculation(name, force, "add_length") # Check if this is being called from a repeated field context # In that case, 'name' will be 'it' and we need to use the repeated version if name == "it": - # For repeated fields, we need to use add_string_field_repeated which includes field ID + # For repeated fields, we need to use add_length_force which includes field ID field_id_size = self.calculate_field_id_size() - return f"ProtoSize::add_string_field_repeated(total_size, {field_id_size}, it);" + return f"size.add_length_force({field_id_size}, it.size());" # For messages that need encoding, use the StringRef size field_id_size = self.calculate_field_id_size() - return f"ProtoSize::add_string_field(total_size, {field_id_size}, this->{self.field_name}_ref_.size());" + return f"size.add_length({field_id_size}, this->{self.field_name}_ref_.size());" def get_estimated_size(self) -> int: return self.calculate_field_id_size() + 8 # field ID + 8 bytes typical string @@ -804,7 +806,7 @@ class BytesType(TypeInfo): return o def get_size_calculation(self, name: str, force: bool = False) -> str: - return f"ProtoSize::add_bytes_field(total_size, {self.calculate_field_id_size()}, this->{self.field_name}_len_);" + return f"size.add_length({self.calculate_field_id_size()}, this->{self.field_name}_len_);" def get_estimated_size(self) -> int: return self.calculate_field_id_size() + 8 # field ID + 8 bytes typical bytes @@ -879,15 +881,11 @@ class FixedArrayBytesType(TypeInfo): field_id_size = self.calculate_field_id_size() if force: - # For repeated fields, always calculate size - return f"total_size += {field_id_size} + ProtoSize::varint(static_cast({length_field})) + {length_field};" + # For repeated fields, always calculate size (no zero check) + return f"size.add_length_force({field_id_size}, {length_field});" else: - # For non-repeated fields, skip if length is 0 (matching encode_string behavior) - return ( - f"if ({length_field} != 0) {{\n" - f" total_size += {field_id_size} + ProtoSize::varint(static_cast({length_field})) + {length_field};\n" - f"}}" - ) + # For non-repeated fields, add_length already checks for zero + return f"size.add_length({field_id_size}, {length_field});" def get_estimated_size(self) -> int: # Estimate based on typical BLE advertisement size @@ -914,7 +912,7 @@ class UInt32Type(TypeInfo): return o def get_size_calculation(self, name: str, force: bool = False) -> str: - return self._get_simple_size_calculation(name, force, "add_uint32_field") + return self._get_simple_size_calculation(name, force, "add_uint32") def get_estimated_size(self) -> int: return self.calculate_field_id_size() + 3 # field ID + 3 bytes typical varint @@ -951,7 +949,7 @@ class EnumType(TypeInfo): def get_size_calculation(self, name: str, force: bool = False) -> str: return self._get_simple_size_calculation( - name, force, "add_enum_field", f"static_cast({name})" + name, force, "add_uint32", f"static_cast({name})" ) def get_estimated_size(self) -> int: @@ -973,7 +971,7 @@ class SFixed32Type(TypeInfo): def get_size_calculation(self, name: str, force: bool = False) -> str: field_id_size = self.calculate_field_id_size() - return f"ProtoSize::add_sfixed32_field(total_size, {field_id_size}, {name});" + return f"size.add_sfixed32({field_id_size}, {name});" def get_fixed_size_bytes(self) -> int: return 4 @@ -997,7 +995,7 @@ class SFixed64Type(TypeInfo): def get_size_calculation(self, name: str, force: bool = False) -> str: field_id_size = self.calculate_field_id_size() - return f"ProtoSize::add_sfixed64_field(total_size, {field_id_size}, {name});" + return f"size.add_sfixed64({field_id_size}, {name});" def get_fixed_size_bytes(self) -> int: return 8 @@ -1020,7 +1018,7 @@ class SInt32Type(TypeInfo): return o def get_size_calculation(self, name: str, force: bool = False) -> str: - return self._get_simple_size_calculation(name, force, "add_sint32_field") + return self._get_simple_size_calculation(name, force, "add_sint32") def get_estimated_size(self) -> int: return self.calculate_field_id_size() + 3 # field ID + 3 bytes typical varint @@ -1040,7 +1038,7 @@ class SInt64Type(TypeInfo): return o def get_size_calculation(self, name: str, force: bool = False) -> str: - return self._get_simple_size_calculation(name, force, "add_sint64_field") + return self._get_simple_size_calculation(name, force, "add_sint64") def get_estimated_size(self) -> int: return self.calculate_field_id_size() + 3 # field ID + 3 bytes typical varint @@ -1274,7 +1272,7 @@ class RepeatedTypeInfo(TypeInfo): if isinstance(self._ti, MessageType): # For repeated messages, use the dedicated helper that handles iteration internally field_id_size = self._ti.calculate_field_id_size() - o = f"ProtoSize::add_repeated_message(total_size, {field_id_size}, {name});" + o = f"size.add_repeated_message({field_id_size}, {name});" return o # For other repeated types, use the underlying type's size calculation with force=True @@ -1287,7 +1285,9 @@ class RepeatedTypeInfo(TypeInfo): field_id_size = self._ti.calculate_field_id_size() # Pre-calculate the total bytes per element bytes_per_element = field_id_size + num_bytes - o += f" total_size += {name}.size() * {bytes_per_element};\n" + o += ( + f" size.add_precalculated_size({name}.size() * {bytes_per_element});\n" + ) else: # Other types need the actual value o += f" for (const auto {'' if self._ti_is_bool else '&'}it : {name}) {{\n" @@ -1719,11 +1719,11 @@ def build_message_type( if needs_encode and encode: o = f"void {desc.name}::encode(ProtoWriteBuffer buffer) const {{" if len(encode) == 1 and len(encode[0]) + len(o) + 3 < 120: - o += f" {encode[0]} " + o += f" {encode[0]} }}\n" else: o += "\n" o += indent("\n".join(encode)) + "\n" - o += "}\n" + o += "}\n" cpp += o prot = "void encode(ProtoWriteBuffer buffer) const override;" public_content.append(prot) @@ -1731,17 +1731,17 @@ def build_message_type( # Add calculate_size method only if this message needs encoding and has fields if needs_encode and size_calc: - o = f"void {desc.name}::calculate_size(uint32_t &total_size) const {{" + o = f"void {desc.name}::calculate_size(ProtoSize &size) const {{" # For a single field, just inline it for simplicity if len(size_calc) == 1 and len(size_calc[0]) + len(o) + 3 < 120: - o += f" {size_calc[0]} " + o += f" {size_calc[0]} }}\n" else: # For multiple fields o += "\n" o += indent("\n".join(size_calc)) + "\n" - o += "}\n" + o += "}\n" cpp += o - prot = "void calculate_size(uint32_t &total_size) const override;" + prot = "void calculate_size(ProtoSize &size) const override;" public_content.append(prot) # If no fields to calculate size for or message doesn't need encoding, the default implementation in ProtoMessage will be used From 4f425c700ae0f596647f466212d7611f1f0d1497 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 28 Jul 2025 13:33:54 -1000 Subject: [PATCH 17/28] [esp32] Enable LWIP core locking on ESP-IDF to reduce socket operation overhead (#9857) --- esphome/components/esp32/__init__.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 2b4c4ff043..78bafcb790 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -571,6 +571,8 @@ CONF_SDKCONFIG_OPTIONS = "sdkconfig_options" CONF_ENABLE_LWIP_DHCP_SERVER = "enable_lwip_dhcp_server" CONF_ENABLE_LWIP_MDNS_QUERIES = "enable_lwip_mdns_queries" CONF_ENABLE_LWIP_BRIDGE_INTERFACE = "enable_lwip_bridge_interface" +CONF_ENABLE_LWIP_TCPIP_CORE_LOCKING = "enable_lwip_tcpip_core_locking" +CONF_ENABLE_LWIP_CHECK_THREAD_SAFETY = "enable_lwip_check_thread_safety" def _validate_idf_component(config: ConfigType) -> ConfigType: @@ -619,6 +621,12 @@ ESP_IDF_FRAMEWORK_SCHEMA = cv.All( cv.Optional( CONF_ENABLE_LWIP_BRIDGE_INTERFACE, default=False ): cv.boolean, + cv.Optional( + CONF_ENABLE_LWIP_TCPIP_CORE_LOCKING, default=True + ): cv.boolean, + cv.Optional( + CONF_ENABLE_LWIP_CHECK_THREAD_SAFETY, default=True + ): cv.boolean, } ), cv.Optional(CONF_COMPONENTS, default=[]): cv.ensure_list( @@ -785,6 +793,18 @@ async def to_code(config): if not advanced.get(CONF_ENABLE_LWIP_BRIDGE_INTERFACE, False): add_idf_sdkconfig_option("CONFIG_LWIP_BRIDGEIF_MAX_PORTS", 0) + # Apply LWIP core locking for better socket performance + # This is already enabled by default in Arduino framework, where it provides + # significant performance benefits. Our benchmarks show socket operations are + # 24-200% faster with core locking enabled: + # - select() on 4 sockets: ~190μs (Arduino/core locking) vs ~235μs (ESP-IDF default) + # - Up to 200% slower under load when all operations queue through tcpip_thread + # Enabling this makes ESP-IDF socket performance match Arduino framework. + if advanced.get(CONF_ENABLE_LWIP_TCPIP_CORE_LOCKING, True): + add_idf_sdkconfig_option("CONFIG_LWIP_TCPIP_CORE_LOCKING", True) + if advanced.get(CONF_ENABLE_LWIP_CHECK_THREAD_SAFETY, True): + add_idf_sdkconfig_option("CONFIG_LWIP_CHECK_THREAD_SAFETY", True) + cg.add_platformio_option("board_build.partitions", "partitions.csv") if CONF_PARTITIONS in config: add_extra_build_file( From 7657316a9249ee90d83cfbad92b17cdf4660346f Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 28 Jul 2025 18:34:52 -0500 Subject: [PATCH 18/28] [sensor] Add support for default filters (#9934) --- esphome/components/sensor/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index bcde623df2..20c6911d28 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -332,6 +332,7 @@ def sensor_schema( device_class: str = cv.UNDEFINED, state_class: str = cv.UNDEFINED, entity_category: str = cv.UNDEFINED, + filters: list = cv.UNDEFINED, ) -> cv.Schema: schema = {} @@ -346,6 +347,7 @@ def sensor_schema( (CONF_DEVICE_CLASS, device_class, validate_device_class), (CONF_STATE_CLASS, state_class, validate_state_class), (CONF_ENTITY_CATEGORY, entity_category, sensor_entity_category), + (CONF_FILTERS, filters, validate_filters), ]: if default is not cv.UNDEFINED: schema[cv.Optional(key, default=default)] = validator From 908891a096a52330216bf60ac6b9ce3f7d3af0f3 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 28 Jul 2025 18:35:11 -0500 Subject: [PATCH 19/28] [binary_sensor] Add support for default filters (#9935) --- esphome/components/binary_sensor/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/binary_sensor/__init__.py b/esphome/components/binary_sensor/__init__.py index e3931e3946..376a399637 100644 --- a/esphome/components/binary_sensor/__init__.py +++ b/esphome/components/binary_sensor/__init__.py @@ -516,6 +516,7 @@ def binary_sensor_schema( icon: str = cv.UNDEFINED, entity_category: str = cv.UNDEFINED, device_class: str = cv.UNDEFINED, + filters: list = cv.UNDEFINED, ) -> cv.Schema: schema = {} @@ -527,6 +528,7 @@ def binary_sensor_schema( (CONF_ICON, icon, cv.icon), (CONF_ENTITY_CATEGORY, entity_category, cv.entity_category), (CONF_DEVICE_CLASS, device_class, validate_device_class), + (CONF_FILTERS, filters, validate_filters), ]: if default is not cv.UNDEFINED: schema[cv.Optional(key, default=default)] = validator From f5f0a01a850e0dcf59c13a7396cde7faf1ecaf18 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 28 Jul 2025 18:35:40 -0500 Subject: [PATCH 20/28] [text_sensor] Add support for default filters (#9936) --- esphome/components/text_sensor/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/text_sensor/__init__.py b/esphome/components/text_sensor/__init__.py index abb2dcae6c..0341ab2f71 100644 --- a/esphome/components/text_sensor/__init__.py +++ b/esphome/components/text_sensor/__init__.py @@ -162,6 +162,7 @@ def text_sensor_schema( device_class: str = cv.UNDEFINED, entity_category: str = cv.UNDEFINED, icon: str = cv.UNDEFINED, + filters: list = cv.UNDEFINED, ) -> cv.Schema: schema = {} @@ -172,6 +173,7 @@ def text_sensor_schema( (CONF_ICON, icon, cv.icon), (CONF_DEVICE_CLASS, device_class, validate_device_class), (CONF_ENTITY_CATEGORY, entity_category, cv.entity_category), + (CONF_FILTERS, filters, validate_filters), ]: if default is not cv.UNDEFINED: schema[cv.Optional(key, default=default)] = validator From f733c43dec39596b12936ff6be5c6c55169cdb4d Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 28 Jul 2025 23:59:58 -0400 Subject: [PATCH 21/28] [heatpumpir] Fix issue with IRremoteESP8266 being included on ESP32 (#9950) --- esphome/components/heatpumpir/climate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/heatpumpir/climate.py b/esphome/components/heatpumpir/climate.py index d2b907d437..4f83bf2435 100644 --- a/esphome/components/heatpumpir/climate.py +++ b/esphome/components/heatpumpir/climate.py @@ -127,5 +127,5 @@ async def to_code(config): cg.add(var.set_min_temperature(config[CONF_MIN_TEMPERATURE])) cg.add_library("tonia/HeatpumpIR", "1.0.37") - if CORE.is_libretiny: + if CORE.is_libretiny or CORE.is_esp32: CORE.add_platformio_option("lib_ignore", "IRremoteESP8266") From 9d43ddd6f110b447f4f0cd5c56a46d36613001b7 Mon Sep 17 00:00:00 2001 From: rwrozelle Date: Tue, 29 Jul 2025 00:25:17 -0400 Subject: [PATCH 22/28] Openthread add Teardown (#9275) Co-authored-by: mc Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/openthread/openthread.cpp | 42 +++++++++++++------ esphome/components/openthread/openthread.h | 3 ++ .../components/openthread/openthread_esp.cpp | 3 ++ 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/esphome/components/openthread/openthread.cpp b/esphome/components/openthread/openthread.cpp index 800128745c..322ff43238 100644 --- a/esphome/components/openthread/openthread.cpp +++ b/esphome/components/openthread/openthread.cpp @@ -1,6 +1,9 @@ #include "esphome/core/defines.h" #ifdef USE_OPENTHREAD #include "openthread.h" +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0) +#include "esp_openthread.h" +#endif #include @@ -28,18 +31,6 @@ OpenThreadComponent *global_openthread_component = // NOLINT(cppcoreguidelines- OpenThreadComponent::OpenThreadComponent() { global_openthread_component = this; } -OpenThreadComponent::~OpenThreadComponent() { - auto lock = InstanceLock::try_acquire(100); - if (!lock) { - ESP_LOGW(TAG, "Failed to acquire OpenThread lock in destructor, leaking memory"); - return; - } - otInstance *instance = lock->get_instance(); - otSrpClientClearHostAndServices(instance); - otSrpClientBuffersFreeAllServices(instance); - global_openthread_component = nullptr; -} - bool OpenThreadComponent::is_connected() { auto lock = InstanceLock::try_acquire(100); if (!lock) { @@ -199,6 +190,33 @@ void *OpenThreadSrpComponent::pool_alloc_(size_t size) { void OpenThreadSrpComponent::set_mdns(esphome::mdns::MDNSComponent *mdns) { this->mdns_ = mdns; } +bool OpenThreadComponent::teardown() { + if (!this->teardown_started_) { + this->teardown_started_ = true; + ESP_LOGD(TAG, "Clear Srp"); + auto lock = InstanceLock::try_acquire(100); + if (!lock) { + ESP_LOGW(TAG, "Failed to acquire OpenThread lock during teardown, leaking memory"); + return true; + } + otInstance *instance = lock->get_instance(); + otSrpClientClearHostAndServices(instance); + otSrpClientBuffersFreeAllServices(instance); + global_openthread_component = nullptr; +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0) + ESP_LOGD(TAG, "Exit main loop "); + int error = esp_openthread_mainloop_exit(); + if (error != ESP_OK) { + ESP_LOGW(TAG, "Failed attempt to stop main loop %d", error); + this->teardown_complete_ = true; + } +#else + this->teardown_complete_ = true; +#endif + } + return this->teardown_complete_; +} + } // namespace openthread } // namespace esphome diff --git a/esphome/components/openthread/openthread.h b/esphome/components/openthread/openthread.h index 77fd58851a..a0ea1b3f3a 100644 --- a/esphome/components/openthread/openthread.h +++ b/esphome/components/openthread/openthread.h @@ -21,6 +21,7 @@ class OpenThreadComponent : public Component { OpenThreadComponent(); ~OpenThreadComponent(); void setup() override; + bool teardown() override; float get_setup_priority() const override { return setup_priority::WIFI; } bool is_connected(); @@ -30,6 +31,8 @@ class OpenThreadComponent : public Component { protected: std::optional get_omr_address_(InstanceLock &lock); + bool teardown_started_{false}; + bool teardown_complete_{false}; }; extern OpenThreadComponent *global_openthread_component; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) diff --git a/esphome/components/openthread/openthread_esp.cpp b/esphome/components/openthread/openthread_esp.cpp index f495027172..b11b7ad34a 100644 --- a/esphome/components/openthread/openthread_esp.cpp +++ b/esphome/components/openthread/openthread_esp.cpp @@ -143,10 +143,13 @@ void OpenThreadComponent::ot_main() { esp_openthread_launch_mainloop(); // Clean up + esp_openthread_deinit(); esp_openthread_netif_glue_deinit(); esp_netif_destroy(openthread_netif); esp_vfs_eventfd_unregister(); + this->teardown_complete_ = true; + vTaskDelete(NULL); } network::IPAddresses OpenThreadComponent::get_ip_addresses() { From 4ff3137c0d2279f5885b2905f543cf69993853f3 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 29 Jul 2025 00:21:52 -0500 Subject: [PATCH 23/28] [gps] Fix slow parsing (#9953) --- esphome/components/gps/gps.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/gps/gps.cpp b/esphome/components/gps/gps.cpp index cbbd36887b..65cddcd984 100644 --- a/esphome/components/gps/gps.cpp +++ b/esphome/components/gps/gps.cpp @@ -52,7 +52,7 @@ void GPS::update() { void GPS::loop() { while (this->available() > 0 && !this->has_time_) { if (!this->tiny_gps_.encode(this->read())) { - return; + continue; } if (this->tiny_gps_.location.isUpdated()) { this->latitude_ = this->tiny_gps_.location.lat(); From 6d30269565f086ef1c8f2edf1c98ef81ab36911c Mon Sep 17 00:00:00 2001 From: Djordje Mandic <6750655+DjordjeMandic@users.noreply.github.com> Date: Tue, 29 Jul 2025 07:22:44 +0200 Subject: [PATCH 24/28] [output] Add `set_min_power` & `set_max_power` actions for `FloatOutput` (#8934) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/output/__init__.py | 38 ++++++++++++++++++++++++++ esphome/components/output/automation.h | 24 ++++++++++++++++ tests/components/output/common.yaml | 6 ++++ 3 files changed, 68 insertions(+) diff --git a/esphome/components/output/__init__.py b/esphome/components/output/__init__.py index 78bfa045e1..bde106b085 100644 --- a/esphome/components/output/__init__.py +++ b/esphome/components/output/__init__.py @@ -43,6 +43,8 @@ FloatOutputPtr = FloatOutput.operator("ptr") TurnOffAction = output_ns.class_("TurnOffAction", automation.Action) TurnOnAction = output_ns.class_("TurnOnAction", automation.Action) SetLevelAction = output_ns.class_("SetLevelAction", automation.Action) +SetMinPowerAction = output_ns.class_("SetMinPowerAction", automation.Action) +SetMaxPowerAction = output_ns.class_("SetMaxPowerAction", automation.Action) async def setup_output_platform_(obj, config): @@ -104,6 +106,42 @@ async def output_set_level_to_code(config, action_id, template_arg, args): return var +@automation.register_action( + "output.set_min_power", + SetMinPowerAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(FloatOutput), + cv.Required(CONF_MIN_POWER): cv.templatable(cv.percentage), + } + ), +) +async def output_set_min_power_to_code(config, action_id, template_arg, args): + paren = await cg.get_variable(config[CONF_ID]) + var = cg.new_Pvariable(action_id, template_arg, paren) + template_ = await cg.templatable(config[CONF_MIN_POWER], args, float) + cg.add(var.set_min_power(template_)) + return var + + +@automation.register_action( + "output.set_max_power", + SetMaxPowerAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(FloatOutput), + cv.Required(CONF_MAX_POWER): cv.templatable(cv.percentage), + } + ), +) +async def output_set_max_power_to_code(config, action_id, template_arg, args): + paren = await cg.get_variable(config[CONF_ID]) + var = cg.new_Pvariable(action_id, template_arg, paren) + template_ = await cg.templatable(config[CONF_MAX_POWER], args, float) + cg.add(var.set_max_power(template_)) + return var + + async def to_code(config): cg.add_define("USE_OUTPUT") cg.add_global(output_ns.using) diff --git a/esphome/components/output/automation.h b/esphome/components/output/automation.h index 51c2849702..de84bb91ca 100644 --- a/esphome/components/output/automation.h +++ b/esphome/components/output/automation.h @@ -40,5 +40,29 @@ template class SetLevelAction : public Action { FloatOutput *output_; }; +template class SetMinPowerAction : public Action { + public: + SetMinPowerAction(FloatOutput *output) : output_(output) {} + + TEMPLATABLE_VALUE(float, min_power) + + void play(Ts... x) override { this->output_->set_min_power(this->min_power_.value(x...)); } + + protected: + FloatOutput *output_; +}; + +template class SetMaxPowerAction : public Action { + public: + SetMaxPowerAction(FloatOutput *output) : output_(output) {} + + TEMPLATABLE_VALUE(float, max_power) + + void play(Ts... x) override { this->output_->set_max_power(this->max_power_.value(x...)); } + + protected: + FloatOutput *output_; +}; + } // namespace output } // namespace esphome diff --git a/tests/components/output/common.yaml b/tests/components/output/common.yaml index 5f31ae50a8..81d802e9bf 100644 --- a/tests/components/output/common.yaml +++ b/tests/components/output/common.yaml @@ -6,6 +6,12 @@ esphome: - output.set_level: id: light_output_1 level: 50% + - output.set_min_power: + id: light_output_1 + min_power: 20% + - output.set_max_power: + id: light_output_1 + max_power: 80% output: - platform: ${output_platform} From 3d5b602288bd922b898b53429079e8aae8217c0a Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 29 Jul 2025 01:52:34 -0400 Subject: [PATCH 25/28] [esp32] Bump platform to 54.03.21-1 and add support for tagged releases (#9926) Co-authored-by: J. Nick Koston --- .clang-tidy.hash | 2 +- esphome/components/esp32/__init__.py | 12 ++++++------ esphome/config_validation.py | 2 ++ platformio.ini | 4 ++-- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index 02b528b0d6..5dd779effb 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -b7056e39f1484500ca2d237068670b789fe9241786b48da0681d646b25af05d5 +f84518ea4140c194b21cc516aae05aaa0cf876ab866f89e22e91842df46333ed diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 78bafcb790..4ab85a55cd 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -313,7 +313,7 @@ def _format_framework_espidf_version( RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(3, 2, 1) # The platform-espressif32 version to use for arduino frameworks # - https://github.com/pioarduino/platform-espressif32/releases -ARDUINO_PLATFORM_VERSION = cv.Version(54, 3, 21) +ARDUINO_PLATFORM_VERSION = cv.Version(54, 3, 21, "1") # The default/recommended esp-idf framework version # - https://github.com/espressif/esp-idf/releases @@ -322,7 +322,7 @@ RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION = cv.Version(5, 4, 2) # The platformio/espressif32 version to use for esp-idf frameworks # - https://github.com/platformio/platform-espressif32/releases # - https://api.registry.platformio.org/v3/packages/platformio/platform/espressif32 -ESP_IDF_PLATFORM_VERSION = cv.Version(54, 3, 21) +ESP_IDF_PLATFORM_VERSION = cv.Version(54, 3, 21, "1") # List based on https://registry.platformio.org/tools/platformio/framework-espidf/versions SUPPORTED_PLATFORMIO_ESP_IDF_5X = [ @@ -468,10 +468,10 @@ def _parse_platform_version(value): try: ver = cv.Version.parse(cv.version_number(value)) if ver.major >= 50: # a pioarduino version - if "-" in value: - # maybe a release candidate?...definitely not our default, just use it as-is... - return f"https://github.com/pioarduino/platform-espressif32/releases/download/{value}/platform-espressif32.zip" - return f"https://github.com/pioarduino/platform-espressif32/releases/download/{ver.major}.{ver.minor:02d}.{ver.patch:02d}/platform-espressif32.zip" + release = f"{ver.major}.{ver.minor:02d}.{ver.patch:02d}" + if ver.extra: + release += f"-{ver.extra}" + return f"https://github.com/pioarduino/platform-espressif32/releases/download/{release}/platform-espressif32.zip" # if platform version is a valid version constraint, prefix the default package cv.platformio_version_constraint(value) return f"platformio/espressif32@{value}" diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 1a4976e235..a79f8cd17c 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -291,6 +291,8 @@ class Version: extra: str = "" def __str__(self): + if self.extra: + return f"{self.major}.{self.minor}.{self.patch}-{self.extra}" return f"{self.major}.{self.minor}.{self.patch}" @classmethod diff --git a/platformio.ini b/platformio.ini index 5956ae8117..ab0774b29f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -125,7 +125,7 @@ extra_scripts = post:esphome/components/esp8266/post_build.py.script ; This are common settings for the ESP32 (all variants) using Arduino. [common:esp32-arduino] extends = common:arduino -platform = https://github.com/pioarduino/platform-espressif32/releases/download/54.03.21/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/54.03.21-1/platform-espressif32.zip platform_packages = pioarduino/framework-arduinoespressif32@https://github.com/espressif/arduino-esp32/releases/download/3.2.1/esp32-3.2.1.zip @@ -161,7 +161,7 @@ extra_scripts = post:esphome/components/esp32/post_build.py.script ; This are common settings for the ESP32 (all variants) using IDF. [common:esp32-idf] extends = common:idf -platform = https://github.com/pioarduino/platform-espressif32/releases/download/54.03.21/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/54.03.21-1/platform-espressif32.zip platform_packages = pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v5.4.2/esp-idf-v5.4.2.zip From 5f7c2f771f156c29fe24da1f4033bf33e5904d0b Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 29 Jul 2025 16:20:37 +1000 Subject: [PATCH 26/28] [adc] Enable ADC on ESP32-P4 (#9954) --- esphome/components/adc/__init__.py | 20 +++++++++++++++++++- esphome/components/adc/adc_sensor.h | 4 ++-- esphome/components/adc/adc_sensor_esp32.cpp | 13 ++++++------- tests/components/adc/test.esp32-p4-idf.yaml | 6 ++++++ 4 files changed, 33 insertions(+), 10 deletions(-) create mode 100644 tests/components/adc/test.esp32-p4-idf.yaml diff --git a/esphome/components/adc/__init__.py b/esphome/components/adc/__init__.py index efe3b190af..1232d9677f 100644 --- a/esphome/components/adc/__init__.py +++ b/esphome/components/adc/__init__.py @@ -1,6 +1,6 @@ from esphome import pins import esphome.codegen as cg -from esphome.components.esp32 import get_esp32_variant +from esphome.components.esp32 import VARIANT_ESP32P4, get_esp32_variant from esphome.components.esp32.const import ( VARIANT_ESP32, VARIANT_ESP32C2, @@ -140,6 +140,16 @@ ESP32_VARIANT_ADC1_PIN_TO_CHANNEL = { 9: adc_channel_t.ADC_CHANNEL_8, 10: adc_channel_t.ADC_CHANNEL_9, }, + VARIANT_ESP32P4: { + 16: adc_channel_t.ADC_CHANNEL_0, + 17: adc_channel_t.ADC_CHANNEL_1, + 18: adc_channel_t.ADC_CHANNEL_2, + 19: adc_channel_t.ADC_CHANNEL_3, + 20: adc_channel_t.ADC_CHANNEL_4, + 21: adc_channel_t.ADC_CHANNEL_5, + 22: adc_channel_t.ADC_CHANNEL_6, + 23: adc_channel_t.ADC_CHANNEL_7, + }, } # pin to adc2 channel mapping @@ -198,6 +208,14 @@ ESP32_VARIANT_ADC2_PIN_TO_CHANNEL = { 19: adc_channel_t.ADC_CHANNEL_8, 20: adc_channel_t.ADC_CHANNEL_9, }, + VARIANT_ESP32P4: { + 49: adc_channel_t.ADC_CHANNEL_0, + 50: adc_channel_t.ADC_CHANNEL_1, + 51: adc_channel_t.ADC_CHANNEL_2, + 52: adc_channel_t.ADC_CHANNEL_3, + 53: adc_channel_t.ADC_CHANNEL_4, + 54: adc_channel_t.ADC_CHANNEL_5, + }, } diff --git a/esphome/components/adc/adc_sensor.h b/esphome/components/adc/adc_sensor.h index a60272a1f7..00a703191e 100644 --- a/esphome/components/adc/adc_sensor.h +++ b/esphome/components/adc/adc_sensor.h @@ -136,8 +136,8 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage adc_oneshot_unit_handle_t adc_handle_{nullptr}; adc_cali_handle_t calibration_handle_{nullptr}; adc_atten_t attenuation_{ADC_ATTEN_DB_0}; - adc_channel_t channel_; - adc_unit_t adc_unit_; + adc_channel_t channel_{}; + adc_unit_t adc_unit_{}; struct SetupFlags { uint8_t init_complete : 1; uint8_t config_complete : 1; diff --git a/esphome/components/adc/adc_sensor_esp32.cpp b/esphome/components/adc/adc_sensor_esp32.cpp index 4f0ffbdc38..9905475b1e 100644 --- a/esphome/components/adc/adc_sensor_esp32.cpp +++ b/esphome/components/adc/adc_sensor_esp32.cpp @@ -72,10 +72,9 @@ void ADCSensor::setup() { // Initialize ADC calibration if (this->calibration_handle_ == nullptr) { adc_cali_handle_t handle = nullptr; - esp_err_t err; #if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \ - USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2 + USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4 // RISC-V variants and S3 use curve fitting calibration adc_cali_curve_fitting_config_t cali_config = {}; // Zero initialize first #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0) @@ -187,7 +186,7 @@ float ADCSensor::sample_fixed_attenuation_() { ESP_LOGW(TAG, "ADC calibration conversion failed with error %d, disabling calibration", err); if (this->calibration_handle_ != nullptr) { #if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \ - USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2 + USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4 adc_cali_delete_scheme_curve_fitting(this->calibration_handle_); #else // Other ESP32 variants use line fitting calibration adc_cali_delete_scheme_line_fitting(this->calibration_handle_); @@ -220,7 +219,7 @@ float ADCSensor::sample_autorange_() { if (this->calibration_handle_ != nullptr) { // Delete old calibration handle #if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \ - USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2 + USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4 adc_cali_delete_scheme_curve_fitting(this->calibration_handle_); #else adc_cali_delete_scheme_line_fitting(this->calibration_handle_); @@ -232,7 +231,7 @@ float ADCSensor::sample_autorange_() { adc_cali_handle_t handle = nullptr; #if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \ - USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2 + USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4 adc_cali_curve_fitting_config_t cali_config = {}; #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0) cali_config.chan = this->channel_; @@ -261,7 +260,7 @@ float ADCSensor::sample_autorange_() { ESP_LOGW(TAG, "ADC read failed in autorange with error %d", err); if (handle != nullptr) { #if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \ - USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2 + USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4 adc_cali_delete_scheme_curve_fitting(handle); #else adc_cali_delete_scheme_line_fitting(handle); @@ -281,7 +280,7 @@ float ADCSensor::sample_autorange_() { } // Clean up calibration handle #if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \ - USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2 + USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4 adc_cali_delete_scheme_curve_fitting(handle); #else adc_cali_delete_scheme_line_fitting(handle); diff --git a/tests/components/adc/test.esp32-p4-idf.yaml b/tests/components/adc/test.esp32-p4-idf.yaml new file mode 100644 index 0000000000..97844cf398 --- /dev/null +++ b/tests/components/adc/test.esp32-p4-idf.yaml @@ -0,0 +1,6 @@ +packages: + base: !include common.yaml + +sensor: + - id: !extend my_sensor + pin: GPIO50 From ace375944c17a3c8bd33d1b051e100b986cfdbf4 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 29 Jul 2025 18:44:45 +1200 Subject: [PATCH 27/28] [esp32] Fix post build (#9951) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/esp32/post_build.py.script | 64 ++++++++++++------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/esphome/components/esp32/post_build.py.script b/esphome/components/esp32/post_build.py.script index 6e0e439011..586f12e00b 100644 --- a/esphome/components/esp32/post_build.py.script +++ b/esphome/components/esp32/post_build.py.script @@ -1,10 +1,11 @@ -Import("env") +Import("env") # noqa: F821 + +import itertools # noqa: E402 +import json # noqa: E402 +import os # noqa: E402 +import pathlib # noqa: E402 +import shutil # noqa: E402 -import os -import json -import shutil -import pathlib -import itertools def merge_factory_bin(source, target, env): """ @@ -25,7 +26,9 @@ def merge_factory_bin(source, target, env): try: with flasher_args_path.open() as f: flash_data = json.load(f) - for addr, fname in sorted(flash_data["flash_files"].items(), key=lambda kv: int(kv[0], 16)): + for addr, fname in sorted( + flash_data["flash_files"].items(), key=lambda kv: int(kv[0], 16) + ): file_path = pathlib.Path(fname) if file_path.exists(): sections.append((addr, str(file_path))) @@ -40,20 +43,27 @@ def merge_factory_bin(source, target, env): if flash_images: print("Using FLASH_EXTRA_IMAGES from PlatformIO environment") # flatten any nested lists - flat = list(itertools.chain.from_iterable( - x if isinstance(x, (list, tuple)) else [x] for x in flash_images - )) + flat = list( + itertools.chain.from_iterable( + x if isinstance(x, (list, tuple)) else [x] for x in flash_images + ) + ) entries = [env.subst(x) for x in flat] for i in range(0, len(entries) - 1, 2): addr, fname = entries[i], entries[i + 1] if isinstance(fname, (list, tuple)): - print(f"Warning: Skipping malformed FLASH_EXTRA_IMAGES entry: {fname}") + print( + f"Warning: Skipping malformed FLASH_EXTRA_IMAGES entry: {fname}" + ) continue file_path = pathlib.Path(str(fname)) if file_path.exists(): - sections.append((addr, str(file_path))) + sections.append((addr, file_path)) else: print(f"Info: {file_path.name} not found — skipping") + if sections: + # Append main firmware to sections + sections.append(("0x10000", firmware_path)) # 3. Final fallback: guess standard image locations if not sections: @@ -62,11 +72,11 @@ def merge_factory_bin(source, target, env): ("0x0", build_dir / "bootloader" / "bootloader.bin"), ("0x8000", build_dir / "partition_table" / "partition-table.bin"), ("0xe000", build_dir / "ota_data_initial.bin"), - ("0x10000", firmware_path) + ("0x10000", firmware_path), ] for addr, file_path in guesses: if file_path.exists(): - sections.append((addr, str(file_path))) + sections.append((addr, file_path)) else: print(f"Info: {file_path.name} not found — skipping") @@ -76,21 +86,25 @@ def merge_factory_bin(source, target, env): return output_path = firmware_path.with_suffix(".factory.bin") + python_exe = f'"{env.subst("$PYTHONEXE")}"' cmd = [ - "--chip", chip, + python_exe, + "-m", + "esptool", + "--chip", + chip, "merge_bin", - "--flash_size", flash_size, - "--output", str(output_path) + "--flash_size", + flash_size, + "--output", + str(output_path), ] for addr, file_path in sections: - cmd += [addr, file_path] + cmd += [addr, str(file_path)] print(f"Merging binaries into {output_path}") result = env.Execute( - env.VerboseAction( - f"{env.subst('$PYTHONEXE')} -m esptool " + " ".join(cmd), - "Merging binaries with esptool" - ) + env.VerboseAction(" ".join(cmd), "Merging binaries with esptool") ) if result == 0: @@ -98,6 +112,7 @@ def merge_factory_bin(source, target, env): else: print(f"Error: esptool merge_bin failed with code {result}") + def esp32_copy_ota_bin(source, target, env): """ Copy the main firmware to a .ota.bin file for compatibility with ESPHome OTA tools. @@ -107,6 +122,7 @@ def esp32_copy_ota_bin(source, target, env): shutil.copyfile(firmware_name, new_file_name) print(f"Copied firmware to {new_file_name}") + # Run merge first, then ota copy second -env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", merge_factory_bin) -env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", esp32_copy_ota_bin) +env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", merge_factory_bin) # noqa: F821 +env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", esp32_copy_ota_bin) # noqa: F821 From e0e0a1a420a413a4bc9b789a7c3769cebf0c688d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 28 Jul 2025 22:08:29 -1000 Subject: [PATCH 28/28] [esp32_touch] Work around ESP-IDF v5.4 regression in touch_pad_read_filtered() --- .../components/esp32_touch/esp32_touch_v1.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/esphome/components/esp32_touch/esp32_touch_v1.cpp b/esphome/components/esp32_touch/esp32_touch_v1.cpp index 629dc8e793..d41f1615c8 100644 --- a/esphome/components/esp32_touch/esp32_touch_v1.cpp +++ b/esphome/components/esp32_touch/esp32_touch_v1.cpp @@ -201,15 +201,13 @@ void IRAM_ATTR ESP32TouchComponent::touch_isr_handler(void *arg) { touch_pad_t pad = child->get_touch_pad(); // Read current value using ISR-safe API - uint32_t value; - if (component->iir_filter_enabled_()) { - uint16_t temp_value = 0; - touch_pad_read_filtered(pad, &temp_value); - value = temp_value; - } else { - // Use low-level HAL function when filter is not enabled - value = touch_ll_read_raw_data(pad); - } + // IMPORTANT: ESP-IDF v5.4 regression - touch_pad_read_filtered() is no longer ISR-safe + // In v5.3 and earlier it was ISR-safe, but v5.4 added mutex protection that causes: + // "assert failed: xQueueSemaphoreTake queue.c:1718" + // We must use raw values even when filter is enabled as a workaround. + // Users should adjust thresholds to compensate for the lack of IIR filtering. + // See: https://github.com/espressif/esp-idf/issues/17045 + uint32_t value = touch_ll_read_raw_data(pad); // Skip pads that aren’t in the trigger mask if (((mask >> pad) & 1) == 0) {