mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	Merge branch 'api_polish' into integration
This commit is contained in:
		| @@ -112,8 +112,7 @@ void APIConnection::start() { | ||||
|   APIError err = this->helper_->init(); | ||||
|   if (err != APIError::OK) { | ||||
|     on_fatal_error(); | ||||
|     ESP_LOGW(TAG, "%s: Helper init failed %s errno=%d", this->get_client_combined_info().c_str(), api_error_to_str(err), | ||||
|              errno); | ||||
|     this->log_warning_("Helper init failed", err); | ||||
|     return; | ||||
|   } | ||||
|   this->client_info_.peername = helper_->getpeername(); | ||||
| @@ -144,8 +143,7 @@ void APIConnection::loop() { | ||||
|   APIError err = this->helper_->loop(); | ||||
|   if (err != APIError::OK) { | ||||
|     on_fatal_error(); | ||||
|     ESP_LOGW(TAG, "%s: Socket operation failed %s errno=%d", this->get_client_combined_info().c_str(), | ||||
|              api_error_to_str(err), errno); | ||||
|     this->log_socket_operation_failed_(err); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
| @@ -161,8 +159,7 @@ void APIConnection::loop() { | ||||
|         break; | ||||
|       } else if (err != APIError::OK) { | ||||
|         on_fatal_error(); | ||||
|         ESP_LOGW(TAG, "%s: Reading failed %s errno=%d", this->get_client_combined_info().c_str(), api_error_to_str(err), | ||||
|                  errno); | ||||
|         this->log_warning_("Reading failed", err); | ||||
|         return; | ||||
|       } else { | ||||
|         this->last_traffic_ = now; | ||||
| @@ -1540,8 +1537,7 @@ bool APIConnection::try_to_clear_buffer(bool log_out_of_space) { | ||||
|   APIError err = this->helper_->loop(); | ||||
|   if (err != APIError::OK) { | ||||
|     on_fatal_error(); | ||||
|     ESP_LOGW(TAG, "%s: Socket operation failed %s errno=%d", this->get_client_combined_info().c_str(), | ||||
|              api_error_to_str(err), errno); | ||||
|     this->log_socket_operation_failed_(err); | ||||
|     return false; | ||||
|   } | ||||
|   if (this->helper_->can_write_without_blocking()) | ||||
| @@ -1561,8 +1557,7 @@ bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) { | ||||
|     return false; | ||||
|   if (err != APIError::OK) { | ||||
|     on_fatal_error(); | ||||
|     ESP_LOGW(TAG, "%s: Packet write failed %s errno=%d", this->get_client_combined_info().c_str(), | ||||
|              api_error_to_str(err), errno); | ||||
|     this->log_warning_("Packet write failed", err); | ||||
|     return false; | ||||
|   } | ||||
|   // Do not set last_traffic_ on send | ||||
| @@ -1647,6 +1642,8 @@ void APIConnection::process_batch_() { | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   // Get shared buffer reference once to avoid multiple calls | ||||
|   auto &shared_buf = this->parent_->get_shared_buffer_ref(); | ||||
|   size_t num_items = this->deferred_batch_.size(); | ||||
|  | ||||
|   // Fast path for single message - allocate exact size needed | ||||
| @@ -1657,8 +1654,7 @@ void APIConnection::process_batch_() { | ||||
|     uint16_t payload_size = | ||||
|         item.creator(item.entity, this, std::numeric_limits<uint16_t>::max(), true, item.message_type); | ||||
|  | ||||
|     if (payload_size > 0 && | ||||
|         this->send_buffer(ProtoWriteBuffer{&this->parent_->get_shared_buffer_ref()}, item.message_type)) { | ||||
|     if (payload_size > 0 && this->send_buffer(ProtoWriteBuffer{&shared_buf}, item.message_type)) { | ||||
| #ifdef HAS_PROTO_MESSAGE_DUMP | ||||
|       // Log messages after send attempt for VV debugging | ||||
|       // It's safe to use the buffer for logging at this point regardless of send result | ||||
| @@ -1685,20 +1681,17 @@ void APIConnection::process_batch_() { | ||||
|   const uint8_t footer_size = this->helper_->frame_footer_size(); | ||||
|  | ||||
|   // Initialize buffer and tracking variables | ||||
|   this->parent_->get_shared_buffer_ref().clear(); | ||||
|   shared_buf.clear(); | ||||
|  | ||||
|   // Pre-calculate exact buffer size needed based on message types | ||||
|   uint32_t total_estimated_size = 0; | ||||
|   for (size_t i = 0; i < this->deferred_batch_.size(); i++) { | ||||
|     const auto &item = this->deferred_batch_[i]; | ||||
|   uint32_t total_estimated_size = num_items * (header_padding + footer_size); | ||||
|   for (const auto &item : this->deferred_batch_.items) { | ||||
|     total_estimated_size += item.estimated_size; | ||||
|   } | ||||
|  | ||||
|   // Calculate total overhead for all messages | ||||
|   uint32_t total_overhead = (header_padding + footer_size) * num_items; | ||||
|  | ||||
|   // Reserve based on estimated size (much more accurate than 24-byte worst-case) | ||||
|   this->parent_->get_shared_buffer_ref().reserve(total_estimated_size + total_overhead); | ||||
|   shared_buf.reserve(total_estimated_size); | ||||
|   this->flags_.batch_first_message = true; | ||||
|  | ||||
|   size_t items_processed = 0; | ||||
| @@ -1740,7 +1733,7 @@ void APIConnection::process_batch_() { | ||||
|     remaining_size -= payload_size; | ||||
|     // Calculate where the next message's header padding will start | ||||
|     // Current buffer size + footer space (that prepare_message_buffer will add for this message) | ||||
|     current_offset = this->parent_->get_shared_buffer_ref().size() + footer_size; | ||||
|     current_offset = shared_buf.size() + footer_size; | ||||
|   } | ||||
|  | ||||
|   if (items_processed == 0) { | ||||
| @@ -1750,17 +1743,15 @@ void APIConnection::process_batch_() { | ||||
|  | ||||
|   // Add footer space for the last message (for Noise protocol MAC) | ||||
|   if (footer_size > 0) { | ||||
|     auto &shared_buf = this->parent_->get_shared_buffer_ref(); | ||||
|     shared_buf.resize(shared_buf.size() + footer_size); | ||||
|   } | ||||
|  | ||||
|   // Send all collected packets | ||||
|   APIError err = this->helper_->write_protobuf_packets(ProtoWriteBuffer{&this->parent_->get_shared_buffer_ref()}, | ||||
|   APIError err = this->helper_->write_protobuf_packets(ProtoWriteBuffer{&shared_buf}, | ||||
|                                                        std::span<const PacketInfo>(packet_info, packet_count)); | ||||
|   if (err != APIError::OK && err != APIError::WOULD_BLOCK) { | ||||
|     on_fatal_error(); | ||||
|     ESP_LOGW(TAG, "%s: Batch write failed %s errno=%d", this->get_client_combined_info().c_str(), api_error_to_str(err), | ||||
|              errno); | ||||
|     this->log_warning_("Batch write failed", err); | ||||
|   } | ||||
|  | ||||
| #ifdef HAS_PROTO_MESSAGE_DUMP | ||||
| @@ -1838,5 +1829,11 @@ void APIConnection::process_state_subscriptions_() { | ||||
| } | ||||
| #endif  // USE_API_HOMEASSISTANT_STATES | ||||
|  | ||||
| void APIConnection::log_warning_(const char *message, APIError err) { | ||||
|   ESP_LOGW(TAG, "%s: %s %s errno=%d", this->get_client_combined_info().c_str(), message, api_error_to_str(err), errno); | ||||
| } | ||||
|  | ||||
| void APIConnection::log_socket_operation_failed_(APIError err) { this->log_warning_("Socket operation failed", err); } | ||||
|  | ||||
| }  // namespace esphome::api | ||||
| #endif | ||||
|   | ||||
| @@ -736,6 +736,11 @@ class APIConnection : public APIServerConnection { | ||||
|     this->deferred_batch_.add_item_front(entity, MessageCreator(function_ptr), message_type, estimated_size); | ||||
|     return this->schedule_batch_(); | ||||
|   } | ||||
|  | ||||
|   // Helper function to log API errors with errno | ||||
|   void log_warning_(const char *message, APIError err); | ||||
|   // Specific helper for duplicated error message | ||||
|   void log_socket_operation_failed_(APIError err); | ||||
| }; | ||||
|  | ||||
| }  // namespace esphome::api | ||||
|   | ||||
		Reference in New Issue
	
	Block a user