From a08d021f77a9d076eebb24d28ae67c067bb44612 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 19 Jun 2025 02:10:01 +0200 Subject: [PATCH] Reduce code duplication in auto-generated API protocol code (#9097) --- esphome/components/api/api_pb2_service.cpp | 442 +++++---------------- esphome/components/api/proto.h | 20 + script/api_protobuf/api_protobuf.py | 49 ++- 3 files changed, 151 insertions(+), 360 deletions(-) diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index dacb23c12b..03017fdfff 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -620,544 +620,300 @@ void APIServerConnection::on_ping_request(const PingRequest &msg) { } } void APIServerConnection::on_device_info_request(const DeviceInfoRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; - } - DeviceInfoResponse ret = this->device_info(msg); - if (!this->send_message(ret)) { - this->on_fatal_error(); + if (this->check_connection_setup_()) { + DeviceInfoResponse ret = this->device_info(msg); + if (!this->send_message(ret)) { + this->on_fatal_error(); + } } } void APIServerConnection::on_list_entities_request(const ListEntitiesRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->list_entities(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->list_entities(msg); } void APIServerConnection::on_subscribe_states_request(const SubscribeStatesRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->subscribe_states(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->subscribe_states(msg); } void APIServerConnection::on_subscribe_logs_request(const SubscribeLogsRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->subscribe_logs(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->subscribe_logs(msg); } void APIServerConnection::on_subscribe_homeassistant_services_request( const SubscribeHomeassistantServicesRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->subscribe_homeassistant_services(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->subscribe_homeassistant_services(msg); } void APIServerConnection::on_subscribe_home_assistant_states_request(const SubscribeHomeAssistantStatesRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->subscribe_home_assistant_states(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->subscribe_home_assistant_states(msg); } void APIServerConnection::on_get_time_request(const GetTimeRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; - } - GetTimeResponse ret = this->get_time(msg); - if (!this->send_message(ret)) { - this->on_fatal_error(); + if (this->check_connection_setup_()) { + GetTimeResponse ret = this->get_time(msg); + if (!this->send_message(ret)) { + this->on_fatal_error(); + } } } void APIServerConnection::on_execute_service_request(const ExecuteServiceRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->execute_service(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->execute_service(msg); } #ifdef USE_API_NOISE void APIServerConnection::on_noise_encryption_set_key_request(const NoiseEncryptionSetKeyRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; - } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - NoiseEncryptionSetKeyResponse ret = this->noise_encryption_set_key(msg); - if (!this->send_message(ret)) { - this->on_fatal_error(); + if (this->check_authenticated_()) { + NoiseEncryptionSetKeyResponse ret = this->noise_encryption_set_key(msg); + if (!this->send_message(ret)) { + this->on_fatal_error(); + } } } #endif #ifdef USE_BUTTON void APIServerConnection::on_button_command_request(const ButtonCommandRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->button_command(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->button_command(msg); } #endif #ifdef USE_ESP32_CAMERA void APIServerConnection::on_camera_image_request(const CameraImageRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->camera_image(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->camera_image(msg); } #endif #ifdef USE_CLIMATE void APIServerConnection::on_climate_command_request(const ClimateCommandRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->climate_command(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->climate_command(msg); } #endif #ifdef USE_COVER void APIServerConnection::on_cover_command_request(const CoverCommandRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->cover_command(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->cover_command(msg); } #endif #ifdef USE_DATETIME_DATE void APIServerConnection::on_date_command_request(const DateCommandRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->date_command(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->date_command(msg); } #endif #ifdef USE_DATETIME_DATETIME void APIServerConnection::on_date_time_command_request(const DateTimeCommandRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->datetime_command(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->datetime_command(msg); } #endif #ifdef USE_FAN void APIServerConnection::on_fan_command_request(const FanCommandRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->fan_command(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->fan_command(msg); } #endif #ifdef USE_LIGHT void APIServerConnection::on_light_command_request(const LightCommandRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->light_command(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->light_command(msg); } #endif #ifdef USE_LOCK void APIServerConnection::on_lock_command_request(const LockCommandRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->lock_command(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->lock_command(msg); } #endif #ifdef USE_MEDIA_PLAYER void APIServerConnection::on_media_player_command_request(const MediaPlayerCommandRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->media_player_command(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->media_player_command(msg); } #endif #ifdef USE_NUMBER void APIServerConnection::on_number_command_request(const NumberCommandRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->number_command(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->number_command(msg); } #endif #ifdef USE_SELECT void APIServerConnection::on_select_command_request(const SelectCommandRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->select_command(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->select_command(msg); } #endif #ifdef USE_SIREN void APIServerConnection::on_siren_command_request(const SirenCommandRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->siren_command(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->siren_command(msg); } #endif #ifdef USE_SWITCH void APIServerConnection::on_switch_command_request(const SwitchCommandRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->switch_command(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->switch_command(msg); } #endif #ifdef USE_TEXT void APIServerConnection::on_text_command_request(const TextCommandRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->text_command(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->text_command(msg); } #endif #ifdef USE_DATETIME_TIME void APIServerConnection::on_time_command_request(const TimeCommandRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->time_command(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->time_command(msg); } #endif #ifdef USE_UPDATE void APIServerConnection::on_update_command_request(const UpdateCommandRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->update_command(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->update_command(msg); } #endif #ifdef USE_VALVE void APIServerConnection::on_valve_command_request(const ValveCommandRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->valve_command(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->valve_command(msg); } #endif #ifdef USE_BLUETOOTH_PROXY void APIServerConnection::on_subscribe_bluetooth_le_advertisements_request( const SubscribeBluetoothLEAdvertisementsRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->subscribe_bluetooth_le_advertisements(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->subscribe_bluetooth_le_advertisements(msg); } #endif #ifdef USE_BLUETOOTH_PROXY void APIServerConnection::on_bluetooth_device_request(const BluetoothDeviceRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->bluetooth_device_request(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->bluetooth_device_request(msg); } #endif #ifdef USE_BLUETOOTH_PROXY void APIServerConnection::on_bluetooth_gatt_get_services_request(const BluetoothGATTGetServicesRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->bluetooth_gatt_get_services(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->bluetooth_gatt_get_services(msg); } #endif #ifdef USE_BLUETOOTH_PROXY void APIServerConnection::on_bluetooth_gatt_read_request(const BluetoothGATTReadRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->bluetooth_gatt_read(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->bluetooth_gatt_read(msg); } #endif #ifdef USE_BLUETOOTH_PROXY void APIServerConnection::on_bluetooth_gatt_write_request(const BluetoothGATTWriteRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->bluetooth_gatt_write(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->bluetooth_gatt_write(msg); } #endif #ifdef USE_BLUETOOTH_PROXY void APIServerConnection::on_bluetooth_gatt_read_descriptor_request(const BluetoothGATTReadDescriptorRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->bluetooth_gatt_read_descriptor(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->bluetooth_gatt_read_descriptor(msg); } #endif #ifdef USE_BLUETOOTH_PROXY void APIServerConnection::on_bluetooth_gatt_write_descriptor_request(const BluetoothGATTWriteDescriptorRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->bluetooth_gatt_write_descriptor(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->bluetooth_gatt_write_descriptor(msg); } #endif #ifdef USE_BLUETOOTH_PROXY void APIServerConnection::on_bluetooth_gatt_notify_request(const BluetoothGATTNotifyRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->bluetooth_gatt_notify(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->bluetooth_gatt_notify(msg); } #endif #ifdef USE_BLUETOOTH_PROXY void APIServerConnection::on_subscribe_bluetooth_connections_free_request( const SubscribeBluetoothConnectionsFreeRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; - } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - BluetoothConnectionsFreeResponse ret = this->subscribe_bluetooth_connections_free(msg); - if (!this->send_message(ret)) { - this->on_fatal_error(); + if (this->check_authenticated_()) { + BluetoothConnectionsFreeResponse ret = this->subscribe_bluetooth_connections_free(msg); + if (!this->send_message(ret)) { + this->on_fatal_error(); + } } } #endif #ifdef USE_BLUETOOTH_PROXY void APIServerConnection::on_unsubscribe_bluetooth_le_advertisements_request( const UnsubscribeBluetoothLEAdvertisementsRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->unsubscribe_bluetooth_le_advertisements(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->unsubscribe_bluetooth_le_advertisements(msg); } #endif #ifdef USE_BLUETOOTH_PROXY void APIServerConnection::on_bluetooth_scanner_set_mode_request(const BluetoothScannerSetModeRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->bluetooth_scanner_set_mode(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->bluetooth_scanner_set_mode(msg); } #endif #ifdef USE_VOICE_ASSISTANT void APIServerConnection::on_subscribe_voice_assistant_request(const SubscribeVoiceAssistantRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->subscribe_voice_assistant(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->subscribe_voice_assistant(msg); } #endif #ifdef USE_VOICE_ASSISTANT void APIServerConnection::on_voice_assistant_configuration_request(const VoiceAssistantConfigurationRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; - } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - VoiceAssistantConfigurationResponse ret = this->voice_assistant_get_configuration(msg); - if (!this->send_message(ret)) { - this->on_fatal_error(); + if (this->check_authenticated_()) { + VoiceAssistantConfigurationResponse ret = this->voice_assistant_get_configuration(msg); + if (!this->send_message(ret)) { + this->on_fatal_error(); + } } } #endif #ifdef USE_VOICE_ASSISTANT void APIServerConnection::on_voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->voice_assistant_set_configuration(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->voice_assistant_set_configuration(msg); } #endif #ifdef USE_ALARM_CONTROL_PANEL void APIServerConnection::on_alarm_control_panel_command_request(const AlarmControlPanelCommandRequest &msg) { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return; + if (this->check_authenticated_()) { + this->alarm_control_panel_command(msg); } - if (!this->is_authenticated()) { - this->on_unauthenticated_access(); - return; - } - this->alarm_control_panel_command(msg); } #endif diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 6ece509c8d..e850236db6 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -379,6 +379,26 @@ class ProtoService { // Send the buffer return this->send_buffer(buffer, message_type); } + + // Authentication helper methods + bool check_connection_setup_() { + if (!this->is_connection_setup()) { + this->on_no_setup_connection(); + return false; + } + return true; + } + + bool check_authenticated_() { + if (!this->check_connection_setup_()) { + return false; + } + if (!this->is_authenticated()) { + this->on_unauthenticated_access(); + return false; + } + return true; + } }; } // namespace api diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 5ac101c673..bd1be66649 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -1424,25 +1424,40 @@ def main() -> None: hpp_protected += f" void {on_func}(const {inp} &msg) override;\n" hpp += f" virtual {ret} {func}(const {inp} &msg) = 0;\n" cpp += f"void {class_name}::{on_func}(const {inp} &msg) {{\n" - body = "" - if needs_conn: - body += "if (!this->is_connection_setup()) {\n" - body += " this->on_no_setup_connection();\n" - body += " return;\n" - body += "}\n" - if needs_auth: - body += "if (!this->is_authenticated()) {\n" - body += " this->on_unauthenticated_access();\n" - body += " return;\n" - body += "}\n" - if is_void: - body += f"this->{func}(msg);\n" - else: - body += f"{ret} ret = this->{func}(msg);\n" - body += "if (!this->send_message(ret)) {\n" - body += " this->on_fatal_error();\n" + # Start with authentication/connection check if needed + if needs_auth or needs_conn: + # Determine which check to use + if needs_auth: + check_func = "this->check_authenticated_()" + else: + check_func = "this->check_connection_setup_()" + + body = f"if ({check_func}) {{\n" + + # Add the actual handler code, indented + handler_body = "" + if is_void: + handler_body = f"this->{func}(msg);\n" + else: + handler_body = f"{ret} ret = this->{func}(msg);\n" + handler_body += "if (!this->send_message(ret)) {\n" + handler_body += " this->on_fatal_error();\n" + handler_body += "}\n" + + body += indent(handler_body) + "\n" body += "}\n" + else: + # No auth check needed, just call the handler + body = "" + if is_void: + body += f"this->{func}(msg);\n" + else: + body += f"{ret} ret = this->{func}(msg);\n" + body += "if (!this->send_message(ret)) {\n" + body += " this->on_fatal_error();\n" + body += "}\n" + cpp += indent(body) + "\n" + "}\n" if ifdef is not None: