[api] Devirtualize protobuf encode/calculate_size (#14449)

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
J. Nick Koston
2026-03-06 09:03:54 -10:00
committed by GitHub
parent 9654140c00
commit 42dbb51022
14 changed files with 1373 additions and 1387 deletions

View File

@@ -275,7 +275,7 @@ void APIConnection::check_keepalive_(uint32_t now) {
// Only send ping if we're not disconnecting
ESP_LOGVV(TAG, "Sending keepalive PING");
PingRequest req;
this->flags_.sent_ping = this->send_message(req, PingRequest::MESSAGE_TYPE);
this->flags_.sent_ping = this->send_message(req);
if (!this->flags_.sent_ping) {
// If we can't send the ping request directly (tx_buffer full),
// schedule it at the front of the batch so it will be sent with priority
@@ -336,7 +336,7 @@ bool APIConnection::send_disconnect_response_() {
this->log_client_(ESPHOME_LOG_LEVEL_DEBUG, LOG_STR("disconnected"));
this->flags_.next_close = true;
DisconnectResponse resp;
return this->send_message(resp, DisconnectResponse::MESSAGE_TYPE);
return this->send_message(resp);
}
void APIConnection::on_disconnect_response() {
// Don't close socket here, let APIServer::loop() do it
@@ -344,61 +344,19 @@ void APIConnection::on_disconnect_response() {
this->flags_.remove = true;
}
// Encodes a message to the buffer and returns the total number of bytes used,
// including header and footer overhead. Returns 0 if the message doesn't fit.
uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint8_t message_type, APIConnection *conn,
uint32_t remaining_size) {
#ifdef HAS_PROTO_MESSAGE_DUMP
// If in log-only mode, just log and return
if (conn->flags_.log_only_mode) {
DumpBuffer dump_buf;
conn->log_send_message_(msg.message_name(), msg.dump_to(dump_buf));
return 1; // Return non-zero to indicate "success" for logging
}
uint16_t APIConnection::fill_and_encode_entity_state(EntityBase *entity, StateResponseProtoMessage &msg,
CalculateSizeFn size_fn, MessageEncodeFn encode_fn,
APIConnection *conn, uint32_t remaining_size) {
msg.key = entity->get_object_id_hash();
#ifdef USE_DEVICES
msg.device_id = entity->get_device_id();
#endif
// Calculate size
uint32_t calculated_size = msg.calculated_size();
// Cache frame sizes to avoid repeated virtual calls
const uint8_t header_padding = conn->helper_->frame_header_padding();
const uint8_t footer_size = conn->helper_->frame_footer_size();
// Calculate total size with padding for buffer allocation
size_t total_calculated_size = calculated_size + header_padding + footer_size;
// Check if it fits
if (total_calculated_size > remaining_size) {
return 0; // Doesn't fit
}
// Get buffer size after allocation (which includes header padding)
std::vector<uint8_t> &shared_buf = conn->parent_->get_shared_buffer_ref();
if (conn->flags_.batch_first_message) {
// First message - buffer already prepared by caller, just clear flag
conn->flags_.batch_first_message = false;
} else {
// Batch message second or later
// Add padding for previous message footer + this message header
size_t current_size = shared_buf.size();
shared_buf.reserve(current_size + total_calculated_size);
shared_buf.resize(current_size + footer_size + header_padding);
}
// Pre-resize buffer to include payload, then encode through raw pointer
size_t write_start = shared_buf.size();
shared_buf.resize(write_start + calculated_size);
ProtoWriteBuffer buffer{&shared_buf, write_start};
msg.encode(buffer);
// Return total size (header + payload + footer)
return static_cast<uint16_t>(header_padding + calculated_size + footer_size);
return encode_to_buffer(size_fn(&msg), encode_fn, &msg, conn, remaining_size);
}
uint16_t APIConnection::fill_and_encode_entity_info(EntityBase *entity, InfoResponseProtoMessage &msg,
uint8_t message_type, APIConnection *conn,
uint32_t remaining_size) {
CalculateSizeFn size_fn, MessageEncodeFn encode_fn,
APIConnection *conn, uint32_t remaining_size) {
// Set common fields that are shared by all entity types
msg.key = entity->get_object_id_hash();
@@ -406,7 +364,7 @@ uint16_t APIConnection::fill_and_encode_entity_info(EntityBase *entity, InfoResp
// For older clients, we must send object_id for backward compatibility
// See: https://github.com/esphome/backlog/issues/76
// TODO: Remove this backward compat code before 2026.7.0 - all clients should support API 1.14 by then
// Buffer must remain in scope until encode_message_to_buffer is called
// Buffer must remain in scope until encode_to_buffer is called
char object_id_buf[OBJECT_ID_MAX_LEN];
if (!conn->client_supports_api_version(1, 14)) {
msg.object_id = entity->get_object_id_to(object_id_buf);
@@ -426,16 +384,17 @@ uint16_t APIConnection::fill_and_encode_entity_info(EntityBase *entity, InfoResp
#ifdef USE_DEVICES
msg.device_id = entity->get_device_id();
#endif
return encode_message_to_buffer(msg, message_type, conn, remaining_size);
return encode_to_buffer(size_fn(&msg), encode_fn, &msg, conn, remaining_size);
}
uint16_t APIConnection::fill_and_encode_entity_info_with_device_class(EntityBase *entity, InfoResponseProtoMessage &msg,
StringRef &device_class_field,
uint8_t message_type, APIConnection *conn,
CalculateSizeFn size_fn,
MessageEncodeFn encode_fn, APIConnection *conn,
uint32_t remaining_size) {
char dc_buf[MAX_DEVICE_CLASS_LENGTH];
device_class_field = StringRef(entity->get_device_class_to(dc_buf));
return fill_and_encode_entity_info(entity, msg, message_type, conn, remaining_size);
return fill_and_encode_entity_info(entity, msg, size_fn, encode_fn, conn, remaining_size);
}
#ifdef USE_BINARY_SENSOR
@@ -449,16 +408,14 @@ uint16_t APIConnection::try_send_binary_sensor_state(EntityBase *entity, APIConn
BinarySensorStateResponse resp;
resp.state = binary_sensor->state;
resp.missing_state = !binary_sensor->has_state();
return fill_and_encode_entity_state(binary_sensor, resp, BinarySensorStateResponse::MESSAGE_TYPE, conn,
remaining_size);
return fill_and_encode_entity_state(binary_sensor, resp, conn, remaining_size);
}
uint16_t APIConnection::try_send_binary_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
auto *binary_sensor = static_cast<binary_sensor::BinarySensor *>(entity);
ListEntitiesBinarySensorResponse msg;
msg.is_status_binary_sensor = binary_sensor->is_status_binary_sensor();
return fill_and_encode_entity_info_with_device_class(
binary_sensor, msg, msg.device_class, ListEntitiesBinarySensorResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_info_with_device_class(binary_sensor, msg, msg.device_class, conn, remaining_size);
}
#endif
@@ -474,7 +431,7 @@ uint16_t APIConnection::try_send_cover_state(EntityBase *entity, APIConnection *
if (traits.get_supports_tilt())
msg.tilt = cover->tilt;
msg.current_operation = static_cast<enums::CoverOperation>(cover->current_operation);
return fill_and_encode_entity_state(cover, msg, CoverStateResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_state(cover, msg, conn, remaining_size);
}
uint16_t APIConnection::try_send_cover_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
auto *cover = static_cast<cover::Cover *>(entity);
@@ -484,8 +441,7 @@ uint16_t APIConnection::try_send_cover_info(EntityBase *entity, APIConnection *c
msg.supports_position = traits.get_supports_position();
msg.supports_tilt = traits.get_supports_tilt();
msg.supports_stop = traits.get_supports_stop();
return fill_and_encode_entity_info_with_device_class(cover, msg, msg.device_class,
ListEntitiesCoverResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_info_with_device_class(cover, msg, msg.device_class, conn, remaining_size);
}
void APIConnection::on_cover_command_request(const CoverCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(cover::Cover, cover, cover)
@@ -517,7 +473,7 @@ uint16_t APIConnection::try_send_fan_state(EntityBase *entity, APIConnection *co
msg.direction = static_cast<enums::FanDirection>(fan->direction);
if (traits.supports_preset_modes() && fan->has_preset_mode())
msg.preset_mode = fan->get_preset_mode();
return fill_and_encode_entity_state(fan, msg, FanStateResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_state(fan, msg, conn, remaining_size);
}
uint16_t APIConnection::try_send_fan_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
auto *fan = static_cast<fan::Fan *>(entity);
@@ -528,7 +484,7 @@ uint16_t APIConnection::try_send_fan_info(EntityBase *entity, APIConnection *con
msg.supports_direction = traits.supports_direction();
msg.supported_speed_count = traits.supported_speed_count();
msg.supported_preset_modes = &traits.supported_preset_modes();
return fill_and_encode_entity_info(fan, msg, ListEntitiesFanResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_info(fan, msg, conn, remaining_size);
}
void APIConnection::on_fan_command_request(const FanCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(fan::Fan, fan, fan)
@@ -571,7 +527,7 @@ uint16_t APIConnection::try_send_light_state(EntityBase *entity, APIConnection *
if (light->supports_effects()) {
resp.effect = light->get_effect_name();
}
return fill_and_encode_entity_state(light, resp, LightStateResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_state(light, resp, conn, remaining_size);
}
uint16_t APIConnection::try_send_light_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
auto *light = static_cast<light::LightState *>(entity);
@@ -596,7 +552,7 @@ uint16_t APIConnection::try_send_light_info(EntityBase *entity, APIConnection *c
}
}
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, conn, remaining_size);
}
void APIConnection::on_light_command_request(const LightCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(light::LightState, light, light)
@@ -641,7 +597,7 @@ uint16_t APIConnection::try_send_sensor_state(EntityBase *entity, APIConnection
SensorStateResponse resp;
resp.state = sensor->state;
resp.missing_state = !sensor->has_state();
return fill_and_encode_entity_state(sensor, resp, SensorStateResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_state(sensor, resp, conn, remaining_size);
}
uint16_t APIConnection::try_send_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
@@ -651,8 +607,7 @@ uint16_t APIConnection::try_send_sensor_info(EntityBase *entity, APIConnection *
msg.accuracy_decimals = sensor->get_accuracy_decimals();
msg.force_update = sensor->get_force_update();
msg.state_class = static_cast<enums::SensorStateClass>(sensor->get_state_class());
return fill_and_encode_entity_info_with_device_class(sensor, msg, msg.device_class,
ListEntitiesSensorResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_info_with_device_class(sensor, msg, msg.device_class, conn, remaining_size);
}
#endif
@@ -665,15 +620,14 @@ uint16_t APIConnection::try_send_switch_state(EntityBase *entity, APIConnection
auto *a_switch = static_cast<switch_::Switch *>(entity);
SwitchStateResponse resp;
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, conn, remaining_size);
}
uint16_t APIConnection::try_send_switch_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
auto *a_switch = static_cast<switch_::Switch *>(entity);
ListEntitiesSwitchResponse msg;
msg.assumed_state = a_switch->assumed_state();
return fill_and_encode_entity_info_with_device_class(a_switch, msg, msg.device_class,
ListEntitiesSwitchResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_info_with_device_class(a_switch, msg, msg.device_class, conn, remaining_size);
}
void APIConnection::on_switch_command_request(const SwitchCommandRequest &msg) {
ENTITY_COMMAND_GET(switch_::Switch, a_switch, switch)
@@ -697,13 +651,12 @@ uint16_t APIConnection::try_send_text_sensor_state(EntityBase *entity, APIConnec
TextSensorStateResponse resp;
resp.state = StringRef(text_sensor->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, conn, remaining_size);
}
uint16_t APIConnection::try_send_text_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
auto *text_sensor = static_cast<text_sensor::TextSensor *>(entity);
ListEntitiesTextSensorResponse msg;
return fill_and_encode_entity_info_with_device_class(
text_sensor, msg, msg.device_class, ListEntitiesTextSensorResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_info_with_device_class(text_sensor, msg, msg.device_class, conn, remaining_size);
}
#endif
@@ -743,7 +696,7 @@ uint16_t APIConnection::try_send_climate_state(EntityBase *entity, APIConnection
resp.current_humidity = climate->current_humidity;
if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_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, conn, remaining_size);
}
uint16_t APIConnection::try_send_climate_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
auto *climate = static_cast<climate::Climate *>(entity);
@@ -770,7 +723,7 @@ uint16_t APIConnection::try_send_climate_info(EntityBase *entity, APIConnection
msg.supported_presets = &traits.get_supported_presets();
msg.supported_custom_presets = &traits.get_supported_custom_presets();
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, conn, remaining_size);
}
void APIConnection::on_climate_command_request(const ClimateCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(climate::Climate, climate, climate)
@@ -808,7 +761,7 @@ uint16_t APIConnection::try_send_number_state(EntityBase *entity, APIConnection
NumberStateResponse resp;
resp.state = number->state;
resp.missing_state = !number->has_state();
return fill_and_encode_entity_state(number, resp, NumberStateResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_state(number, resp, conn, remaining_size);
}
uint16_t APIConnection::try_send_number_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
@@ -819,8 +772,7 @@ uint16_t APIConnection::try_send_number_info(EntityBase *entity, APIConnection *
msg.min_value = number->traits.get_min_value();
msg.max_value = number->traits.get_max_value();
msg.step = number->traits.get_step();
return fill_and_encode_entity_info_with_device_class(number, msg, msg.device_class,
ListEntitiesNumberResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_info_with_device_class(number, msg, msg.device_class, conn, remaining_size);
}
void APIConnection::on_number_command_request(const NumberCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(number::Number, number, number)
@@ -840,12 +792,12 @@ uint16_t APIConnection::try_send_date_state(EntityBase *entity, APIConnection *c
resp.year = date->year;
resp.month = date->month;
resp.day = date->day;
return fill_and_encode_entity_state(date, resp, DateStateResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_state(date, resp, conn, remaining_size);
}
uint16_t APIConnection::try_send_date_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
auto *date = static_cast<datetime::DateEntity *>(entity);
ListEntitiesDateResponse msg;
return fill_and_encode_entity_info(date, msg, ListEntitiesDateResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_info(date, msg, conn, remaining_size);
}
void APIConnection::on_date_command_request(const DateCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(datetime::DateEntity, date, date)
@@ -865,12 +817,12 @@ uint16_t APIConnection::try_send_time_state(EntityBase *entity, APIConnection *c
resp.hour = time->hour;
resp.minute = time->minute;
resp.second = time->second;
return fill_and_encode_entity_state(time, resp, TimeStateResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_state(time, resp, conn, remaining_size);
}
uint16_t APIConnection::try_send_time_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
auto *time = static_cast<datetime::TimeEntity *>(entity);
ListEntitiesTimeResponse msg;
return fill_and_encode_entity_info(time, msg, ListEntitiesTimeResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_info(time, msg, conn, remaining_size);
}
void APIConnection::on_time_command_request(const TimeCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(datetime::TimeEntity, time, time)
@@ -892,12 +844,12 @@ uint16_t APIConnection::try_send_datetime_state(EntityBase *entity, APIConnectio
ESPTime state = datetime->state_as_esptime();
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, conn, remaining_size);
}
uint16_t APIConnection::try_send_datetime_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
auto *datetime = static_cast<datetime::DateTimeEntity *>(entity);
ListEntitiesDateTimeResponse msg;
return fill_and_encode_entity_info(datetime, msg, ListEntitiesDateTimeResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_info(datetime, msg, conn, remaining_size);
}
void APIConnection::on_date_time_command_request(const DateTimeCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(datetime::DateTimeEntity, datetime, datetime)
@@ -916,7 +868,7 @@ uint16_t APIConnection::try_send_text_state(EntityBase *entity, APIConnection *c
TextStateResponse resp;
resp.state = StringRef(text->state);
resp.missing_state = !text->has_state();
return fill_and_encode_entity_state(text, resp, TextStateResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_state(text, resp, conn, remaining_size);
}
uint16_t APIConnection::try_send_text_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
@@ -926,7 +878,7 @@ uint16_t APIConnection::try_send_text_info(EntityBase *entity, APIConnection *co
msg.min_length = text->traits.get_min_length();
msg.max_length = text->traits.get_max_length();
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, conn, remaining_size);
}
void APIConnection::on_text_command_request(const TextCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(text::Text, text, text)
@@ -945,14 +897,14 @@ uint16_t APIConnection::try_send_select_state(EntityBase *entity, APIConnection
SelectStateResponse resp;
resp.state = select->current_option();
resp.missing_state = !select->has_state();
return fill_and_encode_entity_state(select, resp, SelectStateResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_state(select, resp, conn, remaining_size);
}
uint16_t APIConnection::try_send_select_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
auto *select = static_cast<select::Select *>(entity);
ListEntitiesSelectResponse msg;
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, conn, remaining_size);
}
void APIConnection::on_select_command_request(const SelectCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(select::Select, select, select)
@@ -965,8 +917,7 @@ void APIConnection::on_select_command_request(const SelectCommandRequest &msg) {
uint16_t APIConnection::try_send_button_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
auto *button = static_cast<button::Button *>(entity);
ListEntitiesButtonResponse msg;
return fill_and_encode_entity_info_with_device_class(button, msg, msg.device_class,
ListEntitiesButtonResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_info_with_device_class(button, msg, msg.device_class, conn, remaining_size);
}
void esphome::api::APIConnection::on_button_command_request(const ButtonCommandRequest &msg) {
ENTITY_COMMAND_GET(button::Button, button, button)
@@ -983,7 +934,7 @@ uint16_t APIConnection::try_send_lock_state(EntityBase *entity, APIConnection *c
auto *a_lock = static_cast<lock::Lock *>(entity);
LockStateResponse resp;
resp.state = static_cast<enums::LockState>(a_lock->state);
return fill_and_encode_entity_state(a_lock, resp, LockStateResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_state(a_lock, resp, conn, remaining_size);
}
uint16_t APIConnection::try_send_lock_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
@@ -992,7 +943,7 @@ uint16_t APIConnection::try_send_lock_info(EntityBase *entity, APIConnection *co
msg.assumed_state = a_lock->traits.get_assumed_state();
msg.supports_open = a_lock->traits.get_supports_open();
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, conn, remaining_size);
}
void APIConnection::on_lock_command_request(const LockCommandRequest &msg) {
ENTITY_COMMAND_GET(lock::Lock, a_lock, lock)
@@ -1020,7 +971,7 @@ uint16_t APIConnection::try_send_valve_state(EntityBase *entity, APIConnection *
ValveStateResponse resp;
resp.position = valve->position;
resp.current_operation = static_cast<enums::ValveOperation>(valve->current_operation);
return fill_and_encode_entity_state(valve, resp, ValveStateResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_state(valve, resp, conn, remaining_size);
}
uint16_t APIConnection::try_send_valve_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
auto *valve = static_cast<valve::Valve *>(entity);
@@ -1029,8 +980,7 @@ uint16_t APIConnection::try_send_valve_info(EntityBase *entity, APIConnection *c
msg.assumed_state = traits.get_is_assumed_state();
msg.supports_position = traits.get_supports_position();
msg.supports_stop = traits.get_supports_stop();
return fill_and_encode_entity_info_with_device_class(valve, msg, msg.device_class,
ListEntitiesValveResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_info_with_device_class(valve, msg, msg.device_class, conn, remaining_size);
}
void APIConnection::on_valve_command_request(const ValveCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(valve::Valve, valve, valve)
@@ -1056,7 +1006,7 @@ uint16_t APIConnection::try_send_media_player_state(EntityBase *entity, APIConne
resp.state = static_cast<enums::MediaPlayerState>(report_state);
resp.volume = media_player->volume;
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, conn, remaining_size);
}
uint16_t APIConnection::try_send_media_player_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
auto *media_player = static_cast<media_player::MediaPlayer *>(entity);
@@ -1073,8 +1023,7 @@ uint16_t APIConnection::try_send_media_player_info(EntityBase *entity, APIConnec
media_format.purpose = static_cast<enums::MediaPlayerFormatPurpose>(supported_format.purpose);
media_format.sample_bytes = supported_format.sample_bytes;
}
return fill_and_encode_entity_info(media_player, msg, ListEntitiesMediaPlayerResponse::MESSAGE_TYPE, conn,
remaining_size);
return fill_and_encode_entity_info(media_player, msg, conn, remaining_size);
}
void APIConnection::on_media_player_command_request(const MediaPlayerCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(media_player::MediaPlayer, media_player, media_player)
@@ -1115,7 +1064,7 @@ void APIConnection::try_send_camera_image_() {
msg.device_id = camera::Camera::instance()->get_device_id();
#endif
if (!this->send_message_impl(msg, CameraImageResponse::MESSAGE_TYPE)) {
if (!this->send_message(msg)) {
return; // Send failed, try again later
}
this->image_reader_->consume_data(to_send);
@@ -1141,7 +1090,7 @@ void APIConnection::set_camera_state(std::shared_ptr<camera::CameraImage> image)
uint16_t APIConnection::try_send_camera_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
auto *camera = static_cast<camera::Camera *>(entity);
ListEntitiesCameraResponse msg;
return fill_and_encode_entity_info(camera, msg, ListEntitiesCameraResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_info(camera, msg, conn, remaining_size);
}
void APIConnection::on_camera_image_request(const CameraImageRequest &msg) {
if (camera::Camera::instance() == nullptr)
@@ -1296,7 +1245,7 @@ void APIConnection::on_voice_assistant_announce_request(const VoiceAssistantAnno
bool APIConnection::send_voice_assistant_get_configuration_response_(const VoiceAssistantConfigurationRequest &msg) {
VoiceAssistantConfigurationResponse resp;
if (!this->check_voice_assistant_api_connection_()) {
return this->send_message(resp, VoiceAssistantConfigurationResponse::MESSAGE_TYPE);
return this->send_message(resp);
}
auto &config = voice_assistant::global_voice_assistant->get_configuration();
@@ -1328,7 +1277,7 @@ bool APIConnection::send_voice_assistant_get_configuration_response_(const Voice
resp.active_wake_words = &config.active_wake_words;
resp.max_active_wake_words = config.max_active_wake_words;
return this->send_message(resp, VoiceAssistantConfigurationResponse::MESSAGE_TYPE);
return this->send_message(resp);
}
void APIConnection::on_voice_assistant_configuration_request(const VoiceAssistantConfigurationRequest &msg) {
if (!this->send_voice_assistant_get_configuration_response_(msg)) {
@@ -1363,8 +1312,7 @@ uint16_t APIConnection::try_send_alarm_control_panel_state(EntityBase *entity, A
auto *a_alarm_control_panel = static_cast<alarm_control_panel::AlarmControlPanel *>(entity);
AlarmControlPanelStateResponse resp;
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,
remaining_size);
return fill_and_encode_entity_state(a_alarm_control_panel, resp, conn, remaining_size);
}
uint16_t APIConnection::try_send_alarm_control_panel_info(EntityBase *entity, APIConnection *conn,
uint32_t remaining_size) {
@@ -1373,8 +1321,7 @@ uint16_t APIConnection::try_send_alarm_control_panel_info(EntityBase *entity, AP
msg.supported_features = a_alarm_control_panel->get_supported_features();
msg.requires_code = a_alarm_control_panel->get_requires_code();
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,
conn, remaining_size);
return fill_and_encode_entity_info(a_alarm_control_panel, msg, conn, remaining_size);
}
void APIConnection::on_alarm_control_panel_command_request(const AlarmControlPanelCommandRequest &msg) {
ENTITY_COMMAND_MAKE_CALL(alarm_control_panel::AlarmControlPanel, a_alarm_control_panel, alarm_control_panel)
@@ -1421,7 +1368,7 @@ uint16_t APIConnection::try_send_water_heater_state(EntityBase *entity, APIConne
resp.target_temperature_high = wh->get_target_temperature_high();
resp.state = wh->get_state();
return fill_and_encode_entity_state(wh, resp, WaterHeaterStateResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_state(wh, resp, conn, remaining_size);
}
uint16_t APIConnection::try_send_water_heater_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
auto *wh = static_cast<water_heater::WaterHeater *>(entity);
@@ -1432,7 +1379,7 @@ uint16_t APIConnection::try_send_water_heater_info(EntityBase *entity, APIConnec
msg.target_temperature_step = traits.get_target_temperature_step();
msg.supported_modes = &traits.get_supported_modes();
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, conn, remaining_size);
}
void APIConnection::on_water_heater_command_request(const WaterHeaterCommandRequest &msg) {
@@ -1468,15 +1415,14 @@ uint16_t APIConnection::try_send_event_response(event::Event *event, StringRef e
uint32_t remaining_size) {
EventResponse resp;
resp.event_type = event_type;
return fill_and_encode_entity_state(event, resp, EventResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_state(event, resp, conn, remaining_size);
}
uint16_t APIConnection::try_send_event_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
auto *event = static_cast<event::Event *>(entity);
ListEntitiesEventResponse msg;
msg.event_types = &event->get_event_types();
return fill_and_encode_entity_info_with_device_class(event, msg, msg.device_class,
ListEntitiesEventResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_info_with_device_class(event, msg, msg.device_class, conn, remaining_size);
}
#endif
@@ -1493,9 +1439,7 @@ void APIConnection::on_infrared_rf_transmit_raw_timings_request(const InfraredRF
#endif
}
void APIConnection::send_infrared_rf_receive_event(const InfraredRFReceiveEvent &msg) {
this->send_message(msg, InfraredRFReceiveEvent::MESSAGE_TYPE);
}
void APIConnection::send_infrared_rf_receive_event(const InfraredRFReceiveEvent &msg) { this->send_message(msg); }
#endif
#ifdef USE_INFRARED
@@ -1503,7 +1447,7 @@ uint16_t APIConnection::try_send_infrared_info(EntityBase *entity, APIConnection
auto *infrared = static_cast<infrared::Infrared *>(entity);
ListEntitiesInfraredResponse msg;
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, conn, remaining_size);
}
#endif
@@ -1527,13 +1471,12 @@ uint16_t APIConnection::try_send_update_state(EntityBase *entity, APIConnection
resp.release_summary = StringRef(update->update_info.summary);
resp.release_url = StringRef(update->update_info.release_url);
}
return fill_and_encode_entity_state(update, resp, UpdateStateResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_state(update, resp, conn, remaining_size);
}
uint16_t APIConnection::try_send_update_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
auto *update = static_cast<update::UpdateEntity *>(entity);
ListEntitiesUpdateResponse msg;
return fill_and_encode_entity_info_with_device_class(update, msg, msg.device_class,
ListEntitiesUpdateResponse::MESSAGE_TYPE, conn, remaining_size);
return fill_and_encode_entity_info_with_device_class(update, msg, msg.device_class, conn, remaining_size);
}
void APIConnection::on_update_command_request(const UpdateCommandRequest &msg) {
ENTITY_COMMAND_GET(update::UpdateEntity, update, update)
@@ -1559,7 +1502,7 @@ bool APIConnection::try_send_log_message(int level, const char *tag, const char
SubscribeLogsResponse msg;
msg.level = static_cast<enums::LogLevel>(level);
msg.set_message(reinterpret_cast<const uint8_t *>(line), message_len);
return this->send_message_impl(msg, SubscribeLogsResponse::MESSAGE_TYPE);
return this->send_message(msg);
}
void APIConnection::complete_authentication_() {
@@ -1616,12 +1559,12 @@ bool APIConnection::send_hello_response_(const HelloRequest &msg) {
// Auto-authenticate - password auth was removed in ESPHome 2026.1.0
this->complete_authentication_();
return this->send_message(resp, HelloResponse::MESSAGE_TYPE);
return this->send_message(resp);
}
bool APIConnection::send_ping_response_() {
PingResponse resp;
return this->send_message(resp, PingResponse::MESSAGE_TYPE);
return this->send_message(resp);
}
bool APIConnection::send_device_info_response_() {
@@ -1745,7 +1688,7 @@ bool APIConnection::send_device_info_response_() {
}
#endif
return this->send_message(resp, DeviceInfoResponse::MESSAGE_TYPE);
return this->send_message(resp);
}
void APIConnection::on_hello_request(const HelloRequest &msg) {
if (!this->send_hello_response_(msg)) {
@@ -1845,7 +1788,7 @@ void APIConnection::send_execute_service_response(uint32_t call_id, bool success
resp.call_id = call_id;
resp.success = success;
resp.error_message = error_message;
this->send_message(resp, ExecuteServiceResponse::MESSAGE_TYPE);
this->send_message(resp);
}
#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES_JSON
void APIConnection::send_execute_service_response(uint32_t call_id, bool success, StringRef error_message,
@@ -1856,7 +1799,7 @@ void APIConnection::send_execute_service_response(uint32_t call_id, bool success
resp.error_message = error_message;
resp.response_data = response_data;
resp.response_data_len = response_data_len;
this->send_message(resp, ExecuteServiceResponse::MESSAGE_TYPE);
this->send_message(resp);
}
#endif // USE_API_USER_DEFINED_ACTION_RESPONSES_JSON
#endif // USE_API_USER_DEFINED_ACTION_RESPONSES
@@ -1895,7 +1838,7 @@ bool APIConnection::send_noise_encryption_set_key_response_(const NoiseEncryptio
resp.success = true;
}
return this->send_message(resp, NoiseEncryptionSetKeyResponse::MESSAGE_TYPE);
return this->send_message(resp);
}
void APIConnection::on_noise_encryption_set_key_request(const NoiseEncryptionSetKeyRequest &msg) {
if (!this->send_noise_encryption_set_key_response_(msg)) {
@@ -1924,16 +1867,73 @@ bool APIConnection::try_to_clear_buffer(bool log_out_of_space) {
}
return false;
}
bool APIConnection::send_message_impl(const ProtoMessage &msg, uint8_t message_type) {
uint32_t payload_size = msg.calculated_size();
std::vector<uint8_t> &shared_buf = this->parent_->get_shared_buffer_ref();
bool APIConnection::send_message_(uint32_t payload_size, uint8_t message_type, MessageEncodeFn encode_fn,
const void *msg) {
#ifdef HAS_PROTO_MESSAGE_DUMP
// Skip dump for log messages (recursive logging risk) and camera frames (high-frequency noise)
if (message_type != SubscribeLogsResponse::MESSAGE_TYPE
#ifdef USE_CAMERA
&& message_type != CameraImageResponse::MESSAGE_TYPE
#endif
) {
auto *proto_msg = static_cast<const ProtoMessage *>(msg);
DumpBuffer dump_buf;
this->log_send_message_(proto_msg->message_name(), proto_msg->dump_to(dump_buf));
}
#endif
auto &shared_buf = this->parent_->get_shared_buffer_ref();
this->prepare_first_message_buffer(shared_buf, payload_size);
size_t write_start = shared_buf.size();
shared_buf.resize(write_start + payload_size);
ProtoWriteBuffer buffer{&shared_buf, write_start};
msg.encode(buffer);
encode_fn(msg, buffer);
return this->send_buffer(ProtoWriteBuffer{&shared_buf}, message_type);
}
// Encodes a message to the buffer and returns the total number of bytes used,
// including header and footer overhead. Returns 0 if the message doesn't fit.
uint16_t APIConnection::encode_to_buffer(uint32_t calculated_size, MessageEncodeFn encode_fn, const void *msg,
APIConnection *conn, uint32_t remaining_size) {
#ifdef HAS_PROTO_MESSAGE_DUMP
if (conn->flags_.log_only_mode) {
auto *proto_msg = static_cast<const ProtoMessage *>(msg);
DumpBuffer dump_buf;
conn->log_send_message_(proto_msg->message_name(), proto_msg->dump_to(dump_buf));
return 1;
}
#endif
// Cache frame sizes to avoid repeated virtual calls
const uint8_t header_padding = conn->helper_->frame_header_padding();
const uint8_t footer_size = conn->helper_->frame_footer_size();
// Calculate total size with padding for buffer allocation
size_t total_calculated_size = calculated_size + header_padding + footer_size;
// Check if it fits
if (total_calculated_size > remaining_size)
return 0; // Doesn't fit
std::vector<uint8_t> &shared_buf = conn->parent_->get_shared_buffer_ref();
if (conn->flags_.batch_first_message) {
// First message - buffer already prepared by caller, just clear flag
conn->flags_.batch_first_message = false;
} else {
// Batch message second or later
// Add padding for previous message footer + this message header
size_t current_size = shared_buf.size();
shared_buf.reserve(current_size + total_calculated_size);
shared_buf.resize(current_size + footer_size + header_padding);
}
// Pre-resize buffer to include payload, then encode through raw pointer
size_t write_start = shared_buf.size();
shared_buf.resize(write_start + calculated_size);
ProtoWriteBuffer buffer{&shared_buf, write_start};
encode_fn(msg, buffer);
// Return total size (header + payload + footer)
return static_cast<uint16_t>(header_padding + calculated_size + footer_size);
}
bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) {
const bool is_log_message = (message_type == SubscribeLogsResponse::MESSAGE_TYPE);
@@ -2292,17 +2292,17 @@ uint16_t APIConnection::dispatch_message_(const DeferredBatch::BatchItem &item,
uint16_t APIConnection::try_send_list_info_done(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
ListEntitiesDoneResponse resp;
return encode_message_to_buffer(resp, ListEntitiesDoneResponse::MESSAGE_TYPE, conn, remaining_size);
return encode_message_to_buffer(resp, conn, remaining_size);
}
uint16_t APIConnection::try_send_disconnect_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
DisconnectRequest req;
return encode_message_to_buffer(req, DisconnectRequest::MESSAGE_TYPE, conn, remaining_size);
return encode_message_to_buffer(req, conn, remaining_size);
}
uint16_t APIConnection::try_send_ping_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
PingRequest req;
return encode_message_to_buffer(req, PingRequest::MESSAGE_TYPE, conn, remaining_size);
return encode_message_to_buffer(req, conn, remaining_size);
}
#ifdef USE_API_HOMEASSISTANT_STATES
@@ -2321,7 +2321,7 @@ void APIConnection::process_state_subscriptions_() {
resp.attribute = it.attribute != nullptr ? StringRef(it.attribute) : StringRef("");
resp.once = it.once;
if (this->send_message(resp, SubscribeHomeAssistantStateResponse::MESSAGE_TYPE)) {
if (this->send_message(resp)) {
this->state_subs_at_++;
}
}

View File

@@ -129,7 +129,7 @@ class APIConnection final : public APIServerConnectionBase {
void send_homeassistant_action(const HomeassistantActionRequest &call) {
if (!this->flags_.service_call_subscription)
return;
this->send_message(call, HomeassistantActionRequest::MESSAGE_TYPE);
this->send_message(call);
}
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
void on_homeassistant_action_response(const HomeassistantActionResponse &msg) override;
@@ -153,7 +153,7 @@ class APIConnection final : public APIServerConnectionBase {
#ifdef USE_HOMEASSISTANT_TIME
void send_time_request() {
GetTimeRequest req;
this->send_message(req, GetTimeRequest::MESSAGE_TYPE);
this->send_message(req);
}
#endif
@@ -263,7 +263,19 @@ class APIConnection final : public APIServerConnectionBase {
void on_fatal_error() override;
void on_no_setup_connection() override;
bool send_message_impl(const ProtoMessage &msg, uint8_t message_type) override;
// Function pointer type for type-erased message encoding
using MessageEncodeFn = void (*)(const void *, ProtoWriteBuffer &);
// Function pointer type for type-erased size calculation
using CalculateSizeFn = uint32_t (*)(const void *);
template<typename T> bool send_message(const T &msg) {
if constexpr (T::ESTIMATED_SIZE == 0) {
return this->send_message_(0, T::MESSAGE_TYPE, &encode_msg_noop, &msg);
} else {
return this->send_message_(msg.calculate_size(), T::MESSAGE_TYPE, &proto_encode_msg<T>, &msg);
}
}
void prepare_first_message_buffer(std::vector<uint8_t> &shared_buf, size_t header_padding, size_t total_size) {
shared_buf.clear();
@@ -318,28 +330,68 @@ class APIConnection final : public APIServerConnectionBase {
void process_state_subscriptions_();
#endif
// Non-template helper to encode any ProtoMessage
static uint16_t encode_message_to_buffer(ProtoMessage &msg, uint8_t message_type, APIConnection *conn,
uint32_t remaining_size);
// 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,
APIConnection *conn, uint32_t remaining_size) {
msg.key = entity->get_object_id_hash();
#ifdef USE_DEVICES
msg.device_id = entity->get_device_id();
#endif
return encode_message_to_buffer(msg, message_type, conn, remaining_size);
// Size thunk — converts void* back to concrete type for direct calculate_size() call
template<typename T> static uint32_t calc_size(const void *msg) {
return static_cast<const T *>(msg)->calculate_size();
}
// 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,
APIConnection *conn, uint32_t remaining_size);
// Shared no-op encode thunk for empty messages (ESTIMATED_SIZE == 0)
static void encode_msg_noop(const void *, ProtoWriteBuffer &) {}
// Wrapper for entity types that have a device_class field
// Non-template buffer management for send_message
bool send_message_(uint32_t payload_size, uint8_t message_type, MessageEncodeFn encode_fn, const void *msg);
// Non-template buffer management for batch encoding
static uint16_t encode_to_buffer(uint32_t calculated_size, MessageEncodeFn encode_fn, const void *msg,
APIConnection *conn, uint32_t remaining_size);
// Thin template wrapper — computes size, delegates buffer work to non-template helper
template<typename T> static uint16_t encode_message_to_buffer(T &msg, APIConnection *conn, uint32_t remaining_size) {
if constexpr (T::ESTIMATED_SIZE == 0) {
return encode_to_buffer(0, &encode_msg_noop, &msg, conn, remaining_size);
} else {
return encode_to_buffer(msg.calculate_size(), &proto_encode_msg<T>, &msg, conn, remaining_size);
}
}
// Non-template core — fills state fields and encodes
static uint16_t fill_and_encode_entity_state(EntityBase *entity, StateResponseProtoMessage &msg,
CalculateSizeFn size_fn, MessageEncodeFn encode_fn, APIConnection *conn,
uint32_t remaining_size);
// Thin template wrapper
template<typename T>
static uint16_t fill_and_encode_entity_state(EntityBase *entity, T &msg, APIConnection *conn,
uint32_t remaining_size) {
return fill_and_encode_entity_state(entity, msg, &calc_size<T>, &proto_encode_msg<T>, conn, remaining_size);
}
// Non-template core — fills info fields, allocates buffers, and encodes
static uint16_t fill_and_encode_entity_info(EntityBase *entity, InfoResponseProtoMessage &msg,
CalculateSizeFn size_fn, MessageEncodeFn encode_fn, APIConnection *conn,
uint32_t remaining_size);
// Thin template wrapper
template<typename T>
static uint16_t fill_and_encode_entity_info(EntityBase *entity, T &msg, APIConnection *conn,
uint32_t remaining_size) {
return fill_and_encode_entity_info(entity, msg, &calc_size<T>, &proto_encode_msg<T>, conn, remaining_size);
}
// Non-template core — fills device_class, then delegates to fill_and_encode_entity_info
static uint16_t fill_and_encode_entity_info_with_device_class(EntityBase *entity, InfoResponseProtoMessage &msg,
StringRef &device_class_field, uint8_t message_type,
APIConnection *conn, uint32_t remaining_size);
StringRef &device_class_field, CalculateSizeFn size_fn,
MessageEncodeFn encode_fn, APIConnection *conn,
uint32_t remaining_size);
// Thin template wrapper
template<typename T>
static uint16_t fill_and_encode_entity_info_with_device_class(EntityBase *entity, T &msg,
StringRef &device_class_field, APIConnection *conn,
uint32_t remaining_size) {
return fill_and_encode_entity_info_with_device_class(entity, msg, device_class_field, &calc_size<T>,
&proto_encode_msg<T>, conn, remaining_size);
}
#ifdef USE_VOICE_ASSISTANT
// Helper to check voice assistant validity and connection ownership

File diff suppressed because it is too large Load Diff

View File

@@ -388,8 +388,8 @@ class HelloResponse final : public ProtoMessage {
uint32_t api_version_minor{0};
StringRef server_info{};
StringRef name{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -453,8 +453,8 @@ class AreaInfo final : public ProtoMessage {
public:
uint32_t area_id{0};
StringRef name{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -468,8 +468,8 @@ class DeviceInfo final : public ProtoMessage {
uint32_t device_id{0};
StringRef name{};
uint32_t area_id{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -533,8 +533,8 @@ class DeviceInfoResponse final : public ProtoMessage {
#ifdef USE_ZWAVE_PROXY
uint32_t zwave_home_id{0};
#endif
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -564,8 +564,8 @@ class ListEntitiesBinarySensorResponse final : public InfoResponseProtoMessage {
#endif
StringRef device_class{};
bool is_status_binary_sensor{false};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -581,8 +581,8 @@ class BinarySensorStateResponse final : public StateResponseProtoMessage {
#endif
bool state{false};
bool missing_state{false};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -603,8 +603,8 @@ class ListEntitiesCoverResponse final : public InfoResponseProtoMessage {
bool supports_tilt{false};
StringRef device_class{};
bool supports_stop{false};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -621,8 +621,8 @@ class CoverStateResponse final : public StateResponseProtoMessage {
float position{0.0f};
float tilt{0.0f};
enums::CoverOperation current_operation{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -663,8 +663,8 @@ class ListEntitiesFanResponse final : public InfoResponseProtoMessage {
bool supports_direction{false};
int32_t supported_speed_count{0};
const std::vector<const char *> *supported_preset_modes{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -683,8 +683,8 @@ class FanStateResponse final : public StateResponseProtoMessage {
enums::FanDirection direction{};
int32_t speed_level{0};
StringRef preset_mode{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -730,8 +730,8 @@ class ListEntitiesLightResponse final : public InfoResponseProtoMessage {
float min_mireds{0.0f};
float max_mireds{0.0f};
const FixedVector<const char *> *effects{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -757,8 +757,8 @@ class LightStateResponse final : public StateResponseProtoMessage {
float cold_white{0.0f};
float warm_white{0.0f};
StringRef effect{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -821,8 +821,8 @@ class ListEntitiesSensorResponse final : public InfoResponseProtoMessage {
bool force_update{false};
StringRef device_class{};
enums::SensorStateClass state_class{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -838,8 +838,8 @@ class SensorStateResponse final : public StateResponseProtoMessage {
#endif
float state{0.0f};
bool missing_state{false};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -857,8 +857,8 @@ class ListEntitiesSwitchResponse final : public InfoResponseProtoMessage {
#endif
bool assumed_state{false};
StringRef device_class{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -873,8 +873,8 @@ class SwitchStateResponse final : public StateResponseProtoMessage {
const char *message_name() const override { return "switch_state_response"; }
#endif
bool state{false};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -907,8 +907,8 @@ class ListEntitiesTextSensorResponse final : public InfoResponseProtoMessage {
const char *message_name() const override { return "list_entities_text_sensor_response"; }
#endif
StringRef device_class{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -924,8 +924,8 @@ class TextSensorStateResponse final : public StateResponseProtoMessage {
#endif
StringRef state{};
bool missing_state{false};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -963,8 +963,8 @@ class SubscribeLogsResponse final : public ProtoMessage {
this->message_ptr_ = data;
this->message_len_ = len;
}
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -996,8 +996,8 @@ class NoiseEncryptionSetKeyResponse final : public ProtoMessage {
const char *message_name() const override { return "noise_encryption_set_key_response"; }
#endif
bool success{false};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1010,8 +1010,8 @@ class HomeassistantServiceMap final : public ProtoMessage {
public:
StringRef key{};
StringRef value{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1039,8 +1039,8 @@ class HomeassistantActionRequest final : public ProtoMessage {
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
StringRef response_template{};
#endif
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1083,8 +1083,8 @@ class SubscribeHomeAssistantStateResponse final : public ProtoMessage {
StringRef entity_id{};
StringRef attribute{};
bool once{false};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1174,8 +1174,8 @@ class ListEntitiesServicesArgument final : public ProtoMessage {
public:
StringRef name{};
enums::ServiceArgType type{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1193,8 +1193,8 @@ class ListEntitiesServicesResponse final : public ProtoMessage {
uint32_t key{0};
FixedVector<ListEntitiesServicesArgument> args{};
enums::SupportsResponseType supports_response{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1263,8 +1263,8 @@ class ExecuteServiceResponse final : public ProtoMessage {
const uint8_t *response_data{nullptr};
uint16_t response_data_len{0};
#endif
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1280,8 +1280,8 @@ class ListEntitiesCameraResponse final : public InfoResponseProtoMessage {
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "list_entities_camera_response"; }
#endif
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1302,8 +1302,8 @@ class CameraImageResponse final : public StateResponseProtoMessage {
this->data_len_ = len;
}
bool done{false};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1353,8 +1353,8 @@ class ListEntitiesClimateResponse final : public InfoResponseProtoMessage {
float visual_min_humidity{0.0f};
float visual_max_humidity{0.0f};
uint32_t feature_flags{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1381,8 +1381,8 @@ class ClimateStateResponse final : public StateResponseProtoMessage {
StringRef custom_preset{};
float current_humidity{0.0f};
float target_humidity{0.0f};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1439,8 +1439,8 @@ class ListEntitiesWaterHeaterResponse final : public InfoResponseProtoMessage {
float target_temperature_step{0.0f};
const water_heater::WaterHeaterModeMask *supported_modes{};
uint32_t supported_features{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1460,8 +1460,8 @@ class WaterHeaterStateResponse final : public StateResponseProtoMessage {
uint32_t state{0};
float target_temperature_low{0.0f};
float target_temperature_high{0.0f};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1504,8 +1504,8 @@ class ListEntitiesNumberResponse final : public InfoResponseProtoMessage {
StringRef unit_of_measurement{};
enums::NumberMode mode{};
StringRef device_class{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1521,8 +1521,8 @@ class NumberStateResponse final : public StateResponseProtoMessage {
#endif
float state{0.0f};
bool missing_state{false};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1555,8 +1555,8 @@ class ListEntitiesSelectResponse final : public InfoResponseProtoMessage {
const char *message_name() const override { return "list_entities_select_response"; }
#endif
const FixedVector<const char *> *options{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1572,8 +1572,8 @@ class SelectStateResponse final : public StateResponseProtoMessage {
#endif
StringRef state{};
bool missing_state{false};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1609,8 +1609,8 @@ class ListEntitiesSirenResponse final : public InfoResponseProtoMessage {
const FixedVector<const char *> *tones{};
bool supports_duration{false};
bool supports_volume{false};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1625,8 +1625,8 @@ class SirenStateResponse final : public StateResponseProtoMessage {
const char *message_name() const override { return "siren_state_response"; }
#endif
bool state{false};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1670,8 +1670,8 @@ class ListEntitiesLockResponse final : public InfoResponseProtoMessage {
bool supports_open{false};
bool requires_code{false};
StringRef code_format{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1686,8 +1686,8 @@ class LockStateResponse final : public StateResponseProtoMessage {
const char *message_name() const override { return "lock_state_response"; }
#endif
enums::LockState state{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1723,8 +1723,8 @@ class ListEntitiesButtonResponse final : public InfoResponseProtoMessage {
const char *message_name() const override { return "list_entities_button_response"; }
#endif
StringRef device_class{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1755,8 +1755,8 @@ class MediaPlayerSupportedFormat final : public ProtoMessage {
uint32_t num_channels{0};
enums::MediaPlayerFormatPurpose purpose{};
uint32_t sample_bytes{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1773,8 +1773,8 @@ class ListEntitiesMediaPlayerResponse final : public InfoResponseProtoMessage {
bool supports_pause{false};
std::vector<MediaPlayerSupportedFormat> supported_formats{};
uint32_t feature_flags{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1791,8 +1791,8 @@ class MediaPlayerStateResponse final : public StateResponseProtoMessage {
enums::MediaPlayerState state{};
float volume{0.0f};
bool muted{false};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1847,8 +1847,8 @@ class BluetoothLERawAdvertisement final : public ProtoMessage {
uint32_t address_type{0};
uint8_t data[62]{};
uint8_t data_len{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1864,8 +1864,8 @@ class BluetoothLERawAdvertisementsResponse final : public ProtoMessage {
#endif
std::array<BluetoothLERawAdvertisement, BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE> advertisements{};
uint16_t advertisements_len{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1901,8 +1901,8 @@ class BluetoothDeviceConnectionResponse final : public ProtoMessage {
bool connected{false};
uint32_t mtu{0};
int32_t error{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1929,8 +1929,8 @@ class BluetoothGATTDescriptor final : public ProtoMessage {
std::array<uint64_t, 2> uuid{};
uint32_t handle{0};
uint32_t short_uuid{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1944,8 +1944,8 @@ class BluetoothGATTCharacteristic final : public ProtoMessage {
uint32_t properties{0};
FixedVector<BluetoothGATTDescriptor> descriptors{};
uint32_t short_uuid{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1958,8 +1958,8 @@ class BluetoothGATTService final : public ProtoMessage {
uint32_t handle{0};
FixedVector<BluetoothGATTCharacteristic> characteristics{};
uint32_t short_uuid{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1975,8 +1975,8 @@ class BluetoothGATTGetServicesResponse final : public ProtoMessage {
#endif
uint64_t address{0};
std::vector<BluetoothGATTService> services{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -1991,8 +1991,8 @@ class BluetoothGATTGetServicesDoneResponse final : public ProtoMessage {
const char *message_name() const override { return "bluetooth_gatt_get_services_done_response"; }
#endif
uint64_t address{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2030,8 +2030,8 @@ class BluetoothGATTReadResponse final : public ProtoMessage {
this->data_ptr_ = data;
this->data_len_ = len;
}
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2125,8 +2125,8 @@ class BluetoothGATTNotifyDataResponse final : public ProtoMessage {
this->data_ptr_ = data;
this->data_len_ = len;
}
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2143,8 +2143,8 @@ class BluetoothConnectionsFreeResponse final : public ProtoMessage {
uint32_t free{0};
uint32_t limit{0};
std::array<uint64_t, BLUETOOTH_PROXY_MAX_CONNECTIONS> allocated{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2161,8 +2161,8 @@ class BluetoothGATTErrorResponse final : public ProtoMessage {
uint64_t address{0};
uint32_t handle{0};
int32_t error{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2178,8 +2178,8 @@ class BluetoothGATTWriteResponse final : public ProtoMessage {
#endif
uint64_t address{0};
uint32_t handle{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2195,8 +2195,8 @@ class BluetoothGATTNotifyResponse final : public ProtoMessage {
#endif
uint64_t address{0};
uint32_t handle{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2213,8 +2213,8 @@ class BluetoothDevicePairingResponse final : public ProtoMessage {
uint64_t address{0};
bool paired{false};
int32_t error{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2231,8 +2231,8 @@ class BluetoothDeviceUnpairingResponse final : public ProtoMessage {
uint64_t address{0};
bool success{false};
int32_t error{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2249,8 +2249,8 @@ class BluetoothDeviceClearCacheResponse final : public ProtoMessage {
uint64_t address{0};
bool success{false};
int32_t error{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2267,8 +2267,8 @@ class BluetoothScannerStateResponse final : public ProtoMessage {
enums::BluetoothScannerState state{};
enums::BluetoothScannerMode mode{};
enums::BluetoothScannerMode configured_mode{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2313,8 +2313,8 @@ class VoiceAssistantAudioSettings final : public ProtoMessage {
uint32_t noise_suppression_level{0};
uint32_t auto_gain{0};
float volume_multiplier{0.0f};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2333,8 +2333,8 @@ class VoiceAssistantRequest final : public ProtoMessage {
uint32_t flags{0};
VoiceAssistantAudioSettings audio_settings{};
StringRef wake_word_phrase{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2395,8 +2395,8 @@ class VoiceAssistantAudio final : public ProtoDecodableMessage {
const uint8_t *data{nullptr};
uint16_t data_len{0};
bool end{false};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2453,8 +2453,8 @@ class VoiceAssistantAnnounceFinished final : public ProtoMessage {
const char *message_name() const override { return "voice_assistant_announce_finished"; }
#endif
bool success{false};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2466,8 +2466,8 @@ class VoiceAssistantWakeWord final : public ProtoMessage {
StringRef id{};
StringRef wake_word{};
std::vector<std::string> trained_languages{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2516,8 +2516,8 @@ class VoiceAssistantConfigurationResponse final : public ProtoMessage {
std::vector<VoiceAssistantWakeWord> available_wake_words{};
const std::vector<std::string> *active_wake_words{};
uint32_t max_active_wake_words{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2551,8 +2551,8 @@ class ListEntitiesAlarmControlPanelResponse final : public InfoResponseProtoMess
uint32_t supported_features{0};
bool requires_code{false};
bool requires_code_to_arm{false};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2567,8 +2567,8 @@ class AlarmControlPanelStateResponse final : public StateResponseProtoMessage {
const char *message_name() const override { return "alarm_control_panel_state_response"; }
#endif
enums::AlarmControlPanelState state{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2606,8 +2606,8 @@ class ListEntitiesTextResponse final : public InfoResponseProtoMessage {
uint32_t max_length{0};
StringRef pattern{};
enums::TextMode mode{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2623,8 +2623,8 @@ class TextStateResponse final : public StateResponseProtoMessage {
#endif
StringRef state{};
bool missing_state{false};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2657,8 +2657,8 @@ class ListEntitiesDateResponse final : public InfoResponseProtoMessage {
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "list_entities_date_response"; }
#endif
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2676,8 +2676,8 @@ class DateStateResponse final : public StateResponseProtoMessage {
uint32_t year{0};
uint32_t month{0};
uint32_t day{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2711,8 +2711,8 @@ class ListEntitiesTimeResponse final : public InfoResponseProtoMessage {
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "list_entities_time_response"; }
#endif
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2730,8 +2730,8 @@ class TimeStateResponse final : public StateResponseProtoMessage {
uint32_t hour{0};
uint32_t minute{0};
uint32_t second{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2767,8 +2767,8 @@ class ListEntitiesEventResponse final : public InfoResponseProtoMessage {
#endif
StringRef device_class{};
const FixedVector<const char *> *event_types{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2783,8 +2783,8 @@ class EventResponse final : public StateResponseProtoMessage {
const char *message_name() const override { return "event_response"; }
#endif
StringRef event_type{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2804,8 +2804,8 @@ class ListEntitiesValveResponse final : public InfoResponseProtoMessage {
bool assumed_state{false};
bool supports_position{false};
bool supports_stop{false};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2821,8 +2821,8 @@ class ValveStateResponse final : public StateResponseProtoMessage {
#endif
float position{0.0f};
enums::ValveOperation current_operation{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2856,8 +2856,8 @@ class ListEntitiesDateTimeResponse final : public InfoResponseProtoMessage {
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "list_entities_date_time_response"; }
#endif
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2873,8 +2873,8 @@ class DateTimeStateResponse final : public StateResponseProtoMessage {
#endif
bool missing_state{false};
uint32_t epoch_seconds{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2907,8 +2907,8 @@ class ListEntitiesUpdateResponse final : public InfoResponseProtoMessage {
const char *message_name() const override { return "list_entities_update_response"; }
#endif
StringRef device_class{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2931,8 +2931,8 @@ class UpdateStateResponse final : public StateResponseProtoMessage {
StringRef title{};
StringRef release_summary{};
StringRef release_url{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2966,8 +2966,8 @@ class ZWaveProxyFrame final : public ProtoDecodableMessage {
#endif
const uint8_t *data{nullptr};
uint16_t data_len{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -2985,8 +2985,8 @@ class ZWaveProxyRequest final : public ProtoDecodableMessage {
enums::ZWaveProxyRequestType type{};
const uint8_t *data{nullptr};
uint16_t data_len{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -3005,8 +3005,8 @@ class ListEntitiesInfraredResponse final : public InfoResponseProtoMessage {
const char *message_name() const override { return "list_entities_infrared_response"; }
#endif
uint32_t capabilities{0};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
@@ -3052,8 +3052,8 @@ class InfraredRFReceiveEvent final : public ProtoMessage {
#endif
uint32_t key{0};
const std::vector<int32_t> *timings{};
void encode(ProtoWriteBuffer &buffer) const override;
void calculate_size(ProtoSize &size) const override;
void encode(ProtoWriteBuffer &buffer) const;
uint32_t calculate_size() const;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif

View File

@@ -19,14 +19,6 @@ class APIServerConnectionBase : public ProtoService {
public:
#endif
bool send_message(const ProtoMessage &msg, uint8_t message_type) {
#ifdef HAS_PROTO_MESSAGE_DUMP
DumpBuffer dump_buf;
this->log_send_message_(msg.message_name(), msg.dump_to(dump_buf));
#endif
return this->send_message_impl(msg, message_type);
}
virtual void on_hello_request(const HelloRequest &value){};
virtual void on_disconnect_request(){};

View File

@@ -359,11 +359,11 @@ void APIServer::on_update(update::UpdateEntity *obj) {
#endif
#ifdef USE_ZWAVE_PROXY
void APIServer::on_zwave_proxy_request(const esphome::api::ProtoMessage &msg) {
void APIServer::on_zwave_proxy_request(const ZWaveProxyRequest &msg) {
// We could add code to manage a second subscription type, but, since this message type is
// very infrequent and small, we simply send it to all clients
for (auto &c : this->clients_)
c->send_message(msg, api::ZWaveProxyRequest::MESSAGE_TYPE);
c->send_message(msg);
}
#endif
@@ -531,7 +531,7 @@ bool APIServer::update_noise_psk_(const SavedNoisePsk &new_psk, const LogString
this->set_noise_psk(active_psk);
for (auto &c : this->clients_) {
DisconnectRequest req;
c->send_message(req, DisconnectRequest::MESSAGE_TYPE);
c->send_message(req);
}
});
}
@@ -631,7 +631,7 @@ void APIServer::on_shutdown() {
// Send disconnect requests to all connected clients
for (auto &c : this->clients_) {
DisconnectRequest req;
if (!c->send_message(req, DisconnectRequest::MESSAGE_TYPE)) {
if (!c->send_message(req)) {
// If we can't send the disconnect request directly (tx_buffer full),
// schedule it at the front of the batch so it will be sent with priority
c->schedule_message_front_(nullptr, DisconnectRequest::MESSAGE_TYPE, DisconnectRequest::ESTIMATED_SIZE);

View File

@@ -179,7 +179,7 @@ class APIServer : public Component,
void on_update(update::UpdateEntity *obj) override;
#endif
#ifdef USE_ZWAVE_PROXY
void on_zwave_proxy_request(const esphome::api::ProtoMessage &msg);
void on_zwave_proxy_request(const ZWaveProxyRequest &msg);
#endif
#ifdef USE_IR_RF
void send_infrared_rf_receive_event(uint32_t device_id, uint32_t key, const std::vector<int32_t> *timings);

View File

@@ -94,7 +94,7 @@ ListEntitiesIterator::ListEntitiesIterator(APIConnection *client) : client_(clie
#ifdef USE_API_USER_DEFINED_ACTIONS
bool ListEntitiesIterator::on_service(UserServiceDescriptor *service) {
auto resp = service->encode_list_service_response();
return this->client_->send_message(resp, ListEntitiesServicesResponse::MESSAGE_TYPE);
return this->client_->send_message(resp);
}
#endif

View File

@@ -364,7 +364,11 @@ class ProtoWriteBuffer {
/// Encode a packed repeated sint32 field (zero-copy from vector)
void encode_packed_sint32(uint32_t field_id, const std::vector<int32_t> &values);
/// Encode a nested message field (force=true for repeated, false for singular)
void encode_message(uint32_t field_id, const ProtoMessage &value, bool force = true);
/// Templated so concrete message type is preserved for direct encode/calculate_size calls.
template<typename T> void encode_message(uint32_t field_id, const T &value, bool force = true);
// Non-template core for encode_message — all buffer work happens here
void encode_message(uint32_t field_id, uint32_t msg_length_bytes, const void *value,
void (*encode_fn)(const void *, ProtoWriteBuffer &), bool force);
std::vector<uint8_t> *get_buffer() const { return buffer_; }
protected:
@@ -452,20 +456,20 @@ class DumpBuffer {
class ProtoMessage {
public:
// Default implementation for messages with no fields
virtual void encode(ProtoWriteBuffer &buffer) const {}
// Default implementation for messages with no fields
virtual void calculate_size(ProtoSize &size) const {}
// Convenience: calculate and return size directly (defined after ProtoSize)
uint32_t calculated_size() const;
// Non-virtual defaults for messages with no fields.
// Concrete message classes hide these with their own implementations.
// All call sites use templates to preserve the concrete type, so virtual
// dispatch is not needed. This eliminates per-message vtable entries for
// encode/calculate_size, saving ~1.3 KB of flash across all message types.
void encode(ProtoWriteBuffer &buffer) const {}
uint32_t calculate_size() const { return 0; }
#ifdef HAS_PROTO_MESSAGE_DUMP
virtual const char *dump_to(DumpBuffer &out) const = 0;
virtual const char *message_name() const { return "unknown"; }
#endif
protected:
// Non-virtual: messages are never deleted polymorphically.
// Protected prevents accidental `delete base_ptr` (compile error).
// Non-virtual destructor is protected to prevent polymorphic deletion.
~ProtoMessage() = default;
};
@@ -494,32 +498,7 @@ class ProtoDecodableMessage : public ProtoMessage {
};
class ProtoSize {
private:
uint32_t total_size_ = 0;
public:
/**
* @brief ProtoSize class for Protocol Buffer serialization size calculation
*
* This class provides methods to calculate the exact byte counts needed
* for encoding various Protocol Buffer field types. The class now uses an
* object-based approach to reduce parameter passing overhead while keeping
* varint calculation methods static for external use.
*
* Implements Protocol Buffer encoding size calculation according to:
* https://protobuf.dev/programming-guides/encoding/
*
* Key features:
* - Object-based approach reduces flash usage by eliminating parameter passing
* - Early-return optimization for zero/default values
* - Static varint methods for external callers
* - Specialized handling for different field types according to protobuf spec
*/
ProtoSize() = default;
uint32_t get_size() const { return total_size_; }
/**
* @brief Calculates the size in bytes needed to encode a uint32_t value as a varint
*
@@ -616,320 +595,77 @@ class ProtoSize {
return varint(tag);
}
/**
* @brief Common parameters for all add_*_field methods
*
* All add_*_field methods follow these common patterns:
* * @param field_id_size Pre-calculated size of the field ID in bytes
* @param value The value to calculate size for (type varies)
* @param force Whether to calculate size even if the value is default/zero/empty
*
* Each method follows this implementation pattern:
* 1. Skip calculation if value is default (0, false, empty) and not forced
* 2. Calculate the size based on the field's encoding rules
* 3. Add the field_id_size + calculated value size to total_size
*/
/**
* @brief Calculates and adds the size of an int32 field to the total message size
*/
inline void add_int32(uint32_t field_id_size, int32_t value) {
if (value != 0) {
add_int32_force(field_id_size, value);
}
// Static methods that RETURN size contribution (no ProtoSize object needed).
// Used by generated calculate_size() methods to accumulate into a plain uint32_t register.
static constexpr uint32_t calc_int32(uint32_t field_id_size, int32_t value) {
return value ? field_id_size + (value < 0 ? 10 : varint(static_cast<uint32_t>(value))) : 0;
}
/**
* @brief Calculates and adds the size of an int32 field to the total message size (force version)
*/
inline void add_int32_force(uint32_t field_id_size, int32_t value) {
// Always calculate size when forced
// Negative values are encoded as 10-byte varints in protobuf
total_size_ += field_id_size + (value < 0 ? 10 : varint(static_cast<uint32_t>(value)));
static constexpr uint32_t calc_int32_force(uint32_t field_id_size, int32_t value) {
return field_id_size + (value < 0 ? 10 : varint(static_cast<uint32_t>(value)));
}
/**
* @brief Calculates and adds the size of a uint32 field to the total message size
*/
inline void add_uint32(uint32_t field_id_size, uint32_t value) {
if (value != 0) {
add_uint32_force(field_id_size, value);
}
static constexpr uint32_t calc_uint32(uint32_t field_id_size, uint32_t value) {
return value ? field_id_size + varint(value) : 0;
}
/**
* @brief Calculates and adds the size of a uint32 field to the total message size (force version)
*/
inline void add_uint32_force(uint32_t field_id_size, uint32_t value) {
// Always calculate size when force is true
total_size_ += field_id_size + varint(value);
static constexpr uint32_t calc_uint32_force(uint32_t field_id_size, uint32_t value) {
return field_id_size + varint(value);
}
/**
* @brief Calculates and adds the size of a boolean field to the total message size
*/
inline void add_bool(uint32_t field_id_size, bool value) {
if (value) {
// Boolean fields always use 1 byte when true
total_size_ += field_id_size + 1;
}
static constexpr uint32_t calc_bool(uint32_t field_id_size, bool value) { return value ? field_id_size + 1 : 0; }
static constexpr uint32_t calc_bool_force(uint32_t field_id_size) { return field_id_size + 1; }
static constexpr uint32_t calc_float(uint32_t field_id_size, float value) {
return value != 0.0f ? field_id_size + 4 : 0;
}
/**
* @brief Calculates and adds the size of a boolean field to the total message size (force version)
*/
inline void add_bool_force(uint32_t field_id_size, bool value) {
// Always calculate size when force is true
// Boolean fields always use 1 byte
total_size_ += field_id_size + 1;
static constexpr uint32_t calc_fixed32(uint32_t field_id_size, uint32_t value) {
return value ? field_id_size + 4 : 0;
}
/**
* @brief Calculates and adds the size of a float field to the total message size
*/
inline void add_float(uint32_t field_id_size, float value) {
if (value != 0.0f) {
total_size_ += field_id_size + 4;
}
static constexpr uint32_t calc_sfixed32(uint32_t field_id_size, int32_t value) {
return value ? field_id_size + 4 : 0;
}
// NOTE: add_double_field removed - wire type 1 (64-bit: double) not supported
// to reduce overhead on embedded systems
/**
* @brief Calculates and adds the size of a fixed32 field to the total message size
*/
inline void add_fixed32(uint32_t field_id_size, uint32_t value) {
if (value != 0) {
total_size_ += field_id_size + 4;
}
static constexpr uint32_t calc_sint32(uint32_t field_id_size, int32_t value) {
return value ? field_id_size + varint(encode_zigzag32(value)) : 0;
}
// NOTE: add_fixed64_field removed - wire type 1 (64-bit: fixed64) not supported
// to reduce overhead on embedded systems
/**
* @brief Calculates and adds the size of a sfixed32 field to the total message size
*/
inline void add_sfixed32(uint32_t field_id_size, int32_t value) {
if (value != 0) {
total_size_ += field_id_size + 4;
}
static constexpr uint32_t calc_sint32_force(uint32_t field_id_size, int32_t value) {
return field_id_size + varint(encode_zigzag32(value));
}
// NOTE: add_sfixed64_field removed - wire type 1 (64-bit: sfixed64) not supported
// to reduce overhead on embedded systems
/**
* @brief Calculates and adds the size of a sint32 field to the total message size
*
* Sint32 fields use ZigZag encoding, which is more efficient for negative values.
*/
inline void add_sint32(uint32_t field_id_size, int32_t value) {
if (value != 0) {
add_sint32_force(field_id_size, value);
}
static constexpr uint32_t calc_int64(uint32_t field_id_size, int64_t value) {
return value ? field_id_size + varint(value) : 0;
}
/**
* @brief Calculates and adds the size of a sint32 field to the total message size (force version)
*
* Sint32 fields use ZigZag encoding, which is more efficient for negative values.
*/
inline void add_sint32_force(uint32_t field_id_size, int32_t value) {
// Always calculate size when force is true
// ZigZag encoding for sint32
total_size_ += field_id_size + varint(encode_zigzag32(value));
static constexpr uint32_t calc_int64_force(uint32_t field_id_size, int64_t value) {
return field_id_size + varint(value);
}
/**
* @brief Calculates and adds the size of an int64 field to the total message size
*/
inline void add_int64(uint32_t field_id_size, int64_t value) {
if (value != 0) {
add_int64_force(field_id_size, value);
}
static constexpr uint32_t calc_uint64(uint32_t field_id_size, uint64_t value) {
return value ? field_id_size + varint(value) : 0;
}
/**
* @brief Calculates and adds the size of an int64 field to the total message size (force version)
*/
inline void add_int64_force(uint32_t field_id_size, int64_t value) {
// Always calculate size when force is true
total_size_ += field_id_size + varint(value);
static constexpr uint32_t calc_uint64_force(uint32_t field_id_size, uint64_t value) {
return field_id_size + varint(value);
}
/**
* @brief Calculates and adds the size of a uint64 field to the total message size
*/
inline void add_uint64(uint32_t field_id_size, uint64_t value) {
if (value != 0) {
add_uint64_force(field_id_size, value);
}
static constexpr uint32_t calc_length(uint32_t field_id_size, size_t len) {
return len ? field_id_size + varint(static_cast<uint32_t>(len)) + static_cast<uint32_t>(len) : 0;
}
/**
* @brief Calculates and adds the size of a uint64 field to the total message size (force version)
*/
inline void add_uint64_force(uint32_t field_id_size, uint64_t value) {
// Always calculate size when force is true
total_size_ += field_id_size + varint(value);
static constexpr uint32_t calc_length_force(uint32_t field_id_size, size_t len) {
return field_id_size + varint(static_cast<uint32_t>(len)) + static_cast<uint32_t>(len);
}
// NOTE: sint64 support functions (add_sint64_field, add_sint64_field_force) removed
// sint64 type is not supported by ESPHome API to reduce overhead on embedded systems
/**
* @brief Calculates and adds the size of a length-delimited field (string/bytes) to the total message size
*/
inline void add_length(uint32_t field_id_size, size_t len) {
if (len != 0) {
add_length_force(field_id_size, len);
}
static constexpr uint32_t calc_sint64(uint32_t field_id_size, int64_t value) {
return value ? field_id_size + varint(encode_zigzag64(value)) : 0;
}
/**
* @brief Calculates and adds the size of a length-delimited field (string/bytes) to the total message size (repeated
* field version)
*/
inline void add_length_force(uint32_t field_id_size, size_t len) {
// Always calculate size when force is true
// Field ID + length varint + data bytes
total_size_ += field_id_size + varint(static_cast<uint32_t>(len)) + static_cast<uint32_t>(len);
static constexpr uint32_t calc_sint64_force(uint32_t field_id_size, int64_t value) {
return field_id_size + varint(encode_zigzag64(value));
}
/**
* @brief Adds a pre-calculated size directly to the total
*
* This is used when we can calculate the total size by multiplying the number
* of elements by the bytes per element (for repeated fixed-size types like float, fixed32, etc.)
*
* @param size The pre-calculated total size to add
*/
inline void add_precalculated_size(uint32_t size) { total_size_ += size; }
/**
* @brief Calculates and adds the size of a nested message field to the total message size
*
* This helper function directly updates the total_size reference if the nested size
* is greater than zero.
*
* @param nested_size The pre-calculated size of the nested message
*/
inline void add_message_field(uint32_t field_id_size, uint32_t nested_size) {
if (nested_size != 0) {
add_message_field_force(field_id_size, nested_size);
}
static constexpr uint32_t calc_fixed64(uint32_t field_id_size, uint64_t value) {
return value ? field_id_size + 8 : 0;
}
/**
* @brief Calculates and adds the size of a nested message field to the total message size (force version)
*
* @param nested_size The pre-calculated size of the nested message
*/
inline void add_message_field_force(uint32_t field_id_size, uint32_t nested_size) {
// Always calculate size when force is true
// Field ID + length varint + nested message content
total_size_ += field_id_size + varint(nested_size) + nested_size;
static constexpr uint32_t calc_sfixed64(uint32_t field_id_size, int64_t value) {
return value ? field_id_size + 8 : 0;
}
/**
* @brief Calculates and adds the size of a nested message field to the total message size
*
* This version takes a ProtoMessage object, calculates its size internally,
* and updates the total_size reference. This eliminates the need for a temporary variable
* at the call site.
*
* @param message The nested message object
*/
inline void add_message_object(uint32_t field_id_size, const ProtoMessage &message) {
// Calculate nested message size by creating a temporary ProtoSize
ProtoSize nested_calc;
message.calculate_size(nested_calc);
uint32_t nested_size = nested_calc.get_size();
// Use the base implementation with the calculated nested_size
add_message_field(field_id_size, nested_size);
static constexpr uint32_t calc_message(uint32_t field_id_size, uint32_t nested_size) {
return nested_size ? field_id_size + varint(nested_size) + nested_size : 0;
}
/**
* @brief Calculates and adds the size of a nested message field to the total message size (force version)
*
* @param message The nested message object
*/
inline void add_message_object_force(uint32_t field_id_size, const ProtoMessage &message) {
// Calculate nested message size by creating a temporary ProtoSize
ProtoSize nested_calc;
message.calculate_size(nested_calc);
uint32_t nested_size = nested_calc.get_size();
// Use the base implementation with the calculated nested_size
add_message_field_force(field_id_size, nested_size);
}
/**
* @brief Calculates and adds the sizes of all messages in a repeated field to the total message size
*
* This helper processes a vector of message objects, calculating the size for each message
* and adding it to the total size.
*
* @tparam MessageType The type of the nested messages in the vector
* @param messages Vector of message objects
*/
template<typename MessageType>
inline void add_repeated_message(uint32_t field_id_size, const std::vector<MessageType> &messages) {
// Skip if the vector is empty
if (!messages.empty()) {
// Use the force version for all messages in the repeated field
for (const auto &message : messages) {
add_message_object_force(field_id_size, message);
}
}
}
/**
* @brief Calculates and adds the sizes of all messages in a repeated field to the total message size (FixedVector
* version)
*
* @tparam MessageType The type of the nested messages in the FixedVector
* @param messages FixedVector of message objects
*/
template<typename MessageType>
inline void add_repeated_message(uint32_t field_id_size, const FixedVector<MessageType> &messages) {
// Skip if the fixed vector is empty
if (!messages.empty()) {
// Use the force version for all messages in the repeated field
for (const auto &message : messages) {
add_message_object_force(field_id_size, message);
}
}
}
/**
* @brief Calculate size of a packed repeated sint32 field
*/
inline void add_packed_sint32(uint32_t field_id_size, const std::vector<int32_t> &values) {
if (values.empty())
return;
size_t packed_size = 0;
for (int value : values) {
packed_size += varint(encode_zigzag32(value));
}
// field_id + length varint + packed data
total_size_ += field_id_size + varint(static_cast<uint32_t>(packed_size)) + static_cast<uint32_t>(packed_size);
static constexpr uint32_t calc_message_force(uint32_t field_id_size, uint32_t nested_size) {
return field_id_size + varint(nested_size) + nested_size;
}
};
// Implementation of methods that depend on ProtoSize being fully defined
inline uint32_t ProtoMessage::calculated_size() const {
ProtoSize size;
this->calculate_size(size);
return size.get_size();
}
// Implementation of encode_packed_sint32 - must be after ProtoSize is defined
inline void ProtoWriteBuffer::encode_packed_sint32(uint32_t field_id, const std::vector<int32_t> &values) {
if (values.empty())
@@ -949,31 +685,30 @@ inline void ProtoWriteBuffer::encode_packed_sint32(uint32_t field_id, const std:
}
}
// Implementation of encode_message - must be after ProtoMessage is defined
inline void ProtoWriteBuffer::encode_message(uint32_t field_id, const ProtoMessage &value, bool force) {
// Calculate the message size first
ProtoSize msg_size;
value.calculate_size(msg_size);
uint32_t msg_length_bytes = msg_size.get_size();
// Encode thunk — converts void* back to concrete type for direct encode() call
template<typename T> void proto_encode_msg(const void *msg, ProtoWriteBuffer &buf) {
static_cast<const T *>(msg)->encode(buf);
}
// Skip empty singular messages (matches add_message_field which skips when nested_size == 0)
// Repeated messages (force=true) are always encoded since an empty item is meaningful
// Implementation of encode_message - must be after ProtoMessage is defined
template<typename T> inline void ProtoWriteBuffer::encode_message(uint32_t field_id, const T &value, bool force) {
this->encode_message(field_id, value.calculate_size(), &value, &proto_encode_msg<T>, force);
}
// Non-template core for encode_message
inline void ProtoWriteBuffer::encode_message(uint32_t field_id, uint32_t msg_length_bytes, const void *value,
void (*encode_fn)(const void *, ProtoWriteBuffer &), bool force) {
if (msg_length_bytes == 0 && !force)
return;
this->encode_field_raw(field_id, 2); // type 2: Length-delimited message
// Write the length varint directly through pos_
this->encode_field_raw(field_id, 2);
this->encode_varint_raw(msg_length_bytes);
// Encode nested message - pos_ advances directly through the reference
#ifdef ESPHOME_DEBUG_API
uint8_t *start = this->pos_;
value.encode(*this);
encode_fn(value, *this);
if (static_cast<uint32_t>(this->pos_ - start) != msg_length_bytes)
this->debug_check_encode_size_(field_id, msg_length_bytes, this->pos_ - start);
#else
value.encode(*this);
encode_fn(value, *this);
#endif
}
@@ -993,14 +728,6 @@ class ProtoService {
virtual void on_no_setup_connection() = 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;
/**
* Send a protobuf message by calculating its size, allocating a buffer, encoding, and sending.
* This is the implementation method - callers should use send_message() which adds logging.
* @param msg The protobuf message to send.
* @param message_type The message type identifier.
* @return True if the message was sent successfully, false otherwise.
*/
virtual bool send_message_impl(const ProtoMessage &msg, uint8_t message_type) = 0;
// Authentication helper methods
inline bool check_connection_setup_() {

View File

@@ -183,10 +183,7 @@ void BluetoothConnection::send_service_for_discovery_() {
static constexpr size_t MAX_PACKET_SIZE = 1360;
// Keep running total of actual message size
size_t current_size = 0;
api::ProtoSize size;
resp.calculate_size(size);
current_size = size.get_size();
size_t current_size = resp.calculate_size();
while (this->send_service_ < this->service_count_) {
esp_gattc_service_elem_t service_result;
@@ -302,9 +299,7 @@ void BluetoothConnection::send_service_for_discovery_() {
} // end if (total_char_count > 0)
// Calculate the actual size of just this service
api::ProtoSize service_sizer;
service_resp.calculate_size(service_sizer);
size_t service_size = service_sizer.get_size() + 1; // +1 for field tag
size_t service_size = service_resp.calculate_size() + 1; // +1 for field tag
// Check if adding this service would exceed the limit
if (current_size + service_size > MAX_PACKET_SIZE) {
@@ -333,7 +328,7 @@ void BluetoothConnection::send_service_for_discovery_() {
}
// Send the message with dynamically batched services
api_conn->send_message(resp, api::BluetoothGATTGetServicesResponse::MESSAGE_TYPE);
api_conn->send_message(resp);
}
void BluetoothConnection::log_connection_error_(const char *operation, esp_gatt_status_t status) {
@@ -422,7 +417,7 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
resp.address = this->address_;
resp.handle = param->read.handle;
resp.set_data(param->read.value, param->read.value_len);
api_connection->send_message(resp, api::BluetoothGATTReadResponse::MESSAGE_TYPE);
api_connection->send_message(resp);
break;
}
case ESP_GATTC_WRITE_CHAR_EVT:
@@ -438,7 +433,7 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
api::BluetoothGATTWriteResponse resp;
resp.address = this->address_;
resp.handle = param->write.handle;
api_connection->send_message(resp, api::BluetoothGATTWriteResponse::MESSAGE_TYPE);
api_connection->send_message(resp);
break;
}
case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: {
@@ -454,7 +449,7 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
api::BluetoothGATTNotifyResponse resp;
resp.address = this->address_;
resp.handle = param->unreg_for_notify.handle;
api_connection->send_message(resp, api::BluetoothGATTNotifyResponse::MESSAGE_TYPE);
api_connection->send_message(resp);
break;
}
case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
@@ -470,7 +465,7 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
api::BluetoothGATTNotifyResponse resp;
resp.address = this->address_;
resp.handle = param->reg_for_notify.handle;
api_connection->send_message(resp, api::BluetoothGATTNotifyResponse::MESSAGE_TYPE);
api_connection->send_message(resp);
break;
}
case ESP_GATTC_NOTIFY_EVT: {
@@ -483,7 +478,7 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
resp.address = this->address_;
resp.handle = param->notify.handle;
resp.set_data(param->notify.value, param->notify.value_len);
api_connection->send_message(resp, api::BluetoothGATTNotifyDataResponse::MESSAGE_TYPE);
api_connection->send_message(resp);
break;
}
default:

View File

@@ -44,7 +44,7 @@ void BluetoothProxy::send_bluetooth_scanner_state_(esp32_ble_tracker::ScannerSta
resp.configured_mode = this->configured_scan_active_
? api::enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_ACTIVE
: api::enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_PASSIVE;
this->api_connection_->send_message(resp, api::BluetoothScannerStateResponse::MESSAGE_TYPE);
this->api_connection_->send_message(resp);
}
void BluetoothProxy::log_connection_request_ignored_(BluetoothConnection *connection, espbt::ClientState state) {
@@ -112,7 +112,7 @@ void BluetoothProxy::flush_pending_advertisements() {
return;
// Send the message
this->api_connection_->send_message(this->response_, api::BluetoothLERawAdvertisementsResponse::MESSAGE_TYPE);
this->api_connection_->send_message(this->response_);
ESP_LOGV(TAG, "Sent batch of %u BLE advertisements", this->response_.advertisements_len);
@@ -269,7 +269,7 @@ void BluetoothProxy::bluetooth_device_request(const api::BluetoothDeviceRequest
call.success = ret == ESP_OK;
call.error = ret;
this->api_connection_->send_message(call, api::BluetoothDeviceClearCacheResponse::MESSAGE_TYPE);
this->api_connection_->send_message(call);
break;
}
@@ -389,7 +389,7 @@ void BluetoothProxy::send_device_connection(uint64_t address, bool connected, ui
call.connected = connected;
call.mtu = mtu;
call.error = error;
this->api_connection_->send_message(call, api::BluetoothDeviceConnectionResponse::MESSAGE_TYPE);
this->api_connection_->send_message(call);
}
void BluetoothProxy::send_connections_free() {
if (this->api_connection_ != nullptr) {
@@ -398,7 +398,7 @@ void BluetoothProxy::send_connections_free() {
}
void BluetoothProxy::send_connections_free(api::APIConnection *api_connection) {
api_connection->send_message(this->connections_free_response_, api::BluetoothConnectionsFreeResponse::MESSAGE_TYPE);
api_connection->send_message(this->connections_free_response_);
}
void BluetoothProxy::send_gatt_services_done(uint64_t address) {
@@ -406,7 +406,7 @@ void BluetoothProxy::send_gatt_services_done(uint64_t address) {
return;
api::BluetoothGATTGetServicesDoneResponse call;
call.address = address;
this->api_connection_->send_message(call, api::BluetoothGATTGetServicesDoneResponse::MESSAGE_TYPE);
this->api_connection_->send_message(call);
}
void BluetoothProxy::send_gatt_error(uint64_t address, uint16_t handle, esp_err_t error) {
@@ -416,7 +416,7 @@ void BluetoothProxy::send_gatt_error(uint64_t address, uint16_t handle, esp_err_
call.address = address;
call.handle = handle;
call.error = error;
this->api_connection_->send_message(call, api::BluetoothGATTWriteResponse::MESSAGE_TYPE);
this->api_connection_->send_message(call);
}
void BluetoothProxy::send_device_pairing(uint64_t address, bool paired, esp_err_t error) {
@@ -427,7 +427,7 @@ void BluetoothProxy::send_device_pairing(uint64_t address, bool paired, esp_err_
call.paired = paired;
call.error = error;
this->api_connection_->send_message(call, api::BluetoothDevicePairingResponse::MESSAGE_TYPE);
this->api_connection_->send_message(call);
}
void BluetoothProxy::send_device_unpairing(uint64_t address, bool success, esp_err_t error) {
@@ -438,7 +438,7 @@ void BluetoothProxy::send_device_unpairing(uint64_t address, bool success, esp_e
call.success = success;
call.error = error;
this->api_connection_->send_message(call, api::BluetoothDeviceUnpairingResponse::MESSAGE_TYPE);
this->api_connection_->send_message(call);
}
void BluetoothProxy::bluetooth_scanner_set_mode(bool active) {

View File

@@ -251,8 +251,7 @@ void VoiceAssistant::loop() {
}
#endif
if (this->api_client_ == nullptr ||
!this->api_client_->send_message(msg, api::VoiceAssistantRequest::MESSAGE_TYPE)) {
if (this->api_client_ == nullptr || !this->api_client_->send_message(msg)) {
ESP_LOGW(TAG, "Could not request start");
this->error_trigger_.trigger("not-connected", "Could not request start");
this->continuous_ = false;
@@ -275,7 +274,7 @@ void VoiceAssistant::loop() {
api::VoiceAssistantAudio msg;
msg.data = this->send_buffer_;
msg.data_len = read_bytes;
this->api_client_->send_message(msg, api::VoiceAssistantAudio::MESSAGE_TYPE);
this->api_client_->send_message(msg);
} else {
if (!this->udp_socket_running_) {
if (!this->start_udp_socket_()) {
@@ -354,7 +353,7 @@ void VoiceAssistant::loop() {
api::VoiceAssistantAnnounceFinished msg;
msg.success = true;
this->api_client_->send_message(msg, api::VoiceAssistantAnnounceFinished::MESSAGE_TYPE);
this->api_client_->send_message(msg);
break;
}
}
@@ -612,7 +611,7 @@ void VoiceAssistant::signal_stop_() {
ESP_LOGD(TAG, "Signaling stop");
api::VoiceAssistantRequest msg;
msg.start = false;
this->api_client_->send_message(msg, api::VoiceAssistantRequest::MESSAGE_TYPE);
this->api_client_->send_message(msg);
}
void VoiceAssistant::start_playback_timeout_() {
@@ -622,7 +621,7 @@ void VoiceAssistant::start_playback_timeout_() {
api::VoiceAssistantAnnounceFinished msg;
msg.success = true;
this->api_client_->send_message(msg, api::VoiceAssistantAnnounceFinished::MESSAGE_TYPE);
this->api_client_->send_message(msg);
});
}

View File

@@ -119,7 +119,7 @@ void ZWaveProxy::process_uart_() {
// If this is a data frame, use frame length indicator + 2 (for SoF + checksum), else assume 1 for ACK/NAK/CAN
this->outgoing_proto_msg_.data_len = this->buffer_[0] == ZWAVE_FRAME_TYPE_START ? this->buffer_[1] + 2 : 1;
}
this->api_connection_->send_message(this->outgoing_proto_msg_, api::ZWaveProxyFrame::MESSAGE_TYPE);
this->api_connection_->send_message(this->outgoing_proto_msg_);
}
}
}
@@ -209,7 +209,7 @@ void ZWaveProxy::send_homeid_changed_msg_(api::APIConnection *conn) {
msg.data_len = this->home_id_.size();
if (conn != nullptr) {
// Send to specific connection
conn->send_message(msg, api::ZWaveProxyRequest::MESSAGE_TYPE);
conn->send_message(msg);
} else if (api::global_api_server != nullptr) {
// We could add code to manage a second subscription type, but, since this message is
// very infrequent and small, we simply send it to all clients
@@ -346,7 +346,7 @@ void ZWaveProxy::parse_start_(uint8_t byte) {
this->buffer_[0] = byte;
this->outgoing_proto_msg_.data = this->buffer_.data();
this->outgoing_proto_msg_.data_len = 1;
this->api_connection_->send_message(this->outgoing_proto_msg_, api::ZWaveProxyFrame::MESSAGE_TYPE);
this->api_connection_->send_message(this->outgoing_proto_msg_);
}
}

View File

@@ -270,18 +270,21 @@ class TypeInfo(ABC):
def _get_simple_size_calculation(
self, name: str, force: bool, base_method: str, value_expr: str = None
) -> str:
"""Helper for simple size calculations.
"""Helper for simple size calculations using static ProtoSize methods.
Args:
name: Field name
force: Whether this is for a repeated field
base_method: Base method name (e.g., "add_int32")
base_method: Base method name (e.g., "int32")
value_expr: Optional value expression (defaults to name)
"""
field_id_size = self.calculate_field_id_size()
method = f"{base_method}_force" if force else base_method
method = f"calc_{base_method}_force" if force else f"calc_{base_method}"
# calc_bool_force only takes field_id_size (no value needed - bool is always 1 byte)
if base_method == "bool" and force:
return f"size += ProtoSize::{method}({field_id_size});"
value = value_expr or name
return f"size.{method}({field_id_size}, {value});"
return f"size += ProtoSize::{method}({field_id_size}, {value});"
@abstractmethod
def get_size_calculation(self, name: str, force: bool = False) -> str:
@@ -410,7 +413,7 @@ class DoubleType(TypeInfo):
def get_size_calculation(self, name: str, force: bool = False) -> str:
field_id_size = self.calculate_field_id_size()
return f"size.add_double({field_id_size}, {name});"
return f"size += ProtoSize::calc_fixed64({field_id_size}, {name});"
def get_fixed_size_bytes(self) -> int:
return 8
@@ -434,7 +437,7 @@ class FloatType(TypeInfo):
def get_size_calculation(self, name: str, force: bool = False) -> str:
field_id_size = self.calculate_field_id_size()
return f"size.add_float({field_id_size}, {name});"
return f"size += ProtoSize::calc_float({field_id_size}, {name});"
def get_fixed_size_bytes(self) -> int:
return 4
@@ -457,7 +460,7 @@ class Int64Type(TypeInfo):
return o
def get_size_calculation(self, name: str, force: bool = False) -> str:
return self._get_simple_size_calculation(name, force, "add_int64")
return self._get_simple_size_calculation(name, force, "int64")
def get_estimated_size(self) -> int:
return self.calculate_field_id_size() + 3 # field ID + 3 bytes typical varint
@@ -477,7 +480,7 @@ class UInt64Type(TypeInfo):
return o
def get_size_calculation(self, name: str, force: bool = False) -> str:
return self._get_simple_size_calculation(name, force, "add_uint64")
return self._get_simple_size_calculation(name, force, "uint64")
def get_estimated_size(self) -> int:
return self.calculate_field_id_size() + 3 # field ID + 3 bytes typical varint
@@ -497,7 +500,7 @@ class Int32Type(TypeInfo):
return o
def get_size_calculation(self, name: str, force: bool = False) -> str:
return self._get_simple_size_calculation(name, force, "add_int32")
return self._get_simple_size_calculation(name, force, "int32")
def get_estimated_size(self) -> int:
return self.calculate_field_id_size() + 3 # field ID + 3 bytes typical varint
@@ -518,7 +521,7 @@ class Fixed64Type(TypeInfo):
def get_size_calculation(self, name: str, force: bool = False) -> str:
field_id_size = self.calculate_field_id_size()
return f"size.add_fixed64({field_id_size}, {name});"
return f"size += ProtoSize::calc_fixed64({field_id_size}, {name});"
def get_fixed_size_bytes(self) -> int:
return 8
@@ -542,7 +545,7 @@ class Fixed32Type(TypeInfo):
def get_size_calculation(self, name: str, force: bool = False) -> str:
field_id_size = self.calculate_field_id_size()
return f"size.add_fixed32({field_id_size}, {name});"
return f"size += ProtoSize::calc_fixed32({field_id_size}, {name});"
def get_fixed_size_bytes(self) -> int:
return 4
@@ -563,7 +566,7 @@ class BoolType(TypeInfo):
return f"out.append(YESNO({name}));"
def get_size_calculation(self, name: str, force: bool = False) -> str:
return self._get_simple_size_calculation(name, force, "add_bool")
return self._get_simple_size_calculation(name, force, "bool")
def get_estimated_size(self) -> int:
return self.calculate_field_id_size() + 1 # field ID + 1 byte
@@ -647,18 +650,18 @@ class StringType(TypeInfo):
def get_size_calculation(self, name: str, force: bool = False) -> str:
# For SOURCE_CLIENT only messages, use the string field directly
if not self._needs_encode:
return self._get_simple_size_calculation(name, force, "add_length")
return self._get_simple_size_calculation(name, force, "length")
# Check if this is being called from a repeated field context
# In that case, 'name' will be 'it' and we need to use the repeated version
if name == "it":
# For repeated fields, we need to use add_length_force which includes field ID
# For repeated fields, we need to use length_force which includes field ID
field_id_size = self.calculate_field_id_size()
return f"size.add_length_force({field_id_size}, it.size());"
return f"size += ProtoSize::calc_length_force({field_id_size}, it.size());"
# For messages that need encoding, use the StringRef size
field_id_size = self.calculate_field_id_size()
return f"size.add_length({field_id_size}, this->{self.field_name}_ref_.size());"
return f"size += ProtoSize::calc_length({field_id_size}, this->{self.field_name}_ref_.size());"
def get_estimated_size(self) -> int:
return self.calculate_field_id_size() + 8 # field ID + 8 bytes typical string
@@ -721,7 +724,9 @@ class MessageType(TypeInfo):
return o
def get_size_calculation(self, name: str, force: bool = False) -> str:
return self._get_simple_size_calculation(name, force, "add_message_object")
field_id_size = self.calculate_field_id_size()
method = "calc_message_force" if force else "calc_message"
return f"size += ProtoSize::{method}({field_id_size}, {name}.calculate_size());"
def get_estimated_size(self) -> int:
# For message types, we can't easily estimate the submessage size without
@@ -822,7 +827,7 @@ class BytesType(TypeInfo):
)
def get_size_calculation(self, name: str, force: bool = False) -> str:
return f"size.add_length({self.calculate_field_id_size()}, this->{self.field_name}_len_);"
return f"size += ProtoSize::calc_length({self.calculate_field_id_size()}, this->{self.field_name}_len_);"
def get_estimated_size(self) -> int:
return self.calculate_field_id_size() + 8 # field ID + 8 bytes typical bytes
@@ -897,7 +902,7 @@ class PointerToBytesBufferType(PointerToBufferTypeBase):
)
def get_size_calculation(self, name: str, force: bool = False) -> str:
return f"size.add_length({self.calculate_field_id_size()}, this->{self.field_name}_len);"
return f"size += ProtoSize::calc_length({self.calculate_field_id_size()}, this->{self.field_name}_len);"
class PointerToStringBufferType(PointerToBufferTypeBase):
@@ -939,7 +944,7 @@ class PointerToStringBufferType(PointerToBufferTypeBase):
return f'dump_field(out, "{self.name}", this->{self.field_name});'
def get_size_calculation(self, name: str, force: bool = False) -> str:
return f"size.add_length({self.calculate_field_id_size()}, this->{self.field_name}.size());"
return f"size += ProtoSize::calc_length({self.calculate_field_id_size()}, this->{self.field_name}.size());"
def get_estimated_size(self) -> int:
return self.calculate_field_id_size() + 8 # field ID + 8 bytes typical string
@@ -1103,9 +1108,9 @@ class FixedArrayBytesType(TypeInfo):
if force:
# For repeated fields, always calculate size (no zero check)
return f"size.add_length_force({field_id_size}, {length_field});"
# For non-repeated fields, add_length already checks for zero
return f"size.add_length({field_id_size}, {length_field});"
return f"size += ProtoSize::calc_length_force({field_id_size}, {length_field});"
# For non-repeated fields, length already checks for zero
return f"size += ProtoSize::calc_length({field_id_size}, {length_field});"
def get_estimated_size(self) -> int:
# Estimate based on typical BLE advertisement size
@@ -1132,7 +1137,7 @@ class UInt32Type(TypeInfo):
return o
def get_size_calculation(self, name: str, force: bool = False) -> str:
return self._get_simple_size_calculation(name, force, "add_uint32")
return self._get_simple_size_calculation(name, force, "uint32")
def get_estimated_size(self) -> int:
return self.calculate_field_id_size() + 3 # field ID + 3 bytes typical varint
@@ -1168,7 +1173,7 @@ class EnumType(TypeInfo):
def get_size_calculation(self, name: str, force: bool = False) -> str:
return self._get_simple_size_calculation(
name, force, "add_uint32", f"static_cast<uint32_t>({name})"
name, force, "uint32", f"static_cast<uint32_t>({name})"
)
def get_estimated_size(self) -> int:
@@ -1190,7 +1195,7 @@ class SFixed32Type(TypeInfo):
def get_size_calculation(self, name: str, force: bool = False) -> str:
field_id_size = self.calculate_field_id_size()
return f"size.add_sfixed32({field_id_size}, {name});"
return f"size += ProtoSize::calc_sfixed32({field_id_size}, {name});"
def get_fixed_size_bytes(self) -> int:
return 4
@@ -1214,7 +1219,7 @@ class SFixed64Type(TypeInfo):
def get_size_calculation(self, name: str, force: bool = False) -> str:
field_id_size = self.calculate_field_id_size()
return f"size.add_sfixed64({field_id_size}, {name});"
return f"size += ProtoSize::calc_sfixed64({field_id_size}, {name});"
def get_fixed_size_bytes(self) -> int:
return 8
@@ -1237,7 +1242,7 @@ class SInt32Type(TypeInfo):
return o
def get_size_calculation(self, name: str, force: bool = False) -> str:
return self._get_simple_size_calculation(name, force, "add_sint32")
return self._get_simple_size_calculation(name, force, "sint32")
def get_estimated_size(self) -> int:
return self.calculate_field_id_size() + 3 # field ID + 3 bytes typical varint
@@ -1257,7 +1262,7 @@ class SInt64Type(TypeInfo):
return o
def get_size_calculation(self, name: str, force: bool = False) -> str:
return self._get_simple_size_calculation(name, force, "add_sint64")
return self._get_simple_size_calculation(name, force, "sint64")
def get_estimated_size(self) -> int:
return self.calculate_field_id_size() + 3 # field ID + 3 bytes typical varint
@@ -1694,11 +1699,17 @@ class RepeatedTypeInfo(TypeInfo):
# For repeated fields, we always need to pass force=True to the underlying type's calculation
# This is because the encode method always sets force=true for repeated fields
# Handle message types separately as they use a dedicated helper
# Handle message types separately - generate inline loop
if isinstance(self._ti, MessageType):
field_id_size = self._ti.calculate_field_id_size()
container = f"*{name}" if self._use_pointer else name
return f"size.add_repeated_message({field_id_size}, {container});"
container_ref = f"*{name}" if self._use_pointer else name
empty_check = f"{name}->empty()" if self._use_pointer else f"{name}.empty()"
o = f"if (!{empty_check}) {{\n"
o += f" for (const auto &it : {container_ref}) {{\n"
o += f" size += ProtoSize::calc_message_force({field_id_size}, it.calculate_size());\n"
o += " }\n"
o += "}"
return o
# For non-message types, generate size calculation with iteration
container_ref = f"*{name}" if self._use_pointer else name
@@ -1713,14 +1724,14 @@ class RepeatedTypeInfo(TypeInfo):
field_id_size = self._ti.calculate_field_id_size()
bytes_per_element = field_id_size + num_bytes
size_expr = f"{name}->size()" if self._use_pointer else f"{name}.size()"
o += f" size.add_precalculated_size({size_expr} * {bytes_per_element});\n"
o += f" size += {size_expr} * {bytes_per_element};\n"
else:
# Other types need the actual value
# Special handling for const char* elements
if self._use_pointer and "const char" in self._container_no_template:
field_id_size = self.calculate_field_id_size()
o += f" for (const char *it : {container_ref}) {{\n"
o += f" size.add_length_force({field_id_size}, strlen(it));\n"
o += f" size += ProtoSize::calc_length_force({field_id_size}, strlen(it));\n"
else:
auto_ref = "" if self._ti_is_bool else "&"
o += f" for (const auto {auto_ref}it : {container_ref}) {{\n"
@@ -2233,23 +2244,19 @@ def build_message_type(
o += indent("\n".join(encode)) + "\n"
o += "}\n"
cpp += o
prot = "void encode(ProtoWriteBuffer &buffer) const override;"
prot = "void encode(ProtoWriteBuffer &buffer) const;"
public_content.append(prot)
# If no fields to encode or message doesn't need encoding, the default implementation in ProtoMessage will be used
# Add calculate_size method only if this message needs encoding and has fields
if needs_encode and size_calc:
o = f"void {desc.name}::calculate_size(ProtoSize &size) const {{"
# For a single field, just inline it for simplicity
if len(size_calc) == 1 and len(size_calc[0]) + len(o) + 3 < 120:
o += f" {size_calc[0]} }}\n"
else:
# For multiple fields
o += "\n"
o += indent("\n".join(size_calc)) + "\n"
o += "}\n"
o = f"uint32_t {desc.name}::calculate_size() const {{\n"
o += " uint32_t size = 0;\n"
o += indent("\n".join(size_calc)) + "\n"
o += " return size;\n"
o += "}\n"
cpp += o
prot = "void calculate_size(ProtoSize &size) const override;"
prot = "uint32_t calculate_size() const;"
public_content.append(prot)
# If no fields to calculate size for or message doesn't need encoding, the default implementation in ProtoMessage will be used
@@ -2933,14 +2940,8 @@ static const char *const TAG = "api.service";
hpp += " public:\n"
hpp += "#endif\n\n"
# Add non-template send_message method
hpp += " bool send_message(const ProtoMessage &msg, uint8_t message_type) {\n"
hpp += "#ifdef HAS_PROTO_MESSAGE_DUMP\n"
hpp += " DumpBuffer dump_buf;\n"
hpp += " this->log_send_message_(msg.message_name(), msg.dump_to(dump_buf));\n"
hpp += "#endif\n"
hpp += " return this->send_message_impl(msg, message_type);\n"
hpp += " }\n\n"
# send_message is now a template on APIConnection directly
# No non-template send_message method needed here
# Add logging helper method implementations to cpp
cpp += "#ifdef HAS_PROTO_MESSAGE_DUMP\n"