diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 779784e787..63b6383afc 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1535,6 +1535,7 @@ void APIConnection::on_home_assistant_state_response(const HomeAssistantStateRes } } void APIConnection::execute_service(const ExecuteServiceRequest &msg) { + ESP_LOGD(TAG, "execute_service called with key: %u, args count: %zu", msg.key, msg.args.size()); bool found = false; for (auto *service : this->parent_->get_user_services()) { if (service->execute_service(msg)) { diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index ac944c6dfd..d255113aa6 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -329,10 +329,20 @@ const FieldMeta DeviceInfoResponse::FIELDS[19] = { 2, {.decode_varint = &decode_bool_field}}}; const RepeatedFieldMeta DeviceInfoResponse::REPEATED_FIELDS[2] = { - {20, PROTO_FIELD_OFFSET(DeviceInfoResponse, devices), &encode_repeated_message_field, - &size_repeated_message_field, 2}, - {21, PROTO_FIELD_OFFSET(DeviceInfoResponse, areas), &encode_repeated_message_field, - &size_repeated_message_field, 2}}; + {20, + PROTO_FIELD_OFFSET(DeviceInfoResponse, devices), + &encode_repeated_message_field, + &size_repeated_message_field, + 2, + 2, + {.decode_length = &decode_repeated_message_field}}, + {21, + PROTO_FIELD_OFFSET(DeviceInfoResponse, areas), + &encode_repeated_message_field, + &size_repeated_message_field, + 2, + 2, + {.decode_length = &decode_repeated_message_field}}}; #ifdef USE_BINARY_SENSOR const FieldMeta ListEntitiesBinarySensorResponse::FIELDS[10] = { {1, @@ -766,8 +776,13 @@ const FieldMeta ListEntitiesFanResponse::FIELDS[12] = { 1, {.decode_varint = &decode_uint32_field}}}; const RepeatedFieldMeta ListEntitiesFanResponse::REPEATED_FIELDS[1] = { - {12, PROTO_FIELD_OFFSET(ListEntitiesFanResponse, supported_preset_modes), &encode_repeated_string_field, - &size_repeated_string_field, 1}}; + {12, + PROTO_FIELD_OFFSET(ListEntitiesFanResponse, supported_preset_modes), + &encode_repeated_string_field, + &size_repeated_string_field, + 1, + 2, + {.decode_length = &decode_repeated_string_field}}}; const FieldMeta FanStateResponse::FIELDS[8] = {{1, PROTO_FIELD_OFFSET(FanStateResponse, key), &encode_fixed32_field, @@ -1052,10 +1067,20 @@ const FieldMeta ListEntitiesLightResponse::FIELDS[14] = { 2, {.decode_varint = &decode_uint32_field}}}; const RepeatedFieldMeta ListEntitiesLightResponse::REPEATED_FIELDS[2] = { - {12, PROTO_FIELD_OFFSET(ListEntitiesLightResponse, supported_color_modes), - &encode_repeated_enum_field, &size_repeated_enum_field, 1}, - {11, PROTO_FIELD_OFFSET(ListEntitiesLightResponse, effects), &encode_repeated_string_field, - &size_repeated_string_field, 1}}; + {12, + PROTO_FIELD_OFFSET(ListEntitiesLightResponse, supported_color_modes), + &encode_repeated_enum_field, + &size_repeated_enum_field, + 1, + 0, + {.decode_varint = &decode_repeated_enum_field}}, + {11, + PROTO_FIELD_OFFSET(ListEntitiesLightResponse, effects), + &encode_repeated_string_field, + &size_repeated_string_field, + 1, + 2, + {.decode_length = &decode_repeated_string_field}}}; const FieldMeta LightStateResponse::FIELDS[14] = {{1, PROTO_FIELD_OFFSET(LightStateResponse, key), &encode_fixed32_field, @@ -1853,13 +1878,27 @@ const FieldMeta HomeassistantServiceResponse::FIELDS[2] = {{1, 1, {.decode_varint = &decode_bool_field}}}; const RepeatedFieldMeta HomeassistantServiceResponse::REPEATED_FIELDS[3] = { - {2, PROTO_FIELD_OFFSET(HomeassistantServiceResponse, data), &encode_repeated_message_field, - &size_repeated_message_field, 1}, - {3, PROTO_FIELD_OFFSET(HomeassistantServiceResponse, data_template), - &encode_repeated_message_field, &size_repeated_message_field, 1}, - {4, PROTO_FIELD_OFFSET(HomeassistantServiceResponse, variables), - &encode_repeated_message_field, &size_repeated_message_field, - 1}}; + {2, + PROTO_FIELD_OFFSET(HomeassistantServiceResponse, data), + &encode_repeated_message_field, + &size_repeated_message_field, + 1, + 2, + {.decode_length = &decode_repeated_message_field}}, + {3, + PROTO_FIELD_OFFSET(HomeassistantServiceResponse, data_template), + &encode_repeated_message_field, + &size_repeated_message_field, + 1, + 2, + {.decode_length = &decode_repeated_message_field}}, + {4, + PROTO_FIELD_OFFSET(HomeassistantServiceResponse, variables), + &encode_repeated_message_field, + &size_repeated_message_field, + 1, + 2, + {.decode_length = &decode_repeated_message_field}}}; const FieldMeta SubscribeHomeAssistantStateResponse::FIELDS[3] = { {1, PROTO_FIELD_OFFSET(SubscribeHomeAssistantStateResponse, entity_id), @@ -1951,9 +1990,13 @@ const FieldMeta ListEntitiesServicesResponse::FIELDS[2] = {{1, 1, {.decode_32bit = &decode_fixed32_field}}}; const RepeatedFieldMeta ListEntitiesServicesResponse::REPEATED_FIELDS[1] = { - {3, PROTO_FIELD_OFFSET(ListEntitiesServicesResponse, args), + {3, + PROTO_FIELD_OFFSET(ListEntitiesServicesResponse, args), &encode_repeated_message_field, - &size_repeated_message_field, 1}}; + &size_repeated_message_field, + 1, + 2, + {.decode_length = &decode_repeated_message_field}}}; const FieldMeta ExecuteServiceArgument::FIELDS[5] = {{1, PROTO_FIELD_OFFSET(ExecuteServiceArgument, bool_), &encode_bool_field, @@ -1995,14 +2038,34 @@ const FieldMeta ExecuteServiceArgument::FIELDS[5] = {{1, 1, {.decode_varint = &decode_sint32_field}}}; const RepeatedFieldMeta ExecuteServiceArgument::REPEATED_FIELDS[4] = { - {6, PROTO_FIELD_OFFSET(ExecuteServiceArgument, bool_array), &encode_repeated_bool_field, &size_repeated_bool_field, - 1}, - {7, PROTO_FIELD_OFFSET(ExecuteServiceArgument, int_array), &encode_repeated_sint32_field, - &size_repeated_sint32_field, 1}, - {8, PROTO_FIELD_OFFSET(ExecuteServiceArgument, float_array), &encode_repeated_float_field, - &size_repeated_float_field, 1}, - {9, PROTO_FIELD_OFFSET(ExecuteServiceArgument, string_array), &encode_repeated_string_field, - &size_repeated_string_field, 1}}; + {6, + PROTO_FIELD_OFFSET(ExecuteServiceArgument, bool_array), + &encode_repeated_bool_field, + &size_repeated_bool_field, + 1, + 0, + {.decode_varint = &decode_repeated_bool_field}}, + {7, + PROTO_FIELD_OFFSET(ExecuteServiceArgument, int_array), + &encode_repeated_sint32_field, + &size_repeated_sint32_field, + 1, + 0, + {.decode_varint = &decode_repeated_sint32_field}}, + {8, + PROTO_FIELD_OFFSET(ExecuteServiceArgument, float_array), + &encode_repeated_float_field, + &size_repeated_float_field, + 1, + 5, + {.decode_32bit = &decode_repeated_float_field}}, + {9, + PROTO_FIELD_OFFSET(ExecuteServiceArgument, string_array), + &encode_repeated_string_field, + &size_repeated_string_field, + 1, + 2, + {.decode_length = &decode_repeated_string_field}}}; const FieldMeta ExecuteServiceRequest::FIELDS[1] = {{1, PROTO_FIELD_OFFSET(ExecuteServiceRequest, key), &encode_fixed32_field, @@ -2012,8 +2075,13 @@ const FieldMeta ExecuteServiceRequest::FIELDS[1] = {{1, 1, {.decode_32bit = &decode_fixed32_field}}}; const RepeatedFieldMeta ExecuteServiceRequest::REPEATED_FIELDS[1] = { - {2, PROTO_FIELD_OFFSET(ExecuteServiceRequest, args), &encode_repeated_message_field, - &size_repeated_message_field, 1}}; + {2, + PROTO_FIELD_OFFSET(ExecuteServiceRequest, args), + &encode_repeated_message_field, + &size_repeated_message_field, + 1, + 2, + {.decode_length = &decode_repeated_message_field}}}; #ifdef USE_CAMERA const FieldMeta ListEntitiesCameraResponse::FIELDS[8] = { {1, @@ -2284,18 +2352,48 @@ const FieldMeta ListEntitiesClimateResponse::FIELDS[20] = { 2, {.decode_varint = &decode_uint32_field}}}; const RepeatedFieldMeta ListEntitiesClimateResponse::REPEATED_FIELDS[6] = { - {7, PROTO_FIELD_OFFSET(ListEntitiesClimateResponse, supported_modes), - &encode_repeated_enum_field, &size_repeated_enum_field, 1}, - {13, PROTO_FIELD_OFFSET(ListEntitiesClimateResponse, supported_fan_modes), - &encode_repeated_enum_field, &size_repeated_enum_field, 1}, - {14, PROTO_FIELD_OFFSET(ListEntitiesClimateResponse, supported_swing_modes), - &encode_repeated_enum_field, &size_repeated_enum_field, 1}, - {15, PROTO_FIELD_OFFSET(ListEntitiesClimateResponse, supported_custom_fan_modes), &encode_repeated_string_field, - &size_repeated_string_field, 1}, - {16, PROTO_FIELD_OFFSET(ListEntitiesClimateResponse, supported_presets), - &encode_repeated_enum_field, &size_repeated_enum_field, 2}, - {17, PROTO_FIELD_OFFSET(ListEntitiesClimateResponse, supported_custom_presets), &encode_repeated_string_field, - &size_repeated_string_field, 2}}; + {7, + PROTO_FIELD_OFFSET(ListEntitiesClimateResponse, supported_modes), + &encode_repeated_enum_field, + &size_repeated_enum_field, + 1, + 0, + {.decode_varint = &decode_repeated_enum_field}}, + {13, + PROTO_FIELD_OFFSET(ListEntitiesClimateResponse, supported_fan_modes), + &encode_repeated_enum_field, + &size_repeated_enum_field, + 1, + 0, + {.decode_varint = &decode_repeated_enum_field}}, + {14, + PROTO_FIELD_OFFSET(ListEntitiesClimateResponse, supported_swing_modes), + &encode_repeated_enum_field, + &size_repeated_enum_field, + 1, + 0, + {.decode_varint = &decode_repeated_enum_field}}, + {15, + PROTO_FIELD_OFFSET(ListEntitiesClimateResponse, supported_custom_fan_modes), + &encode_repeated_string_field, + &size_repeated_string_field, + 1, + 2, + {.decode_length = &decode_repeated_string_field}}, + {16, + PROTO_FIELD_OFFSET(ListEntitiesClimateResponse, supported_presets), + &encode_repeated_enum_field, + &size_repeated_enum_field, + 2, + 0, + {.decode_varint = &decode_repeated_enum_field}}, + {17, + PROTO_FIELD_OFFSET(ListEntitiesClimateResponse, supported_custom_presets), + &encode_repeated_string_field, + &size_repeated_string_field, + 2, + 2, + {.decode_length = &decode_repeated_string_field}}}; const FieldMeta ClimateStateResponse::FIELDS[16] = {{1, PROTO_FIELD_OFFSET(ClimateStateResponse, key), &encode_fixed32_field, @@ -2840,8 +2938,13 @@ const FieldMeta ListEntitiesSelectResponse::FIELDS[8] = { 1, {.decode_varint = &decode_uint32_field}}}; const RepeatedFieldMeta ListEntitiesSelectResponse::REPEATED_FIELDS[1] = { - {6, PROTO_FIELD_OFFSET(ListEntitiesSelectResponse, options), &encode_repeated_string_field, - &size_repeated_string_field, 1}}; + {6, + PROTO_FIELD_OFFSET(ListEntitiesSelectResponse, options), + &encode_repeated_string_field, + &size_repeated_string_field, + 1, + 2, + {.decode_length = &decode_repeated_string_field}}}; const FieldMeta SelectStateResponse::FIELDS[4] = {{1, PROTO_FIELD_OFFSET(SelectStateResponse, key), &encode_fixed32_field, @@ -2974,8 +3077,13 @@ const FieldMeta ListEntitiesSirenResponse::FIELDS[10] = { 1, {.decode_varint = &decode_uint32_field}}}; const RepeatedFieldMeta ListEntitiesSirenResponse::REPEATED_FIELDS[1] = { - {7, PROTO_FIELD_OFFSET(ListEntitiesSirenResponse, tones), &encode_repeated_string_field, - &size_repeated_string_field, 1}}; + {7, + PROTO_FIELD_OFFSET(ListEntitiesSirenResponse, tones), + &encode_repeated_string_field, + &size_repeated_string_field, + 1, + 2, + {.decode_length = &decode_repeated_string_field}}}; const FieldMeta SirenStateResponse::FIELDS[3] = {{1, PROTO_FIELD_OFFSET(SirenStateResponse, key), &encode_fixed32_field, @@ -3427,9 +3535,13 @@ const FieldMeta ListEntitiesMediaPlayerResponse::FIELDS[9] = { 1, {.decode_varint = &decode_uint32_field}}}; const RepeatedFieldMeta ListEntitiesMediaPlayerResponse::REPEATED_FIELDS[1] = { - {9, PROTO_FIELD_OFFSET(ListEntitiesMediaPlayerResponse, supported_formats), + {9, + PROTO_FIELD_OFFSET(ListEntitiesMediaPlayerResponse, supported_formats), &encode_repeated_message_field, - &size_repeated_message_field, 1}}; + &size_repeated_message_field, + 1, + 2, + {.decode_length = &decode_repeated_message_field}}}; const FieldMeta MediaPlayerStateResponse::FIELDS[5] = {{1, PROTO_FIELD_OFFSET(MediaPlayerStateResponse, key), &encode_fixed32_field, @@ -3571,8 +3683,13 @@ const FieldMeta BluetoothServiceData::FIELDS[2] = {{1, 1, {.decode_length = &decode_bytes_field}}}; const RepeatedFieldMeta BluetoothServiceData::REPEATED_FIELDS[1] = { - {2, PROTO_FIELD_OFFSET(BluetoothServiceData, legacy_data), &encode_repeated_uint32_field, - &size_repeated_uint32_field, 1}}; + {2, + PROTO_FIELD_OFFSET(BluetoothServiceData, legacy_data), + &encode_repeated_uint32_field, + &size_repeated_uint32_field, + 1, + 0, + {.decode_varint = &decode_repeated_uint32_field}}}; const FieldMeta BluetoothLEAdvertisementResponse::FIELDS[4] = { {1, PROTO_FIELD_OFFSET(BluetoothLEAdvertisementResponse, address), @@ -3607,12 +3724,27 @@ const FieldMeta BluetoothLEAdvertisementResponse::FIELDS[4] = { 1, {.decode_varint = &decode_uint32_field}}}; const RepeatedFieldMeta BluetoothLEAdvertisementResponse::REPEATED_FIELDS[3] = { - {4, PROTO_FIELD_OFFSET(BluetoothLEAdvertisementResponse, service_uuids), &encode_repeated_string_field, - &size_repeated_string_field, 1}, - {5, PROTO_FIELD_OFFSET(BluetoothLEAdvertisementResponse, service_data), - &encode_repeated_message_field, &size_repeated_message_field, 1}, - {6, PROTO_FIELD_OFFSET(BluetoothLEAdvertisementResponse, manufacturer_data), - &encode_repeated_message_field, &size_repeated_message_field, 1}}; + {4, + PROTO_FIELD_OFFSET(BluetoothLEAdvertisementResponse, service_uuids), + &encode_repeated_string_field, + &size_repeated_string_field, + 1, + 2, + {.decode_length = &decode_repeated_string_field}}, + {5, + PROTO_FIELD_OFFSET(BluetoothLEAdvertisementResponse, service_data), + &encode_repeated_message_field, + &size_repeated_message_field, + 1, + 2, + {.decode_length = &decode_repeated_message_field}}, + {6, + PROTO_FIELD_OFFSET(BluetoothLEAdvertisementResponse, manufacturer_data), + &encode_repeated_message_field, + &size_repeated_message_field, + 1, + 2, + {.decode_length = &decode_repeated_message_field}}}; const FieldMeta BluetoothLERawAdvertisement::FIELDS[4] = { {1, PROTO_FIELD_OFFSET(BluetoothLERawAdvertisement, address), @@ -3647,9 +3779,13 @@ const FieldMeta BluetoothLERawAdvertisement::FIELDS[4] = { 1, {.decode_length = &decode_bytes_field}}}; const RepeatedFieldMeta BluetoothLERawAdvertisementsResponse::REPEATED_FIELDS[1] = { - {1, PROTO_FIELD_OFFSET(BluetoothLERawAdvertisementsResponse, advertisements), + {1, + PROTO_FIELD_OFFSET(BluetoothLERawAdvertisementsResponse, advertisements), &encode_repeated_message_field, - &size_repeated_message_field, 1}}; + &size_repeated_message_field, + 1, + 2, + {.decode_length = &decode_repeated_message_field}}}; const FieldMeta BluetoothDeviceRequest::FIELDS[4] = { {1, PROTO_FIELD_OFFSET(BluetoothDeviceRequest, address), @@ -3734,8 +3870,13 @@ const FieldMeta BluetoothGATTDescriptor::FIELDS[1] = {{2, 1, {.decode_varint = &decode_uint32_field}}}; const RepeatedFieldMeta BluetoothGATTDescriptor::REPEATED_FIELDS[1] = { - {1, PROTO_FIELD_OFFSET(BluetoothGATTDescriptor, uuid), &encode_repeated_uint64_field, &size_repeated_uint64_field, - 1}}; + {1, + PROTO_FIELD_OFFSET(BluetoothGATTDescriptor, uuid), + &encode_repeated_uint64_field, + &size_repeated_uint64_field, + 1, + 0, + {.decode_varint = &decode_repeated_uint64_field}}}; const FieldMeta BluetoothGATTCharacteristic::FIELDS[2] = {{2, PROTO_FIELD_OFFSET(BluetoothGATTCharacteristic, handle), &encode_uint32_field, @@ -3753,11 +3894,20 @@ const FieldMeta BluetoothGATTCharacteristic::FIELDS[2] = {{2, 1, {.decode_varint = &decode_uint32_field}}}; const RepeatedFieldMeta BluetoothGATTCharacteristic::REPEATED_FIELDS[2] = { - {1, PROTO_FIELD_OFFSET(BluetoothGATTCharacteristic, uuid), &encode_repeated_uint64_field, - &size_repeated_uint64_field, 1}, - {4, PROTO_FIELD_OFFSET(BluetoothGATTCharacteristic, descriptors), - &encode_repeated_message_field, &size_repeated_message_field, - 1}}; + {1, + PROTO_FIELD_OFFSET(BluetoothGATTCharacteristic, uuid), + &encode_repeated_uint64_field, + &size_repeated_uint64_field, + 1, + 0, + {.decode_varint = &decode_repeated_uint64_field}}, + {4, + PROTO_FIELD_OFFSET(BluetoothGATTCharacteristic, descriptors), + &encode_repeated_message_field, + &size_repeated_message_field, + 1, + 2, + {.decode_length = &decode_repeated_message_field}}}; const FieldMeta BluetoothGATTService::FIELDS[1] = {{2, PROTO_FIELD_OFFSET(BluetoothGATTService, handle), &encode_uint32_field, @@ -3767,10 +3917,20 @@ const FieldMeta BluetoothGATTService::FIELDS[1] = {{2, 1, {.decode_varint = &decode_uint32_field}}}; const RepeatedFieldMeta BluetoothGATTService::REPEATED_FIELDS[2] = { - {1, PROTO_FIELD_OFFSET(BluetoothGATTService, uuid), &encode_repeated_uint64_field, &size_repeated_uint64_field, 1}, - {3, PROTO_FIELD_OFFSET(BluetoothGATTService, characteristics), + {1, + PROTO_FIELD_OFFSET(BluetoothGATTService, uuid), + &encode_repeated_uint64_field, + &size_repeated_uint64_field, + 1, + 0, + {.decode_varint = &decode_repeated_uint64_field}}, + {3, + PROTO_FIELD_OFFSET(BluetoothGATTService, characteristics), &encode_repeated_message_field, - &size_repeated_message_field, 1}}; + &size_repeated_message_field, + 1, + 2, + {.decode_length = &decode_repeated_message_field}}}; const FieldMeta BluetoothGATTGetServicesResponse::FIELDS[1] = { {1, PROTO_FIELD_OFFSET(BluetoothGATTGetServicesResponse, address), @@ -3781,8 +3941,13 @@ const FieldMeta BluetoothGATTGetServicesResponse::FIELDS[1] = { 1, {.decode_varint = &decode_uint64_field}}}; const RepeatedFieldMeta BluetoothGATTGetServicesResponse::REPEATED_FIELDS[1] = { - {2, PROTO_FIELD_OFFSET(BluetoothGATTGetServicesResponse, services), - &encode_repeated_message_field, &size_repeated_message_field, 1}}; + {2, + PROTO_FIELD_OFFSET(BluetoothGATTGetServicesResponse, services), + &encode_repeated_message_field, + &size_repeated_message_field, + 1, + 2, + {.decode_length = &decode_repeated_message_field}}}; const FieldMeta BluetoothGATTGetServicesDoneResponse::FIELDS[1] = { {1, PROTO_FIELD_OFFSET(BluetoothGATTGetServicesDoneResponse, address), @@ -3973,8 +4138,13 @@ const FieldMeta BluetoothConnectionsFreeResponse::FIELDS[2] = { 1, {.decode_varint = &decode_uint32_field}}}; const RepeatedFieldMeta BluetoothConnectionsFreeResponse::REPEATED_FIELDS[1] = { - {3, PROTO_FIELD_OFFSET(BluetoothConnectionsFreeResponse, allocated), &encode_repeated_uint64_field, - &size_repeated_uint64_field, 1}}; + {3, + PROTO_FIELD_OFFSET(BluetoothConnectionsFreeResponse, allocated), + &encode_repeated_uint64_field, + &size_repeated_uint64_field, + 1, + 0, + {.decode_varint = &decode_repeated_uint64_field}}}; const FieldMeta BluetoothGATTErrorResponse::FIELDS[3] = {{1, PROTO_FIELD_OFFSET(BluetoothGATTErrorResponse, address), &encode_uint64_field, @@ -4250,8 +4420,13 @@ const FieldMeta VoiceAssistantEventResponse::FIELDS[1] = { 1, {.decode_varint = &decode_enum_field}}}; const RepeatedFieldMeta VoiceAssistantEventResponse::REPEATED_FIELDS[1] = { - {2, PROTO_FIELD_OFFSET(VoiceAssistantEventResponse, data), &encode_repeated_message_field, - &size_repeated_message_field, 1}}; + {2, + PROTO_FIELD_OFFSET(VoiceAssistantEventResponse, data), + &encode_repeated_message_field, + &size_repeated_message_field, + 1, + 2, + {.decode_length = &decode_repeated_message_field}}}; const FieldMeta VoiceAssistantAudio::FIELDS[2] = {{1, PROTO_FIELD_OFFSET(VoiceAssistantAudio, data), &encode_bytes_field, @@ -4376,8 +4551,13 @@ const FieldMeta VoiceAssistantWakeWord::FIELDS[2] = {{1, 1, {.decode_length = &decode_string_field}}}; const RepeatedFieldMeta VoiceAssistantWakeWord::REPEATED_FIELDS[1] = { - {3, PROTO_FIELD_OFFSET(VoiceAssistantWakeWord, trained_languages), &encode_repeated_string_field, - &size_repeated_string_field, 1}}; + {3, + PROTO_FIELD_OFFSET(VoiceAssistantWakeWord, trained_languages), + &encode_repeated_string_field, + &size_repeated_string_field, + 1, + 2, + {.decode_length = &decode_repeated_string_field}}}; const FieldMeta VoiceAssistantConfigurationResponse::FIELDS[1] = { {3, PROTO_FIELD_OFFSET(VoiceAssistantConfigurationResponse, max_active_wake_words), @@ -4388,13 +4568,28 @@ const FieldMeta VoiceAssistantConfigurationResponse::FIELDS[1] = { 1, {.decode_varint = &decode_uint32_field}}}; const RepeatedFieldMeta VoiceAssistantConfigurationResponse::REPEATED_FIELDS[2] = { - {1, PROTO_FIELD_OFFSET(VoiceAssistantConfigurationResponse, available_wake_words), - &encode_repeated_message_field, &size_repeated_message_field, 1}, - {2, PROTO_FIELD_OFFSET(VoiceAssistantConfigurationResponse, active_wake_words), &encode_repeated_string_field, - &size_repeated_string_field, 1}}; + {1, + PROTO_FIELD_OFFSET(VoiceAssistantConfigurationResponse, available_wake_words), + &encode_repeated_message_field, + &size_repeated_message_field, + 1, + 2, + {.decode_length = &decode_repeated_message_field}}, + {2, + PROTO_FIELD_OFFSET(VoiceAssistantConfigurationResponse, active_wake_words), + &encode_repeated_string_field, + &size_repeated_string_field, + 1, + 2, + {.decode_length = &decode_repeated_string_field}}}; const RepeatedFieldMeta VoiceAssistantSetConfiguration::REPEATED_FIELDS[1] = { - {1, PROTO_FIELD_OFFSET(VoiceAssistantSetConfiguration, active_wake_words), &encode_repeated_string_field, - &size_repeated_string_field, 1}}; + {1, + PROTO_FIELD_OFFSET(VoiceAssistantSetConfiguration, active_wake_words), + &encode_repeated_string_field, + &size_repeated_string_field, + 1, + 2, + {.decode_length = &decode_repeated_string_field}}}; #endif #ifdef USE_ALARM_CONTROL_PANEL const FieldMeta ListEntitiesAlarmControlPanelResponse::FIELDS[11] = { @@ -5053,8 +5248,13 @@ const FieldMeta ListEntitiesEventResponse::FIELDS[9] = { 1, {.decode_varint = &decode_uint32_field}}}; const RepeatedFieldMeta ListEntitiesEventResponse::REPEATED_FIELDS[1] = { - {9, PROTO_FIELD_OFFSET(ListEntitiesEventResponse, event_types), &encode_repeated_string_field, - &size_repeated_string_field, 1}}; + {9, + PROTO_FIELD_OFFSET(ListEntitiesEventResponse, event_types), + &encode_repeated_string_field, + &size_repeated_string_field, + 1, + 2, + {.decode_length = &decode_repeated_string_field}}}; const FieldMeta EventResponse::FIELDS[3] = {{1, PROTO_FIELD_OFFSET(EventResponse, key), &encode_fixed32_field, diff --git a/esphome/components/api/proto.cpp b/esphome/components/api/proto.cpp index 759f68c15d..c23e3bc7f6 100644 --- a/esphome/components/api/proto.cpp +++ b/esphome/components/api/proto.cpp @@ -491,6 +491,79 @@ void size_repeated_double_field(uint32_t &total_size, const void *field_ptr, uin // Template size functions moved to header +// Repeated field decode functions +bool decode_repeated_string_field(void *field_ptr, ProtoLengthDelimited value) { + auto *vec = static_cast *>(field_ptr); + vec->push_back(value.as_string()); + return true; +} + +bool decode_repeated_bool_field(void *field_ptr, ProtoVarInt value) { + auto *vec = static_cast *>(field_ptr); + vec->push_back(value.as_bool()); + return true; +} + +bool decode_repeated_uint32_field(void *field_ptr, ProtoVarInt value) { + auto *vec = static_cast *>(field_ptr); + vec->push_back(value.as_uint32()); + return true; +} + +bool decode_repeated_int32_field(void *field_ptr, ProtoVarInt value) { + auto *vec = static_cast *>(field_ptr); + vec->push_back(value.as_int32()); + return true; +} + +bool decode_repeated_uint64_field(void *field_ptr, ProtoVarInt value) { + auto *vec = static_cast *>(field_ptr); + vec->push_back(value.as_uint64()); + return true; +} + +bool decode_repeated_int64_field(void *field_ptr, ProtoVarInt value) { + auto *vec = static_cast *>(field_ptr); + vec->push_back(value.as_int64()); + return true; +} + +bool decode_repeated_sint32_field(void *field_ptr, ProtoVarInt value) { + auto *vec = static_cast *>(field_ptr); + vec->push_back(value.as_sint32()); + return true; +} + +bool decode_repeated_sint64_field(void *field_ptr, ProtoVarInt value) { + auto *vec = static_cast *>(field_ptr); + vec->push_back(value.as_sint64()); + return true; +} + +bool decode_repeated_fixed32_field(void *field_ptr, Proto32Bit value) { + auto *vec = static_cast *>(field_ptr); + vec->push_back(value.as_fixed32()); + return true; +} + +bool decode_repeated_fixed64_field(void *field_ptr, Proto64Bit value) { + auto *vec = static_cast *>(field_ptr); + vec->push_back(value.as_fixed64()); + return true; +} + +bool decode_repeated_float_field(void *field_ptr, Proto32Bit value) { + auto *vec = static_cast *>(field_ptr); + vec->push_back(value.as_float()); + return true; +} + +bool decode_repeated_double_field(void *field_ptr, Proto64Bit value) { + auto *vec = static_cast *>(field_ptr); + vec->push_back(value.as_double()); + return true; +} + // Core shared functions void encode_from_metadata(ProtoWriteBuffer buffer, const void *obj, const FieldMeta *fields, size_t field_count, const RepeatedFieldMeta *repeated_fields, size_t repeated_count) { @@ -570,12 +643,26 @@ bool ProtoMetadataMessage::decode_varint_metadata(uint32_t field_id, ProtoVarInt size_t field_count) { uint8_t *base = reinterpret_cast(this); + // Check regular fields for (size_t i = 0; i < field_count; i++) { if (fields[i].field_num == field_id && fields[i].wire_type == 0) { // varint void *field_addr = base + fields[i].offset; return fields[i].decoder.decode_varint(field_addr, value); } } + + // Check repeated fields + const RepeatedFieldMeta *repeated_fields = get_repeated_field_metadata(); + size_t repeated_count = get_repeated_field_count(); + if (repeated_fields) { + for (size_t i = 0; i < repeated_count; i++) { + if (repeated_fields[i].field_num == field_id && repeated_fields[i].wire_type == 0) { // varint + void *field_addr = base + repeated_fields[i].offset; + return repeated_fields[i].decoder.decode_varint(field_addr, value); + } + } + } + return false; } @@ -583,12 +670,26 @@ bool ProtoMetadataMessage::decode_length_metadata(uint32_t field_id, ProtoLength const FieldMeta *fields, size_t field_count) { uint8_t *base = reinterpret_cast(this); + // Check regular fields for (size_t i = 0; i < field_count; i++) { if (fields[i].field_num == field_id && fields[i].wire_type == 2) { // length-delimited void *field_addr = base + fields[i].offset; return fields[i].decoder.decode_length(field_addr, value); } } + + // Check repeated fields + const RepeatedFieldMeta *repeated_fields = get_repeated_field_metadata(); + size_t repeated_count = get_repeated_field_count(); + if (repeated_fields) { + for (size_t i = 0; i < repeated_count; i++) { + if (repeated_fields[i].field_num == field_id && repeated_fields[i].wire_type == 2) { // length-delimited + void *field_addr = base + repeated_fields[i].offset; + return repeated_fields[i].decoder.decode_length(field_addr, value); + } + } + } + return false; } @@ -596,12 +697,26 @@ bool ProtoMetadataMessage::decode_32bit_metadata(uint32_t field_id, Proto32Bit v size_t field_count) { uint8_t *base = reinterpret_cast(this); + // Check regular fields for (size_t i = 0; i < field_count; i++) { if (fields[i].field_num == field_id && fields[i].wire_type == 5) { // 32-bit void *field_addr = base + fields[i].offset; return fields[i].decoder.decode_32bit(field_addr, value); } } + + // Check repeated fields + const RepeatedFieldMeta *repeated_fields = get_repeated_field_metadata(); + size_t repeated_count = get_repeated_field_count(); + if (repeated_fields) { + for (size_t i = 0; i < repeated_count; i++) { + if (repeated_fields[i].field_num == field_id && repeated_fields[i].wire_type == 5) { // 32-bit + void *field_addr = base + repeated_fields[i].offset; + return repeated_fields[i].decoder.decode_32bit(field_addr, value); + } + } + } + return false; } @@ -609,12 +724,26 @@ bool ProtoMetadataMessage::decode_64bit_metadata(uint32_t field_id, Proto64Bit v size_t field_count) { uint8_t *base = reinterpret_cast(this); + // Check regular fields for (size_t i = 0; i < field_count; i++) { if (fields[i].field_num == field_id && fields[i].wire_type == 1) { // 64-bit void *field_addr = base + fields[i].offset; return fields[i].decoder.decode_64bit(field_addr, value); } } + + // Check repeated fields + const RepeatedFieldMeta *repeated_fields = get_repeated_field_metadata(); + size_t repeated_count = get_repeated_field_count(); + if (repeated_fields) { + for (size_t i = 0; i < repeated_count; i++) { + if (repeated_fields[i].field_num == field_id && repeated_fields[i].wire_type == 1) { // 64-bit + void *field_addr = base + repeated_fields[i].offset; + return repeated_fields[i].decoder.decode_64bit(field_addr, value); + } + } + } + return false; } diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 0299031051..0972f6346c 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -29,14 +29,8 @@ using SizeFunc = void (*)(uint32_t &total_size, const void *field_ptr, uint8_t p using RepeatedEncodeFunc = void (*)(ProtoWriteBuffer &, const void *field_ptr, uint8_t field_num); using RepeatedSizeFunc = void (*)(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_id_size); -// Special metadata for repeated fields -struct RepeatedFieldMeta { - uint8_t field_num; - uint16_t offset; - RepeatedEncodeFunc encoder; // Encoder for the entire vector - RepeatedSizeFunc sizer; // Sizer for the entire vector - uint8_t precalced_field_id_size; // Pre-calculated size of field tag in bytes -}; +// Forward declaration for RepeatedFieldMeta - will be defined after Proto* classes +struct RepeatedFieldMeta; /// Representation of a VarInt - in ProtoBuf should be 64bit but we only use 32bit class ProtoVarInt { @@ -372,6 +366,28 @@ class ProtoWriteBuffer { std::vector *buffer_; }; +// Forward declarations for repeated field decode - now that Proto* classes are defined +using RepeatedDecodeVarintFunc = bool (*)(void *field_ptr, ProtoVarInt value); +using RepeatedDecodeLengthFunc = bool (*)(void *field_ptr, ProtoLengthDelimited value); +using RepeatedDecode32BitFunc = bool (*)(void *field_ptr, Proto32Bit value); +using RepeatedDecode64BitFunc = bool (*)(void *field_ptr, Proto64Bit value); + +// Special metadata for repeated fields +struct RepeatedFieldMeta { + uint8_t field_num; + uint16_t offset; + RepeatedEncodeFunc encoder; // Encoder for the entire vector + RepeatedSizeFunc sizer; // Sizer for the entire vector + uint8_t precalced_field_id_size; // Pre-calculated size of field tag in bytes + uint8_t wire_type; // Wire type for decoding + union { + RepeatedDecodeVarintFunc decode_varint; + RepeatedDecodeLengthFunc decode_length; + RepeatedDecode32BitFunc decode_32bit; + RepeatedDecode64BitFunc decode_64bit; + } decoder; +}; + class ProtoMessage { public: virtual ~ProtoMessage() = default; @@ -572,6 +588,24 @@ void size_repeated_enum_field(uint32_t &total_size, const void *field_ptr, uint8 template void size_repeated_message_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_id_size); +// Repeated field decode functions +bool decode_repeated_string_field(void *field_ptr, ProtoLengthDelimited value); +bool decode_repeated_bool_field(void *field_ptr, ProtoVarInt value); +bool decode_repeated_uint32_field(void *field_ptr, ProtoVarInt value); +bool decode_repeated_int32_field(void *field_ptr, ProtoVarInt value); +bool decode_repeated_uint64_field(void *field_ptr, ProtoVarInt value); +bool decode_repeated_int64_field(void *field_ptr, ProtoVarInt value); +bool decode_repeated_sint32_field(void *field_ptr, ProtoVarInt value); +bool decode_repeated_sint64_field(void *field_ptr, ProtoVarInt value); +bool decode_repeated_fixed32_field(void *field_ptr, Proto32Bit value); +bool decode_repeated_fixed64_field(void *field_ptr, Proto64Bit value); +bool decode_repeated_float_field(void *field_ptr, Proto32Bit value); +bool decode_repeated_double_field(void *field_ptr, Proto64Bit value); + +template bool decode_repeated_enum_field(void *field_ptr, ProtoVarInt value); + +template bool decode_repeated_message_field(void *field_ptr, ProtoLengthDelimited value); + // Core shared functions void encode_from_metadata(ProtoWriteBuffer buffer, const void *obj, const FieldMeta *fields, size_t field_count, const RepeatedFieldMeta *repeated_fields = nullptr, size_t repeated_count = 0); diff --git a/esphome/components/api/proto_templates.h b/esphome/components/api/proto_templates.h index 9b9bb5d744..9bfd375569 100644 --- a/esphome/components/api/proto_templates.h +++ b/esphome/components/api/proto_templates.h @@ -57,5 +57,18 @@ inline void size_repeated_message_field(uint32_t &total_size, const void *field_ ProtoSize::add_repeated_message(total_size, precalced_field_id_size, *vec); } +// Template decode functions for repeated fields +template inline bool decode_repeated_enum_field(void *field_ptr, ProtoVarInt value) { + auto *vec = static_cast *>(field_ptr); + vec->push_back(value.as_enum()); + return true; +} + +template inline bool decode_repeated_message_field(void *field_ptr, ProtoLengthDelimited value) { + auto *vec = static_cast *>(field_ptr); + vec->push_back(value.as_message()); + return true; +} + } // namespace api } // namespace esphome \ No newline at end of file diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index e24de494e9..84a6c8955e 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -1125,6 +1125,53 @@ def get_decoder_function(type_info: TypeInfo, wire_type: int) -> str: return None +def get_repeated_decoder_function(type_info): + """Get the appropriate repeated decoder function based on type.""" + # For repeated fields, we get the underlying type from RepeatedTypeInfo + if hasattr(type_info, "_ti"): + underlying_type = type_info._ti + else: + underlying_type = type_info + + wire_type = get_wire_type(underlying_type) + + # Map based on both type and wire type + if wire_type == 0: # VARINT + type_map = { + "BoolType": "&decode_repeated_bool_field", + "Int32Type": "&decode_repeated_int32_field", + "UInt32Type": "&decode_repeated_uint32_field", + "Int64Type": "&decode_repeated_int64_field", + "UInt64Type": "&decode_repeated_uint64_field", + "SInt32Type": "&decode_repeated_sint32_field", + "SInt64Type": "&decode_repeated_sint64_field", + } + type_name = underlying_type.__class__.__name__ + return type_map.get(type_name, None) + elif wire_type == 2: # LENGTH_DELIMITED + type_map = { + "StringType": "&decode_repeated_string_field", + } + type_name = underlying_type.__class__.__name__ + return type_map.get(type_name, None) + elif wire_type == 5: # FIXED32 + type_map = { + "FloatType": "&decode_repeated_float_field", + "Fixed32Type": "&decode_repeated_fixed32_field", + } + type_name = underlying_type.__class__.__name__ + return type_map.get(type_name, None) + elif wire_type == 1: # FIXED64 + type_map = { + "DoubleType": "&decode_repeated_double_field", + "Fixed64Type": "&decode_repeated_fixed64_field", + } + type_name = underlying_type.__class__.__name__ + return type_map.get(type_name, None) + + return None + + def build_message_type( desc: descriptor.DescriptorProto, base_class_fields: dict[str, list[descriptor.FieldDescriptorProto]] = None, @@ -1211,25 +1258,39 @@ def build_message_type( ti = RepeatedTypeInfo(field) encoder = get_repeated_encoder_function(ti) sizer = get_repeated_sizer_function(ti) + decoder = get_repeated_decoder_function(ti) field_tag_size = ti.calculate_field_id_size() + wire_type = get_wire_type(ti._ti) - if encoder and sizer: + if encoder and sizer and decoder: + # Format: {field_num, offset, encoder, sizer, precalced_field_id_size, wire_type, {decoder}} + decoder_field = ( + f".decode_varint = {decoder}" + if wire_type == 0 + else f".decode_length = {decoder}" + if wire_type == 2 + else f".decode_32bit = {decoder}" + if wire_type == 5 + else f".decode_64bit = {decoder}" + ) repeated_fields.append( - f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), {encoder}, {sizer}, {field_tag_size}}}" + f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), {encoder}, {sizer}, {field_tag_size}, {wire_type}, {{{decoder_field}}}}}" ) elif isinstance(ti._ti, EnumType): # Handle enum repeated fields with template enum_type = ti._ti.cpp_type repeated_fields.append( f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), " - f"&encode_repeated_enum_field<{enum_type}>, &size_repeated_enum_field<{enum_type}>, {field_tag_size}}}" + f"&encode_repeated_enum_field<{enum_type}>, &size_repeated_enum_field<{enum_type}>, {field_tag_size}, 0, " + f"{{.decode_varint = &decode_repeated_enum_field<{enum_type}>}}}}" ) elif isinstance(ti._ti, MessageType): # Handle message repeated fields with template msg_type = ti._ti.cpp_type repeated_fields.append( f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), " - f"&encode_repeated_message_field<{msg_type}>, &size_repeated_message_field<{msg_type}>, {field_tag_size}}}" + f"&encode_repeated_message_field<{msg_type}>, &size_repeated_message_field<{msg_type}>, {field_tag_size}, 2, " + f"{{.decode_length = &decode_repeated_message_field<{msg_type}>}}}}" ) else: ti = TYPE_INFO[field.type](field)