diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index e4e8333cc71..dc665da27c2 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -331,12 +331,8 @@ uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint8_t mess std::vector &shared_buf = conn->parent_->get_shared_buffer_ref(); if (conn->flags_.batch_first_message) { - // First message - clear flag + // First message - buffer already prepared by caller, just clear flag conn->flags_.batch_first_message = false; - // If buffer not prepped by caller (batch pre-reserves with size == header_padding), prep now - if (shared_buf.size() != header_padding) { - conn->prepare_first_message_buffer(shared_buf, header_padding, total_calculated_size); - } } else { // Batch message second or later // Add padding for previous message footer + this message header @@ -1863,6 +1859,7 @@ void APIConnection::process_batch_() { // Fast path for single message - allocate exact size needed if (num_items == 1) { const auto &item = this->deferred_batch_[0]; + this->prepare_first_message_buffer(shared_buf, item.estimated_size); // Let dispatch_message_ calculate size and encode if it fits uint16_t payload_size = this->dispatch_message_(item, std::numeric_limits::max(), true); @@ -1902,9 +1899,10 @@ void APIConnection::process_batch_() { total_estimated_size += item.estimated_size; } - // Calculate total overhead for all messages - // Reserve based on estimated size (much more accurate than 24-byte worst-case) + // Prepare buffer with total estimated size for all messages (already cleared above) shared_buf.reserve(total_estimated_size); + shared_buf.resize(header_padding); + this->flags_.batch_first_message = true; size_t items_processed = 0; uint16_t remaining_size = std::numeric_limits::max(); diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 2c9202b561b..5f7975d5e74 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -653,9 +653,11 @@ class APIConnection final : public APIServerConnection { bool send_message_smart_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size, uint8_t aux_data_index = DeferredBatch::AUX_DATA_UNUSED) { if (this->should_send_immediately_(message_type) && this->helper_->can_write_without_blocking()) { + auto &shared_buf = this->parent_->get_shared_buffer_ref(); + this->prepare_first_message_buffer(shared_buf, estimated_size); DeferredBatch::BatchItem item{entity, message_type, estimated_size, aux_data_index}; if (this->dispatch_message_(item, MAX_BATCH_PACKET_SIZE, true) && - this->send_buffer(ProtoWriteBuffer{&this->parent_->get_shared_buffer_ref()}, message_type)) { + this->send_buffer(ProtoWriteBuffer{&shared_buf}, message_type)) { #ifdef HAS_PROTO_MESSAGE_DUMP this->log_batch_item_(item); #endif