From 5b3d61b4a6832a516955181c3da8a6a9158e805d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 19 Jul 2025 17:41:00 -1000 Subject: [PATCH] [api] Fix missing ifdef guards for field_ifdef fields in protobuf base classes (#9693) --- esphome/components/api/api_connection.h | 4 +++- esphome/components/api/api_pb2.h | 8 +++++++ script/api_protobuf/api_protobuf.py | 31 +++++++++++++++++++++++-- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 3873c7fcac..9ed18c24dc 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -301,8 +301,10 @@ class APIConnection : public APIServerConnection { if (entity->has_own_name()) msg.name = entity->get_name(); - // Set common EntityBase properties + // Set common EntityBase properties +#ifdef USE_ENTITY_ICON msg.icon = entity->get_icon(); +#endif msg.disabled_by_default = entity->is_disabled_by_default(); msg.entity_category = static_cast(entity->get_entity_category()); #ifdef USE_DEVICES diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 39f00b4adc..95db58aae9 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -292,9 +292,13 @@ class InfoResponseProtoMessage : public ProtoMessage { uint32_t key{0}; std::string name{}; bool disabled_by_default{false}; +#ifdef USE_ENTITY_ICON std::string icon{}; +#endif enums::EntityCategory entity_category{}; +#ifdef USE_DEVICES uint32_t device_id{0}; +#endif protected: }; @@ -303,7 +307,9 @@ class StateResponseProtoMessage : public ProtoMessage { public: ~StateResponseProtoMessage() override = default; uint32_t key{0}; +#ifdef USE_DEVICES uint32_t device_id{0}; +#endif protected: }; @@ -312,7 +318,9 @@ class CommandProtoMessage : public ProtoDecodableMessage { public: ~CommandProtoMessage() override = default; uint32_t key{0}; +#ifdef USE_DEVICES uint32_t device_id{0}; +#endif protected: }; diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 4df7692167..bb0e01d171 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -1491,6 +1491,28 @@ def find_common_fields( return common_fields +def get_common_field_ifdef( + field_name: str, messages: list[descriptor.DescriptorProto] +) -> str | None: + """Get the field_ifdef option if it's consistent across all messages. + + Args: + field_name: Name of the field to check + messages: List of messages that contain this field + + Returns: + The field_ifdef string if all messages have the same value, None otherwise + """ + field_ifdefs = { + get_field_opt(field, pb.field_ifdef) + for msg in messages + if (field := next((f for f in msg.field if f.name == field_name), None)) + } + + # Return the ifdef only if all messages agree on the same value + return field_ifdefs.pop() if len(field_ifdefs) == 1 else None + + def build_base_class( base_class_name: str, common_fields: list[descriptor.FieldDescriptorProto], @@ -1506,9 +1528,14 @@ def build_base_class( for field in common_fields: ti = create_field_type_info(field) + # Get field_ifdef if it's consistent across all messages + field_ifdef = get_common_field_ifdef(field.name, messages) + # Only add field declarations, not encode/decode logic - protected_content.extend(ti.protected_content) - public_content.extend(ti.public_content) + if ti.protected_content: + protected_content.extend(wrap_with_ifdef(ti.protected_content, field_ifdef)) + if ti.public_content: + public_content.extend(wrap_with_ifdef(ti.public_content, field_ifdef)) # Determine if any message using this base class needs decoding needs_decode = any(