|
| 1 | +# License: MIT |
| 2 | +# Copyright © 2025 Frequenz Energy-as-a-Service GmbH |
| 3 | + |
| 4 | +"""Loading of ComponentConnection objects from protobuf messages.""" |
| 5 | + |
| 6 | +import logging |
| 7 | + |
| 8 | +from frequenz.api.common.v1.microgrid.components import components_pb2 |
| 9 | +from frequenz.client.common.microgrid.components import ComponentId |
| 10 | + |
| 11 | +from .._lifetime import Lifetime |
| 12 | +from .._lifetime_proto import lifetime_from_proto |
| 13 | +from ._connection import ComponentConnection |
| 14 | + |
| 15 | +_logger = logging.getLogger(__name__) |
| 16 | + |
| 17 | + |
| 18 | +def component_connection_from_proto( |
| 19 | + message: components_pb2.ComponentConnection, |
| 20 | +) -> ComponentConnection | None: |
| 21 | + """Create a `ComponentConnection` from a protobuf message.""" |
| 22 | + major_issues: list[str] = [] |
| 23 | + minor_issues: list[str] = [] |
| 24 | + |
| 25 | + connection = component_connection_from_proto_with_issues( |
| 26 | + message, major_issues=major_issues, minor_issues=minor_issues |
| 27 | + ) |
| 28 | + |
| 29 | + if major_issues: |
| 30 | + _logger.warning( |
| 31 | + "Found issues in component connection: %s | Protobuf message:\n%s", |
| 32 | + ", ".join(major_issues), |
| 33 | + message, |
| 34 | + ) |
| 35 | + if minor_issues: |
| 36 | + _logger.debug( |
| 37 | + "Found minor issues in component connection: %s | Protobuf message:\n%s", |
| 38 | + ", ".join(minor_issues), |
| 39 | + message, |
| 40 | + ) |
| 41 | + |
| 42 | + return connection |
| 43 | + |
| 44 | + |
| 45 | +def component_connection_from_proto_with_issues( |
| 46 | + message: components_pb2.ComponentConnection, |
| 47 | + *, |
| 48 | + major_issues: list[str], |
| 49 | + minor_issues: list[str], |
| 50 | +) -> ComponentConnection | None: |
| 51 | + """Create a `ComponentConnection` from a protobuf message collecting issues. |
| 52 | +
|
| 53 | + This function is useful when you want to collect issues during the parsing |
| 54 | + of multiple connections, rather than logging them immediately. |
| 55 | +
|
| 56 | + Args: |
| 57 | + message: The protobuf message to parse. |
| 58 | + major_issues: A list to collect major issues found during parsing. |
| 59 | + minor_issues: A list to collect minor issues found during parsing. |
| 60 | +
|
| 61 | + Returns: |
| 62 | + A `ComponentConnection` object created from the protobuf message, or |
| 63 | + `None` if the protobuf message is completely invalid and a |
| 64 | + `ComponentConnection` cannot be created. |
| 65 | + """ |
| 66 | + source_component_id = ComponentId(message.source_component_id) |
| 67 | + destination_component_id = ComponentId(message.destination_component_id) |
| 68 | + if source_component_id == destination_component_id: |
| 69 | + major_issues.append( |
| 70 | + f"connection ignored: source and destination are the same ({source_component_id})", |
| 71 | + ) |
| 72 | + return None |
| 73 | + |
| 74 | + lifetime = _get_operational_lifetime_from_proto( |
| 75 | + message, major_issues=major_issues, minor_issues=minor_issues |
| 76 | + ) |
| 77 | + |
| 78 | + return ComponentConnection( |
| 79 | + source=source_component_id, |
| 80 | + destination=destination_component_id, |
| 81 | + operational_lifetime=lifetime, |
| 82 | + ) |
| 83 | + |
| 84 | + |
| 85 | +def _get_operational_lifetime_from_proto( |
| 86 | + message: components_pb2.ComponentConnection, |
| 87 | + *, |
| 88 | + major_issues: list[str], |
| 89 | + minor_issues: list[str], |
| 90 | +) -> Lifetime: |
| 91 | + """Get the operational lifetime from a protobuf message.""" |
| 92 | + if message.HasField("operational_lifetime"): |
| 93 | + try: |
| 94 | + return lifetime_from_proto(message.operational_lifetime) |
| 95 | + except ValueError as exc: |
| 96 | + major_issues.append( |
| 97 | + f"invalid operational lifetime ({exc}), considering it as missing " |
| 98 | + "(i.e. always operational)", |
| 99 | + ) |
| 100 | + else: |
| 101 | + minor_issues.append( |
| 102 | + "missing operational lifetime, considering it always operational", |
| 103 | + ) |
| 104 | + return Lifetime() |
0 commit comments