1
0
mirror of https://github.com/esphome/esphome.git synced 2026-02-08 00:31:58 +00:00

[api] Remove is_single parameter and fix batch buffer preparation (#13773)

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
J. Nick Koston
2026-02-05 15:19:03 +01:00
committed by GitHub
parent 081f953dc3
commit 55ef8393af
5 changed files with 221 additions and 345 deletions

View File

@@ -300,7 +300,7 @@ void APIConnection::on_disconnect_response(const DisconnectResponse &value) {
// Encodes a message to the buffer and returns the total number of bytes used, // 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. // including header and footer overhead. Returns 0 if the message doesn't fit.
uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint8_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) { uint32_t remaining_size) {
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
// If in log-only mode, just log and return // If in log-only mode, just log and return
if (conn->flags_.log_only_mode) { if (conn->flags_.log_only_mode) {
@@ -330,12 +330,9 @@ uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint8_t mess
// Get buffer size after allocation (which includes header padding) // Get buffer size after allocation (which includes header padding)
std::vector<uint8_t> &shared_buf = conn->parent_->get_shared_buffer_ref(); std::vector<uint8_t> &shared_buf = conn->parent_->get_shared_buffer_ref();
if (is_single || conn->flags_.batch_first_message) { if (conn->flags_.batch_first_message) {
// Single message or first batch message // First message - buffer already prepared by caller, just clear flag
conn->prepare_first_message_buffer(shared_buf, header_padding, total_calculated_size); conn->flags_.batch_first_message = false;
if (conn->flags_.batch_first_message) {
conn->flags_.batch_first_message = false;
}
} else { } else {
// Batch message second or later // Batch message second or later
// Add padding for previous message footer + this message header // Add padding for previous message footer + this message header
@@ -365,24 +362,22 @@ bool APIConnection::send_binary_sensor_state(binary_sensor::BinarySensor *binary
BinarySensorStateResponse::ESTIMATED_SIZE); BinarySensorStateResponse::ESTIMATED_SIZE);
} }
uint16_t APIConnection::try_send_binary_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_binary_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *binary_sensor = static_cast<binary_sensor::BinarySensor *>(entity); auto *binary_sensor = static_cast<binary_sensor::BinarySensor *>(entity);
BinarySensorStateResponse resp; BinarySensorStateResponse resp;
resp.state = binary_sensor->state; resp.state = binary_sensor->state;
resp.missing_state = !binary_sensor->has_state(); resp.missing_state = !binary_sensor->has_state();
return fill_and_encode_entity_state(binary_sensor, resp, BinarySensorStateResponse::MESSAGE_TYPE, conn, return fill_and_encode_entity_state(binary_sensor, resp, BinarySensorStateResponse::MESSAGE_TYPE, conn,
remaining_size, is_single); remaining_size);
} }
uint16_t APIConnection::try_send_binary_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_binary_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *binary_sensor = static_cast<binary_sensor::BinarySensor *>(entity); auto *binary_sensor = static_cast<binary_sensor::BinarySensor *>(entity);
ListEntitiesBinarySensorResponse msg; ListEntitiesBinarySensorResponse msg;
msg.device_class = binary_sensor->get_device_class_ref(); msg.device_class = binary_sensor->get_device_class_ref();
msg.is_status_binary_sensor = binary_sensor->is_status_binary_sensor(); msg.is_status_binary_sensor = binary_sensor->is_status_binary_sensor();
return fill_and_encode_entity_info(binary_sensor, msg, ListEntitiesBinarySensorResponse::MESSAGE_TYPE, conn, return fill_and_encode_entity_info(binary_sensor, msg, ListEntitiesBinarySensorResponse::MESSAGE_TYPE, conn,
remaining_size, is_single); remaining_size);
} }
#endif #endif
@@ -390,8 +385,7 @@ uint16_t APIConnection::try_send_binary_sensor_info(EntityBase *entity, APIConne
bool APIConnection::send_cover_state(cover::Cover *cover) { bool APIConnection::send_cover_state(cover::Cover *cover) {
return this->send_message_smart_(cover, CoverStateResponse::MESSAGE_TYPE, CoverStateResponse::ESTIMATED_SIZE); return this->send_message_smart_(cover, CoverStateResponse::MESSAGE_TYPE, CoverStateResponse::ESTIMATED_SIZE);
} }
uint16_t APIConnection::try_send_cover_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_cover_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *cover = static_cast<cover::Cover *>(entity); auto *cover = static_cast<cover::Cover *>(entity);
CoverStateResponse msg; CoverStateResponse msg;
auto traits = cover->get_traits(); auto traits = cover->get_traits();
@@ -399,10 +393,9 @@ uint16_t APIConnection::try_send_cover_state(EntityBase *entity, APIConnection *
if (traits.get_supports_tilt()) if (traits.get_supports_tilt())
msg.tilt = cover->tilt; msg.tilt = cover->tilt;
msg.current_operation = static_cast<enums::CoverOperation>(cover->current_operation); msg.current_operation = static_cast<enums::CoverOperation>(cover->current_operation);
return fill_and_encode_entity_state(cover, msg, CoverStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); return fill_and_encode_entity_state(cover, msg, CoverStateResponse::MESSAGE_TYPE, conn, remaining_size);
} }
uint16_t APIConnection::try_send_cover_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_cover_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *cover = static_cast<cover::Cover *>(entity); auto *cover = static_cast<cover::Cover *>(entity);
ListEntitiesCoverResponse msg; ListEntitiesCoverResponse msg;
auto traits = cover->get_traits(); auto traits = cover->get_traits();
@@ -411,8 +404,7 @@ uint16_t APIConnection::try_send_cover_info(EntityBase *entity, APIConnection *c
msg.supports_tilt = traits.get_supports_tilt(); msg.supports_tilt = traits.get_supports_tilt();
msg.supports_stop = traits.get_supports_stop(); msg.supports_stop = traits.get_supports_stop();
msg.device_class = cover->get_device_class_ref(); msg.device_class = cover->get_device_class_ref();
return fill_and_encode_entity_info(cover, msg, ListEntitiesCoverResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_info(cover, msg, ListEntitiesCoverResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
void APIConnection::cover_command(const CoverCommandRequest &msg) { void APIConnection::cover_command(const CoverCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(cover::Cover, cover, cover) ENTITY_COMMAND_MAKE_CALL(cover::Cover, cover, cover)
@@ -430,8 +422,7 @@ void APIConnection::cover_command(const CoverCommandRequest &msg) {
bool APIConnection::send_fan_state(fan::Fan *fan) { bool APIConnection::send_fan_state(fan::Fan *fan) {
return this->send_message_smart_(fan, FanStateResponse::MESSAGE_TYPE, FanStateResponse::ESTIMATED_SIZE); return this->send_message_smart_(fan, FanStateResponse::MESSAGE_TYPE, FanStateResponse::ESTIMATED_SIZE);
} }
uint16_t APIConnection::try_send_fan_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_fan_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *fan = static_cast<fan::Fan *>(entity); auto *fan = static_cast<fan::Fan *>(entity);
FanStateResponse msg; FanStateResponse msg;
auto traits = fan->get_traits(); auto traits = fan->get_traits();
@@ -445,10 +436,9 @@ uint16_t APIConnection::try_send_fan_state(EntityBase *entity, APIConnection *co
msg.direction = static_cast<enums::FanDirection>(fan->direction); msg.direction = static_cast<enums::FanDirection>(fan->direction);
if (traits.supports_preset_modes() && fan->has_preset_mode()) if (traits.supports_preset_modes() && fan->has_preset_mode())
msg.preset_mode = fan->get_preset_mode(); msg.preset_mode = fan->get_preset_mode();
return fill_and_encode_entity_state(fan, msg, FanStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); return fill_and_encode_entity_state(fan, msg, FanStateResponse::MESSAGE_TYPE, conn, remaining_size);
} }
uint16_t APIConnection::try_send_fan_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_fan_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *fan = static_cast<fan::Fan *>(entity); auto *fan = static_cast<fan::Fan *>(entity);
ListEntitiesFanResponse msg; ListEntitiesFanResponse msg;
auto traits = fan->get_traits(); auto traits = fan->get_traits();
@@ -457,7 +447,7 @@ uint16_t APIConnection::try_send_fan_info(EntityBase *entity, APIConnection *con
msg.supports_direction = traits.supports_direction(); msg.supports_direction = traits.supports_direction();
msg.supported_speed_count = traits.supported_speed_count(); msg.supported_speed_count = traits.supported_speed_count();
msg.supported_preset_modes = &traits.supported_preset_modes(); msg.supported_preset_modes = &traits.supported_preset_modes();
return fill_and_encode_entity_info(fan, msg, ListEntitiesFanResponse::MESSAGE_TYPE, conn, remaining_size, is_single); return fill_and_encode_entity_info(fan, msg, ListEntitiesFanResponse::MESSAGE_TYPE, conn, remaining_size);
} }
void APIConnection::fan_command(const FanCommandRequest &msg) { void APIConnection::fan_command(const FanCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(fan::Fan, fan, fan) ENTITY_COMMAND_MAKE_CALL(fan::Fan, fan, fan)
@@ -481,8 +471,7 @@ void APIConnection::fan_command(const FanCommandRequest &msg) {
bool APIConnection::send_light_state(light::LightState *light) { bool APIConnection::send_light_state(light::LightState *light) {
return this->send_message_smart_(light, LightStateResponse::MESSAGE_TYPE, LightStateResponse::ESTIMATED_SIZE); return this->send_message_smart_(light, LightStateResponse::MESSAGE_TYPE, LightStateResponse::ESTIMATED_SIZE);
} }
uint16_t APIConnection::try_send_light_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_light_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *light = static_cast<light::LightState *>(entity); auto *light = static_cast<light::LightState *>(entity);
LightStateResponse resp; LightStateResponse resp;
auto values = light->remote_values; auto values = light->remote_values;
@@ -501,10 +490,9 @@ uint16_t APIConnection::try_send_light_state(EntityBase *entity, APIConnection *
if (light->supports_effects()) { if (light->supports_effects()) {
resp.effect = light->get_effect_name(); resp.effect = light->get_effect_name();
} }
return fill_and_encode_entity_state(light, resp, LightStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); return fill_and_encode_entity_state(light, resp, LightStateResponse::MESSAGE_TYPE, conn, remaining_size);
} }
uint16_t APIConnection::try_send_light_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_light_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *light = static_cast<light::LightState *>(entity); auto *light = static_cast<light::LightState *>(entity);
ListEntitiesLightResponse msg; ListEntitiesLightResponse msg;
auto traits = light->get_traits(); auto traits = light->get_traits();
@@ -527,8 +515,7 @@ uint16_t APIConnection::try_send_light_info(EntityBase *entity, APIConnection *c
} }
} }
msg.effects = &effects_list; msg.effects = &effects_list;
return fill_and_encode_entity_info(light, msg, ListEntitiesLightResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_info(light, msg, ListEntitiesLightResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
void APIConnection::light_command(const LightCommandRequest &msg) { void APIConnection::light_command(const LightCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(light::LightState, light, light) ENTITY_COMMAND_MAKE_CALL(light::LightState, light, light)
@@ -568,17 +555,15 @@ bool APIConnection::send_sensor_state(sensor::Sensor *sensor) {
return this->send_message_smart_(sensor, SensorStateResponse::MESSAGE_TYPE, SensorStateResponse::ESTIMATED_SIZE); return this->send_message_smart_(sensor, SensorStateResponse::MESSAGE_TYPE, SensorStateResponse::ESTIMATED_SIZE);
} }
uint16_t APIConnection::try_send_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *sensor = static_cast<sensor::Sensor *>(entity); auto *sensor = static_cast<sensor::Sensor *>(entity);
SensorStateResponse resp; SensorStateResponse resp;
resp.state = sensor->state; resp.state = sensor->state;
resp.missing_state = !sensor->has_state(); resp.missing_state = !sensor->has_state();
return fill_and_encode_entity_state(sensor, resp, SensorStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); return fill_and_encode_entity_state(sensor, resp, SensorStateResponse::MESSAGE_TYPE, conn, remaining_size);
} }
uint16_t APIConnection::try_send_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *sensor = static_cast<sensor::Sensor *>(entity); auto *sensor = static_cast<sensor::Sensor *>(entity);
ListEntitiesSensorResponse msg; ListEntitiesSensorResponse msg;
msg.unit_of_measurement = sensor->get_unit_of_measurement_ref(); msg.unit_of_measurement = sensor->get_unit_of_measurement_ref();
@@ -586,8 +571,7 @@ uint16_t APIConnection::try_send_sensor_info(EntityBase *entity, APIConnection *
msg.force_update = sensor->get_force_update(); msg.force_update = sensor->get_force_update();
msg.device_class = sensor->get_device_class_ref(); msg.device_class = sensor->get_device_class_ref();
msg.state_class = static_cast<enums::SensorStateClass>(sensor->get_state_class()); msg.state_class = static_cast<enums::SensorStateClass>(sensor->get_state_class());
return fill_and_encode_entity_info(sensor, msg, ListEntitiesSensorResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_info(sensor, msg, ListEntitiesSensorResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
#endif #endif
@@ -596,23 +580,19 @@ bool APIConnection::send_switch_state(switch_::Switch *a_switch) {
return this->send_message_smart_(a_switch, SwitchStateResponse::MESSAGE_TYPE, SwitchStateResponse::ESTIMATED_SIZE); return this->send_message_smart_(a_switch, SwitchStateResponse::MESSAGE_TYPE, SwitchStateResponse::ESTIMATED_SIZE);
} }
uint16_t APIConnection::try_send_switch_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_switch_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *a_switch = static_cast<switch_::Switch *>(entity); auto *a_switch = static_cast<switch_::Switch *>(entity);
SwitchStateResponse resp; SwitchStateResponse resp;
resp.state = a_switch->state; resp.state = a_switch->state;
return fill_and_encode_entity_state(a_switch, resp, SwitchStateResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_state(a_switch, resp, SwitchStateResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
uint16_t APIConnection::try_send_switch_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_switch_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *a_switch = static_cast<switch_::Switch *>(entity); auto *a_switch = static_cast<switch_::Switch *>(entity);
ListEntitiesSwitchResponse msg; ListEntitiesSwitchResponse msg;
msg.assumed_state = a_switch->assumed_state(); msg.assumed_state = a_switch->assumed_state();
msg.device_class = a_switch->get_device_class_ref(); msg.device_class = a_switch->get_device_class_ref();
return fill_and_encode_entity_info(a_switch, msg, ListEntitiesSwitchResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_info(a_switch, msg, ListEntitiesSwitchResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
void APIConnection::switch_command(const SwitchCommandRequest &msg) { void APIConnection::switch_command(const SwitchCommandRequest &msg) {
ENTITY_COMMAND_GET(switch_::Switch, a_switch, switch) ENTITY_COMMAND_GET(switch_::Switch, a_switch, switch)
@@ -631,22 +611,19 @@ bool APIConnection::send_text_sensor_state(text_sensor::TextSensor *text_sensor)
TextSensorStateResponse::ESTIMATED_SIZE); TextSensorStateResponse::ESTIMATED_SIZE);
} }
uint16_t APIConnection::try_send_text_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_text_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *text_sensor = static_cast<text_sensor::TextSensor *>(entity); auto *text_sensor = static_cast<text_sensor::TextSensor *>(entity);
TextSensorStateResponse resp; TextSensorStateResponse resp;
resp.state = StringRef(text_sensor->state); resp.state = StringRef(text_sensor->state);
resp.missing_state = !text_sensor->has_state(); resp.missing_state = !text_sensor->has_state();
return fill_and_encode_entity_state(text_sensor, resp, TextSensorStateResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_state(text_sensor, resp, TextSensorStateResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
uint16_t APIConnection::try_send_text_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_text_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *text_sensor = static_cast<text_sensor::TextSensor *>(entity); auto *text_sensor = static_cast<text_sensor::TextSensor *>(entity);
ListEntitiesTextSensorResponse msg; ListEntitiesTextSensorResponse msg;
msg.device_class = text_sensor->get_device_class_ref(); msg.device_class = text_sensor->get_device_class_ref();
return fill_and_encode_entity_info(text_sensor, msg, ListEntitiesTextSensorResponse::MESSAGE_TYPE, conn, return fill_and_encode_entity_info(text_sensor, msg, ListEntitiesTextSensorResponse::MESSAGE_TYPE, conn,
remaining_size, is_single); remaining_size);
} }
#endif #endif
@@ -654,8 +631,7 @@ uint16_t APIConnection::try_send_text_sensor_info(EntityBase *entity, APIConnect
bool APIConnection::send_climate_state(climate::Climate *climate) { bool APIConnection::send_climate_state(climate::Climate *climate) {
return this->send_message_smart_(climate, ClimateStateResponse::MESSAGE_TYPE, ClimateStateResponse::ESTIMATED_SIZE); return this->send_message_smart_(climate, ClimateStateResponse::MESSAGE_TYPE, ClimateStateResponse::ESTIMATED_SIZE);
} }
uint16_t APIConnection::try_send_climate_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_climate_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *climate = static_cast<climate::Climate *>(entity); auto *climate = static_cast<climate::Climate *>(entity);
ClimateStateResponse resp; ClimateStateResponse resp;
auto traits = climate->get_traits(); auto traits = climate->get_traits();
@@ -687,11 +663,9 @@ uint16_t APIConnection::try_send_climate_state(EntityBase *entity, APIConnection
resp.current_humidity = climate->current_humidity; resp.current_humidity = climate->current_humidity;
if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TARGET_HUMIDITY)) if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TARGET_HUMIDITY))
resp.target_humidity = climate->target_humidity; resp.target_humidity = climate->target_humidity;
return fill_and_encode_entity_state(climate, resp, ClimateStateResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_state(climate, resp, ClimateStateResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
uint16_t APIConnection::try_send_climate_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_climate_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *climate = static_cast<climate::Climate *>(entity); auto *climate = static_cast<climate::Climate *>(entity);
ListEntitiesClimateResponse msg; ListEntitiesClimateResponse msg;
auto traits = climate->get_traits(); auto traits = climate->get_traits();
@@ -716,8 +690,7 @@ uint16_t APIConnection::try_send_climate_info(EntityBase *entity, APIConnection
msg.supported_presets = &traits.get_supported_presets(); msg.supported_presets = &traits.get_supported_presets();
msg.supported_custom_presets = &traits.get_supported_custom_presets(); msg.supported_custom_presets = &traits.get_supported_custom_presets();
msg.supported_swing_modes = &traits.get_supported_swing_modes(); msg.supported_swing_modes = &traits.get_supported_swing_modes();
return fill_and_encode_entity_info(climate, msg, ListEntitiesClimateResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_info(climate, msg, ListEntitiesClimateResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
void APIConnection::climate_command(const ClimateCommandRequest &msg) { void APIConnection::climate_command(const ClimateCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(climate::Climate, climate, climate) ENTITY_COMMAND_MAKE_CALL(climate::Climate, climate, climate)
@@ -750,17 +723,15 @@ bool APIConnection::send_number_state(number::Number *number) {
return this->send_message_smart_(number, NumberStateResponse::MESSAGE_TYPE, NumberStateResponse::ESTIMATED_SIZE); return this->send_message_smart_(number, NumberStateResponse::MESSAGE_TYPE, NumberStateResponse::ESTIMATED_SIZE);
} }
uint16_t APIConnection::try_send_number_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_number_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *number = static_cast<number::Number *>(entity); auto *number = static_cast<number::Number *>(entity);
NumberStateResponse resp; NumberStateResponse resp;
resp.state = number->state; resp.state = number->state;
resp.missing_state = !number->has_state(); resp.missing_state = !number->has_state();
return fill_and_encode_entity_state(number, resp, NumberStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); return fill_and_encode_entity_state(number, resp, NumberStateResponse::MESSAGE_TYPE, conn, remaining_size);
} }
uint16_t APIConnection::try_send_number_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_number_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *number = static_cast<number::Number *>(entity); auto *number = static_cast<number::Number *>(entity);
ListEntitiesNumberResponse msg; ListEntitiesNumberResponse msg;
msg.unit_of_measurement = number->traits.get_unit_of_measurement_ref(); msg.unit_of_measurement = number->traits.get_unit_of_measurement_ref();
@@ -769,8 +740,7 @@ uint16_t APIConnection::try_send_number_info(EntityBase *entity, APIConnection *
msg.min_value = number->traits.get_min_value(); msg.min_value = number->traits.get_min_value();
msg.max_value = number->traits.get_max_value(); msg.max_value = number->traits.get_max_value();
msg.step = number->traits.get_step(); msg.step = number->traits.get_step();
return fill_and_encode_entity_info(number, msg, ListEntitiesNumberResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_info(number, msg, ListEntitiesNumberResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
void APIConnection::number_command(const NumberCommandRequest &msg) { void APIConnection::number_command(const NumberCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(number::Number, number, number) ENTITY_COMMAND_MAKE_CALL(number::Number, number, number)
@@ -783,22 +753,19 @@ void APIConnection::number_command(const NumberCommandRequest &msg) {
bool APIConnection::send_date_state(datetime::DateEntity *date) { bool APIConnection::send_date_state(datetime::DateEntity *date) {
return this->send_message_smart_(date, DateStateResponse::MESSAGE_TYPE, DateStateResponse::ESTIMATED_SIZE); return this->send_message_smart_(date, DateStateResponse::MESSAGE_TYPE, DateStateResponse::ESTIMATED_SIZE);
} }
uint16_t APIConnection::try_send_date_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_date_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *date = static_cast<datetime::DateEntity *>(entity); auto *date = static_cast<datetime::DateEntity *>(entity);
DateStateResponse resp; DateStateResponse resp;
resp.missing_state = !date->has_state(); resp.missing_state = !date->has_state();
resp.year = date->year; resp.year = date->year;
resp.month = date->month; resp.month = date->month;
resp.day = date->day; resp.day = date->day;
return fill_and_encode_entity_state(date, resp, DateStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); return fill_and_encode_entity_state(date, resp, DateStateResponse::MESSAGE_TYPE, conn, remaining_size);
} }
uint16_t APIConnection::try_send_date_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_date_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *date = static_cast<datetime::DateEntity *>(entity); auto *date = static_cast<datetime::DateEntity *>(entity);
ListEntitiesDateResponse msg; ListEntitiesDateResponse msg;
return fill_and_encode_entity_info(date, msg, ListEntitiesDateResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_info(date, msg, ListEntitiesDateResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
void APIConnection::date_command(const DateCommandRequest &msg) { void APIConnection::date_command(const DateCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(datetime::DateEntity, date, date) ENTITY_COMMAND_MAKE_CALL(datetime::DateEntity, date, date)
@@ -811,22 +778,19 @@ void APIConnection::date_command(const DateCommandRequest &msg) {
bool APIConnection::send_time_state(datetime::TimeEntity *time) { bool APIConnection::send_time_state(datetime::TimeEntity *time) {
return this->send_message_smart_(time, TimeStateResponse::MESSAGE_TYPE, TimeStateResponse::ESTIMATED_SIZE); return this->send_message_smart_(time, TimeStateResponse::MESSAGE_TYPE, TimeStateResponse::ESTIMATED_SIZE);
} }
uint16_t APIConnection::try_send_time_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_time_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *time = static_cast<datetime::TimeEntity *>(entity); auto *time = static_cast<datetime::TimeEntity *>(entity);
TimeStateResponse resp; TimeStateResponse resp;
resp.missing_state = !time->has_state(); resp.missing_state = !time->has_state();
resp.hour = time->hour; resp.hour = time->hour;
resp.minute = time->minute; resp.minute = time->minute;
resp.second = time->second; resp.second = time->second;
return fill_and_encode_entity_state(time, resp, TimeStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); return fill_and_encode_entity_state(time, resp, TimeStateResponse::MESSAGE_TYPE, conn, remaining_size);
} }
uint16_t APIConnection::try_send_time_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_time_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *time = static_cast<datetime::TimeEntity *>(entity); auto *time = static_cast<datetime::TimeEntity *>(entity);
ListEntitiesTimeResponse msg; ListEntitiesTimeResponse msg;
return fill_and_encode_entity_info(time, msg, ListEntitiesTimeResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_info(time, msg, ListEntitiesTimeResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
void APIConnection::time_command(const TimeCommandRequest &msg) { void APIConnection::time_command(const TimeCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(datetime::TimeEntity, time, time) ENTITY_COMMAND_MAKE_CALL(datetime::TimeEntity, time, time)
@@ -840,8 +804,7 @@ bool APIConnection::send_datetime_state(datetime::DateTimeEntity *datetime) {
return this->send_message_smart_(datetime, DateTimeStateResponse::MESSAGE_TYPE, return this->send_message_smart_(datetime, DateTimeStateResponse::MESSAGE_TYPE,
DateTimeStateResponse::ESTIMATED_SIZE); DateTimeStateResponse::ESTIMATED_SIZE);
} }
uint16_t APIConnection::try_send_datetime_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_datetime_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *datetime = static_cast<datetime::DateTimeEntity *>(entity); auto *datetime = static_cast<datetime::DateTimeEntity *>(entity);
DateTimeStateResponse resp; DateTimeStateResponse resp;
resp.missing_state = !datetime->has_state(); resp.missing_state = !datetime->has_state();
@@ -849,15 +812,12 @@ uint16_t APIConnection::try_send_datetime_state(EntityBase *entity, APIConnectio
ESPTime state = datetime->state_as_esptime(); ESPTime state = datetime->state_as_esptime();
resp.epoch_seconds = state.timestamp; resp.epoch_seconds = state.timestamp;
} }
return fill_and_encode_entity_state(datetime, resp, DateTimeStateResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_state(datetime, resp, DateTimeStateResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
uint16_t APIConnection::try_send_datetime_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_datetime_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *datetime = static_cast<datetime::DateTimeEntity *>(entity); auto *datetime = static_cast<datetime::DateTimeEntity *>(entity);
ListEntitiesDateTimeResponse msg; ListEntitiesDateTimeResponse msg;
return fill_and_encode_entity_info(datetime, msg, ListEntitiesDateTimeResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_info(datetime, msg, ListEntitiesDateTimeResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
void APIConnection::datetime_command(const DateTimeCommandRequest &msg) { void APIConnection::datetime_command(const DateTimeCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(datetime::DateTimeEntity, datetime, datetime) ENTITY_COMMAND_MAKE_CALL(datetime::DateTimeEntity, datetime, datetime)
@@ -871,25 +831,22 @@ bool APIConnection::send_text_state(text::Text *text) {
return this->send_message_smart_(text, TextStateResponse::MESSAGE_TYPE, TextStateResponse::ESTIMATED_SIZE); return this->send_message_smart_(text, TextStateResponse::MESSAGE_TYPE, TextStateResponse::ESTIMATED_SIZE);
} }
uint16_t APIConnection::try_send_text_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_text_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *text = static_cast<text::Text *>(entity); auto *text = static_cast<text::Text *>(entity);
TextStateResponse resp; TextStateResponse resp;
resp.state = StringRef(text->state); resp.state = StringRef(text->state);
resp.missing_state = !text->has_state(); resp.missing_state = !text->has_state();
return fill_and_encode_entity_state(text, resp, TextStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); return fill_and_encode_entity_state(text, resp, TextStateResponse::MESSAGE_TYPE, conn, remaining_size);
} }
uint16_t APIConnection::try_send_text_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_text_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *text = static_cast<text::Text *>(entity); auto *text = static_cast<text::Text *>(entity);
ListEntitiesTextResponse msg; ListEntitiesTextResponse msg;
msg.mode = static_cast<enums::TextMode>(text->traits.get_mode()); msg.mode = static_cast<enums::TextMode>(text->traits.get_mode());
msg.min_length = text->traits.get_min_length(); msg.min_length = text->traits.get_min_length();
msg.max_length = text->traits.get_max_length(); msg.max_length = text->traits.get_max_length();
msg.pattern = text->traits.get_pattern_ref(); msg.pattern = text->traits.get_pattern_ref();
return fill_and_encode_entity_info(text, msg, ListEntitiesTextResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_info(text, msg, ListEntitiesTextResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
void APIConnection::text_command(const TextCommandRequest &msg) { void APIConnection::text_command(const TextCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(text::Text, text, text) ENTITY_COMMAND_MAKE_CALL(text::Text, text, text)
@@ -903,22 +860,19 @@ bool APIConnection::send_select_state(select::Select *select) {
return this->send_message_smart_(select, SelectStateResponse::MESSAGE_TYPE, SelectStateResponse::ESTIMATED_SIZE); return this->send_message_smart_(select, SelectStateResponse::MESSAGE_TYPE, SelectStateResponse::ESTIMATED_SIZE);
} }
uint16_t APIConnection::try_send_select_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_select_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *select = static_cast<select::Select *>(entity); auto *select = static_cast<select::Select *>(entity);
SelectStateResponse resp; SelectStateResponse resp;
resp.state = select->current_option(); resp.state = select->current_option();
resp.missing_state = !select->has_state(); resp.missing_state = !select->has_state();
return fill_and_encode_entity_state(select, resp, SelectStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); return fill_and_encode_entity_state(select, resp, SelectStateResponse::MESSAGE_TYPE, conn, remaining_size);
} }
uint16_t APIConnection::try_send_select_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_select_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *select = static_cast<select::Select *>(entity); auto *select = static_cast<select::Select *>(entity);
ListEntitiesSelectResponse msg; ListEntitiesSelectResponse msg;
msg.options = &select->traits.get_options(); msg.options = &select->traits.get_options();
return fill_and_encode_entity_info(select, msg, ListEntitiesSelectResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_info(select, msg, ListEntitiesSelectResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
void APIConnection::select_command(const SelectCommandRequest &msg) { void APIConnection::select_command(const SelectCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(select::Select, select, select) ENTITY_COMMAND_MAKE_CALL(select::Select, select, select)
@@ -928,13 +882,11 @@ void APIConnection::select_command(const SelectCommandRequest &msg) {
#endif #endif
#ifdef USE_BUTTON #ifdef USE_BUTTON
uint16_t APIConnection::try_send_button_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_button_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *button = static_cast<button::Button *>(entity); auto *button = static_cast<button::Button *>(entity);
ListEntitiesButtonResponse msg; ListEntitiesButtonResponse msg;
msg.device_class = button->get_device_class_ref(); msg.device_class = button->get_device_class_ref();
return fill_and_encode_entity_info(button, msg, ListEntitiesButtonResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_info(button, msg, ListEntitiesButtonResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
void esphome::api::APIConnection::button_command(const ButtonCommandRequest &msg) { void esphome::api::APIConnection::button_command(const ButtonCommandRequest &msg) {
ENTITY_COMMAND_GET(button::Button, button, button) ENTITY_COMMAND_GET(button::Button, button, button)
@@ -947,23 +899,20 @@ bool APIConnection::send_lock_state(lock::Lock *a_lock) {
return this->send_message_smart_(a_lock, LockStateResponse::MESSAGE_TYPE, LockStateResponse::ESTIMATED_SIZE); return this->send_message_smart_(a_lock, LockStateResponse::MESSAGE_TYPE, LockStateResponse::ESTIMATED_SIZE);
} }
uint16_t APIConnection::try_send_lock_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_lock_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *a_lock = static_cast<lock::Lock *>(entity); auto *a_lock = static_cast<lock::Lock *>(entity);
LockStateResponse resp; LockStateResponse resp;
resp.state = static_cast<enums::LockState>(a_lock->state); resp.state = static_cast<enums::LockState>(a_lock->state);
return fill_and_encode_entity_state(a_lock, resp, LockStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); return fill_and_encode_entity_state(a_lock, resp, LockStateResponse::MESSAGE_TYPE, conn, remaining_size);
} }
uint16_t APIConnection::try_send_lock_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_lock_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *a_lock = static_cast<lock::Lock *>(entity); auto *a_lock = static_cast<lock::Lock *>(entity);
ListEntitiesLockResponse msg; ListEntitiesLockResponse msg;
msg.assumed_state = a_lock->traits.get_assumed_state(); msg.assumed_state = a_lock->traits.get_assumed_state();
msg.supports_open = a_lock->traits.get_supports_open(); msg.supports_open = a_lock->traits.get_supports_open();
msg.requires_code = a_lock->traits.get_requires_code(); msg.requires_code = a_lock->traits.get_requires_code();
return fill_and_encode_entity_info(a_lock, msg, ListEntitiesLockResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_info(a_lock, msg, ListEntitiesLockResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
void APIConnection::lock_command(const LockCommandRequest &msg) { void APIConnection::lock_command(const LockCommandRequest &msg) {
ENTITY_COMMAND_GET(lock::Lock, a_lock, lock) ENTITY_COMMAND_GET(lock::Lock, a_lock, lock)
@@ -986,16 +935,14 @@ void APIConnection::lock_command(const LockCommandRequest &msg) {
bool APIConnection::send_valve_state(valve::Valve *valve) { bool APIConnection::send_valve_state(valve::Valve *valve) {
return this->send_message_smart_(valve, ValveStateResponse::MESSAGE_TYPE, ValveStateResponse::ESTIMATED_SIZE); return this->send_message_smart_(valve, ValveStateResponse::MESSAGE_TYPE, ValveStateResponse::ESTIMATED_SIZE);
} }
uint16_t APIConnection::try_send_valve_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_valve_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *valve = static_cast<valve::Valve *>(entity); auto *valve = static_cast<valve::Valve *>(entity);
ValveStateResponse resp; ValveStateResponse resp;
resp.position = valve->position; resp.position = valve->position;
resp.current_operation = static_cast<enums::ValveOperation>(valve->current_operation); resp.current_operation = static_cast<enums::ValveOperation>(valve->current_operation);
return fill_and_encode_entity_state(valve, resp, ValveStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); return fill_and_encode_entity_state(valve, resp, ValveStateResponse::MESSAGE_TYPE, conn, remaining_size);
} }
uint16_t APIConnection::try_send_valve_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_valve_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *valve = static_cast<valve::Valve *>(entity); auto *valve = static_cast<valve::Valve *>(entity);
ListEntitiesValveResponse msg; ListEntitiesValveResponse msg;
auto traits = valve->get_traits(); auto traits = valve->get_traits();
@@ -1003,8 +950,7 @@ uint16_t APIConnection::try_send_valve_info(EntityBase *entity, APIConnection *c
msg.assumed_state = traits.get_is_assumed_state(); msg.assumed_state = traits.get_is_assumed_state();
msg.supports_position = traits.get_supports_position(); msg.supports_position = traits.get_supports_position();
msg.supports_stop = traits.get_supports_stop(); msg.supports_stop = traits.get_supports_stop();
return fill_and_encode_entity_info(valve, msg, ListEntitiesValveResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_info(valve, msg, ListEntitiesValveResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
void APIConnection::valve_command(const ValveCommandRequest &msg) { void APIConnection::valve_command(const ValveCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(valve::Valve, valve, valve) ENTITY_COMMAND_MAKE_CALL(valve::Valve, valve, valve)
@@ -1021,8 +967,7 @@ bool APIConnection::send_media_player_state(media_player::MediaPlayer *media_pla
return this->send_message_smart_(media_player, MediaPlayerStateResponse::MESSAGE_TYPE, return this->send_message_smart_(media_player, MediaPlayerStateResponse::MESSAGE_TYPE,
MediaPlayerStateResponse::ESTIMATED_SIZE); MediaPlayerStateResponse::ESTIMATED_SIZE);
} }
uint16_t APIConnection::try_send_media_player_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_media_player_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *media_player = static_cast<media_player::MediaPlayer *>(entity); auto *media_player = static_cast<media_player::MediaPlayer *>(entity);
MediaPlayerStateResponse resp; MediaPlayerStateResponse resp;
media_player::MediaPlayerState report_state = media_player->state == media_player::MEDIA_PLAYER_STATE_ANNOUNCING media_player::MediaPlayerState report_state = media_player->state == media_player::MEDIA_PLAYER_STATE_ANNOUNCING
@@ -1031,11 +976,9 @@ uint16_t APIConnection::try_send_media_player_state(EntityBase *entity, APIConne
resp.state = static_cast<enums::MediaPlayerState>(report_state); resp.state = static_cast<enums::MediaPlayerState>(report_state);
resp.volume = media_player->volume; resp.volume = media_player->volume;
resp.muted = media_player->is_muted(); resp.muted = media_player->is_muted();
return fill_and_encode_entity_state(media_player, resp, MediaPlayerStateResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_state(media_player, resp, MediaPlayerStateResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
uint16_t APIConnection::try_send_media_player_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_media_player_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *media_player = static_cast<media_player::MediaPlayer *>(entity); auto *media_player = static_cast<media_player::MediaPlayer *>(entity);
ListEntitiesMediaPlayerResponse msg; ListEntitiesMediaPlayerResponse msg;
auto traits = media_player->get_traits(); auto traits = media_player->get_traits();
@@ -1051,7 +994,7 @@ uint16_t APIConnection::try_send_media_player_info(EntityBase *entity, APIConnec
media_format.sample_bytes = supported_format.sample_bytes; media_format.sample_bytes = supported_format.sample_bytes;
} }
return fill_and_encode_entity_info(media_player, msg, ListEntitiesMediaPlayerResponse::MESSAGE_TYPE, conn, return fill_and_encode_entity_info(media_player, msg, ListEntitiesMediaPlayerResponse::MESSAGE_TYPE, conn,
remaining_size, is_single); remaining_size);
} }
void APIConnection::media_player_command(const MediaPlayerCommandRequest &msg) { void APIConnection::media_player_command(const MediaPlayerCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(media_player::MediaPlayer, media_player, media_player) ENTITY_COMMAND_MAKE_CALL(media_player::MediaPlayer, media_player, media_player)
@@ -1092,7 +1035,7 @@ void APIConnection::try_send_camera_image_() {
msg.device_id = camera::Camera::instance()->get_device_id(); msg.device_id = camera::Camera::instance()->get_device_id();
#endif #endif
if (!this->send_message_(msg, CameraImageResponse::MESSAGE_TYPE)) { if (!this->send_message_impl(msg, CameraImageResponse::MESSAGE_TYPE)) {
return; // Send failed, try again later return; // Send failed, try again later
} }
this->image_reader_->consume_data(to_send); this->image_reader_->consume_data(to_send);
@@ -1115,12 +1058,10 @@ void APIConnection::set_camera_state(std::shared_ptr<camera::CameraImage> image)
this->try_send_camera_image_(); this->try_send_camera_image_();
} }
} }
uint16_t APIConnection::try_send_camera_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_camera_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *camera = static_cast<camera::Camera *>(entity); auto *camera = static_cast<camera::Camera *>(entity);
ListEntitiesCameraResponse msg; ListEntitiesCameraResponse msg;
return fill_and_encode_entity_info(camera, msg, ListEntitiesCameraResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_info(camera, msg, ListEntitiesCameraResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
void APIConnection::camera_image(const CameraImageRequest &msg) { void APIConnection::camera_image(const CameraImageRequest &msg) {
if (camera::Camera::instance() == nullptr) if (camera::Camera::instance() == nullptr)
@@ -1305,22 +1246,22 @@ bool APIConnection::send_alarm_control_panel_state(alarm_control_panel::AlarmCon
AlarmControlPanelStateResponse::ESTIMATED_SIZE); AlarmControlPanelStateResponse::ESTIMATED_SIZE);
} }
uint16_t APIConnection::try_send_alarm_control_panel_state(EntityBase *entity, APIConnection *conn, uint16_t APIConnection::try_send_alarm_control_panel_state(EntityBase *entity, APIConnection *conn,
uint32_t remaining_size, bool is_single) { uint32_t remaining_size) {
auto *a_alarm_control_panel = static_cast<alarm_control_panel::AlarmControlPanel *>(entity); auto *a_alarm_control_panel = static_cast<alarm_control_panel::AlarmControlPanel *>(entity);
AlarmControlPanelStateResponse resp; AlarmControlPanelStateResponse resp;
resp.state = static_cast<enums::AlarmControlPanelState>(a_alarm_control_panel->get_state()); resp.state = static_cast<enums::AlarmControlPanelState>(a_alarm_control_panel->get_state());
return fill_and_encode_entity_state(a_alarm_control_panel, resp, AlarmControlPanelStateResponse::MESSAGE_TYPE, conn, return fill_and_encode_entity_state(a_alarm_control_panel, resp, AlarmControlPanelStateResponse::MESSAGE_TYPE, conn,
remaining_size, is_single); remaining_size);
} }
uint16_t APIConnection::try_send_alarm_control_panel_info(EntityBase *entity, APIConnection *conn, uint16_t APIConnection::try_send_alarm_control_panel_info(EntityBase *entity, APIConnection *conn,
uint32_t remaining_size, bool is_single) { uint32_t remaining_size) {
auto *a_alarm_control_panel = static_cast<alarm_control_panel::AlarmControlPanel *>(entity); auto *a_alarm_control_panel = static_cast<alarm_control_panel::AlarmControlPanel *>(entity);
ListEntitiesAlarmControlPanelResponse msg; ListEntitiesAlarmControlPanelResponse msg;
msg.supported_features = a_alarm_control_panel->get_supported_features(); msg.supported_features = a_alarm_control_panel->get_supported_features();
msg.requires_code = a_alarm_control_panel->get_requires_code(); msg.requires_code = a_alarm_control_panel->get_requires_code();
msg.requires_code_to_arm = a_alarm_control_panel->get_requires_code_to_arm(); msg.requires_code_to_arm = a_alarm_control_panel->get_requires_code_to_arm();
return fill_and_encode_entity_info(a_alarm_control_panel, msg, ListEntitiesAlarmControlPanelResponse::MESSAGE_TYPE, return fill_and_encode_entity_info(a_alarm_control_panel, msg, ListEntitiesAlarmControlPanelResponse::MESSAGE_TYPE,
conn, remaining_size, is_single); conn, remaining_size);
} }
void APIConnection::alarm_control_panel_command(const AlarmControlPanelCommandRequest &msg) { void APIConnection::alarm_control_panel_command(const AlarmControlPanelCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(alarm_control_panel::AlarmControlPanel, a_alarm_control_panel, alarm_control_panel) ENTITY_COMMAND_MAKE_CALL(alarm_control_panel::AlarmControlPanel, a_alarm_control_panel, alarm_control_panel)
@@ -1357,8 +1298,7 @@ bool APIConnection::send_water_heater_state(water_heater::WaterHeater *water_hea
return this->send_message_smart_(water_heater, WaterHeaterStateResponse::MESSAGE_TYPE, return this->send_message_smart_(water_heater, WaterHeaterStateResponse::MESSAGE_TYPE,
WaterHeaterStateResponse::ESTIMATED_SIZE); WaterHeaterStateResponse::ESTIMATED_SIZE);
} }
uint16_t APIConnection::try_send_water_heater_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_water_heater_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *wh = static_cast<water_heater::WaterHeater *>(entity); auto *wh = static_cast<water_heater::WaterHeater *>(entity);
WaterHeaterStateResponse resp; WaterHeaterStateResponse resp;
resp.mode = static_cast<enums::WaterHeaterMode>(wh->get_mode()); resp.mode = static_cast<enums::WaterHeaterMode>(wh->get_mode());
@@ -1369,10 +1309,9 @@ uint16_t APIConnection::try_send_water_heater_state(EntityBase *entity, APIConne
resp.state = wh->get_state(); resp.state = wh->get_state();
resp.key = wh->get_object_id_hash(); resp.key = wh->get_object_id_hash();
return encode_message_to_buffer(resp, WaterHeaterStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); return encode_message_to_buffer(resp, WaterHeaterStateResponse::MESSAGE_TYPE, conn, remaining_size);
} }
uint16_t APIConnection::try_send_water_heater_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_water_heater_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *wh = static_cast<water_heater::WaterHeater *>(entity); auto *wh = static_cast<water_heater::WaterHeater *>(entity);
ListEntitiesWaterHeaterResponse msg; ListEntitiesWaterHeaterResponse msg;
auto traits = wh->get_traits(); auto traits = wh->get_traits();
@@ -1381,8 +1320,7 @@ uint16_t APIConnection::try_send_water_heater_info(EntityBase *entity, APIConnec
msg.target_temperature_step = traits.get_target_temperature_step(); msg.target_temperature_step = traits.get_target_temperature_step();
msg.supported_modes = &traits.get_supported_modes(); msg.supported_modes = &traits.get_supported_modes();
msg.supported_features = traits.get_feature_flags(); msg.supported_features = traits.get_feature_flags();
return fill_and_encode_entity_info(wh, msg, ListEntitiesWaterHeaterResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_info(wh, msg, ListEntitiesWaterHeaterResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
void APIConnection::water_heater_command(const WaterHeaterCommandRequest &msg) { void APIConnection::water_heater_command(const WaterHeaterCommandRequest &msg) {
@@ -1411,20 +1349,18 @@ void APIConnection::send_event(event::Event *event) {
event->get_last_event_type_index()); event->get_last_event_type_index());
} }
uint16_t APIConnection::try_send_event_response(event::Event *event, StringRef event_type, APIConnection *conn, uint16_t APIConnection::try_send_event_response(event::Event *event, StringRef event_type, APIConnection *conn,
uint32_t remaining_size, bool is_single) { uint32_t remaining_size) {
EventResponse resp; EventResponse resp;
resp.event_type = event_type; resp.event_type = event_type;
return fill_and_encode_entity_state(event, resp, EventResponse::MESSAGE_TYPE, conn, remaining_size, is_single); return fill_and_encode_entity_state(event, resp, EventResponse::MESSAGE_TYPE, conn, remaining_size);
} }
uint16_t APIConnection::try_send_event_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_event_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *event = static_cast<event::Event *>(entity); auto *event = static_cast<event::Event *>(entity);
ListEntitiesEventResponse msg; ListEntitiesEventResponse msg;
msg.device_class = event->get_device_class_ref(); msg.device_class = event->get_device_class_ref();
msg.event_types = &event->get_event_types(); msg.event_types = &event->get_event_types();
return fill_and_encode_entity_info(event, msg, ListEntitiesEventResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_info(event, msg, ListEntitiesEventResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
#endif #endif
@@ -1447,13 +1383,11 @@ void APIConnection::send_infrared_rf_receive_event(const InfraredRFReceiveEvent
#endif #endif
#ifdef USE_INFRARED #ifdef USE_INFRARED
uint16_t APIConnection::try_send_infrared_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_infrared_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *infrared = static_cast<infrared::Infrared *>(entity); auto *infrared = static_cast<infrared::Infrared *>(entity);
ListEntitiesInfraredResponse msg; ListEntitiesInfraredResponse msg;
msg.capabilities = infrared->get_capability_flags(); msg.capabilities = infrared->get_capability_flags();
return fill_and_encode_entity_info(infrared, msg, ListEntitiesInfraredResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_info(infrared, msg, ListEntitiesInfraredResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
#endif #endif
@@ -1461,8 +1395,7 @@ uint16_t APIConnection::try_send_infrared_info(EntityBase *entity, APIConnection
bool APIConnection::send_update_state(update::UpdateEntity *update) { bool APIConnection::send_update_state(update::UpdateEntity *update) {
return this->send_message_smart_(update, UpdateStateResponse::MESSAGE_TYPE, UpdateStateResponse::ESTIMATED_SIZE); return this->send_message_smart_(update, UpdateStateResponse::MESSAGE_TYPE, UpdateStateResponse::ESTIMATED_SIZE);
} }
uint16_t APIConnection::try_send_update_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_update_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *update = static_cast<update::UpdateEntity *>(entity); auto *update = static_cast<update::UpdateEntity *>(entity);
UpdateStateResponse resp; UpdateStateResponse resp;
resp.missing_state = !update->has_state(); resp.missing_state = !update->has_state();
@@ -1478,15 +1411,13 @@ uint16_t APIConnection::try_send_update_state(EntityBase *entity, APIConnection
resp.release_summary = StringRef(update->update_info.summary); resp.release_summary = StringRef(update->update_info.summary);
resp.release_url = StringRef(update->update_info.release_url); resp.release_url = StringRef(update->update_info.release_url);
} }
return fill_and_encode_entity_state(update, resp, UpdateStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); return fill_and_encode_entity_state(update, resp, UpdateStateResponse::MESSAGE_TYPE, conn, remaining_size);
} }
uint16_t APIConnection::try_send_update_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_update_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
auto *update = static_cast<update::UpdateEntity *>(entity); auto *update = static_cast<update::UpdateEntity *>(entity);
ListEntitiesUpdateResponse msg; ListEntitiesUpdateResponse msg;
msg.device_class = update->get_device_class_ref(); msg.device_class = update->get_device_class_ref();
return fill_and_encode_entity_info(update, msg, ListEntitiesUpdateResponse::MESSAGE_TYPE, conn, remaining_size, return fill_and_encode_entity_info(update, msg, ListEntitiesUpdateResponse::MESSAGE_TYPE, conn, remaining_size);
is_single);
} }
void APIConnection::update_command(const UpdateCommandRequest &msg) { void APIConnection::update_command(const UpdateCommandRequest &msg) {
ENTITY_COMMAND_GET(update::UpdateEntity, update, update) ENTITY_COMMAND_GET(update::UpdateEntity, update, update)
@@ -1512,7 +1443,7 @@ bool APIConnection::try_send_log_message(int level, const char *tag, const char
SubscribeLogsResponse msg; SubscribeLogsResponse msg;
msg.level = static_cast<enums::LogLevel>(level); msg.level = static_cast<enums::LogLevel>(level);
msg.set_message(reinterpret_cast<const uint8_t *>(line), message_len); msg.set_message(reinterpret_cast<const uint8_t *>(line), message_len);
return this->send_message_(msg, SubscribeLogsResponse::MESSAGE_TYPE); return this->send_message_impl(msg, SubscribeLogsResponse::MESSAGE_TYPE);
} }
void APIConnection::complete_authentication_() { void APIConnection::complete_authentication_() {
@@ -1837,6 +1768,14 @@ bool APIConnection::try_to_clear_buffer(bool log_out_of_space) {
} }
return false; return false;
} }
bool APIConnection::send_message_impl(const ProtoMessage &msg, uint8_t message_type) {
ProtoSize size;
msg.calculate_size(size);
std::vector<uint8_t> &shared_buf = this->parent_->get_shared_buffer_ref();
this->prepare_first_message_buffer(shared_buf, size.get_size());
msg.encode({&shared_buf});
return this->send_buffer({&shared_buf}, message_type);
}
bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) { bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) {
const bool is_log_message = (message_type == SubscribeLogsResponse::MESSAGE_TYPE); const bool is_log_message = (message_type == SubscribeLogsResponse::MESSAGE_TYPE);
@@ -1897,6 +1836,23 @@ void APIConnection::DeferredBatch::add_item_front(EntityBase *entity, uint8_t me
} }
} }
bool APIConnection::send_message_smart_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size,
uint8_t aux_data_index) {
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{&shared_buf}, message_type)) {
#ifdef HAS_PROTO_MESSAGE_DUMP
this->log_batch_item_(item);
#endif
return true;
}
}
return this->schedule_message_(entity, message_type, estimated_size, aux_data_index);
}
bool APIConnection::schedule_batch_() { bool APIConnection::schedule_batch_() {
if (!this->flags_.batch_scheduled) { if (!this->flags_.batch_scheduled) {
this->flags_.batch_scheduled = true; this->flags_.batch_scheduled = true;
@@ -1925,10 +1881,21 @@ void APIConnection::process_batch_() {
auto &shared_buf = this->parent_->get_shared_buffer_ref(); auto &shared_buf = this->parent_->get_shared_buffer_ref();
size_t num_items = this->deferred_batch_.size(); size_t num_items = this->deferred_batch_.size();
// Fast path for single message - allocate exact size needed // Cache these values to avoid repeated virtual calls
const uint8_t header_padding = this->helper_->frame_header_padding();
const uint8_t footer_size = this->helper_->frame_footer_size();
// Pre-calculate exact buffer size needed based on message types
uint32_t total_estimated_size = num_items * (header_padding + footer_size);
for (size_t i = 0; i < num_items; i++) {
total_estimated_size += this->deferred_batch_[i].estimated_size;
}
this->prepare_first_message_buffer(shared_buf, header_padding, total_estimated_size);
// Fast path for single message - buffer already allocated above
if (num_items == 1) { if (num_items == 1) {
const auto &item = this->deferred_batch_[0]; const auto &item = this->deferred_batch_[0];
// Let dispatch_message_ calculate size and encode if it fits // Let dispatch_message_ calculate size and encode if it fits
uint16_t payload_size = this->dispatch_message_(item, std::numeric_limits<uint16_t>::max(), true); uint16_t payload_size = this->dispatch_message_(item, std::numeric_limits<uint16_t>::max(), true);
@@ -1951,30 +1918,8 @@ void APIConnection::process_batch_() {
// Stack-allocated array for message info // Stack-allocated array for message info
alignas(MessageInfo) char message_info_storage[MAX_MESSAGES_PER_BATCH * sizeof(MessageInfo)]; alignas(MessageInfo) char message_info_storage[MAX_MESSAGES_PER_BATCH * sizeof(MessageInfo)];
MessageInfo *message_info = reinterpret_cast<MessageInfo *>(message_info_storage); MessageInfo *message_info = reinterpret_cast<MessageInfo *>(message_info_storage);
size_t message_count = 0;
// Cache these values to avoid repeated virtual calls
const uint8_t header_padding = this->helper_->frame_header_padding();
const uint8_t footer_size = this->helper_->frame_footer_size();
// Initialize buffer and tracking variables
shared_buf.clear();
// Pre-calculate exact buffer size needed based on message types
uint32_t total_estimated_size = num_items * (header_padding + footer_size);
for (size_t i = 0; i < this->deferred_batch_.size(); i++) {
const auto &item = this->deferred_batch_[i];
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)
shared_buf.reserve(total_estimated_size);
this->flags_.batch_first_message = true;
size_t items_processed = 0; size_t items_processed = 0;
uint16_t remaining_size = std::numeric_limits<uint16_t>::max(); uint16_t remaining_size = std::numeric_limits<uint16_t>::max();
// Track where each message's header padding begins in the buffer // Track where each message's header padding begins in the buffer
// For plaintext: this is where the 6-byte header padding starts // For plaintext: this is where the 6-byte header padding starts
// For noise: this is where the 7-byte header padding starts // For noise: this is where the 7-byte header padding starts
@@ -1986,7 +1931,7 @@ void APIConnection::process_batch_() {
const auto &item = this->deferred_batch_[i]; const auto &item = this->deferred_batch_[i];
// Try to encode message via dispatch // Try to encode message via dispatch
// The dispatch function calculates overhead to determine if the message fits // The dispatch function calculates overhead to determine if the message fits
uint16_t payload_size = this->dispatch_message_(item, remaining_size, false); uint16_t payload_size = this->dispatch_message_(item, remaining_size, i == 0);
if (payload_size == 0) { if (payload_size == 0) {
// Message won't fit, stop processing // Message won't fit, stop processing
@@ -2000,10 +1945,7 @@ void APIConnection::process_batch_() {
// This avoids default-constructing all MAX_MESSAGES_PER_BATCH elements // This avoids default-constructing all MAX_MESSAGES_PER_BATCH elements
// Explicit destruction is not needed because MessageInfo is trivially destructible, // Explicit destruction is not needed because MessageInfo is trivially destructible,
// as ensured by the static_assert in its definition. // as ensured by the static_assert in its definition.
new (&message_info[message_count++]) MessageInfo(item.message_type, current_offset, proto_payload_size); new (&message_info[items_processed++]) MessageInfo(item.message_type, current_offset, proto_payload_size);
// Update tracking variables
items_processed++;
// After first message, set remaining size to MAX_BATCH_PACKET_SIZE to avoid fragmentation // After first message, set remaining size to MAX_BATCH_PACKET_SIZE to avoid fragmentation
if (items_processed == 1) { if (items_processed == 1) {
remaining_size = MAX_BATCH_PACKET_SIZE; remaining_size = MAX_BATCH_PACKET_SIZE;
@@ -2026,7 +1968,7 @@ void APIConnection::process_batch_() {
// Send all collected messages // Send all collected messages
APIError err = this->helper_->write_protobuf_messages(ProtoWriteBuffer{&shared_buf}, APIError err = this->helper_->write_protobuf_messages(ProtoWriteBuffer{&shared_buf},
std::span<const MessageInfo>(message_info, message_count)); std::span<const MessageInfo>(message_info, items_processed));
if (err != APIError::OK && err != APIError::WOULD_BLOCK) { if (err != APIError::OK && err != APIError::WOULD_BLOCK) {
this->fatal_error_with_log_(LOG_STR("Batch write failed"), err); this->fatal_error_with_log_(LOG_STR("Batch write failed"), err);
} }
@@ -2055,7 +1997,8 @@ void APIConnection::process_batch_() {
// Dispatch message encoding based on message_type // Dispatch message encoding based on message_type
// Switch assigns function pointer, single call site for smaller code size // Switch assigns function pointer, single call site for smaller code size
uint16_t APIConnection::dispatch_message_(const DeferredBatch::BatchItem &item, uint32_t remaining_size, uint16_t APIConnection::dispatch_message_(const DeferredBatch::BatchItem &item, uint32_t remaining_size,
bool is_single) { bool batch_first) {
this->flags_.batch_first_message = batch_first;
#ifdef USE_EVENT #ifdef USE_EVENT
// Events need aux_data_index to look up event type from entity // Events need aux_data_index to look up event type from entity
if (item.message_type == EventResponse::MESSAGE_TYPE) { if (item.message_type == EventResponse::MESSAGE_TYPE) {
@@ -2064,7 +2007,7 @@ uint16_t APIConnection::dispatch_message_(const DeferredBatch::BatchItem &item,
return 0; return 0;
auto *event = static_cast<event::Event *>(item.entity); auto *event = static_cast<event::Event *>(item.entity);
return try_send_event_response(event, StringRef::from_maybe_nullptr(event->get_event_type(item.aux_data_index)), return try_send_event_response(event, StringRef::from_maybe_nullptr(event->get_event_type(item.aux_data_index)),
this, remaining_size, is_single); this, remaining_size);
} }
#endif #endif
@@ -2174,25 +2117,22 @@ uint16_t APIConnection::dispatch_message_(const DeferredBatch::BatchItem &item,
#undef CASE_STATE_INFO #undef CASE_STATE_INFO
#undef CASE_INFO_ONLY #undef CASE_INFO_ONLY
return func(item.entity, this, remaining_size, is_single); return func(item.entity, this, remaining_size);
} }
uint16_t APIConnection::try_send_list_info_done(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_list_info_done(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
ListEntitiesDoneResponse resp; ListEntitiesDoneResponse resp;
return encode_message_to_buffer(resp, ListEntitiesDoneResponse::MESSAGE_TYPE, conn, remaining_size, is_single); return encode_message_to_buffer(resp, ListEntitiesDoneResponse::MESSAGE_TYPE, conn, remaining_size);
} }
uint16_t APIConnection::try_send_disconnect_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_disconnect_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
DisconnectRequest req; DisconnectRequest req;
return encode_message_to_buffer(req, DisconnectRequest::MESSAGE_TYPE, conn, remaining_size, is_single); return encode_message_to_buffer(req, DisconnectRequest::MESSAGE_TYPE, conn, remaining_size);
} }
uint16_t APIConnection::try_send_ping_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, uint16_t APIConnection::try_send_ping_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
bool is_single) {
PingRequest req; PingRequest req;
return encode_message_to_buffer(req, PingRequest::MESSAGE_TYPE, conn, remaining_size, is_single); return encode_message_to_buffer(req, PingRequest::MESSAGE_TYPE, conn, remaining_size);
} }
#ifdef USE_API_HOMEASSISTANT_STATES #ifdef USE_API_HOMEASSISTANT_STATES

View File

@@ -255,17 +255,7 @@ class APIConnection final : public APIServerConnection {
void on_fatal_error() override; void on_fatal_error() override;
void on_no_setup_connection() override; void on_no_setup_connection() override;
ProtoWriteBuffer create_buffer(uint32_t reserve_size) override { bool send_message_impl(const ProtoMessage &msg, uint8_t message_type) override;
// FIXME: ensure no recursive writes can happen
// Get header padding size - used for both reserve and insert
uint8_t header_padding = this->helper_->frame_header_padding();
// Get shared buffer from parent server
std::vector<uint8_t> &shared_buf = this->parent_->get_shared_buffer_ref();
this->prepare_first_message_buffer(shared_buf, header_padding,
reserve_size + header_padding + this->helper_->frame_footer_size());
return {&shared_buf};
}
void prepare_first_message_buffer(std::vector<uint8_t> &shared_buf, size_t header_padding, size_t total_size) { void prepare_first_message_buffer(std::vector<uint8_t> &shared_buf, size_t header_padding, size_t total_size) {
shared_buf.clear(); shared_buf.clear();
@@ -277,6 +267,13 @@ class APIConnection final : public APIServerConnection {
shared_buf.resize(header_padding); shared_buf.resize(header_padding);
} }
// Convenience overload - computes frame overhead internally
void prepare_first_message_buffer(std::vector<uint8_t> &shared_buf, size_t payload_size) {
const uint8_t header_padding = this->helper_->frame_header_padding();
const uint8_t footer_size = this->helper_->frame_footer_size();
this->prepare_first_message_buffer(shared_buf, header_padding, payload_size + header_padding + footer_size);
}
bool try_to_clear_buffer(bool log_out_of_space); bool try_to_clear_buffer(bool log_out_of_space);
bool send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) override; bool send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) override;
@@ -298,21 +295,21 @@ class APIConnection final : public APIServerConnection {
// Non-template helper to encode any ProtoMessage // Non-template helper to encode any ProtoMessage
static uint16_t encode_message_to_buffer(ProtoMessage &msg, uint8_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); uint32_t remaining_size);
// Helper to fill entity state base and encode message // Helper to fill entity state base and encode message
static uint16_t fill_and_encode_entity_state(EntityBase *entity, StateResponseProtoMessage &msg, uint8_t message_type, static uint16_t fill_and_encode_entity_state(EntityBase *entity, StateResponseProtoMessage &msg, uint8_t message_type,
APIConnection *conn, uint32_t remaining_size, bool is_single) { APIConnection *conn, uint32_t remaining_size) {
msg.key = entity->get_object_id_hash(); msg.key = entity->get_object_id_hash();
#ifdef USE_DEVICES #ifdef USE_DEVICES
msg.device_id = entity->get_device_id(); msg.device_id = entity->get_device_id();
#endif #endif
return encode_message_to_buffer(msg, message_type, conn, remaining_size, is_single); return encode_message_to_buffer(msg, message_type, conn, remaining_size);
} }
// Helper to fill entity info base and encode message // Helper to fill entity info base and encode message
static uint16_t fill_and_encode_entity_info(EntityBase *entity, InfoResponseProtoMessage &msg, uint8_t message_type, static uint16_t fill_and_encode_entity_info(EntityBase *entity, InfoResponseProtoMessage &msg, uint8_t message_type,
APIConnection *conn, uint32_t remaining_size, bool is_single) { APIConnection *conn, uint32_t remaining_size) {
// Set common fields that are shared by all entity types // Set common fields that are shared by all entity types
msg.key = entity->get_object_id_hash(); msg.key = entity->get_object_id_hash();
@@ -339,7 +336,7 @@ class APIConnection final : public APIServerConnection {
#ifdef USE_DEVICES #ifdef USE_DEVICES
msg.device_id = entity->get_device_id(); msg.device_id = entity->get_device_id();
#endif #endif
return encode_message_to_buffer(msg, message_type, conn, remaining_size, is_single); return encode_message_to_buffer(msg, message_type, conn, remaining_size);
} }
#ifdef USE_VOICE_ASSISTANT #ifdef USE_VOICE_ASSISTANT
@@ -370,141 +367,108 @@ class APIConnection final : public APIServerConnection {
} }
#ifdef USE_BINARY_SENSOR #ifdef USE_BINARY_SENSOR
static uint16_t try_send_binary_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, static uint16_t try_send_binary_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
bool is_single); static uint16_t try_send_binary_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
static uint16_t try_send_binary_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single);
#endif #endif
#ifdef USE_COVER #ifdef USE_COVER
static uint16_t try_send_cover_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, static uint16_t try_send_cover_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
bool is_single); static uint16_t try_send_cover_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
static uint16_t try_send_cover_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single);
#endif #endif
#ifdef USE_FAN #ifdef USE_FAN
static uint16_t try_send_fan_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); static uint16_t try_send_fan_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
static uint16_t try_send_fan_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); static uint16_t try_send_fan_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
#endif #endif
#ifdef USE_LIGHT #ifdef USE_LIGHT
static uint16_t try_send_light_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, static uint16_t try_send_light_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
bool is_single); static uint16_t try_send_light_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
static uint16_t try_send_light_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single);
#endif #endif
#ifdef USE_SENSOR #ifdef USE_SENSOR
static uint16_t try_send_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, static uint16_t try_send_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
bool is_single); static uint16_t try_send_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
static uint16_t try_send_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single);
#endif #endif
#ifdef USE_SWITCH #ifdef USE_SWITCH
static uint16_t try_send_switch_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, static uint16_t try_send_switch_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
bool is_single); static uint16_t try_send_switch_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
static uint16_t try_send_switch_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single);
#endif #endif
#ifdef USE_TEXT_SENSOR #ifdef USE_TEXT_SENSOR
static uint16_t try_send_text_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, static uint16_t try_send_text_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
bool is_single); static uint16_t try_send_text_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
static uint16_t try_send_text_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single);
#endif #endif
#ifdef USE_CLIMATE #ifdef USE_CLIMATE
static uint16_t try_send_climate_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, static uint16_t try_send_climate_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
bool is_single); static uint16_t try_send_climate_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
static uint16_t try_send_climate_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single);
#endif #endif
#ifdef USE_NUMBER #ifdef USE_NUMBER
static uint16_t try_send_number_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, static uint16_t try_send_number_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
bool is_single); static uint16_t try_send_number_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
static uint16_t try_send_number_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single);
#endif #endif
#ifdef USE_DATETIME_DATE #ifdef USE_DATETIME_DATE
static uint16_t try_send_date_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); static uint16_t try_send_date_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
static uint16_t try_send_date_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); static uint16_t try_send_date_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
#endif #endif
#ifdef USE_DATETIME_TIME #ifdef USE_DATETIME_TIME
static uint16_t try_send_time_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); static uint16_t try_send_time_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
static uint16_t try_send_time_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); static uint16_t try_send_time_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
#endif #endif
#ifdef USE_DATETIME_DATETIME #ifdef USE_DATETIME_DATETIME
static uint16_t try_send_datetime_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, static uint16_t try_send_datetime_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
bool is_single); static uint16_t try_send_datetime_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
static uint16_t try_send_datetime_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single);
#endif #endif
#ifdef USE_TEXT #ifdef USE_TEXT
static uint16_t try_send_text_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); static uint16_t try_send_text_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
static uint16_t try_send_text_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); static uint16_t try_send_text_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
#endif #endif
#ifdef USE_SELECT #ifdef USE_SELECT
static uint16_t try_send_select_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, static uint16_t try_send_select_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
bool is_single); static uint16_t try_send_select_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
static uint16_t try_send_select_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single);
#endif #endif
#ifdef USE_BUTTON #ifdef USE_BUTTON
static uint16_t try_send_button_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, static uint16_t try_send_button_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
bool is_single);
#endif #endif
#ifdef USE_LOCK #ifdef USE_LOCK
static uint16_t try_send_lock_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); static uint16_t try_send_lock_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
static uint16_t try_send_lock_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); static uint16_t try_send_lock_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
#endif #endif
#ifdef USE_VALVE #ifdef USE_VALVE
static uint16_t try_send_valve_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, static uint16_t try_send_valve_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
bool is_single); static uint16_t try_send_valve_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
static uint16_t try_send_valve_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single);
#endif #endif
#ifdef USE_MEDIA_PLAYER #ifdef USE_MEDIA_PLAYER
static uint16_t try_send_media_player_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, static uint16_t try_send_media_player_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
bool is_single); static uint16_t try_send_media_player_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
static uint16_t try_send_media_player_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single);
#endif #endif
#ifdef USE_ALARM_CONTROL_PANEL #ifdef USE_ALARM_CONTROL_PANEL
static uint16_t try_send_alarm_control_panel_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, static uint16_t try_send_alarm_control_panel_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
bool is_single); static uint16_t try_send_alarm_control_panel_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
static uint16_t try_send_alarm_control_panel_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single);
#endif #endif
#ifdef USE_WATER_HEATER #ifdef USE_WATER_HEATER
static uint16_t try_send_water_heater_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, static uint16_t try_send_water_heater_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
bool is_single); static uint16_t try_send_water_heater_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
static uint16_t try_send_water_heater_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single);
#endif #endif
#ifdef USE_INFRARED #ifdef USE_INFRARED
static uint16_t try_send_infrared_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, static uint16_t try_send_infrared_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
bool is_single);
#endif #endif
#ifdef USE_EVENT #ifdef USE_EVENT
static uint16_t try_send_event_response(event::Event *event, StringRef event_type, APIConnection *conn, static uint16_t try_send_event_response(event::Event *event, StringRef event_type, APIConnection *conn,
uint32_t remaining_size, bool is_single); uint32_t remaining_size);
static uint16_t try_send_event_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); static uint16_t try_send_event_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
#endif #endif
#ifdef USE_UPDATE #ifdef USE_UPDATE
static uint16_t try_send_update_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, static uint16_t try_send_update_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
bool is_single); static uint16_t try_send_update_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
static uint16_t try_send_update_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single);
#endif #endif
#ifdef USE_CAMERA #ifdef USE_CAMERA
static uint16_t try_send_camera_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, static uint16_t try_send_camera_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
bool is_single);
#endif #endif
// Method for ListEntitiesDone batching // Method for ListEntitiesDone batching
static uint16_t try_send_list_info_done(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, static uint16_t try_send_list_info_done(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
bool is_single);
// Method for DisconnectRequest batching // Method for DisconnectRequest batching
static uint16_t try_send_disconnect_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, static uint16_t try_send_disconnect_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
bool is_single);
// Batch message method for ping requests // Batch message method for ping requests
static uint16_t try_send_ping_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, static uint16_t try_send_ping_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
bool is_single);
// === Optimal member ordering for 32-bit systems === // === Optimal member ordering for 32-bit systems ===
@@ -539,7 +503,7 @@ class APIConnection final : public APIServerConnection {
#endif #endif
// Function pointer type for message encoding // Function pointer type for message encoding
using MessageCreatorPtr = uint16_t (*)(EntityBase *, APIConnection *, uint32_t remaining_size, bool is_single); using MessageCreatorPtr = uint16_t (*)(EntityBase *, APIConnection *, uint32_t remaining_size);
// Generic batching mechanism for both state updates and entity info // Generic batching mechanism for both state updates and entity info
struct DeferredBatch { struct DeferredBatch {
@@ -652,7 +616,7 @@ class APIConnection final : public APIServerConnection {
// Dispatch message encoding based on message_type - replaces function pointer storage // Dispatch message encoding based on message_type - replaces function pointer storage
// Switch assigns pointer, single call site for smaller code size // Switch assigns pointer, single call site for smaller code size
uint16_t dispatch_message_(const DeferredBatch::BatchItem &item, uint32_t remaining_size, bool is_single); uint16_t dispatch_message_(const DeferredBatch::BatchItem &item, uint32_t remaining_size, bool batch_first);
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
void log_batch_item_(const DeferredBatch::BatchItem &item) { void log_batch_item_(const DeferredBatch::BatchItem &item) {
@@ -684,19 +648,7 @@ class APIConnection final : public APIServerConnection {
// Tries immediate send if should_send_immediately_() returns true and buffer has space // Tries immediate send if should_send_immediately_() returns true and buffer has space
// Falls back to batching if immediate send fails or isn't applicable // Falls back to batching if immediate send fails or isn't applicable
bool send_message_smart_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size, bool send_message_smart_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size,
uint8_t aux_data_index = DeferredBatch::AUX_DATA_UNUSED) { uint8_t aux_data_index = DeferredBatch::AUX_DATA_UNUSED);
if (this->should_send_immediately_(message_type) && this->helper_->can_write_without_blocking()) {
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)) {
#ifdef HAS_PROTO_MESSAGE_DUMP
this->log_batch_item_(item);
#endif
return true;
}
}
return this->schedule_message_(entity, message_type, estimated_size, aux_data_index);
}
// Helper function to schedule a deferred message with known message type // Helper function to schedule a deferred message with known message type
bool schedule_message_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size, bool schedule_message_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size,

View File

@@ -23,7 +23,7 @@ class APIServerConnectionBase : public ProtoService {
DumpBuffer dump_buf; DumpBuffer dump_buf;
this->log_send_message_(msg.message_name(), msg.dump_to(dump_buf)); this->log_send_message_(msg.message_name(), msg.dump_to(dump_buf));
#endif #endif
return this->send_message_(msg, message_type); return this->send_message_impl(msg, message_type);
} }
virtual void on_hello_request(const HelloRequest &value){}; virtual void on_hello_request(const HelloRequest &value){};

View File

@@ -957,32 +957,16 @@ class ProtoService {
virtual bool is_connection_setup() = 0; virtual bool is_connection_setup() = 0;
virtual void on_fatal_error() = 0; virtual void on_fatal_error() = 0;
virtual void on_no_setup_connection() = 0; virtual void on_no_setup_connection() = 0;
/**
* Create a buffer with a reserved size.
* @param reserve_size The number of bytes to pre-allocate in the buffer. This is a hint
* to optimize memory usage and avoid reallocations during encoding.
* Implementations should aim to allocate at least this size.
* @return A ProtoWriteBuffer object with the reserved size.
*/
virtual ProtoWriteBuffer create_buffer(uint32_t reserve_size) = 0;
virtual bool send_buffer(ProtoWriteBuffer buffer, uint8_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, const uint8_t *msg_data) = 0; virtual void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) = 0;
/**
// Optimized method that pre-allocates buffer based on message size * Send a protobuf message by calculating its size, allocating a buffer, encoding, and sending.
bool send_message_(const ProtoMessage &msg, uint8_t message_type) { * This is the implementation method - callers should use send_message() which adds logging.
ProtoSize size; * @param msg The protobuf message to send.
msg.calculate_size(size); * @param message_type The message type identifier.
uint32_t msg_size = size.get_size(); * @return True if the message was sent successfully, false otherwise.
*/
// Create a pre-sized buffer virtual bool send_message_impl(const ProtoMessage &msg, uint8_t message_type) = 0;
auto buffer = this->create_buffer(msg_size);
// Encode message into the buffer
msg.encode(buffer);
// Send the buffer
return this->send_buffer(buffer, message_type);
}
// Authentication helper methods // Authentication helper methods
inline bool check_connection_setup_() { inline bool check_connection_setup_() {

View File

@@ -2848,7 +2848,7 @@ static const char *const TAG = "api.service";
hpp += " DumpBuffer dump_buf;\n" hpp += " DumpBuffer dump_buf;\n"
hpp += " this->log_send_message_(msg.message_name(), msg.dump_to(dump_buf));\n" hpp += " this->log_send_message_(msg.message_name(), msg.dump_to(dump_buf));\n"
hpp += "#endif\n" hpp += "#endif\n"
hpp += " return this->send_message_(msg, message_type);\n" hpp += " return this->send_message_impl(msg, message_type);\n"
hpp += " }\n\n" hpp += " }\n\n"
# Add logging helper method implementations to cpp # Add logging helper method implementations to cpp