mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-27 13:13:50 +00:00 
			
		
		
		
	Merge remote-tracking branch 'origin/integration' into integration
This commit is contained in:
		| @@ -193,14 +193,15 @@ void APIConnection::loop() { | ||||
|       // If we can't send the ping request directly (tx_buffer full), | ||||
|       // schedule it at the front of the batch so it will be sent with priority | ||||
|       ESP_LOGW(TAG, "Buffer full, ping queued"); | ||||
|       this->schedule_message_front_(nullptr, &APIConnection::try_send_ping_request, PingRequest::MESSAGE_TYPE); | ||||
|       this->schedule_message_front_(nullptr, &APIConnection::try_send_ping_request, PingRequest::MESSAGE_TYPE, | ||||
|                                     PingRequest::ESTIMATED_SIZE); | ||||
|       this->flags_.sent_ping = true;  // Mark as sent to avoid scheduling multiple pings | ||||
|     } | ||||
|   } | ||||
|  | ||||
| #ifdef USE_CAMERA | ||||
|   if (this->image_reader_ && this->image_reader_->available() && this->helper_->can_write_without_blocking()) { | ||||
|     uint32_t to_send = std::min((size_t) MAX_PACKET_SIZE, this->image_reader_->available()); | ||||
|     uint32_t to_send = std::min((size_t) MAX_BATCH_PACKET_SIZE, this->image_reader_->available()); | ||||
|     bool done = this->image_reader_->available() == to_send; | ||||
|     uint32_t msg_size = 0; | ||||
|     ProtoSize::add_fixed_field<4>(msg_size, 1, true); | ||||
| @@ -265,7 +266,7 @@ void APIConnection::on_disconnect_response(const DisconnectResponse &value) { | ||||
|  | ||||
| // Encodes a message to the buffer and returns the total number of bytes used, | ||||
| // including header and footer overhead. Returns 0 if the message doesn't fit. | ||||
| uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint16_t message_type, APIConnection *conn, | ||||
| uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint8_t message_type, APIConnection *conn, | ||||
|                                                  uint32_t remaining_size, bool is_single) { | ||||
| #ifdef HAS_PROTO_MESSAGE_DUMP | ||||
|   // If in log-only mode, just log and return | ||||
| @@ -316,7 +317,7 @@ uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint16_t mes | ||||
| #ifdef USE_BINARY_SENSOR | ||||
| bool APIConnection::send_binary_sensor_state(binary_sensor::BinarySensor *binary_sensor) { | ||||
|   return this->send_message_smart_(binary_sensor, &APIConnection::try_send_binary_sensor_state, | ||||
|                                    BinarySensorStateResponse::MESSAGE_TYPE); | ||||
|                                    BinarySensorStateResponse::MESSAGE_TYPE, BinarySensorStateResponse::ESTIMATED_SIZE); | ||||
| } | ||||
|  | ||||
| uint16_t APIConnection::try_send_binary_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, | ||||
| @@ -343,7 +344,8 @@ uint16_t APIConnection::try_send_binary_sensor_info(EntityBase *entity, APIConne | ||||
|  | ||||
| #ifdef USE_COVER | ||||
| bool APIConnection::send_cover_state(cover::Cover *cover) { | ||||
|   return this->send_message_smart_(cover, &APIConnection::try_send_cover_state, CoverStateResponse::MESSAGE_TYPE); | ||||
|   return this->send_message_smart_(cover, &APIConnection::try_send_cover_state, CoverStateResponse::MESSAGE_TYPE, | ||||
|                                    CoverStateResponse::ESTIMATED_SIZE); | ||||
| } | ||||
| uint16_t APIConnection::try_send_cover_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, | ||||
|                                              bool is_single) { | ||||
| @@ -400,7 +402,8 @@ void APIConnection::cover_command(const CoverCommandRequest &msg) { | ||||
|  | ||||
| #ifdef USE_FAN | ||||
| bool APIConnection::send_fan_state(fan::Fan *fan) { | ||||
|   return this->send_message_smart_(fan, &APIConnection::try_send_fan_state, FanStateResponse::MESSAGE_TYPE); | ||||
|   return this->send_message_smart_(fan, &APIConnection::try_send_fan_state, FanStateResponse::MESSAGE_TYPE, | ||||
|                                    FanStateResponse::ESTIMATED_SIZE); | ||||
| } | ||||
| uint16_t APIConnection::try_send_fan_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, | ||||
|                                            bool is_single) { | ||||
| @@ -455,7 +458,8 @@ void APIConnection::fan_command(const FanCommandRequest &msg) { | ||||
|  | ||||
| #ifdef USE_LIGHT | ||||
| bool APIConnection::send_light_state(light::LightState *light) { | ||||
|   return this->send_message_smart_(light, &APIConnection::try_send_light_state, LightStateResponse::MESSAGE_TYPE); | ||||
|   return this->send_message_smart_(light, &APIConnection::try_send_light_state, LightStateResponse::MESSAGE_TYPE, | ||||
|                                    LightStateResponse::ESTIMATED_SIZE); | ||||
| } | ||||
| uint16_t APIConnection::try_send_light_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, | ||||
|                                              bool is_single) { | ||||
| @@ -543,7 +547,8 @@ void APIConnection::light_command(const LightCommandRequest &msg) { | ||||
|  | ||||
| #ifdef USE_SENSOR | ||||
| bool APIConnection::send_sensor_state(sensor::Sensor *sensor) { | ||||
|   return this->send_message_smart_(sensor, &APIConnection::try_send_sensor_state, SensorStateResponse::MESSAGE_TYPE); | ||||
|   return this->send_message_smart_(sensor, &APIConnection::try_send_sensor_state, SensorStateResponse::MESSAGE_TYPE, | ||||
|                                    SensorStateResponse::ESTIMATED_SIZE); | ||||
| } | ||||
|  | ||||
| uint16_t APIConnection::try_send_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, | ||||
| @@ -575,7 +580,8 @@ uint16_t APIConnection::try_send_sensor_info(EntityBase *entity, APIConnection * | ||||
|  | ||||
| #ifdef USE_SWITCH | ||||
| bool APIConnection::send_switch_state(switch_::Switch *a_switch) { | ||||
|   return this->send_message_smart_(a_switch, &APIConnection::try_send_switch_state, SwitchStateResponse::MESSAGE_TYPE); | ||||
|   return this->send_message_smart_(a_switch, &APIConnection::try_send_switch_state, SwitchStateResponse::MESSAGE_TYPE, | ||||
|                                    SwitchStateResponse::ESTIMATED_SIZE); | ||||
| } | ||||
|  | ||||
| uint16_t APIConnection::try_send_switch_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, | ||||
| @@ -611,7 +617,7 @@ void APIConnection::switch_command(const SwitchCommandRequest &msg) { | ||||
| #ifdef USE_TEXT_SENSOR | ||||
| bool APIConnection::send_text_sensor_state(text_sensor::TextSensor *text_sensor) { | ||||
|   return this->send_message_smart_(text_sensor, &APIConnection::try_send_text_sensor_state, | ||||
|                                    TextSensorStateResponse::MESSAGE_TYPE); | ||||
|                                    TextSensorStateResponse::MESSAGE_TYPE, TextSensorStateResponse::ESTIMATED_SIZE); | ||||
| } | ||||
|  | ||||
| uint16_t APIConnection::try_send_text_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, | ||||
| @@ -638,7 +644,8 @@ uint16_t APIConnection::try_send_text_sensor_info(EntityBase *entity, APIConnect | ||||
|  | ||||
| #ifdef USE_CLIMATE | ||||
| bool APIConnection::send_climate_state(climate::Climate *climate) { | ||||
|   return this->send_message_smart_(climate, &APIConnection::try_send_climate_state, ClimateStateResponse::MESSAGE_TYPE); | ||||
|   return this->send_message_smart_(climate, &APIConnection::try_send_climate_state, ClimateStateResponse::MESSAGE_TYPE, | ||||
|                                    ClimateStateResponse::ESTIMATED_SIZE); | ||||
| } | ||||
| uint16_t APIConnection::try_send_climate_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, | ||||
|                                                bool is_single) { | ||||
| @@ -734,7 +741,8 @@ void APIConnection::climate_command(const ClimateCommandRequest &msg) { | ||||
|  | ||||
| #ifdef USE_NUMBER | ||||
| bool APIConnection::send_number_state(number::Number *number) { | ||||
|   return this->send_message_smart_(number, &APIConnection::try_send_number_state, NumberStateResponse::MESSAGE_TYPE); | ||||
|   return this->send_message_smart_(number, &APIConnection::try_send_number_state, NumberStateResponse::MESSAGE_TYPE, | ||||
|                                    NumberStateResponse::ESTIMATED_SIZE); | ||||
| } | ||||
|  | ||||
| uint16_t APIConnection::try_send_number_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, | ||||
| @@ -770,7 +778,8 @@ void APIConnection::number_command(const NumberCommandRequest &msg) { | ||||
|  | ||||
| #ifdef USE_DATETIME_DATE | ||||
| bool APIConnection::send_date_state(datetime::DateEntity *date) { | ||||
|   return this->send_message_smart_(date, &APIConnection::try_send_date_state, DateStateResponse::MESSAGE_TYPE); | ||||
|   return this->send_message_smart_(date, &APIConnection::try_send_date_state, DateStateResponse::MESSAGE_TYPE, | ||||
|                                    DateStateResponse::ESTIMATED_SIZE); | ||||
| } | ||||
| uint16_t APIConnection::try_send_date_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, | ||||
|                                             bool is_single) { | ||||
| @@ -800,7 +809,8 @@ void APIConnection::date_command(const DateCommandRequest &msg) { | ||||
|  | ||||
| #ifdef USE_DATETIME_TIME | ||||
| bool APIConnection::send_time_state(datetime::TimeEntity *time) { | ||||
|   return this->send_message_smart_(time, &APIConnection::try_send_time_state, TimeStateResponse::MESSAGE_TYPE); | ||||
|   return this->send_message_smart_(time, &APIConnection::try_send_time_state, TimeStateResponse::MESSAGE_TYPE, | ||||
|                                    TimeStateResponse::ESTIMATED_SIZE); | ||||
| } | ||||
| uint16_t APIConnection::try_send_time_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, | ||||
|                                             bool is_single) { | ||||
| @@ -831,7 +841,7 @@ void APIConnection::time_command(const TimeCommandRequest &msg) { | ||||
| #ifdef USE_DATETIME_DATETIME | ||||
| bool APIConnection::send_datetime_state(datetime::DateTimeEntity *datetime) { | ||||
|   return this->send_message_smart_(datetime, &APIConnection::try_send_datetime_state, | ||||
|                                    DateTimeStateResponse::MESSAGE_TYPE); | ||||
|                                    DateTimeStateResponse::MESSAGE_TYPE, DateTimeStateResponse::ESTIMATED_SIZE); | ||||
| } | ||||
| uint16_t APIConnection::try_send_datetime_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, | ||||
|                                                 bool is_single) { | ||||
| @@ -862,7 +872,8 @@ void APIConnection::datetime_command(const DateTimeCommandRequest &msg) { | ||||
|  | ||||
| #ifdef USE_TEXT | ||||
| bool APIConnection::send_text_state(text::Text *text) { | ||||
|   return this->send_message_smart_(text, &APIConnection::try_send_text_state, TextStateResponse::MESSAGE_TYPE); | ||||
|   return this->send_message_smart_(text, &APIConnection::try_send_text_state, TextStateResponse::MESSAGE_TYPE, | ||||
|                                    TextStateResponse::ESTIMATED_SIZE); | ||||
| } | ||||
|  | ||||
| uint16_t APIConnection::try_send_text_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, | ||||
| @@ -896,7 +907,8 @@ void APIConnection::text_command(const TextCommandRequest &msg) { | ||||
|  | ||||
| #ifdef USE_SELECT | ||||
| bool APIConnection::send_select_state(select::Select *select) { | ||||
|   return this->send_message_smart_(select, &APIConnection::try_send_select_state, SelectStateResponse::MESSAGE_TYPE); | ||||
|   return this->send_message_smart_(select, &APIConnection::try_send_select_state, SelectStateResponse::MESSAGE_TYPE, | ||||
|                                    SelectStateResponse::ESTIMATED_SIZE); | ||||
| } | ||||
|  | ||||
| uint16_t APIConnection::try_send_select_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, | ||||
| @@ -944,7 +956,8 @@ void esphome::api::APIConnection::button_command(const ButtonCommandRequest &msg | ||||
|  | ||||
| #ifdef USE_LOCK | ||||
| bool APIConnection::send_lock_state(lock::Lock *a_lock) { | ||||
|   return this->send_message_smart_(a_lock, &APIConnection::try_send_lock_state, LockStateResponse::MESSAGE_TYPE); | ||||
|   return this->send_message_smart_(a_lock, &APIConnection::try_send_lock_state, LockStateResponse::MESSAGE_TYPE, | ||||
|                                    LockStateResponse::ESTIMATED_SIZE); | ||||
| } | ||||
|  | ||||
| uint16_t APIConnection::try_send_lock_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, | ||||
| @@ -986,7 +999,8 @@ void APIConnection::lock_command(const LockCommandRequest &msg) { | ||||
|  | ||||
| #ifdef USE_VALVE | ||||
| bool APIConnection::send_valve_state(valve::Valve *valve) { | ||||
|   return this->send_message_smart_(valve, &APIConnection::try_send_valve_state, ValveStateResponse::MESSAGE_TYPE); | ||||
|   return this->send_message_smart_(valve, &APIConnection::try_send_valve_state, ValveStateResponse::MESSAGE_TYPE, | ||||
|                                    ValveStateResponse::ESTIMATED_SIZE); | ||||
| } | ||||
| uint16_t APIConnection::try_send_valve_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, | ||||
|                                              bool is_single) { | ||||
| @@ -1023,7 +1037,7 @@ void APIConnection::valve_command(const ValveCommandRequest &msg) { | ||||
| #ifdef USE_MEDIA_PLAYER | ||||
| bool APIConnection::send_media_player_state(media_player::MediaPlayer *media_player) { | ||||
|   return this->send_message_smart_(media_player, &APIConnection::try_send_media_player_state, | ||||
|                                    MediaPlayerStateResponse::MESSAGE_TYPE); | ||||
|                                    MediaPlayerStateResponse::MESSAGE_TYPE, MediaPlayerStateResponse::ESTIMATED_SIZE); | ||||
| } | ||||
| uint16_t APIConnection::try_send_media_player_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, | ||||
|                                                     bool is_single) { | ||||
| @@ -1262,7 +1276,8 @@ void APIConnection::voice_assistant_set_configuration(const VoiceAssistantSetCon | ||||
| #ifdef USE_ALARM_CONTROL_PANEL | ||||
| bool APIConnection::send_alarm_control_panel_state(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) { | ||||
|   return this->send_message_smart_(a_alarm_control_panel, &APIConnection::try_send_alarm_control_panel_state, | ||||
|                                    AlarmControlPanelStateResponse::MESSAGE_TYPE); | ||||
|                                    AlarmControlPanelStateResponse::MESSAGE_TYPE, | ||||
|                                    AlarmControlPanelStateResponse::ESTIMATED_SIZE); | ||||
| } | ||||
| uint16_t APIConnection::try_send_alarm_control_panel_state(EntityBase *entity, APIConnection *conn, | ||||
|                                                            uint32_t remaining_size, bool is_single) { | ||||
| @@ -1316,7 +1331,8 @@ void APIConnection::alarm_control_panel_command(const AlarmControlPanelCommandRe | ||||
|  | ||||
| #ifdef USE_EVENT | ||||
| void APIConnection::send_event(event::Event *event, const std::string &event_type) { | ||||
|   this->schedule_message_(event, MessageCreator(event_type), EventResponse::MESSAGE_TYPE); | ||||
|   this->schedule_message_(event, MessageCreator(event_type), EventResponse::MESSAGE_TYPE, | ||||
|                           EventResponse::ESTIMATED_SIZE); | ||||
| } | ||||
| uint16_t APIConnection::try_send_event_response(event::Event *event, const std::string &event_type, APIConnection *conn, | ||||
|                                                 uint32_t remaining_size, bool is_single) { | ||||
| @@ -1341,7 +1357,8 @@ uint16_t APIConnection::try_send_event_info(EntityBase *entity, APIConnection *c | ||||
|  | ||||
| #ifdef USE_UPDATE | ||||
| bool APIConnection::send_update_state(update::UpdateEntity *update) { | ||||
|   return this->send_message_smart_(update, &APIConnection::try_send_update_state, UpdateStateResponse::MESSAGE_TYPE); | ||||
|   return this->send_message_smart_(update, &APIConnection::try_send_update_state, UpdateStateResponse::MESSAGE_TYPE, | ||||
|                                    UpdateStateResponse::ESTIMATED_SIZE); | ||||
| } | ||||
| uint16_t APIConnection::try_send_update_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, | ||||
|                                               bool is_single) { | ||||
| @@ -1604,7 +1621,7 @@ bool APIConnection::try_to_clear_buffer(bool log_out_of_space) { | ||||
|   } | ||||
|   return false; | ||||
| } | ||||
| bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint16_t message_type) { | ||||
| bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) { | ||||
|   if (!this->try_to_clear_buffer(message_type != SubscribeLogsResponse::MESSAGE_TYPE)) {  // SubscribeLogsResponse | ||||
|     return false; | ||||
|   } | ||||
| @@ -1638,7 +1655,8 @@ void APIConnection::on_fatal_error() { | ||||
|   this->flags_.remove = true; | ||||
| } | ||||
|  | ||||
| void APIConnection::DeferredBatch::add_item(EntityBase *entity, MessageCreator creator, uint16_t message_type) { | ||||
| void APIConnection::DeferredBatch::add_item(EntityBase *entity, MessageCreator creator, uint8_t message_type, | ||||
|                                             uint8_t estimated_size) { | ||||
|   // Check if we already have a message of this type for this entity | ||||
|   // This provides deduplication per entity/message_type combination | ||||
|   // O(n) but optimized for RAM and not performance. | ||||
| @@ -1653,12 +1671,13 @@ void APIConnection::DeferredBatch::add_item(EntityBase *entity, MessageCreator c | ||||
|   } | ||||
|  | ||||
|   // No existing item found, add new one | ||||
|   items.emplace_back(entity, std::move(creator), message_type); | ||||
|   items.emplace_back(entity, std::move(creator), message_type, estimated_size); | ||||
| } | ||||
|  | ||||
| void APIConnection::DeferredBatch::add_item_front(EntityBase *entity, MessageCreator creator, uint16_t message_type) { | ||||
| void APIConnection::DeferredBatch::add_item_front(EntityBase *entity, MessageCreator creator, uint8_t message_type, | ||||
|                                                   uint8_t estimated_size) { | ||||
|   // Insert at front for high priority messages (no deduplication check) | ||||
|   items.insert(items.begin(), BatchItem(entity, std::move(creator), message_type)); | ||||
|   items.insert(items.begin(), BatchItem(entity, std::move(creator), message_type, estimated_size)); | ||||
| } | ||||
|  | ||||
| bool APIConnection::schedule_batch_() { | ||||
| @@ -1730,7 +1749,7 @@ void APIConnection::process_batch_() { | ||||
|   uint32_t total_estimated_size = 0; | ||||
|   for (size_t i = 0; i < this->deferred_batch_.size(); i++) { | ||||
|     const auto &item = this->deferred_batch_[i]; | ||||
|     total_estimated_size += get_estimated_message_size(item.message_type); | ||||
|     total_estimated_size += item.estimated_size; | ||||
|   } | ||||
|  | ||||
|   // Calculate total overhead for all messages | ||||
| @@ -1768,9 +1787,9 @@ void APIConnection::process_batch_() { | ||||
|  | ||||
|     // Update tracking variables | ||||
|     items_processed++; | ||||
|     // After first message, set remaining size to MAX_PACKET_SIZE to avoid fragmentation | ||||
|     // After first message, set remaining size to MAX_BATCH_PACKET_SIZE to avoid fragmentation | ||||
|     if (items_processed == 1) { | ||||
|       remaining_size = MAX_PACKET_SIZE; | ||||
|       remaining_size = MAX_BATCH_PACKET_SIZE; | ||||
|     } | ||||
|     remaining_size -= payload_size; | ||||
|     // Calculate where the next message's header padding will start | ||||
| @@ -1824,7 +1843,7 @@ void APIConnection::process_batch_() { | ||||
| } | ||||
|  | ||||
| uint16_t APIConnection::MessageCreator::operator()(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, | ||||
|                                                    bool is_single, uint16_t message_type) const { | ||||
|                                                    bool is_single, uint8_t message_type) const { | ||||
| #ifdef USE_EVENT | ||||
|   // Special case: EventResponse uses string pointer | ||||
|   if (message_type == EventResponse::MESSAGE_TYPE) { | ||||
| @@ -1855,149 +1874,6 @@ uint16_t APIConnection::try_send_ping_request(EntityBase *entity, APIConnection | ||||
|   return encode_message_to_buffer(req, PingRequest::MESSAGE_TYPE, conn, remaining_size, is_single); | ||||
| } | ||||
|  | ||||
| uint16_t APIConnection::get_estimated_message_size(uint16_t message_type) { | ||||
|   // Use generated ESTIMATED_SIZE constants from each message type | ||||
|   switch (message_type) { | ||||
| #ifdef USE_BINARY_SENSOR | ||||
|     case BinarySensorStateResponse::MESSAGE_TYPE: | ||||
|       return BinarySensorStateResponse::ESTIMATED_SIZE; | ||||
|     case ListEntitiesBinarySensorResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesBinarySensorResponse::ESTIMATED_SIZE; | ||||
| #endif | ||||
| #ifdef USE_SENSOR | ||||
|     case SensorStateResponse::MESSAGE_TYPE: | ||||
|       return SensorStateResponse::ESTIMATED_SIZE; | ||||
|     case ListEntitiesSensorResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesSensorResponse::ESTIMATED_SIZE; | ||||
| #endif | ||||
| #ifdef USE_SWITCH | ||||
|     case SwitchStateResponse::MESSAGE_TYPE: | ||||
|       return SwitchStateResponse::ESTIMATED_SIZE; | ||||
|     case ListEntitiesSwitchResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesSwitchResponse::ESTIMATED_SIZE; | ||||
| #endif | ||||
| #ifdef USE_TEXT_SENSOR | ||||
|     case TextSensorStateResponse::MESSAGE_TYPE: | ||||
|       return TextSensorStateResponse::ESTIMATED_SIZE; | ||||
|     case ListEntitiesTextSensorResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesTextSensorResponse::ESTIMATED_SIZE; | ||||
| #endif | ||||
| #ifdef USE_NUMBER | ||||
|     case NumberStateResponse::MESSAGE_TYPE: | ||||
|       return NumberStateResponse::ESTIMATED_SIZE; | ||||
|     case ListEntitiesNumberResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesNumberResponse::ESTIMATED_SIZE; | ||||
| #endif | ||||
| #ifdef USE_TEXT | ||||
|     case TextStateResponse::MESSAGE_TYPE: | ||||
|       return TextStateResponse::ESTIMATED_SIZE; | ||||
|     case ListEntitiesTextResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesTextResponse::ESTIMATED_SIZE; | ||||
| #endif | ||||
| #ifdef USE_SELECT | ||||
|     case SelectStateResponse::MESSAGE_TYPE: | ||||
|       return SelectStateResponse::ESTIMATED_SIZE; | ||||
|     case ListEntitiesSelectResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesSelectResponse::ESTIMATED_SIZE; | ||||
| #endif | ||||
| #ifdef USE_LOCK | ||||
|     case LockStateResponse::MESSAGE_TYPE: | ||||
|       return LockStateResponse::ESTIMATED_SIZE; | ||||
|     case ListEntitiesLockResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesLockResponse::ESTIMATED_SIZE; | ||||
| #endif | ||||
| #ifdef USE_EVENT | ||||
|     case EventResponse::MESSAGE_TYPE: | ||||
|       return EventResponse::ESTIMATED_SIZE; | ||||
|     case ListEntitiesEventResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesEventResponse::ESTIMATED_SIZE; | ||||
| #endif | ||||
| #ifdef USE_COVER | ||||
|     case CoverStateResponse::MESSAGE_TYPE: | ||||
|       return CoverStateResponse::ESTIMATED_SIZE; | ||||
|     case ListEntitiesCoverResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesCoverResponse::ESTIMATED_SIZE; | ||||
| #endif | ||||
| #ifdef USE_FAN | ||||
|     case FanStateResponse::MESSAGE_TYPE: | ||||
|       return FanStateResponse::ESTIMATED_SIZE; | ||||
|     case ListEntitiesFanResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesFanResponse::ESTIMATED_SIZE; | ||||
| #endif | ||||
| #ifdef USE_LIGHT | ||||
|     case LightStateResponse::MESSAGE_TYPE: | ||||
|       return LightStateResponse::ESTIMATED_SIZE; | ||||
|     case ListEntitiesLightResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesLightResponse::ESTIMATED_SIZE; | ||||
| #endif | ||||
| #ifdef USE_CLIMATE | ||||
|     case ClimateStateResponse::MESSAGE_TYPE: | ||||
|       return ClimateStateResponse::ESTIMATED_SIZE; | ||||
|     case ListEntitiesClimateResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesClimateResponse::ESTIMATED_SIZE; | ||||
| #endif | ||||
| #ifdef USE_CAMERA | ||||
|     case ListEntitiesCameraResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesCameraResponse::ESTIMATED_SIZE; | ||||
| #endif | ||||
| #ifdef USE_BUTTON | ||||
|     case ListEntitiesButtonResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesButtonResponse::ESTIMATED_SIZE; | ||||
| #endif | ||||
| #ifdef USE_MEDIA_PLAYER | ||||
|     case MediaPlayerStateResponse::MESSAGE_TYPE: | ||||
|       return MediaPlayerStateResponse::ESTIMATED_SIZE; | ||||
|     case ListEntitiesMediaPlayerResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesMediaPlayerResponse::ESTIMATED_SIZE; | ||||
| #endif | ||||
| #ifdef USE_ALARM_CONTROL_PANEL | ||||
|     case AlarmControlPanelStateResponse::MESSAGE_TYPE: | ||||
|       return AlarmControlPanelStateResponse::ESTIMATED_SIZE; | ||||
|     case ListEntitiesAlarmControlPanelResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesAlarmControlPanelResponse::ESTIMATED_SIZE; | ||||
| #endif | ||||
| #ifdef USE_DATETIME_DATE | ||||
|     case DateStateResponse::MESSAGE_TYPE: | ||||
|       return DateStateResponse::ESTIMATED_SIZE; | ||||
|     case ListEntitiesDateResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesDateResponse::ESTIMATED_SIZE; | ||||
| #endif | ||||
| #ifdef USE_DATETIME_TIME | ||||
|     case TimeStateResponse::MESSAGE_TYPE: | ||||
|       return TimeStateResponse::ESTIMATED_SIZE; | ||||
|     case ListEntitiesTimeResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesTimeResponse::ESTIMATED_SIZE; | ||||
| #endif | ||||
| #ifdef USE_DATETIME_DATETIME | ||||
|     case DateTimeStateResponse::MESSAGE_TYPE: | ||||
|       return DateTimeStateResponse::ESTIMATED_SIZE; | ||||
|     case ListEntitiesDateTimeResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesDateTimeResponse::ESTIMATED_SIZE; | ||||
| #endif | ||||
| #ifdef USE_VALVE | ||||
|     case ValveStateResponse::MESSAGE_TYPE: | ||||
|       return ValveStateResponse::ESTIMATED_SIZE; | ||||
|     case ListEntitiesValveResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesValveResponse::ESTIMATED_SIZE; | ||||
| #endif | ||||
| #ifdef USE_UPDATE | ||||
|     case UpdateStateResponse::MESSAGE_TYPE: | ||||
|       return UpdateStateResponse::ESTIMATED_SIZE; | ||||
|     case ListEntitiesUpdateResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesUpdateResponse::ESTIMATED_SIZE; | ||||
| #endif | ||||
|     case ListEntitiesServicesResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesServicesResponse::ESTIMATED_SIZE; | ||||
|     case ListEntitiesDoneResponse::MESSAGE_TYPE: | ||||
|       return ListEntitiesDoneResponse::ESTIMATED_SIZE; | ||||
|     case DisconnectRequest::MESSAGE_TYPE: | ||||
|       return DisconnectRequest::ESTIMATED_SIZE; | ||||
|     default: | ||||
|       // Fallback for unknown message types | ||||
|       return 24; | ||||
|   } | ||||
| } | ||||
|  | ||||
| }  // namespace api | ||||
| }  // namespace esphome | ||||
| #endif | ||||
|   | ||||
| @@ -33,7 +33,7 @@ class APIConnection : public APIServerConnection { | ||||
|  | ||||
|   bool send_list_info_done() { | ||||
|     return this->schedule_message_(nullptr, &APIConnection::try_send_list_info_done, | ||||
|                                    ListEntitiesDoneResponse::MESSAGE_TYPE); | ||||
|                                    ListEntitiesDoneResponse::MESSAGE_TYPE, ListEntitiesDoneResponse::ESTIMATED_SIZE); | ||||
|   } | ||||
| #ifdef USE_BINARY_SENSOR | ||||
|   bool send_binary_sensor_state(binary_sensor::BinarySensor *binary_sensor); | ||||
| @@ -256,7 +256,7 @@ class APIConnection : public APIServerConnection { | ||||
|   } | ||||
|  | ||||
|   bool try_to_clear_buffer(bool log_out_of_space); | ||||
|   bool send_buffer(ProtoWriteBuffer buffer, uint16_t message_type) override; | ||||
|   bool send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) override; | ||||
|  | ||||
|   std::string get_client_combined_info() const { | ||||
|     if (this->client_info_ == this->client_peername_) { | ||||
| @@ -301,7 +301,7 @@ class APIConnection : public APIServerConnection { | ||||
|   } | ||||
|  | ||||
|   // Non-template helper to encode any ProtoMessage | ||||
|   static uint16_t encode_message_to_buffer(ProtoMessage &msg, uint16_t message_type, APIConnection *conn, | ||||
|   static uint16_t encode_message_to_buffer(ProtoMessage &msg, uint8_t message_type, APIConnection *conn, | ||||
|                                            uint32_t remaining_size, bool is_single); | ||||
|  | ||||
| #ifdef USE_VOICE_ASSISTANT | ||||
| @@ -446,9 +446,6 @@ class APIConnection : public APIServerConnection { | ||||
|   static uint16_t try_send_disconnect_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, | ||||
|                                               bool is_single); | ||||
|  | ||||
|   // Helper function to get estimated message size for buffer pre-allocation | ||||
|   static uint16_t get_estimated_message_size(uint16_t message_type); | ||||
|  | ||||
|   // Batch message method for ping requests | ||||
|   static uint16_t try_send_ping_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, | ||||
|                                         bool is_single); | ||||
| @@ -508,10 +505,10 @@ class APIConnection : public APIServerConnection { | ||||
|  | ||||
|     // Call operator - uses message_type to determine union type | ||||
|     uint16_t operator()(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single, | ||||
|                         uint16_t message_type) const; | ||||
|                         uint8_t message_type) const; | ||||
|  | ||||
|     // Manual cleanup method - must be called before destruction for string types | ||||
|     void cleanup(uint16_t message_type) { | ||||
|     void cleanup(uint8_t message_type) { | ||||
| #ifdef USE_EVENT | ||||
|       if (message_type == EventResponse::MESSAGE_TYPE && data_.string_ptr != nullptr) { | ||||
|         delete data_.string_ptr; | ||||
| @@ -532,11 +529,12 @@ class APIConnection : public APIServerConnection { | ||||
|     struct BatchItem { | ||||
|       EntityBase *entity;      // Entity pointer | ||||
|       MessageCreator creator;  // Function that creates the message when needed | ||||
|       uint16_t message_type;   // Message type for overhead calculation | ||||
|       uint8_t message_type;    // Message type for overhead calculation (max 255) | ||||
|       uint8_t estimated_size;  // Estimated message size (max 255 bytes) | ||||
|  | ||||
|       // Constructor for creating BatchItem | ||||
|       BatchItem(EntityBase *entity, MessageCreator creator, uint16_t message_type) | ||||
|           : entity(entity), creator(std::move(creator)), message_type(message_type) {} | ||||
|       BatchItem(EntityBase *entity, MessageCreator creator, uint8_t message_type, uint8_t estimated_size) | ||||
|           : entity(entity), creator(std::move(creator)), message_type(message_type), estimated_size(estimated_size) {} | ||||
|     }; | ||||
|  | ||||
|     std::vector<BatchItem> items; | ||||
| @@ -562,9 +560,9 @@ class APIConnection : public APIServerConnection { | ||||
|     } | ||||
|  | ||||
|     // Add item to the batch | ||||
|     void add_item(EntityBase *entity, MessageCreator creator, uint16_t message_type); | ||||
|     void add_item(EntityBase *entity, MessageCreator creator, uint8_t message_type, uint8_t estimated_size); | ||||
|     // Add item to the front of the batch (for high priority messages like ping) | ||||
|     void add_item_front(EntityBase *entity, MessageCreator creator, uint16_t message_type); | ||||
|     void add_item_front(EntityBase *entity, MessageCreator creator, uint8_t message_type, uint8_t estimated_size); | ||||
|  | ||||
|     // Clear all items with proper cleanup | ||||
|     void clear() { | ||||
| @@ -633,7 +631,7 @@ class APIConnection : public APIServerConnection { | ||||
|   // to send in one go. This is the maximum size of a single packet | ||||
|   // that can be sent over the network. | ||||
|   // This is to avoid fragmentation of the packet. | ||||
|   static constexpr size_t MAX_PACKET_SIZE = 1390;  // MTU | ||||
|   static constexpr size_t MAX_BATCH_PACKET_SIZE = 1390;  // MTU | ||||
|  | ||||
|   bool schedule_batch_(); | ||||
|   void process_batch_(); | ||||
| @@ -644,9 +642,9 @@ class APIConnection : public APIServerConnection { | ||||
|  | ||||
| #ifdef HAS_PROTO_MESSAGE_DUMP | ||||
|   // Helper to log a proto message from a MessageCreator object | ||||
|   void log_proto_message_(EntityBase *entity, const MessageCreator &creator, uint16_t message_type) { | ||||
|   void log_proto_message_(EntityBase *entity, const MessageCreator &creator, uint8_t message_type) { | ||||
|     this->flags_.log_only_mode = true; | ||||
|     creator(entity, this, MAX_PACKET_SIZE, true, message_type); | ||||
|     creator(entity, this, MAX_BATCH_PACKET_SIZE, true, message_type); | ||||
|     this->flags_.log_only_mode = false; | ||||
|   } | ||||
|  | ||||
| @@ -657,7 +655,8 @@ class APIConnection : public APIServerConnection { | ||||
| #endif | ||||
|  | ||||
|   // Helper method to send a message either immediately or via batching | ||||
|   bool send_message_smart_(EntityBase *entity, MessageCreatorPtr creator, uint16_t message_type) { | ||||
|   bool send_message_smart_(EntityBase *entity, MessageCreatorPtr creator, uint8_t message_type, | ||||
|                            uint8_t estimated_size) { | ||||
|     // Try to send immediately if: | ||||
|     // 1. We should try to send immediately (should_try_send_immediately = true) | ||||
|     // 2. Batch delay is 0 (user has opted in to immediate sending) | ||||
| @@ -665,7 +664,7 @@ class APIConnection : public APIServerConnection { | ||||
|     if (this->flags_.should_try_send_immediately && this->get_batch_delay_ms_() == 0 && | ||||
|         this->helper_->can_write_without_blocking()) { | ||||
|       // Now actually encode and send | ||||
|       if (creator(entity, this, MAX_PACKET_SIZE, true) && | ||||
|       if (creator(entity, this, MAX_BATCH_PACKET_SIZE, true) && | ||||
|           this->send_buffer(ProtoWriteBuffer{&this->parent_->get_shared_buffer_ref()}, message_type)) { | ||||
| #ifdef HAS_PROTO_MESSAGE_DUMP | ||||
|         // Log the message in verbose mode | ||||
| @@ -678,23 +677,25 @@ class APIConnection : public APIServerConnection { | ||||
|     } | ||||
|  | ||||
|     // Fall back to scheduled batching | ||||
|     return this->schedule_message_(entity, creator, message_type); | ||||
|     return this->schedule_message_(entity, creator, message_type, estimated_size); | ||||
|   } | ||||
|  | ||||
|   // Helper function to schedule a deferred message with known message type | ||||
|   bool schedule_message_(EntityBase *entity, MessageCreator creator, uint16_t message_type) { | ||||
|     this->deferred_batch_.add_item(entity, std::move(creator), message_type); | ||||
|   bool schedule_message_(EntityBase *entity, MessageCreator creator, uint8_t message_type, uint8_t estimated_size) { | ||||
|     this->deferred_batch_.add_item(entity, std::move(creator), message_type, estimated_size); | ||||
|     return this->schedule_batch_(); | ||||
|   } | ||||
|  | ||||
|   // Overload for function pointers (for info messages and current state reads) | ||||
|   bool schedule_message_(EntityBase *entity, MessageCreatorPtr function_ptr, uint16_t message_type) { | ||||
|     return schedule_message_(entity, MessageCreator(function_ptr), message_type); | ||||
|   bool schedule_message_(EntityBase *entity, MessageCreatorPtr function_ptr, uint8_t message_type, | ||||
|                          uint8_t estimated_size) { | ||||
|     return schedule_message_(entity, MessageCreator(function_ptr), message_type, estimated_size); | ||||
|   } | ||||
|  | ||||
|   // Helper function to schedule a high priority message at the front of the batch | ||||
|   bool schedule_message_front_(EntityBase *entity, MessageCreatorPtr function_ptr, uint16_t message_type) { | ||||
|     this->deferred_batch_.add_item_front(entity, MessageCreator(function_ptr), message_type); | ||||
|   bool schedule_message_front_(EntityBase *entity, MessageCreatorPtr function_ptr, uint8_t message_type, | ||||
|                                uint8_t estimated_size) { | ||||
|     this->deferred_batch_.add_item_front(entity, MessageCreator(function_ptr), message_type, estimated_size); | ||||
|     return this->schedule_batch_(); | ||||
|   } | ||||
| }; | ||||
|   | ||||
| @@ -613,11 +613,13 @@ APIError APINoiseFrameHelper::read_packet(ReadPacketBuffer *buffer) { | ||||
|   buffer->type = type; | ||||
|   return APIError::OK; | ||||
| } | ||||
| APIError APINoiseFrameHelper::write_protobuf_packet(uint16_t type, ProtoWriteBuffer buffer) { | ||||
| APIError APINoiseFrameHelper::write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) { | ||||
|   // Resize to include MAC space (required for Noise encryption) | ||||
|   buffer.get_buffer()->resize(buffer.get_buffer()->size() + frame_footer_size_); | ||||
|   PacketInfo packet{type, 0, | ||||
|                     static_cast<uint16_t>(buffer.get_buffer()->size() - frame_header_padding_ - frame_footer_size_)}; | ||||
|   uint16_t payload_size = | ||||
|       static_cast<uint16_t>(buffer.get_buffer()->size() - frame_header_padding_ - frame_footer_size_); | ||||
|  | ||||
|   PacketInfo packet{type, 0, payload_size}; | ||||
|   return write_protobuf_packets(buffer, std::span<const PacketInfo>(&packet, 1)); | ||||
| } | ||||
|  | ||||
| @@ -1002,8 +1004,10 @@ APIError APIPlaintextFrameHelper::read_packet(ReadPacketBuffer *buffer) { | ||||
|   buffer->type = rx_header_parsed_type_; | ||||
|   return APIError::OK; | ||||
| } | ||||
| APIError APIPlaintextFrameHelper::write_protobuf_packet(uint16_t type, ProtoWriteBuffer buffer) { | ||||
|   PacketInfo packet{type, 0, static_cast<uint16_t>(buffer.get_buffer()->size() - frame_header_padding_)}; | ||||
| APIError APIPlaintextFrameHelper::write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) { | ||||
|   uint16_t payload_size = static_cast<uint16_t>(buffer.get_buffer()->size() - frame_header_padding_); | ||||
|  | ||||
|   PacketInfo packet{type, 0, payload_size}; | ||||
|   return write_protobuf_packets(buffer, std::span<const PacketInfo>(&packet, 1)); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -30,13 +30,11 @@ struct ReadPacketBuffer { | ||||
|  | ||||
| // Packed packet info structure to minimize memory usage | ||||
| struct PacketInfo { | ||||
|   uint16_t message_type;  // 2 bytes | ||||
|   uint16_t offset;        // 2 bytes (sufficient for packet size ~1460 bytes) | ||||
|   uint16_t payload_size;  // 2 bytes (up to 65535 bytes) | ||||
|   uint16_t padding;       // 2 byte (for alignment) | ||||
|   uint16_t offset;        // Offset in buffer where message starts | ||||
|   uint16_t payload_size;  // Size of the message payload | ||||
|   uint8_t message_type;   // Message type (0-255) | ||||
|  | ||||
|   PacketInfo(uint16_t type, uint16_t off, uint16_t size) | ||||
|       : message_type(type), offset(off), payload_size(size), padding(0) {} | ||||
|   PacketInfo(uint8_t type, uint16_t off, uint16_t size) : offset(off), payload_size(size), message_type(type) {} | ||||
| }; | ||||
|  | ||||
| enum class APIError : uint16_t { | ||||
| @@ -98,7 +96,7 @@ class APIFrameHelper { | ||||
|   } | ||||
|   // Give this helper a name for logging | ||||
|   void set_log_info(std::string info) { info_ = std::move(info); } | ||||
|   virtual APIError write_protobuf_packet(uint16_t type, ProtoWriteBuffer buffer) = 0; | ||||
|   virtual APIError write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) = 0; | ||||
|   // Write multiple protobuf packets in a single operation | ||||
|   // packets contains (message_type, offset, length) for each message in the buffer | ||||
|   // The buffer contains all messages with appropriate padding before each | ||||
| @@ -197,7 +195,7 @@ class APINoiseFrameHelper : public APIFrameHelper { | ||||
|   APIError init() override; | ||||
|   APIError loop() override; | ||||
|   APIError read_packet(ReadPacketBuffer *buffer) override; | ||||
|   APIError write_protobuf_packet(uint16_t type, ProtoWriteBuffer buffer) override; | ||||
|   APIError write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) override; | ||||
|   APIError write_protobuf_packets(ProtoWriteBuffer buffer, std::span<const PacketInfo> packets) override; | ||||
|   // Get the frame header padding required by this protocol | ||||
|   uint8_t frame_header_padding() override { return frame_header_padding_; } | ||||
| @@ -251,7 +249,7 @@ class APIPlaintextFrameHelper : public APIFrameHelper { | ||||
|   APIError init() override; | ||||
|   APIError loop() override; | ||||
|   APIError read_packet(ReadPacketBuffer *buffer) override; | ||||
|   APIError write_protobuf_packet(uint16_t type, ProtoWriteBuffer buffer) override; | ||||
|   APIError write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) override; | ||||
|   APIError write_protobuf_packets(ProtoWriteBuffer buffer, std::span<const PacketInfo> packets) override; | ||||
|   uint8_t frame_header_padding() override { return frame_header_padding_; } | ||||
|   // Get the frame footer size required by this protocol | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -473,7 +473,8 @@ void APIServer::on_shutdown() { | ||||
|     if (!c->send_message(DisconnectRequest())) { | ||||
|       // If we can't send the disconnect request directly (tx_buffer full), | ||||
|       // schedule it at the front of the batch so it will be sent with priority | ||||
|       c->schedule_message_front_(nullptr, &APIConnection::try_send_disconnect_request, DisconnectRequest::MESSAGE_TYPE); | ||||
|       c->schedule_message_front_(nullptr, &APIConnection::try_send_disconnect_request, DisconnectRequest::MESSAGE_TYPE, | ||||
|                                  DisconnectRequest::ESTIMATED_SIZE); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -14,7 +14,7 @@ class APIConnection; | ||||
| #define LIST_ENTITIES_HANDLER(entity_type, EntityClass, ResponseType) \ | ||||
|   bool ListEntitiesIterator::on_##entity_type(EntityClass *entity) { /* NOLINT(bugprone-macro-parentheses) */ \ | ||||
|     return this->client_->schedule_message_(entity, &APIConnection::try_send_##entity_type##_info, \ | ||||
|                                             ResponseType::MESSAGE_TYPE); \ | ||||
|                                             ResponseType::MESSAGE_TYPE, ResponseType::ESTIMATED_SIZE); \ | ||||
|   } | ||||
|  | ||||
| class ListEntitiesIterator : public ComponentIterator { | ||||
|   | ||||
| @@ -363,11 +363,11 @@ class ProtoService { | ||||
|    * @return A ProtoWriteBuffer object with the reserved size. | ||||
|    */ | ||||
|   virtual ProtoWriteBuffer create_buffer(uint32_t reserve_size) = 0; | ||||
|   virtual bool send_buffer(ProtoWriteBuffer buffer, uint16_t message_type) = 0; | ||||
|   virtual bool send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) = 0; | ||||
|   virtual void read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) = 0; | ||||
|  | ||||
|   // Optimized method that pre-allocates buffer based on message size | ||||
|   bool send_message_(const ProtoMessage &msg, uint16_t message_type) { | ||||
|   bool send_message_(const ProtoMessage &msg, uint8_t message_type) { | ||||
|     uint32_t msg_size = 0; | ||||
|     msg.calculate_size(msg_size); | ||||
|  | ||||
|   | ||||
| @@ -987,13 +987,24 @@ def build_message_type( | ||||
|  | ||||
|     # Add MESSAGE_TYPE method if this is a service message | ||||
|     if message_id is not None: | ||||
|         # Validate that message_id fits in uint8_t | ||||
|         if message_id > 255: | ||||
|             raise ValueError( | ||||
|                 f"Message ID {message_id} for {desc.name} exceeds uint8_t maximum (255)" | ||||
|             ) | ||||
|  | ||||
|         # Add static constexpr for message type | ||||
|         public_content.append(f"static constexpr uint16_t MESSAGE_TYPE = {message_id};") | ||||
|         public_content.append(f"static constexpr uint8_t MESSAGE_TYPE = {message_id};") | ||||
|  | ||||
|         # Add estimated size constant | ||||
|         estimated_size = calculate_message_estimated_size(desc) | ||||
|         # Validate that estimated_size fits in uint8_t | ||||
|         if estimated_size > 255: | ||||
|             raise ValueError( | ||||
|                 f"Estimated size {estimated_size} for {desc.name} exceeds uint8_t maximum (255)" | ||||
|             ) | ||||
|         public_content.append( | ||||
|             f"static constexpr uint16_t ESTIMATED_SIZE = {estimated_size};" | ||||
|             f"static constexpr uint8_t ESTIMATED_SIZE = {estimated_size};" | ||||
|         ) | ||||
|  | ||||
|         # Add message_name method inline in header | ||||
|   | ||||
		Reference in New Issue
	
	Block a user