mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Avoid protobuf message construction when tx buffer is full (#8787)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
		
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -8,13 +8,14 @@ | |||||||
| #include "api_server.h" | #include "api_server.h" | ||||||
| #include "esphome/core/application.h" | #include "esphome/core/application.h" | ||||||
| #include "esphome/core/component.h" | #include "esphome/core/component.h" | ||||||
|  | #include "esphome/core/entity_base.h" | ||||||
|  |  | ||||||
| #include <vector> | #include <vector> | ||||||
|  |  | ||||||
| namespace esphome { | namespace esphome { | ||||||
| namespace api { | namespace api { | ||||||
|  |  | ||||||
| using send_message_t = bool(APIConnection *, void *); | using send_message_t = bool (APIConnection::*)(void *); | ||||||
|  |  | ||||||
| /* | /* | ||||||
|   This class holds a pointer to the source component that wants to publish a message, and a pointer to a function that |   This class holds a pointer to the source component that wants to publish a message, and a pointer to a function that | ||||||
| @@ -30,10 +31,10 @@ class DeferredMessageQueue { | |||||||
|  |  | ||||||
|    protected: |    protected: | ||||||
|     void *source_; |     void *source_; | ||||||
|     send_message_t *send_message_; |     send_message_t send_message_; | ||||||
|  |  | ||||||
|    public: |    public: | ||||||
|     DeferredMessage(void *source, send_message_t *send_message) : source_(source), send_message_(send_message) {} |     DeferredMessage(void *source, send_message_t send_message) : source_(source), send_message_(send_message) {} | ||||||
|     bool operator==(const DeferredMessage &test) const { |     bool operator==(const DeferredMessage &test) const { | ||||||
|       return (source_ == test.source_ && send_message_ == test.send_message_); |       return (source_ == test.source_ && send_message_ == test.send_message_); | ||||||
|     } |     } | ||||||
| @@ -46,12 +47,13 @@ class DeferredMessageQueue { | |||||||
|   APIConnection *api_connection_; |   APIConnection *api_connection_; | ||||||
|  |  | ||||||
|   // helper for allowing only unique entries in the queue |   // helper for allowing only unique entries in the queue | ||||||
|   void dmq_push_back_with_dedup_(void *source, send_message_t *send_message); |   void dmq_push_back_with_dedup_(void *source, send_message_t send_message); | ||||||
|  |  | ||||||
|  public: |  public: | ||||||
|   DeferredMessageQueue(APIConnection *api_connection) : api_connection_(api_connection) {} |   DeferredMessageQueue(APIConnection *api_connection) : api_connection_(api_connection) {} | ||||||
|   void process_queue(); |   void process_queue(); | ||||||
|   void defer(void *source, send_message_t *send_message); |   void defer(void *source, send_message_t send_message); | ||||||
|  |   bool empty() const { return deferred_queue_.empty(); } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| class APIConnection : public APIServerConnection { | class APIConnection : public APIServerConnection { | ||||||
| @@ -69,137 +71,213 @@ class APIConnection : public APIServerConnection { | |||||||
| #ifdef USE_BINARY_SENSOR | #ifdef USE_BINARY_SENSOR | ||||||
|   bool send_binary_sensor_state(binary_sensor::BinarySensor *binary_sensor, bool state); |   bool send_binary_sensor_state(binary_sensor::BinarySensor *binary_sensor, bool state); | ||||||
|   void send_binary_sensor_info(binary_sensor::BinarySensor *binary_sensor); |   void send_binary_sensor_info(binary_sensor::BinarySensor *binary_sensor); | ||||||
|   static bool try_send_binary_sensor_state(APIConnection *api, void *v_binary_sensor); |  | ||||||
|   static bool try_send_binary_sensor_state(APIConnection *api, binary_sensor::BinarySensor *binary_sensor, bool state); |  protected: | ||||||
|   static bool try_send_binary_sensor_info(APIConnection *api, void *v_binary_sensor); |   bool try_send_binary_sensor_state_(binary_sensor::BinarySensor *binary_sensor); | ||||||
|  |   bool try_send_binary_sensor_state_(binary_sensor::BinarySensor *binary_sensor, bool state); | ||||||
|  |   bool try_send_binary_sensor_info_(binary_sensor::BinarySensor *binary_sensor); | ||||||
|  |  | ||||||
|  |  public: | ||||||
| #endif | #endif | ||||||
| #ifdef USE_COVER | #ifdef USE_COVER | ||||||
|   bool send_cover_state(cover::Cover *cover); |   bool send_cover_state(cover::Cover *cover); | ||||||
|   void send_cover_info(cover::Cover *cover); |   void send_cover_info(cover::Cover *cover); | ||||||
|   static bool try_send_cover_state(APIConnection *api, void *v_cover); |  | ||||||
|   static bool try_send_cover_info(APIConnection *api, void *v_cover); |  | ||||||
|   void cover_command(const CoverCommandRequest &msg) override; |   void cover_command(const CoverCommandRequest &msg) override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   bool try_send_cover_state_(cover::Cover *cover); | ||||||
|  |   bool try_send_cover_info_(cover::Cover *cover); | ||||||
|  |  | ||||||
|  |  public: | ||||||
| #endif | #endif | ||||||
| #ifdef USE_FAN | #ifdef USE_FAN | ||||||
|   bool send_fan_state(fan::Fan *fan); |   bool send_fan_state(fan::Fan *fan); | ||||||
|   void send_fan_info(fan::Fan *fan); |   void send_fan_info(fan::Fan *fan); | ||||||
|   static bool try_send_fan_state(APIConnection *api, void *v_fan); |  | ||||||
|   static bool try_send_fan_info(APIConnection *api, void *v_fan); |  | ||||||
|   void fan_command(const FanCommandRequest &msg) override; |   void fan_command(const FanCommandRequest &msg) override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   bool try_send_fan_state_(fan::Fan *fan); | ||||||
|  |   bool try_send_fan_info_(fan::Fan *fan); | ||||||
|  |  | ||||||
|  |  public: | ||||||
| #endif | #endif | ||||||
| #ifdef USE_LIGHT | #ifdef USE_LIGHT | ||||||
|   bool send_light_state(light::LightState *light); |   bool send_light_state(light::LightState *light); | ||||||
|   void send_light_info(light::LightState *light); |   void send_light_info(light::LightState *light); | ||||||
|   static bool try_send_light_state(APIConnection *api, void *v_light); |  | ||||||
|   static bool try_send_light_info(APIConnection *api, void *v_light); |  | ||||||
|   void light_command(const LightCommandRequest &msg) override; |   void light_command(const LightCommandRequest &msg) override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   bool try_send_light_state_(light::LightState *light); | ||||||
|  |   bool try_send_light_info_(light::LightState *light); | ||||||
|  |  | ||||||
|  |  public: | ||||||
| #endif | #endif | ||||||
| #ifdef USE_SENSOR | #ifdef USE_SENSOR | ||||||
|   bool send_sensor_state(sensor::Sensor *sensor, float state); |   bool send_sensor_state(sensor::Sensor *sensor, float state); | ||||||
|   void send_sensor_info(sensor::Sensor *sensor); |   void send_sensor_info(sensor::Sensor *sensor); | ||||||
|   static bool try_send_sensor_state(APIConnection *api, void *v_sensor); |  | ||||||
|   static bool try_send_sensor_state(APIConnection *api, sensor::Sensor *sensor, float state); |  protected: | ||||||
|   static bool try_send_sensor_info(APIConnection *api, void *v_sensor); |   bool try_send_sensor_state_(sensor::Sensor *sensor); | ||||||
|  |   bool try_send_sensor_state_(sensor::Sensor *sensor, float state); | ||||||
|  |   bool try_send_sensor_info_(sensor::Sensor *sensor); | ||||||
|  |  | ||||||
|  |  public: | ||||||
| #endif | #endif | ||||||
| #ifdef USE_SWITCH | #ifdef USE_SWITCH | ||||||
|   bool send_switch_state(switch_::Switch *a_switch, bool state); |   bool send_switch_state(switch_::Switch *a_switch, bool state); | ||||||
|   void send_switch_info(switch_::Switch *a_switch); |   void send_switch_info(switch_::Switch *a_switch); | ||||||
|   static bool try_send_switch_state(APIConnection *api, void *v_a_switch); |  | ||||||
|   static bool try_send_switch_state(APIConnection *api, switch_::Switch *a_switch, bool state); |  | ||||||
|   static bool try_send_switch_info(APIConnection *api, void *v_a_switch); |  | ||||||
|   void switch_command(const SwitchCommandRequest &msg) override; |   void switch_command(const SwitchCommandRequest &msg) override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   bool try_send_switch_state_(switch_::Switch *a_switch); | ||||||
|  |   bool try_send_switch_state_(switch_::Switch *a_switch, bool state); | ||||||
|  |   bool try_send_switch_info_(switch_::Switch *a_switch); | ||||||
|  |  | ||||||
|  |  public: | ||||||
| #endif | #endif | ||||||
| #ifdef USE_TEXT_SENSOR | #ifdef USE_TEXT_SENSOR | ||||||
|   bool send_text_sensor_state(text_sensor::TextSensor *text_sensor, std::string state); |   bool send_text_sensor_state(text_sensor::TextSensor *text_sensor, std::string state); | ||||||
|   void send_text_sensor_info(text_sensor::TextSensor *text_sensor); |   void send_text_sensor_info(text_sensor::TextSensor *text_sensor); | ||||||
|   static bool try_send_text_sensor_state(APIConnection *api, void *v_text_sensor); |  | ||||||
|   static bool try_send_text_sensor_state(APIConnection *api, text_sensor::TextSensor *text_sensor, std::string state); |  protected: | ||||||
|   static bool try_send_text_sensor_info(APIConnection *api, void *v_text_sensor); |   bool try_send_text_sensor_state_(text_sensor::TextSensor *text_sensor); | ||||||
|  |   bool try_send_text_sensor_state_(text_sensor::TextSensor *text_sensor, std::string state); | ||||||
|  |   bool try_send_text_sensor_info_(text_sensor::TextSensor *text_sensor); | ||||||
|  |  | ||||||
|  |  public: | ||||||
| #endif | #endif | ||||||
| #ifdef USE_ESP32_CAMERA | #ifdef USE_ESP32_CAMERA | ||||||
|   void set_camera_state(std::shared_ptr<esp32_camera::CameraImage> image); |   void set_camera_state(std::shared_ptr<esp32_camera::CameraImage> image); | ||||||
|   void send_camera_info(esp32_camera::ESP32Camera *camera); |   void send_camera_info(esp32_camera::ESP32Camera *camera); | ||||||
|   static bool try_send_camera_info(APIConnection *api, void *v_camera); |  | ||||||
|   void camera_image(const CameraImageRequest &msg) override; |   void camera_image(const CameraImageRequest &msg) override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   bool try_send_camera_info_(esp32_camera::ESP32Camera *camera); | ||||||
|  |  | ||||||
|  |  public: | ||||||
| #endif | #endif | ||||||
| #ifdef USE_CLIMATE | #ifdef USE_CLIMATE | ||||||
|   bool send_climate_state(climate::Climate *climate); |   bool send_climate_state(climate::Climate *climate); | ||||||
|   void send_climate_info(climate::Climate *climate); |   void send_climate_info(climate::Climate *climate); | ||||||
|   static bool try_send_climate_state(APIConnection *api, void *v_climate); |  | ||||||
|   static bool try_send_climate_info(APIConnection *api, void *v_climate); |  | ||||||
|   void climate_command(const ClimateCommandRequest &msg) override; |   void climate_command(const ClimateCommandRequest &msg) override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   bool try_send_climate_state_(climate::Climate *climate); | ||||||
|  |   bool try_send_climate_info_(climate::Climate *climate); | ||||||
|  |  | ||||||
|  |  public: | ||||||
| #endif | #endif | ||||||
| #ifdef USE_NUMBER | #ifdef USE_NUMBER | ||||||
|   bool send_number_state(number::Number *number, float state); |   bool send_number_state(number::Number *number, float state); | ||||||
|   void send_number_info(number::Number *number); |   void send_number_info(number::Number *number); | ||||||
|   static bool try_send_number_state(APIConnection *api, void *v_number); |  | ||||||
|   static bool try_send_number_state(APIConnection *api, number::Number *number, float state); |  | ||||||
|   static bool try_send_number_info(APIConnection *api, void *v_number); |  | ||||||
|   void number_command(const NumberCommandRequest &msg) override; |   void number_command(const NumberCommandRequest &msg) override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   bool try_send_number_state_(number::Number *number); | ||||||
|  |   bool try_send_number_state_(number::Number *number, float state); | ||||||
|  |   bool try_send_number_info_(number::Number *number); | ||||||
|  |  | ||||||
|  |  public: | ||||||
| #endif | #endif | ||||||
| #ifdef USE_DATETIME_DATE | #ifdef USE_DATETIME_DATE | ||||||
|   bool send_date_state(datetime::DateEntity *date); |   bool send_date_state(datetime::DateEntity *date); | ||||||
|   void send_date_info(datetime::DateEntity *date); |   void send_date_info(datetime::DateEntity *date); | ||||||
|   static bool try_send_date_state(APIConnection *api, void *v_date); |  | ||||||
|   static bool try_send_date_info(APIConnection *api, void *v_date); |  | ||||||
|   void date_command(const DateCommandRequest &msg) override; |   void date_command(const DateCommandRequest &msg) override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   bool try_send_date_state_(datetime::DateEntity *date); | ||||||
|  |   bool try_send_date_info_(datetime::DateEntity *date); | ||||||
|  |  | ||||||
|  |  public: | ||||||
| #endif | #endif | ||||||
| #ifdef USE_DATETIME_TIME | #ifdef USE_DATETIME_TIME | ||||||
|   bool send_time_state(datetime::TimeEntity *time); |   bool send_time_state(datetime::TimeEntity *time); | ||||||
|   void send_time_info(datetime::TimeEntity *time); |   void send_time_info(datetime::TimeEntity *time); | ||||||
|   static bool try_send_time_state(APIConnection *api, void *v_time); |  | ||||||
|   static bool try_send_time_info(APIConnection *api, void *v_time); |  | ||||||
|   void time_command(const TimeCommandRequest &msg) override; |   void time_command(const TimeCommandRequest &msg) override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   bool try_send_time_state_(datetime::TimeEntity *time); | ||||||
|  |   bool try_send_time_info_(datetime::TimeEntity *time); | ||||||
|  |  | ||||||
|  |  public: | ||||||
| #endif | #endif | ||||||
| #ifdef USE_DATETIME_DATETIME | #ifdef USE_DATETIME_DATETIME | ||||||
|   bool send_datetime_state(datetime::DateTimeEntity *datetime); |   bool send_datetime_state(datetime::DateTimeEntity *datetime); | ||||||
|   void send_datetime_info(datetime::DateTimeEntity *datetime); |   void send_datetime_info(datetime::DateTimeEntity *datetime); | ||||||
|   static bool try_send_datetime_state(APIConnection *api, void *v_datetime); |  | ||||||
|   static bool try_send_datetime_info(APIConnection *api, void *v_datetime); |  | ||||||
|   void datetime_command(const DateTimeCommandRequest &msg) override; |   void datetime_command(const DateTimeCommandRequest &msg) override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   bool try_send_datetime_state_(datetime::DateTimeEntity *datetime); | ||||||
|  |   bool try_send_datetime_info_(datetime::DateTimeEntity *datetime); | ||||||
|  |  | ||||||
|  |  public: | ||||||
| #endif | #endif | ||||||
| #ifdef USE_TEXT | #ifdef USE_TEXT | ||||||
|   bool send_text_state(text::Text *text, std::string state); |   bool send_text_state(text::Text *text, std::string state); | ||||||
|   void send_text_info(text::Text *text); |   void send_text_info(text::Text *text); | ||||||
|   static bool try_send_text_state(APIConnection *api, void *v_text); |  | ||||||
|   static bool try_send_text_state(APIConnection *api, text::Text *text, std::string state); |  | ||||||
|   static bool try_send_text_info(APIConnection *api, void *v_text); |  | ||||||
|   void text_command(const TextCommandRequest &msg) override; |   void text_command(const TextCommandRequest &msg) override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   bool try_send_text_state_(text::Text *text); | ||||||
|  |   bool try_send_text_state_(text::Text *text, std::string state); | ||||||
|  |   bool try_send_text_info_(text::Text *text); | ||||||
|  |  | ||||||
|  |  public: | ||||||
| #endif | #endif | ||||||
| #ifdef USE_SELECT | #ifdef USE_SELECT | ||||||
|   bool send_select_state(select::Select *select, std::string state); |   bool send_select_state(select::Select *select, std::string state); | ||||||
|   void send_select_info(select::Select *select); |   void send_select_info(select::Select *select); | ||||||
|   static bool try_send_select_state(APIConnection *api, void *v_select); |  | ||||||
|   static bool try_send_select_state(APIConnection *api, select::Select *select, std::string state); |  | ||||||
|   static bool try_send_select_info(APIConnection *api, void *v_select); |  | ||||||
|   void select_command(const SelectCommandRequest &msg) override; |   void select_command(const SelectCommandRequest &msg) override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   bool try_send_select_state_(select::Select *select); | ||||||
|  |   bool try_send_select_state_(select::Select *select, std::string state); | ||||||
|  |   bool try_send_select_info_(select::Select *select); | ||||||
|  |  | ||||||
|  |  public: | ||||||
| #endif | #endif | ||||||
| #ifdef USE_BUTTON | #ifdef USE_BUTTON | ||||||
|   void send_button_info(button::Button *button); |   void send_button_info(button::Button *button); | ||||||
|   static bool try_send_button_info(APIConnection *api, void *v_button); |  | ||||||
|   void button_command(const ButtonCommandRequest &msg) override; |   void button_command(const ButtonCommandRequest &msg) override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   bool try_send_button_info_(button::Button *button); | ||||||
|  |  | ||||||
|  |  public: | ||||||
| #endif | #endif | ||||||
| #ifdef USE_LOCK | #ifdef USE_LOCK | ||||||
|   bool send_lock_state(lock::Lock *a_lock, lock::LockState state); |   bool send_lock_state(lock::Lock *a_lock, lock::LockState state); | ||||||
|   void send_lock_info(lock::Lock *a_lock); |   void send_lock_info(lock::Lock *a_lock); | ||||||
|   static bool try_send_lock_state(APIConnection *api, void *v_a_lock); |  | ||||||
|   static bool try_send_lock_state(APIConnection *api, lock::Lock *a_lock, lock::LockState state); |  | ||||||
|   static bool try_send_lock_info(APIConnection *api, void *v_a_lock); |  | ||||||
|   void lock_command(const LockCommandRequest &msg) override; |   void lock_command(const LockCommandRequest &msg) override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   bool try_send_lock_state_(lock::Lock *a_lock); | ||||||
|  |   bool try_send_lock_state_(lock::Lock *a_lock, lock::LockState state); | ||||||
|  |   bool try_send_lock_info_(lock::Lock *a_lock); | ||||||
|  |  | ||||||
|  |  public: | ||||||
| #endif | #endif | ||||||
| #ifdef USE_VALVE | #ifdef USE_VALVE | ||||||
|   bool send_valve_state(valve::Valve *valve); |   bool send_valve_state(valve::Valve *valve); | ||||||
|   void send_valve_info(valve::Valve *valve); |   void send_valve_info(valve::Valve *valve); | ||||||
|   static bool try_send_valve_state(APIConnection *api, void *v_valve); |  | ||||||
|   static bool try_send_valve_info(APIConnection *api, void *v_valve); |  | ||||||
|   void valve_command(const ValveCommandRequest &msg) override; |   void valve_command(const ValveCommandRequest &msg) override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   bool try_send_valve_state_(valve::Valve *valve); | ||||||
|  |   bool try_send_valve_info_(valve::Valve *valve); | ||||||
|  |  | ||||||
|  |  public: | ||||||
| #endif | #endif | ||||||
| #ifdef USE_MEDIA_PLAYER | #ifdef USE_MEDIA_PLAYER | ||||||
|   bool send_media_player_state(media_player::MediaPlayer *media_player); |   bool send_media_player_state(media_player::MediaPlayer *media_player); | ||||||
|   void send_media_player_info(media_player::MediaPlayer *media_player); |   void send_media_player_info(media_player::MediaPlayer *media_player); | ||||||
|   static bool try_send_media_player_state(APIConnection *api, void *v_media_player); |  | ||||||
|   static bool try_send_media_player_info(APIConnection *api, void *v_media_player); |  | ||||||
|   void media_player_command(const MediaPlayerCommandRequest &msg) override; |   void media_player_command(const MediaPlayerCommandRequest &msg) override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   bool try_send_media_player_state_(media_player::MediaPlayer *media_player); | ||||||
|  |   bool try_send_media_player_info_(media_player::MediaPlayer *media_player); | ||||||
|  |  | ||||||
|  |  public: | ||||||
| #endif | #endif | ||||||
|   bool try_send_log_message(int level, const char *tag, const char *line); |   bool try_send_log_message(int level, const char *tag, const char *line); | ||||||
|   void send_homeassistant_service_call(const HomeassistantServiceResponse &call) { |   void send_homeassistant_service_call(const HomeassistantServiceResponse &call) { | ||||||
| @@ -246,25 +324,37 @@ class APIConnection : public APIServerConnection { | |||||||
| #ifdef USE_ALARM_CONTROL_PANEL | #ifdef USE_ALARM_CONTROL_PANEL | ||||||
|   bool send_alarm_control_panel_state(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel); |   bool send_alarm_control_panel_state(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel); | ||||||
|   void send_alarm_control_panel_info(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel); |   void send_alarm_control_panel_info(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel); | ||||||
|   static bool try_send_alarm_control_panel_state(APIConnection *api, void *v_a_alarm_control_panel); |  | ||||||
|   static bool try_send_alarm_control_panel_info(APIConnection *api, void *v_a_alarm_control_panel); |  | ||||||
|   void alarm_control_panel_command(const AlarmControlPanelCommandRequest &msg) override; |   void alarm_control_panel_command(const AlarmControlPanelCommandRequest &msg) override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   bool try_send_alarm_control_panel_state_(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel); | ||||||
|  |   bool try_send_alarm_control_panel_info_(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel); | ||||||
|  |  | ||||||
|  |  public: | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef USE_EVENT | #ifdef USE_EVENT | ||||||
|   void send_event(event::Event *event, std::string event_type); |   void send_event(event::Event *event, std::string event_type); | ||||||
|   void send_event_info(event::Event *event); |   void send_event_info(event::Event *event); | ||||||
|   static bool try_send_event(APIConnection *api, void *v_event); |  | ||||||
|   static bool try_send_event(APIConnection *api, event::Event *event, std::string event_type); |  protected: | ||||||
|   static bool try_send_event_info(APIConnection *api, void *v_event); |   bool try_send_event_(event::Event *event); | ||||||
|  |   bool try_send_event_(event::Event *event, std::string event_type); | ||||||
|  |   bool try_send_event_info_(event::Event *event); | ||||||
|  |  | ||||||
|  |  public: | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef USE_UPDATE | #ifdef USE_UPDATE | ||||||
|   bool send_update_state(update::UpdateEntity *update); |   bool send_update_state(update::UpdateEntity *update); | ||||||
|   void send_update_info(update::UpdateEntity *update); |   void send_update_info(update::UpdateEntity *update); | ||||||
|   static bool try_send_update_state(APIConnection *api, void *v_update); |  | ||||||
|   static bool try_send_update_info(APIConnection *api, void *v_update); |  | ||||||
|   void update_command(const UpdateCommandRequest &msg) override; |   void update_command(const UpdateCommandRequest &msg) override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   bool try_send_update_state_(update::UpdateEntity *update); | ||||||
|  |   bool try_send_update_info_(update::UpdateEntity *update); | ||||||
|  |  | ||||||
|  |  public: | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   void on_disconnect_response(const DisconnectResponse &value) override; |   void on_disconnect_response(const DisconnectResponse &value) override; | ||||||
| @@ -318,6 +408,7 @@ class APIConnection : public APIServerConnection { | |||||||
|     this->proto_write_buffer_.reserve(reserve_size); |     this->proto_write_buffer_.reserve(reserve_size); | ||||||
|     return {&this->proto_write_buffer_}; |     return {&this->proto_write_buffer_}; | ||||||
|   } |   } | ||||||
|  |   bool try_to_clear_buffer(bool log_out_of_space); | ||||||
|   bool send_buffer(ProtoWriteBuffer buffer, uint32_t message_type) override; |   bool send_buffer(ProtoWriteBuffer buffer, uint32_t message_type) override; | ||||||
|  |  | ||||||
|   std::string get_client_combined_info() const { return this->client_combined_info_; } |   std::string get_client_combined_info() const { return this->client_combined_info_; } | ||||||
| @@ -325,6 +416,99 @@ class APIConnection : public APIServerConnection { | |||||||
|  protected: |  protected: | ||||||
|   friend APIServer; |   friend APIServer; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Generic send entity state method to reduce code duplication. | ||||||
|  |    * Only attempts to build and send the message if the transmit buffer is available. | ||||||
|  |    * | ||||||
|  |    * This is the base version for entities that use their current state. | ||||||
|  |    * | ||||||
|  |    * @param entity The entity to send state for | ||||||
|  |    * @param try_send_func The function that tries to send the state | ||||||
|  |    * @return True on success or message deferred, false if subscription check failed | ||||||
|  |    */ | ||||||
|  |   bool send_state_(esphome::EntityBase *entity, send_message_t try_send_func) { | ||||||
|  |     if (!this->state_subscription_) | ||||||
|  |       return false; | ||||||
|  |     if (this->try_to_clear_buffer(true) && (this->*try_send_func)(entity)) { | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|  |     this->deferred_message_queue_.defer(entity, try_send_func); | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Send entity state method that handles explicit state values. | ||||||
|  |    * Only attempts to build and send the message if the transmit buffer is available. | ||||||
|  |    * | ||||||
|  |    * This method accepts a state parameter to be used instead of the entity's current state. | ||||||
|  |    * It attempts to send the state with the provided value first, and if that fails due to buffer constraints, | ||||||
|  |    * it defers the entity for later processing using the entity-only function. | ||||||
|  |    * | ||||||
|  |    * @tparam EntityT The entity type | ||||||
|  |    * @tparam StateT Type of the state parameter | ||||||
|  |    * @tparam Args Additional argument types (if any) | ||||||
|  |    * @param entity The entity to send state for | ||||||
|  |    * @param try_send_entity_func The function that tries to send the state with entity pointer only | ||||||
|  |    * @param try_send_state_func The function that tries to send the state with entity and state parameters | ||||||
|  |    * @param state The state value to send | ||||||
|  |    * @param args Additional arguments to pass to the try_send_state_func | ||||||
|  |    * @return True on success or message deferred, false if subscription check failed | ||||||
|  |    */ | ||||||
|  |   template<typename EntityT, typename StateT, typename... Args> | ||||||
|  |   bool send_state_with_value_(EntityT *entity, bool (APIConnection::*try_send_entity_func)(EntityT *), | ||||||
|  |                               bool (APIConnection::*try_send_state_func)(EntityT *, StateT, Args...), StateT state, | ||||||
|  |                               Args... args) { | ||||||
|  |     if (!this->state_subscription_) | ||||||
|  |       return false; | ||||||
|  |     if (this->try_to_clear_buffer(true) && (this->*try_send_state_func)(entity, state, args...)) { | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|  |     this->deferred_message_queue_.defer(entity, reinterpret_cast<send_message_t>(try_send_entity_func)); | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Generic send entity info method to reduce code duplication. | ||||||
|  |    * Only attempts to build and send the message if the transmit buffer is available. | ||||||
|  |    * | ||||||
|  |    * @param entity The entity to send info for | ||||||
|  |    * @param try_send_func The function that tries to send the info | ||||||
|  |    */ | ||||||
|  |   void send_info_(esphome::EntityBase *entity, send_message_t try_send_func) { | ||||||
|  |     if (this->try_to_clear_buffer(true) && (this->*try_send_func)(entity)) { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |     this->deferred_message_queue_.defer(entity, try_send_func); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Generic function for generating entity info response messages. | ||||||
|  |    * This is used to reduce duplication in the try_send_*_info functions. | ||||||
|  |    * | ||||||
|  |    * @param entity The entity to generate info for | ||||||
|  |    * @param response The response object | ||||||
|  |    * @param send_response_func Function pointer to send the response | ||||||
|  |    * @return True if the message was sent successfully | ||||||
|  |    */ | ||||||
|  |   template<typename ResponseT> | ||||||
|  |   bool try_send_entity_info_(esphome::EntityBase *entity, ResponseT &response, | ||||||
|  |                              bool (APIServerConnectionBase::*send_response_func)(const ResponseT &)) { | ||||||
|  |     // Set common fields that are shared by all entity types | ||||||
|  |     response.key = entity->get_object_id_hash(); | ||||||
|  |     response.object_id = entity->get_object_id(); | ||||||
|  |  | ||||||
|  |     if (entity->has_own_name()) | ||||||
|  |       response.name = entity->get_name(); | ||||||
|  |  | ||||||
|  |     // Set common EntityBase properties | ||||||
|  |     response.icon = entity->get_icon(); | ||||||
|  |     response.disabled_by_default = entity->is_disabled_by_default(); | ||||||
|  |     response.entity_category = static_cast<enums::EntityCategory>(entity->get_entity_category()); | ||||||
|  |  | ||||||
|  |     // Send the response using the provided send method | ||||||
|  |     return (this->*send_response_func)(response); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   bool send_(const void *buf, size_t len, bool force); |   bool send_(const void *buf, size_t len, bool force); | ||||||
|  |  | ||||||
|   enum class ConnectionState { |   enum class ConnectionState { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user