From ef43fa56f4cbf0ca3708af6fba89600b18f7b8f9 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Fri, 19 Sep 2025 10:37:07 +0200 Subject: [PATCH 01/10] Bump the microgrid API dependency to v0.18 For this we also need to update the common API dependency to v0.8.0 and the client common dependency to v0.3.6. Signed-off-by: Leandro Lucarella --- pyproject.toml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7e8ca2d..692ee72 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,10 +36,11 @@ classifiers = [ ] requires-python = ">= 3.11, < 4" dependencies = [ - "frequenz-api-microgrid >= 0.17.2, < 0.18.0", + "frequenz-api-common >= 0.8.0, < 1.0.0", + "frequenz-api-microgrid >= 0.18.0, < 0.19.0", "frequenz-channels >= 1.6.1, < 2.0.0", "frequenz-client-base >= 0.10.0, < 0.12.0", - "frequenz-client-common >= 0.3.2, < 0.4.0", + "frequenz-client-common >= 0.3.6, < 0.4.0", "grpcio >= 1.72.1, < 2", "protobuf >= 6.31.1, < 7", "typing-extensions >= 4.13.0, < 5", From 891846721d4fbdab65690eb6ca02e241872a4348 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Tue, 23 Sep 2025 13:58:10 +0200 Subject: [PATCH 02/10] Remove Fuse component This component was removed from the microgrid API v0.18. Signed-off-by: Leandro Lucarella --- .../client/microgrid/component/__init__.py | 2 - .../client/microgrid/component/_category.py | 3 - .../microgrid/component/_component_proto.py | 15 ----- .../client/microgrid/component/_fuse.py | 39 ----------- .../client/microgrid/component/_types.py | 2 - .../diverse_component_types_case.py | 10 --- .../component/component_proto/test_simple.py | 28 -------- tests/component/test_fuse.py | 65 ------------------- 8 files changed, 164 deletions(-) delete mode 100644 src/frequenz/client/microgrid/component/_fuse.py delete mode 100644 tests/component/test_fuse.py diff --git a/src/frequenz/client/microgrid/component/__init__.py b/src/frequenz/client/microgrid/component/__init__.py index 3341da0..5629c93 100644 --- a/src/frequenz/client/microgrid/component/__init__.py +++ b/src/frequenz/client/microgrid/component/__init__.py @@ -30,7 +30,6 @@ UnrecognizedEvCharger, UnspecifiedEvCharger, ) -from ._fuse import Fuse from ._grid_connection_point import GridConnectionPoint from ._hvac import Hvac from ._inverter import ( @@ -84,7 +83,6 @@ "EvCharger", "EvChargerType", "EvChargerTypes", - "Fuse", "GridConnectionPoint", "Hvac", "HybridEvCharger", diff --git a/src/frequenz/client/microgrid/component/_category.py b/src/frequenz/client/microgrid/component/_category.py index 1f5bff0..20eb139 100644 --- a/src/frequenz/client/microgrid/component/_category.py +++ b/src/frequenz/client/microgrid/component/_category.py @@ -61,9 +61,6 @@ class ComponentCategory(enum.Enum): external precharging modules. """ - FUSE = components_pb2.COMPONENT_CATEGORY_FUSE - """A fuse.""" - VOLTAGE_TRANSFORMER = components_pb2.COMPONENT_CATEGORY_VOLTAGE_TRANSFORMER """A voltage transformer. diff --git a/src/frequenz/client/microgrid/component/_component_proto.py b/src/frequenz/client/microgrid/component/_component_proto.py index 21e9c69..e677b47 100644 --- a/src/frequenz/client/microgrid/component/_component_proto.py +++ b/src/frequenz/client/microgrid/component/_component_proto.py @@ -38,7 +38,6 @@ UnrecognizedEvCharger, UnspecifiedEvCharger, ) -from ._fuse import Fuse from ._grid_connection_point import GridConnectionPoint from ._hvac import Hvac from ._inverter import ( @@ -362,20 +361,6 @@ def component_from_proto_with_issues( ) case unexpected_ev_charger_type: assert_never(unexpected_ev_charger_type) - case ComponentCategory.FUSE: - rated_current = message.category_type.fuse.rated_current - # No need to check for negatives because the protobuf type is uint32. - return Fuse( - id=base_data.component_id, - microgrid_id=base_data.microgrid_id, - name=base_data.name, - manufacturer=base_data.manufacturer, - model_name=base_data.model_name, - status=base_data.status, - operational_lifetime=base_data.lifetime, - rated_bounds=base_data.rated_bounds, - rated_current=rated_current, - ) case ComponentCategory.GRID: rated_fuse_current = message.category_type.grid.rated_fuse_current # No need to check for negatives because the protobuf type is uint32. diff --git a/src/frequenz/client/microgrid/component/_fuse.py b/src/frequenz/client/microgrid/component/_fuse.py deleted file mode 100644 index fc4455b..0000000 --- a/src/frequenz/client/microgrid/component/_fuse.py +++ /dev/null @@ -1,39 +0,0 @@ -# License: MIT -# Copyright © 2024 Frequenz Energy-as-a-Service GmbH - -"""Fuse component.""" - -import dataclasses -from typing import Literal - -from ._category import ComponentCategory -from ._component import Component - - -@dataclasses.dataclass(frozen=True, kw_only=True) -class Fuse(Component): - """A fuse component. - - Fuses are used to protect components from overcurrents. - """ - - category: Literal[ComponentCategory.FUSE] = ComponentCategory.FUSE - """The category of this component.""" - - rated_current: int - """The rated current of the fuse in amperes. - - This is the maximum current that the fuse can withstand for a long time. This limit - applies to currents both flowing in or out of each of the 3 phases individually. - - In other words, a current `i`A at one of the phases of the node must comply with the - following constraint: - `-rated_fuse_current <= i <= rated_fuse_current` - """ - - def __post_init__(self) -> None: - """Validate the fuse's rated current.""" - if self.rated_current < 0: - raise ValueError( - f"rated_current must be a positive integer, not {self.rated_current}" - ) diff --git a/src/frequenz/client/microgrid/component/_types.py b/src/frequenz/client/microgrid/component/_types.py index e362ab7..043a7be 100644 --- a/src/frequenz/client/microgrid/component/_types.py +++ b/src/frequenz/client/microgrid/component/_types.py @@ -11,7 +11,6 @@ from ._crypto_miner import CryptoMiner from ._electrolyzer import Electrolyzer from ._ev_charger import EvChargerTypes, UnrecognizedEvCharger, UnspecifiedEvCharger -from ._fuse import Fuse from ._grid_connection_point import GridConnectionPoint from ._hvac import Hvac from ._inverter import InverterTypes, UnrecognizedInverter, UnspecifiedInverter @@ -52,7 +51,6 @@ | CryptoMiner | Electrolyzer | EvChargerTypes - | Fuse | GridConnectionPoint | Hvac | InverterTypes diff --git a/tests/client_test_cases/list_components/diverse_component_types_case.py b/tests/client_test_cases/list_components/diverse_component_types_case.py index ae55444..8bc7755 100644 --- a/tests/client_test_cases/list_components/diverse_component_types_case.py +++ b/tests/client_test_cases/list_components/diverse_component_types_case.py @@ -9,7 +9,6 @@ battery_pb2, components_pb2, ev_charger_pb2, - fuse_pb2, grid_pb2, inverter_pb2, ) @@ -30,7 +29,6 @@ Electrolyzer, EvCharger, EvChargerType, - Fuse, GridConnectionPoint, Hvac, HybridEvCharger, @@ -109,13 +107,6 @@ def assert_stub_method_call(stub_method: Any) -> None: ) ), ), - components_pb2.Component( - id=7, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_FUSE, - category_type=components_pb2.ComponentCategoryMetadataVariant( - fuse=fuse_pb2.Fuse(rated_current=50) - ), - ), components_pb2.Component( id=8, category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_HVAC ), @@ -279,7 +270,6 @@ def assert_client_result(result: Any) -> None: Converter(id=ComponentId(4), microgrid_id=MicrogridId(0)), Meter(id=ComponentId(5), microgrid_id=MicrogridId(0)), AcEvCharger(id=ComponentId(6), microgrid_id=MicrogridId(0)), - Fuse(id=ComponentId(7), microgrid_id=MicrogridId(0), rated_current=50), Hvac(id=ComponentId(8), microgrid_id=MicrogridId(0)), # Additional battery types UnspecifiedBattery(id=ComponentId(9), microgrid_id=MicrogridId(0)), diff --git a/tests/component/component_proto/test_simple.py b/tests/component/component_proto/test_simple.py index 960a27d..9ff5bff 100644 --- a/tests/component/component_proto/test_simple.py +++ b/tests/component/component_proto/test_simple.py @@ -17,7 +17,6 @@ Converter, CryptoMiner, Electrolyzer, - Fuse, GridConnectionPoint, Hvac, Meter, @@ -165,33 +164,6 @@ def test_voltage_transformer( ) -@pytest.mark.parametrize("rated_current", [None, 0, 23]) -def test_fuse( - default_component_base_data: ComponentBaseData, - rated_current: int | None, -) -> None: - """Test Fuse component with default values.""" - major_issues: list[str] = [] - minor_issues: list[str] = [] - base_data = default_component_base_data._replace(category=ComponentCategory.FUSE) - - proto = base_data_as_proto(base_data) - if rated_current is not None: - proto.category_type.fuse.rated_current = rated_current - - component = component_from_proto_with_issues( - proto, major_issues=major_issues, minor_issues=minor_issues - ) - - assert not major_issues - assert not minor_issues - assert isinstance(component, Fuse) - assert_base_data(base_data, component) - assert component.rated_current == ( - rated_current if rated_current is not None else 0 - ) - - @pytest.mark.parametrize("rated_fuse_current", [None, 0, 23]) def test_grid( default_component_base_data: ComponentBaseData, diff --git a/tests/component/test_fuse.py b/tests/component/test_fuse.py deleted file mode 100644 index e1ae2cd..0000000 --- a/tests/component/test_fuse.py +++ /dev/null @@ -1,65 +0,0 @@ -# License: MIT -# Copyright © 2025 Frequenz Energy-as-a-Service GmbH - -"""Tests for Fuse component.""" - -import pytest -from frequenz.client.common.microgrid import MicrogridId -from frequenz.client.common.microgrid.components import ComponentId - -from frequenz.client.microgrid.component import ComponentCategory, ComponentStatus, Fuse - - -@pytest.fixture -def component_id() -> ComponentId: - """Provide a test component ID.""" - return ComponentId(42) - - -@pytest.fixture -def microgrid_id() -> MicrogridId: - """Provide a test microgrid ID.""" - return MicrogridId(1) - - -@pytest.mark.parametrize("rated_current", [0, 50]) -def test_creation_ok( - component_id: ComponentId, microgrid_id: MicrogridId, rated_current: int -) -> None: - """Test Fuse component initialization with different rated currents.""" - fuse = Fuse( - id=component_id, - microgrid_id=microgrid_id, - name="test_fuse", - manufacturer="test_manufacturer", - model_name="test_model", - status=ComponentStatus.ACTIVE, - rated_current=rated_current, - ) - - assert fuse.id == component_id - assert fuse.microgrid_id == microgrid_id - assert fuse.name == "test_fuse" - assert fuse.manufacturer == "test_manufacturer" - assert fuse.model_name == "test_model" - assert fuse.status == ComponentStatus.ACTIVE - assert fuse.category == ComponentCategory.FUSE - assert fuse.rated_current == rated_current - - -def test_creation_invalid_rated_current( - component_id: ComponentId, microgrid_id: MicrogridId -) -> None: - """Test Fuse component initialization with invalid rated current.""" - with pytest.raises( - ValueError, match="rated_current must be a positive integer, not -1" - ): - Fuse( - id=component_id, - microgrid_id=microgrid_id, - name="test_fuse", - manufacturer="test_manufacturer", - model_name="test_model", - status=ComponentStatus.ACTIVE, - rated_current=-1, - ) From 8fc7c68c79d093f6c1e8c56b7a8e860cd77959ab Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Tue, 23 Sep 2025 14:14:58 +0200 Subject: [PATCH 03/10] Remove `ComponentStatus` and `Component.status` These were removed from the microgrid API v0.18. Signed-off-by: Leandro Lucarella --- .../client/microgrid/component/__init__.py | 2 - .../client/microgrid/component/_component.py | 55 +++---------------- .../microgrid/component/_component_proto.py | 20 ------- .../client/microgrid/component/_status.py | 22 -------- tests/component/component_proto/conftest.py | 13 +---- tests/component/component_proto/test_base.py | 16 ++---- tests/component/test_battery.py | 6 -- tests/component/test_chp.py | 4 +- tests/component/test_component.py | 53 +++--------------- tests/component/test_converter.py | 8 +-- tests/component/test_crypto_miner.py | 8 +-- tests/component/test_electrolyzer.py | 8 +-- tests/component/test_ev_charger.py | 6 -- tests/component/test_grid_connection_point.py | 9 +-- tests/component/test_hvac.py | 4 +- tests/component/test_inverter.py | 6 -- tests/component/test_meter.py | 8 +-- tests/component/test_precharger.py | 8 +-- tests/component/test_problematic.py | 10 ---- tests/component/test_relay.py | 8 +-- tests/component/test_voltage_transformer.py | 8 +-- 21 files changed, 31 insertions(+), 251 deletions(-) delete mode 100644 src/frequenz/client/microgrid/component/_status.py diff --git a/src/frequenz/client/microgrid/component/__init__.py b/src/frequenz/client/microgrid/component/__init__.py index 5629c93..e6dee16 100644 --- a/src/frequenz/client/microgrid/component/__init__.py +++ b/src/frequenz/client/microgrid/component/__init__.py @@ -51,7 +51,6 @@ ) from ._relay import Relay from ._state_sample import ComponentErrorCode, ComponentStateCode, ComponentStateSample -from ._status import ComponentStatus from ._types import ( ComponentTypes, ProblematicComponentTypes, @@ -74,7 +73,6 @@ "ComponentErrorCode", "ComponentStateCode", "ComponentStateSample", - "ComponentStatus", "ComponentTypes", "Converter", "CryptoMiner", diff --git a/src/frequenz/client/microgrid/component/_component.py b/src/frequenz/client/microgrid/component/_component.py index d4a8d53..40954b2 100644 --- a/src/frequenz/client/microgrid/component/_component.py +++ b/src/frequenz/client/microgrid/component/_component.py @@ -4,7 +4,6 @@ """Base component from which all other components inherit.""" import dataclasses -import logging from collections.abc import Mapping from datetime import datetime, timezone from typing import Any, Self @@ -16,9 +15,6 @@ from ..metrics._bounds import Bounds from ..metrics._metric import Metric from ._category import ComponentCategory -from ._status import ComponentStatus - -_logger = logging.getLogger(__name__) @dataclasses.dataclass(frozen=True, kw_only=True) @@ -44,17 +40,6 @@ class Component: # pylint: disable=too-many-instance-attributes and in case some low level code needs to know the category of a component. """ - status: ComponentStatus | int = ComponentStatus.UNSPECIFIED - """The status of this component. - - Tip: - You can also use - [`is_active_now()`][frequenz.client.microgrid.component.Component.is_active_now] - or - [`is_active_at()`][frequenz.client.microgrid.component.Component.is_active_at], - which also checks if the component is operational. - """ - name: str | None = None """The name of this component.""" @@ -100,48 +85,24 @@ def __new__(cls, *_: Any, **__: Any) -> Self: raise TypeError(f"Cannot instantiate {cls.__name__} directly") return super().__new__(cls) - def is_active_at(self, timestamp: datetime) -> bool: - """Check whether this component is active at a specific timestamp. - - A component is considered active if it is in the active state and is - operational at the given timestamp. The operational lifetime is used to - determine whether the component is operational at the given timestamp. - - If a component has an unspecified status, it is assumed to be active - and a warning is logged. + def is_operational_at(self, timestamp: datetime) -> bool: + """Check whether this component is operational at a specific timestamp. Args: timestamp: The timestamp to check. Returns: - Whether this component is active at the given timestamp. + Whether this component is operational at the given timestamp. """ - if self.status is ComponentStatus.UNSPECIFIED: - _logger.warning( - "Component %s has an unspecified status. Assuming it is active.", - self, - ) - return self.operational_lifetime.is_operational_at(timestamp) - - return ( - self.status is ComponentStatus.ACTIVE - and self.operational_lifetime.is_operational_at(timestamp) - ) - - def is_active_now(self) -> bool: - """Check whether this component is currently active. - - A component is considered active if it is in the active state and is - operational at the current time. The operational lifetime is used to - determine whether the component is operational at the current time. + return self.operational_lifetime.is_operational_at(timestamp) - If a component has an unspecified status, it is assumed to be active - and a warning is logged. + def is_operational_now(self) -> bool: + """Check whether this component is currently operational. Returns: - Whether this component is active at the current time. + Whether this component is operational at the current time. """ - return self.is_active_at(datetime.now(timezone.utc)) + return self.is_operational_at(datetime.now(timezone.utc)) @property def identity(self) -> tuple[ComponentId, MicrogridId]: diff --git a/src/frequenz/client/microgrid/component/_component_proto.py b/src/frequenz/client/microgrid/component/_component_proto.py index e677b47..dafef34 100644 --- a/src/frequenz/client/microgrid/component/_component_proto.py +++ b/src/frequenz/client/microgrid/component/_component_proto.py @@ -56,7 +56,6 @@ UnspecifiedComponent, ) from ._relay import Relay -from ._status import ComponentStatus from ._types import ComponentTypes from ._voltage_transformer import VoltageTransformer @@ -109,7 +108,6 @@ class ComponentBaseData(NamedTuple): manufacturer: str | None model_name: str | None category: ComponentCategory | int - status: ComponentStatus | int lifetime: Lifetime rated_bounds: dict[Metric | int, Bounds] category_specific_metadata: dict[str, Any] @@ -147,12 +145,6 @@ def component_base_from_proto_with_issues( if model_name is None: minor_issues.append("model_name is empty") - status = enum_from_proto(message.status, ComponentStatus) - if status is ComponentStatus.UNSPECIFIED: - major_issues.append("status is unspecified") - elif isinstance(status, int): - major_issues.append("status is unrecognized") - lifetime = _get_operational_lifetime_from_proto( message, major_issues=major_issues, minor_issues=minor_issues ) @@ -193,7 +185,6 @@ def component_base_from_proto_with_issues( manufacturer, model_name, category, - status, lifetime, rated_bounds, category_specific_metadata, @@ -229,7 +220,6 @@ def component_from_proto_with_issues( name=base_data.name, manufacturer=base_data.manufacturer, model_name=base_data.model_name, - status=base_data.status, category=base_data.category, operational_lifetime=base_data.lifetime, category_specific_metadata=base_data.category_specific_metadata, @@ -244,7 +234,6 @@ def component_from_proto_with_issues( name=base_data.name, manufacturer=base_data.manufacturer, model_name=base_data.model_name, - status=base_data.status, category=base_data.category, operational_lifetime=base_data.lifetime, rated_bounds=base_data.rated_bounds, @@ -266,7 +255,6 @@ def component_from_proto_with_issues( name=base_data.name, manufacturer=base_data.manufacturer, model_name=base_data.model_name, - status=base_data.status, operational_lifetime=base_data.lifetime, rated_bounds=base_data.rated_bounds, ) @@ -291,7 +279,6 @@ def component_from_proto_with_issues( name=base_data.name, manufacturer=base_data.manufacturer, model_name=base_data.model_name, - status=base_data.status, operational_lifetime=base_data.lifetime, rated_bounds=base_data.rated_bounds, ) @@ -303,7 +290,6 @@ def component_from_proto_with_issues( name=base_data.name, manufacturer=base_data.manufacturer, model_name=base_data.model_name, - status=base_data.status, operational_lifetime=base_data.lifetime, rated_bounds=base_data.rated_bounds, type=battery_type, @@ -340,7 +326,6 @@ def component_from_proto_with_issues( name=base_data.name, manufacturer=base_data.manufacturer, model_name=base_data.model_name, - status=base_data.status, operational_lifetime=base_data.lifetime, rated_bounds=base_data.rated_bounds, ) @@ -354,7 +339,6 @@ def component_from_proto_with_issues( name=base_data.name, manufacturer=base_data.manufacturer, model_name=base_data.model_name, - status=base_data.status, operational_lifetime=base_data.lifetime, rated_bounds=base_data.rated_bounds, type=ev_charger_type, @@ -370,7 +354,6 @@ def component_from_proto_with_issues( name=base_data.name, manufacturer=base_data.manufacturer, model_name=base_data.model_name, - status=base_data.status, operational_lifetime=base_data.lifetime, rated_bounds=base_data.rated_bounds, rated_fuse_current=rated_fuse_current, @@ -408,7 +391,6 @@ def component_from_proto_with_issues( name=base_data.name, manufacturer=base_data.manufacturer, model_name=base_data.model_name, - status=base_data.status, operational_lifetime=base_data.lifetime, rated_bounds=base_data.rated_bounds, ) @@ -422,7 +404,6 @@ def component_from_proto_with_issues( name=base_data.name, manufacturer=base_data.manufacturer, model_name=base_data.model_name, - status=base_data.status, operational_lifetime=base_data.lifetime, rated_bounds=base_data.rated_bounds, type=inverter_type, @@ -436,7 +417,6 @@ def component_from_proto_with_issues( name=base_data.name, manufacturer=base_data.manufacturer, model_name=base_data.model_name, - status=base_data.status, operational_lifetime=base_data.lifetime, rated_bounds=base_data.rated_bounds, primary_voltage=message.category_type.voltage_transformer.primary, diff --git a/src/frequenz/client/microgrid/component/_status.py b/src/frequenz/client/microgrid/component/_status.py deleted file mode 100644 index 727ee24..0000000 --- a/src/frequenz/client/microgrid/component/_status.py +++ /dev/null @@ -1,22 +0,0 @@ -# License: MIT -# Copyright © 2024 Frequenz Energy-as-a-Service GmbH - -"""Status for a component.""" - -import enum - -from frequenz.api.common.v1.microgrid.components import components_pb2 - - -@enum.unique -class ComponentStatus(enum.Enum): - """The known statuses of a component.""" - - UNSPECIFIED = components_pb2.COMPONENT_STATUS_UNSPECIFIED - """The status is unspecified.""" - - ACTIVE = components_pb2.COMPONENT_STATUS_ACTIVE - """The component is active.""" - - INACTIVE = components_pb2.COMPONENT_STATUS_INACTIVE - """The component is inactive.""" diff --git a/tests/component/component_proto/conftest.py b/tests/component/component_proto/conftest.py index b1d2a09..f8a68e0 100644 --- a/tests/component/component_proto/conftest.py +++ b/tests/component/component_proto/conftest.py @@ -15,11 +15,7 @@ from google.protobuf.timestamp_pb2 import Timestamp from frequenz.client.microgrid import Lifetime -from frequenz.client.microgrid.component import ( - Component, - ComponentCategory, - ComponentStatus, -) +from frequenz.client.microgrid.component import Component, ComponentCategory from frequenz.client.microgrid.component._component_proto import ComponentBaseData from frequenz.client.microgrid.metrics import Bounds, Metric @@ -58,7 +54,6 @@ def default_component_base_data( manufacturer=DEFAULT_MANUFACTURER, model_name=DEFAULT_MODEL_NAME, category=ComponentCategory.UNSPECIFIED, - status=ComponentStatus.ACTIVE, lifetime=DEFAULT_LIFETIME, rated_bounds={Metric.AC_ACTIVE_ENERGY: Bounds(lower=0, upper=100)}, category_specific_metadata={}, @@ -74,7 +69,6 @@ def assert_base_data(base_data: ComponentBaseData, other: Component) -> None: assert base_data.manufacturer == other.manufacturer assert base_data.model_name == other.model_name assert base_data.category == other.category - assert base_data.status == other.status assert base_data.lifetime == other.operational_lifetime assert base_data.rated_bounds == other.rated_bounds assert base_data.category_specific_metadata == other.category_specific_metadata @@ -88,11 +82,6 @@ def base_data_as_proto(base_data: ComponentBaseData) -> components_pb2.Component name=base_data.name or "", manufacturer=base_data.manufacturer or "", model_name=base_data.model_name or "", - status=( - base_data.status - if isinstance(base_data.status, int) - else int(base_data.status.value) # type: ignore[arg-type] - ), category=( base_data.category if isinstance(base_data.category, int) diff --git a/tests/component/component_proto/test_base.py b/tests/component/component_proto/test_base.py index 4c20ae9..5fc0d4d 100644 --- a/tests/component/component_proto/test_base.py +++ b/tests/component/component_proto/test_base.py @@ -4,12 +4,11 @@ """Tests for protobuf conversion of the base/common part of Component objects.""" -import pytest from frequenz.api.common.v1.microgrid.components import battery_pb2 from google.protobuf.timestamp_pb2 import Timestamp from frequenz.client.microgrid import Lifetime -from frequenz.client.microgrid.component import ComponentCategory, ComponentStatus +from frequenz.client.microgrid.component import ComponentCategory from frequenz.client.microgrid.component._component_proto import ( ComponentBaseData, component_base_from_proto_with_issues, @@ -35,9 +34,8 @@ def test_complete(default_component_base_data: ComponentBaseData) -> None: assert parsed == base_data -@pytest.mark.parametrize("status", [ComponentStatus.UNSPECIFIED, 999]) -def test_missing_metadata( - default_component_base_data: ComponentBaseData, status: ComponentStatus | int +def test_missing_category_specific_info( + default_component_base_data: ComponentBaseData, ) -> None: """Test parsing with missing optional metadata.""" major_issues: list[str] = [] @@ -47,7 +45,6 @@ def test_missing_metadata( manufacturer=None, model_name=None, category=ComponentCategory.UNSPECIFIED, - status=status, lifetime=Lifetime(), rated_bounds={}, category_specific_metadata={}, @@ -60,12 +57,7 @@ def test_missing_metadata( proto, major_issues=major_issues, minor_issues=minor_issues ) - expected_major_issues = ["category is unspecified"] - if status == ComponentStatus.UNSPECIFIED: - expected_major_issues.append("status is unspecified") - else: - expected_major_issues.append("status is unrecognized") - assert sorted(major_issues) == sorted(expected_major_issues) + assert sorted(major_issues) == sorted(["category is unspecified"]) assert sorted(minor_issues) == sorted( [ "name is empty", diff --git a/tests/component/test_battery.py b/tests/component/test_battery.py index 828aa9b..b9ddfc0 100644 --- a/tests/component/test_battery.py +++ b/tests/component/test_battery.py @@ -13,7 +13,6 @@ Battery, BatteryType, ComponentCategory, - ComponentStatus, LiIonBattery, NaIonBattery, UnrecognizedBattery, @@ -53,7 +52,6 @@ def test_abstract_battery_cannot_be_instantiated( name="test_battery", manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, type=BatteryType.LI_ION, ) @@ -85,7 +83,6 @@ def test_recognized_battery_types( name=case.name, manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, ) assert battery.id == component_id @@ -93,7 +90,6 @@ def test_recognized_battery_types( assert battery.name == case.name assert battery.manufacturer == "test_manufacturer" assert battery.model_name == "test_model" - assert battery.status == ComponentStatus.ACTIVE assert battery.category == ComponentCategory.BATTERY assert battery.type == case.expected_type @@ -108,7 +104,6 @@ def test_unrecognized_battery_type( name="unrecognized_battery", manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, type=999, ) @@ -117,6 +112,5 @@ def test_unrecognized_battery_type( assert battery.name == "unrecognized_battery" assert battery.manufacturer == "test_manufacturer" assert battery.model_name == "test_model" - assert battery.status == ComponentStatus.ACTIVE assert battery.category == ComponentCategory.BATTERY assert battery.type == 999 diff --git a/tests/component/test_chp.py b/tests/component/test_chp.py index c16ff5d..5a5ea77 100644 --- a/tests/component/test_chp.py +++ b/tests/component/test_chp.py @@ -7,7 +7,7 @@ from frequenz.client.common.microgrid import MicrogridId from frequenz.client.common.microgrid.components import ComponentId -from frequenz.client.microgrid.component import Chp, ComponentCategory, ComponentStatus +from frequenz.client.microgrid.component import Chp, ComponentCategory def test_init() -> None: @@ -20,7 +20,6 @@ def test_init() -> None: name="chp_test", manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, ) assert component.id == component_id @@ -28,5 +27,4 @@ def test_init() -> None: assert component.name == "chp_test" assert component.manufacturer == "test_manufacturer" assert component.model_name == "test_model" - assert component.status == ComponentStatus.ACTIVE assert component.category == ComponentCategory.CHP diff --git a/tests/component/test_component.py b/tests/component/test_component.py index 4b2b253..6fb8228 100644 --- a/tests/component/test_component.py +++ b/tests/component/test_component.py @@ -14,7 +14,6 @@ from frequenz.client.microgrid import Lifetime from frequenz.client.microgrid.component._category import ComponentCategory from frequenz.client.microgrid.component._component import Component -from frequenz.client.microgrid.component._status import ComponentStatus from frequenz.client.microgrid.metrics._bounds import Bounds from frequenz.client.microgrid.metrics._metric import Metric @@ -43,7 +42,6 @@ def test_creation_with_defaults() -> None: category=ComponentCategory.UNSPECIFIED, ) - assert component.status == ComponentStatus.UNSPECIFIED assert component.name is None assert component.manufacturer is None assert component.model_name is None @@ -95,42 +93,29 @@ def test_str(name: str | None, expected_str: str) -> None: assert str(component) == expected_str -@pytest.mark.parametrize("status", list(ComponentStatus), ids=lambda s: s.name) @pytest.mark.parametrize( - "lifetime_active", [True, False], ids=["operational", "not-operational"] + "is_operational", [True, False], ids=["operational", "not-operational"] ) -def test_active_at( - status: ComponentStatus, lifetime_active: bool, caplog: pytest.LogCaptureFixture -) -> None: - """Test active_at behavior with different status and lifetime combinations.""" - caplog.set_level("WARNING") - +def test_operational_at(is_operational: bool) -> None: + """Test active_at behavior with lifetime combinations.""" mock_lifetime = Mock(spec=Lifetime) - mock_lifetime.is_operational_at.return_value = lifetime_active + mock_lifetime.is_operational_at.return_value = is_operational component = _TestComponent( id=ComponentId(1), microgrid_id=MicrogridId(1), category=ComponentCategory.UNSPECIFIED, - status=status, operational_lifetime=mock_lifetime, ) test_time = datetime.now(timezone.utc) - expected = status != ComponentStatus.INACTIVE and lifetime_active - assert component.is_active_at(test_time) == expected - - if status in (ComponentStatus.ACTIVE, ComponentStatus.UNSPECIFIED): - mock_lifetime.is_operational_at.assert_called_once_with(test_time) - else: - mock_lifetime.is_operational_at.assert_not_called() + assert component.is_operational_at(test_time) == is_operational - if status is ComponentStatus.UNSPECIFIED: - assert "unspecified status" in caplog.text.lower() + mock_lifetime.is_operational_at.assert_called_once_with(test_time) @patch("frequenz.client.microgrid.component._component.datetime") -def test_is_active_now(mock_datetime: Mock) -> None: +def test_is_operational_now(mock_datetime: Mock) -> None: """Test is_active_now method.""" now = datetime(2025, 1, 1, 12, 0, 0, tzinfo=timezone.utc) mock_datetime.now.side_effect = lambda tz: now.replace(tzinfo=tz) @@ -140,11 +125,10 @@ def test_is_active_now(mock_datetime: Mock) -> None: id=ComponentId(1), microgrid_id=MicrogridId(1), category=ComponentCategory.UNSPECIFIED, - status=ComponentStatus.ACTIVE, operational_lifetime=mock_lifetime, ) - assert component.is_active_now() is True + assert component.is_operational_now() is True mock_lifetime.is_operational_at.assert_called_once_with(now) @@ -153,7 +137,6 @@ def test_is_active_now(mock_datetime: Mock) -> None: id=ComponentId(1), microgrid_id=MicrogridId(1), category=ComponentCategory.UNSPECIFIED, - status=ComponentStatus.ACTIVE, name="test", manufacturer="Test Mfg", model_name="Model A", @@ -165,7 +148,6 @@ def test_is_active_now(mock_datetime: Mock) -> None: id=COMPONENT.id, microgrid_id=COMPONENT.microgrid_id, category=COMPONENT.category, - status=COMPONENT.status, name=COMPONENT.name, manufacturer=COMPONENT.manufacturer, model_name=COMPONENT.model_name, @@ -173,23 +155,10 @@ def test_is_active_now(mock_datetime: Mock) -> None: category_specific_metadata={"different": "metadata"}, ) -DIFFERENT_STATUS = _TestComponent( - id=COMPONENT.id, - microgrid_id=COMPONENT.microgrid_id, - category=COMPONENT.category, - status=ComponentStatus.INACTIVE, - name=COMPONENT.name, - manufacturer=COMPONENT.manufacturer, - model_name=COMPONENT.model_name, - rated_bounds=COMPONENT.rated_bounds, - category_specific_metadata=COMPONENT.category_specific_metadata, -) - DIFFERENT_NAME = _TestComponent( id=COMPONENT.id, microgrid_id=COMPONENT.microgrid_id, category=COMPONENT.category, - status=COMPONENT.status, name="different", manufacturer=COMPONENT.manufacturer, model_name=COMPONENT.model_name, @@ -201,7 +170,6 @@ def test_is_active_now(mock_datetime: Mock) -> None: id=ComponentId(2), microgrid_id=COMPONENT.microgrid_id, category=COMPONENT.category, - status=COMPONENT.status, name=COMPONENT.name, manufacturer=COMPONENT.manufacturer, model_name=COMPONENT.model_name, @@ -213,7 +181,6 @@ def test_is_active_now(mock_datetime: Mock) -> None: id=COMPONENT.id, microgrid_id=MicrogridId(2), category=COMPONENT.category, - status=COMPONENT.status, name=COMPONENT.name, manufacturer=COMPONENT.manufacturer, model_name=COMPONENT.model_name, @@ -225,7 +192,6 @@ def test_is_active_now(mock_datetime: Mock) -> None: id=ComponentId(2), microgrid_id=MicrogridId(2), category=COMPONENT.category, - status=COMPONENT.status, name=COMPONENT.name, manufacturer=COMPONENT.manufacturer, model_name=COMPONENT.model_name, @@ -239,7 +205,6 @@ def test_is_active_now(mock_datetime: Mock) -> None: [ pytest.param(COMPONENT, True, id="self"), pytest.param(DIFFERENT_NONHASHABLE, False, id="other-nonhashable"), - pytest.param(DIFFERENT_STATUS, False, id="other-status"), pytest.param(DIFFERENT_NAME, False, id="other-name"), pytest.param(DIFFERENT_ID, False, id="other-id"), pytest.param(DIFFERENT_MICROGRID_ID, False, id="other-microgrid-id"), @@ -260,7 +225,6 @@ def test_equality(comp: Component, expected: bool) -> None: [ pytest.param(COMPONENT, True, id="self"), pytest.param(DIFFERENT_NONHASHABLE, True, id="other-nonhashable"), - pytest.param(DIFFERENT_STATUS, True, id="other-status"), pytest.param(DIFFERENT_NAME, True, id="other-name"), pytest.param(DIFFERENT_ID, False, id="other-id"), pytest.param(DIFFERENT_MICROGRID_ID, False, id="other-microgrid-id"), @@ -276,7 +240,6 @@ def test_identity(comp: Component, expected: bool) -> None: ALL_COMPONENTS_PARAMS = [ pytest.param(COMPONENT, id="comp"), pytest.param(DIFFERENT_NONHASHABLE, id="nonhashable"), - pytest.param(DIFFERENT_STATUS, id="status"), pytest.param(DIFFERENT_NAME, id="name"), pytest.param(DIFFERENT_ID, id="id"), pytest.param(DIFFERENT_MICROGRID_ID, id="microgrid_id"), diff --git a/tests/component/test_converter.py b/tests/component/test_converter.py index 29a284e..fee15fa 100644 --- a/tests/component/test_converter.py +++ b/tests/component/test_converter.py @@ -6,11 +6,7 @@ from frequenz.client.common.microgrid import MicrogridId from frequenz.client.common.microgrid.components import ComponentId -from frequenz.client.microgrid.component import ( - ComponentCategory, - ComponentStatus, - Converter, -) +from frequenz.client.microgrid.component import ComponentCategory, Converter def test_init() -> None: @@ -23,7 +19,6 @@ def test_init() -> None: name="test_converter", manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, ) assert component.id == component_id @@ -31,5 +26,4 @@ def test_init() -> None: assert component.name == "test_converter" assert component.manufacturer == "test_manufacturer" assert component.model_name == "test_model" - assert component.status == ComponentStatus.ACTIVE assert component.category == ComponentCategory.CONVERTER diff --git a/tests/component/test_crypto_miner.py b/tests/component/test_crypto_miner.py index 9a3a2bd..95b1785 100644 --- a/tests/component/test_crypto_miner.py +++ b/tests/component/test_crypto_miner.py @@ -6,11 +6,7 @@ from frequenz.client.common.microgrid import MicrogridId from frequenz.client.common.microgrid.components import ComponentId -from frequenz.client.microgrid.component import ( - ComponentCategory, - ComponentStatus, - CryptoMiner, -) +from frequenz.client.microgrid.component import ComponentCategory, CryptoMiner def test_init() -> None: @@ -23,7 +19,6 @@ def test_init() -> None: name="test_crypto_miner", manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, ) assert component.id == component_id @@ -31,5 +26,4 @@ def test_init() -> None: assert component.name == "test_crypto_miner" assert component.manufacturer == "test_manufacturer" assert component.model_name == "test_model" - assert component.status == ComponentStatus.ACTIVE assert component.category == ComponentCategory.CRYPTO_MINER diff --git a/tests/component/test_electrolyzer.py b/tests/component/test_electrolyzer.py index 61eeb1e..0a10737 100644 --- a/tests/component/test_electrolyzer.py +++ b/tests/component/test_electrolyzer.py @@ -6,11 +6,7 @@ from frequenz.client.common.microgrid import MicrogridId from frequenz.client.common.microgrid.components import ComponentId -from frequenz.client.microgrid.component import ( - ComponentCategory, - ComponentStatus, - Electrolyzer, -) +from frequenz.client.microgrid.component import ComponentCategory, Electrolyzer def test_init() -> None: @@ -23,7 +19,6 @@ def test_init() -> None: name="test_electrolyzer", manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, ) assert component.id == component_id @@ -31,5 +26,4 @@ def test_init() -> None: assert component.name == "test_electrolyzer" assert component.manufacturer == "test_manufacturer" assert component.model_name == "test_model" - assert component.status == ComponentStatus.ACTIVE assert component.category == ComponentCategory.ELECTROLYZER diff --git a/tests/component/test_ev_charger.py b/tests/component/test_ev_charger.py index 5b9eaf4..705970b 100644 --- a/tests/component/test_ev_charger.py +++ b/tests/component/test_ev_charger.py @@ -12,7 +12,6 @@ from frequenz.client.microgrid.component import ( AcEvCharger, ComponentCategory, - ComponentStatus, DcEvCharger, EvCharger, EvChargerType, @@ -54,7 +53,6 @@ def test_abstract_ev_charger_cannot_be_instantiated( name="test_charger", manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, type=EvChargerType.AC, ) @@ -87,7 +85,6 @@ def test_recognized_ev_charger_types( # Renamed from test_ev_charger_types name=case.name, manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, ) assert charger.id == component_id @@ -95,7 +92,6 @@ def test_recognized_ev_charger_types( # Renamed from test_ev_charger_types assert charger.name == case.name assert charger.manufacturer == "test_manufacturer" assert charger.model_name == "test_model" - assert charger.status == ComponentStatus.ACTIVE assert charger.category == ComponentCategory.EV_CHARGER assert charger.type == case.expected_type @@ -110,7 +106,6 @@ def test_unrecognized_ev_charger_type( name="unrecognized_charger", manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, type=999, # type is passed here for UnrecognizedEvCharger ) @@ -119,6 +114,5 @@ def test_unrecognized_ev_charger_type( assert charger.name == "unrecognized_charger" assert charger.manufacturer == "test_manufacturer" assert charger.model_name == "test_model" - assert charger.status == ComponentStatus.ACTIVE assert charger.category == ComponentCategory.EV_CHARGER assert charger.type == 999 diff --git a/tests/component/test_grid_connection_point.py b/tests/component/test_grid_connection_point.py index 3f102f1..b8adfa0 100644 --- a/tests/component/test_grid_connection_point.py +++ b/tests/component/test_grid_connection_point.py @@ -7,11 +7,7 @@ from frequenz.client.common.microgrid import MicrogridId from frequenz.client.common.microgrid.components import ComponentId -from frequenz.client.microgrid.component import ( - ComponentCategory, - ComponentStatus, - GridConnectionPoint, -) +from frequenz.client.microgrid.component import ComponentCategory, GridConnectionPoint @pytest.fixture @@ -37,7 +33,6 @@ def test_creation_ok( name="test_grid_point", manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, rated_fuse_current=rated_fuse_current, ) @@ -46,7 +41,6 @@ def test_creation_ok( assert grid_point.name == "test_grid_point" assert grid_point.manufacturer == "test_manufacturer" assert grid_point.model_name == "test_model" - assert grid_point.status == ComponentStatus.ACTIVE assert grid_point.category == ComponentCategory.GRID assert grid_point.rated_fuse_current == rated_fuse_current @@ -64,6 +58,5 @@ def test_creation_invalid_rated_fuse_current( name="test_grid_point", manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, rated_fuse_current=-1, ) diff --git a/tests/component/test_hvac.py b/tests/component/test_hvac.py index ff39879..3fca3d5 100644 --- a/tests/component/test_hvac.py +++ b/tests/component/test_hvac.py @@ -6,7 +6,7 @@ from frequenz.client.common.microgrid import MicrogridId from frequenz.client.common.microgrid.components import ComponentId -from frequenz.client.microgrid.component import ComponentCategory, ComponentStatus, Hvac +from frequenz.client.microgrid.component import ComponentCategory, Hvac def test_init() -> None: @@ -19,7 +19,6 @@ def test_init() -> None: name="test_hvac", manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, ) assert component.id == component_id @@ -27,5 +26,4 @@ def test_init() -> None: assert component.name == "test_hvac" assert component.manufacturer == "test_manufacturer" assert component.model_name == "test_model" - assert component.status == ComponentStatus.ACTIVE assert component.category == ComponentCategory.HVAC diff --git a/tests/component/test_inverter.py b/tests/component/test_inverter.py index c598ce4..db1b356 100644 --- a/tests/component/test_inverter.py +++ b/tests/component/test_inverter.py @@ -12,7 +12,6 @@ from frequenz.client.microgrid.component import ( BatteryInverter, ComponentCategory, - ComponentStatus, HybridInverter, Inverter, InverterType, @@ -54,7 +53,6 @@ def test_abstract_inverter_cannot_be_instantiated( name="test_inverter", manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, type=InverterType.BATTERY, ) @@ -89,7 +87,6 @@ def test_recognized_inverter_types( name=case.name, manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, ) assert inverter.id == component_id @@ -97,7 +94,6 @@ def test_recognized_inverter_types( assert inverter.name == case.name assert inverter.manufacturer == "test_manufacturer" assert inverter.model_name == "test_model" - assert inverter.status == ComponentStatus.ACTIVE assert inverter.category == ComponentCategory.INVERTER assert inverter.type == case.expected_type @@ -112,7 +108,6 @@ def test_unrecognized_inverter_type( name="unrecognized_inverter", manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, type=999, # type is passed here for UnrecognizedInverter ) @@ -121,6 +116,5 @@ def test_unrecognized_inverter_type( assert inverter.name == "unrecognized_inverter" assert inverter.manufacturer == "test_manufacturer" assert inverter.model_name == "test_model" - assert inverter.status == ComponentStatus.ACTIVE assert inverter.category == ComponentCategory.INVERTER assert inverter.type == 999 diff --git a/tests/component/test_meter.py b/tests/component/test_meter.py index 80ed02f..90f6c3f 100644 --- a/tests/component/test_meter.py +++ b/tests/component/test_meter.py @@ -7,11 +7,7 @@ from frequenz.client.common.microgrid import MicrogridId from frequenz.client.common.microgrid.components import ComponentId -from frequenz.client.microgrid.component import ( - ComponentCategory, - ComponentStatus, - Meter, -) +from frequenz.client.microgrid.component import ComponentCategory, Meter def test_init() -> None: @@ -24,7 +20,6 @@ def test_init() -> None: name="meter_test", manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, ) assert component.id == component_id @@ -32,5 +27,4 @@ def test_init() -> None: assert component.name == "meter_test" assert component.manufacturer == "test_manufacturer" assert component.model_name == "test_model" - assert component.status == ComponentStatus.ACTIVE assert component.category == ComponentCategory.METER diff --git a/tests/component/test_precharger.py b/tests/component/test_precharger.py index 16edfd0..413e372 100644 --- a/tests/component/test_precharger.py +++ b/tests/component/test_precharger.py @@ -7,11 +7,7 @@ from frequenz.client.common.microgrid import MicrogridId from frequenz.client.common.microgrid.components import ComponentId -from frequenz.client.microgrid.component import ( - ComponentCategory, - ComponentStatus, - Precharger, -) +from frequenz.client.microgrid.component import ComponentCategory, Precharger def test_init() -> None: @@ -24,7 +20,6 @@ def test_init() -> None: name="precharger_test", manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, ) assert component.id == component_id @@ -32,5 +27,4 @@ def test_init() -> None: assert component.name == "precharger_test" assert component.manufacturer == "test_manufacturer" assert component.model_name == "test_model" - assert component.status == ComponentStatus.ACTIVE assert component.category == ComponentCategory.PRECHARGER diff --git a/tests/component/test_problematic.py b/tests/component/test_problematic.py index 8ab8feb..63002c4 100644 --- a/tests/component/test_problematic.py +++ b/tests/component/test_problematic.py @@ -9,7 +9,6 @@ from frequenz.client.microgrid.component import ( ComponentCategory, - ComponentStatus, MismatchedCategoryComponent, ProblematicComponent, UnrecognizedComponent, @@ -42,7 +41,6 @@ def test_abstract_problematic_component_cannot_be_instantiated( name="test_problematic", manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, category=ComponentCategory.UNSPECIFIED, ) @@ -57,7 +55,6 @@ def test_unspecified_component( name="unspecified_component", manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, ) assert component.id == component_id @@ -65,7 +62,6 @@ def test_unspecified_component( assert component.name == "unspecified_component" assert component.manufacturer == "test_manufacturer" assert component.model_name == "test_model" - assert component.status == ComponentStatus.ACTIVE assert component.category == ComponentCategory.UNSPECIFIED @@ -80,7 +76,6 @@ def test_mismatched_category_component_with_known_category( name="mismatched_battery", manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, category=expected_category, ) @@ -89,7 +84,6 @@ def test_mismatched_category_component_with_known_category( assert component.name == "mismatched_battery" assert component.manufacturer == "test_manufacturer" assert component.model_name == "test_model" - assert component.status == ComponentStatus.ACTIVE assert component.category == expected_category @@ -104,7 +98,6 @@ def test_mismatched_category_component_with_unrecognized_category( name="mismatched_unrecognized", manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, category=expected_category, ) @@ -113,7 +106,6 @@ def test_mismatched_category_component_with_unrecognized_category( assert component.name == "mismatched_unrecognized" assert component.manufacturer == "test_manufacturer" assert component.model_name == "test_model" - assert component.status == ComponentStatus.ACTIVE assert component.category == expected_category @@ -127,7 +119,6 @@ def test_unrecognized_component_type( name="unrecognized_component", manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, category=999, ) @@ -136,5 +127,4 @@ def test_unrecognized_component_type( assert component.name == "unrecognized_component" assert component.manufacturer == "test_manufacturer" assert component.model_name == "test_model" - assert component.status == ComponentStatus.ACTIVE assert component.category == 999 diff --git a/tests/component/test_relay.py b/tests/component/test_relay.py index 2ad82df..0cfd1b6 100644 --- a/tests/component/test_relay.py +++ b/tests/component/test_relay.py @@ -7,11 +7,7 @@ from frequenz.client.common.microgrid import MicrogridId from frequenz.client.common.microgrid.components import ComponentId -from frequenz.client.microgrid.component import ( - ComponentCategory, - ComponentStatus, - Relay, -) +from frequenz.client.microgrid.component import ComponentCategory, Relay def test_init() -> None: @@ -24,7 +20,6 @@ def test_init() -> None: name="relay_test", manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, ) assert component.id == component_id @@ -32,5 +27,4 @@ def test_init() -> None: assert component.name == "relay_test" assert component.manufacturer == "test_manufacturer" assert component.model_name == "test_model" - assert component.status == ComponentStatus.ACTIVE assert component.category == ComponentCategory.RELAY diff --git a/tests/component/test_voltage_transformer.py b/tests/component/test_voltage_transformer.py index ca70a48..6d1d44f 100644 --- a/tests/component/test_voltage_transformer.py +++ b/tests/component/test_voltage_transformer.py @@ -7,11 +7,7 @@ from frequenz.client.common.microgrid import MicrogridId from frequenz.client.common.microgrid.components import ComponentId -from frequenz.client.microgrid.component import ( - ComponentCategory, - ComponentStatus, - VoltageTransformer, -) +from frequenz.client.microgrid.component import ComponentCategory, VoltageTransformer @pytest.fixture @@ -42,7 +38,6 @@ def test_creation_ok( name="test_voltage_transformer", manufacturer="test_manufacturer", model_name="test_model", - status=ComponentStatus.ACTIVE, primary_voltage=primary, secondary_voltage=secondary, ) @@ -52,7 +47,6 @@ def test_creation_ok( assert voltage_transformer.name == "test_voltage_transformer" assert voltage_transformer.manufacturer == "test_manufacturer" assert voltage_transformer.model_name == "test_model" - assert voltage_transformer.status == ComponentStatus.ACTIVE assert voltage_transformer.category == ComponentCategory.VOLTAGE_TRANSFORMER assert voltage_transformer.primary_voltage == pytest.approx(primary) assert voltage_transformer.secondary_voltage == pytest.approx(secondary) From 3dcb2447b8ffced554bc1a3f56ee9a18b5f6349c Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Tue, 23 Sep 2025 14:16:53 +0200 Subject: [PATCH 04/10] Improve documentation for `_IterableResponseWrapper` Signed-off-by: Leandro Lucarella --- tests/util.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/util.py b/tests/util.py index 05c42d0..6dfc9cd 100644 --- a/tests/util.py +++ b/tests/util.py @@ -1243,7 +1243,15 @@ async def _iter_to_async_iter(it: Iterable[Any]) -> AsyncIterator[Any]: class _IterableResponseWrapper(AsyncIterator[Any]): """Wrap a response to make it an async iterator. - Supports + Supports the following types of `response`: + + * Async generator function + * Generator function + * Async generator + * Generator + * Async iterable + * Iterable + * Single value (`str`, `bytes` and non-iterables) """ def __init__(self, response: Any) -> None: From 7280c5eceb7d686756a5311d0d61e4c6ee574f09 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Tue, 23 Sep 2025 14:20:37 +0200 Subject: [PATCH 05/10] Support testing unary-stream calls that return a coroutine Originally testing unary-stream calls assumed a `GrpcStreamBroadcaster` is used, which means a `Receiver` is returned synchronously. But not all unary-stream calls adopt this pattern, and some might be async, so returning a coroutine instead. With this commit we inspect the return value and if it is a coroutine, we await for it and assign the awaited value as the client result. Signed-off-by: Leandro Lucarella --- tests/util.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/util.py b/tests/util.py index 6dfc9cd..5787cc0 100644 --- a/tests/util.py +++ b/tests/util.py @@ -1001,6 +1001,10 @@ def create_response_wrapper(*_: Any, **__: Any) -> AsyncIterator[Any]: client_result = client_method( *test_case.client_args, **test_case.client_kwargs ) + if asyncio.iscoroutine(client_result): + _logger.debug("The client method is a coroutine, awaiting it...") + async with asyncio.timeout(60): + client_result = await client_result _logger.debug("Client method result: %r", client_result) except Exception as err: # pylint: disable=broad-exception-caught _logger.debug("Client method raised an exception: %r", err) From 087c7feff3bb1006a1e8ebb258eb1babf6a6c871 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Wed, 24 Sep 2025 12:08:26 +0200 Subject: [PATCH 06/10] Upgrade to microgrid v0.18 / common v0.8 This commit updates the import and perform simple symbol renames, as well as adapting some structural changes. The interface is not affected, changes should be backwards compatible, although some minor behaviour changes might be present (for example responses of set_component_power_xxx()). The structural changes are: * set_component_power_active()/reactive() changed from unary-unary to unary-stream. For now we are only receiving the first response and returning that, but this will be improved in the future. * add_component_bounds() changed the Validity enum to have int values to cope with the more flexible API. In the future we'll add the possibility to pass arbitrary validities. * ComponentStateSample's errors and warnings are now wrapped in a message with multiple fields, for now we are only retrieving the code. In the future we'll wrap the new fields too. * MetricSample.connection is now also wrapped in a message with multiple fields. We are only getting the connection name for now, but we'll add the new information in the future too. * Some component categories were renamed, we added the new names but kept the old ones as deprecated. We needed to add the new names in this commit to avoid having to adapt the code too much, as the category name is tied to the category_specific_info.kind value, so we needed the new values. We need to disable the "unique" constraint for ComponentCategory temporarily to allow for the deprecated aliases. Other changes (and there are many pending) are left as future improvements. Some of these pending changes are: * Rename component -> electrical component (including IDs and fields) * Rename grid -> grid connection point * Rename voltage transformer -> power transformer * Rename relay -> breaker * Rename SOLAR -> PV * Rename source -> connection * Add new component categories, Metrics and other new enum fields * Deprecate UNDERVOLTAGE_SHUTDOWN and old Metric names * Rename category_speific_metadata -> category_specific_info * Rename sampled_at -> origin_time / sample_time Signed-off-by: Leandro Lucarella --- src/frequenz/client/microgrid/_client.py | 194 ++++++++------- .../client/microgrid/_delivery_area.py | 2 +- .../client/microgrid/_delivery_area_proto.py | 2 +- .../client/microgrid/_lifetime_proto.py | 2 +- .../client/microgrid/_location_proto.py | 2 +- .../client/microgrid/_microgrid_info.py | 2 +- .../client/microgrid/_microgrid_info_proto.py | 2 +- .../client/microgrid/component/_battery.py | 10 +- .../client/microgrid/component/_category.py | 72 ++++-- .../microgrid/component/_component_proto.py | 56 +++-- .../microgrid/component/_connection_proto.py | 14 +- .../component/_data_samples_proto.py | 12 +- .../client/microgrid/component/_ev_charger.py | 12 +- .../client/microgrid/component/_inverter.py | 12 +- .../microgrid/component/_state_sample.py | 184 ++++++++++----- .../component/_state_sample_proto.py | 18 +- .../client/microgrid/metrics/_bounds_proto.py | 2 +- .../client/microgrid/metrics/_metric.py | 146 ++++++------ .../client/microgrid/metrics/_sample_proto.py | 12 +- .../add_component_bounds/no_validity_case.py | 12 +- .../add_component_bounds/success_case.py | 18 +- .../get_microgrid_info/defaults_case.py | 6 +- .../get_microgrid_info/full_case.py | 10 +- .../diverse_component_types_case.py | 221 +++++++++--------- .../list_components/empty_case.py | 8 +- .../list_components/error_case.py | 6 +- .../filter_by_categories_case.py | 48 ++-- .../filter_by_component_ids_case.py | 43 ++-- .../filter_by_component_objects_case.py | 40 ++-- .../filter_by_integer_category_case.py | 18 +- .../list_components/filter_combined_case.py | 35 +-- .../list_connections/empty_case.py | 11 +- .../list_connections/error_case.py | 5 +- .../list_connections/mixed_filters_case.py | 19 +- .../list_connections/success_case.py | 27 ++- .../empty_case.py | 30 ++- .../error_case.py | 32 +-- .../many_case.py | 84 +++---- .../set_component_power_active/_config.py | 4 +- .../invalid_power_no_validate_case.py | 2 +- .../no_lifetime_case.py | 2 +- .../success_case.py | 4 +- .../set_component_power_reactive/_config.py | 4 +- tests/component/component_proto/conftest.py | 20 +- tests/component/component_proto/test_base.py | 20 +- .../component/component_proto/test_simple.py | 34 +-- .../component_proto/test_with_type.py | 34 ++- tests/component/test_connection_proto.py | 44 ++-- tests/component/test_data_samples.py | 128 +++++----- tests/component/test_state_sample.py | 26 ++- tests/metrics/test_bounds.py | 2 +- tests/metrics/test_sample.py | 60 ++--- tests/test_client.py | 18 +- tests/test_delivery_area.py | 2 +- tests/test_lifetime.py | 2 +- tests/test_location.py | 2 +- tests/test_microgrid_info.py | 4 +- 57 files changed, 1042 insertions(+), 799 deletions(-) diff --git a/src/frequenz/client/microgrid/_client.py b/src/frequenz/client/microgrid/_client.py index 5477d0c..072db2e 100644 --- a/src/frequenz/client/microgrid/_client.py +++ b/src/frequenz/client/microgrid/_client.py @@ -14,13 +14,17 @@ from datetime import datetime, timedelta from typing import Any, assert_never -from frequenz.api.common.v1.metrics import bounds_pb2, metric_sample_pb2 -from frequenz.api.common.v1.microgrid.components import components_pb2 -from frequenz.api.microgrid.v1 import microgrid_pb2, microgrid_pb2_grpc +from frequenz.api.common.v1alpha8.metrics import bounds_pb2, metrics_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2, microgrid_pb2_grpc from frequenz.channels import Receiver from frequenz.client.base import channel, client, conversion, retry, streaming +from frequenz.client.base.exception import ApiClientError from frequenz.client.common.microgrid.components import ComponentId from google.protobuf.empty_pb2 import Empty +from grpc.aio import AioRpcError from typing_extensions import override from ._exception import ClientNotConnected @@ -90,7 +94,8 @@ def __init__( self._component_data_broadcasters: dict[ str, streaming.GrpcStreamBroadcaster[ - microgrid_pb2.ReceiveComponentDataStreamResponse, ComponentDataSamples + microgrid_pb2.ReceiveElectricalComponentTelemetryStreamResponse, + ComponentDataSamples, ], ] = {} self._sensor_data_broadcasters: dict[ @@ -165,10 +170,7 @@ async def get_microgrid_info( # noqa: DOC502 (raises ApiClientError indirectly) """ response = await client.call_stub_method( self, - lambda: self.stub.GetMicrogridMetadata( - Empty(), - timeout=DEFAULT_GRPC_CALL_TIMEOUT, - ), + lambda: self.stub.GetMicrogrid(Empty(), timeout=DEFAULT_GRPC_CALL_TIMEOUT), method_name="GetMicrogridMetadata", ) @@ -217,17 +219,19 @@ async def list_components( # noqa: DOC502 (raises ApiClientError indirectly) """ response = await client.call_stub_method( self, - lambda: self.stub.ListComponents( - microgrid_pb2.ListComponentsRequest( - component_ids=map(_get_component_id, components), - categories=map(_get_category_value, categories), + lambda: self.stub.ListElectricalComponents( + microgrid_pb2.ListElectricalComponentsRequest( + electrical_component_ids=map(_get_component_id, components), + electrical_component_categories=map( + _get_category_value, categories + ), ), timeout=DEFAULT_GRPC_CALL_TIMEOUT, ), method_name="ListComponents", ) - return map(component_from_proto, response.components) + return map(component_from_proto, response.electrical_components) async def list_connections( # noqa: DOC502 (raises ApiClientError indirectly) self, @@ -271,10 +275,12 @@ async def list_connections( # noqa: DOC502 (raises ApiClientError indirectly) """ response = await client.call_stub_method( self, - lambda: self.stub.ListConnections( - microgrid_pb2.ListConnectionsRequest( - starts=map(_get_component_id, sources), - ends=map(_get_component_id, destinations), + lambda: self.stub.ListElectricalComponentConnections( + microgrid_pb2.ListElectricalComponentConnectionsRequest( + source_electrical_component_ids=map(_get_component_id, sources), + destination_electrical_component_ids=map( + _get_component_id, destinations + ), ), timeout=DEFAULT_GRPC_CALL_TIMEOUT, ), @@ -283,11 +289,19 @@ async def list_connections( # noqa: DOC502 (raises ApiClientError indirectly) return ( conn - for conn in map(component_connection_from_proto, response.connections) + for conn in map( + component_connection_from_proto, + response.electrical_component_connections, + ) if conn is not None ) - async def set_component_power_active( # noqa: DOC502 (raises ApiClientError indirectly) + # pylint: disable-next=fixme + # TODO: Unifi set_component_power_active and set_component_power_reactive, or at + # least use a common implementation. + # Return an iterator or receiver with the streamed responses instead of + # returning just the first one + async def set_component_power_active( # noqa: DOC503 self, component: ComponentId | Component, power: float, @@ -341,25 +355,37 @@ async def set_component_power_active( # noqa: DOC502 (raises ApiClientError ind if validate_arguments: _validate_set_power_args(power=power, request_lifetime=lifetime_seconds) - response = await client.call_stub_method( - self, - lambda: self.stub.SetComponentPowerActive( - microgrid_pb2.SetComponentPowerActiveRequest( - component_id=_get_component_id(component), - power=power, - request_lifetime=lifetime_seconds, - ), - timeout=DEFAULT_GRPC_CALL_TIMEOUT, - ), - method_name="SetComponentPowerActive", - ) + method_name = "SetElectricalComponentPower" + if not self.is_connected: + raise ClientNotConnected(server_url=self.server_url, operation=method_name) + + try: + response = await anext( + aiter( + self.stub.SetElectricalComponentPower( + microgrid_pb2.SetElectricalComponentPowerRequest( + electrical_component_id=_get_component_id(component), + power_type=microgrid_pb2.POWER_TYPE_ACTIVE, + power=power, + request_lifetime=lifetime_seconds, + ), + timeout=DEFAULT_GRPC_CALL_TIMEOUT, + ) + ) + ) + except AioRpcError as grpc_error: + raise ApiClientError.from_grpc_error( + server_url=self.server_url, + operation=method_name, + grpc_error=grpc_error, + ) from grpc_error - if response.HasField("valid_until"): - return conversion.to_datetime(response.valid_until) + if response.HasField("valid_until_time"): + return conversion.to_datetime(response.valid_until_time) return None - async def set_component_power_reactive( # noqa: DOC502 (raises ApiClientError indirectly) + async def set_component_power_reactive( # noqa: DOC503 self, component: ComponentId | Component, power: float, @@ -419,21 +445,33 @@ async def set_component_power_reactive( # noqa: DOC502 (raises ApiClientError i if validate_arguments: _validate_set_power_args(power=power, request_lifetime=lifetime_seconds) - response = await client.call_stub_method( - self, - lambda: self.stub.SetComponentPowerReactive( - microgrid_pb2.SetComponentPowerReactiveRequest( - component_id=_get_component_id(component), - power=power, - request_lifetime=lifetime_seconds, - ), - timeout=DEFAULT_GRPC_CALL_TIMEOUT, - ), - method_name="SetComponentPowerReactive", - ) + method_name = "SetElectricalComponentPower" + if not self.is_connected: + raise ClientNotConnected(server_url=self.server_url, operation=method_name) - if response.HasField("valid_until"): - return conversion.to_datetime(response.valid_until) + try: + response = await anext( + aiter( + self.stub.SetElectricalComponentPower( + microgrid_pb2.SetElectricalComponentPowerRequest( + electrical_component_id=_get_component_id(component), + power_type=microgrid_pb2.POWER_TYPE_REACTIVE, + power=power, + request_lifetime=lifetime_seconds, + ), + timeout=DEFAULT_GRPC_CALL_TIMEOUT, + ) + ) + ) + except AioRpcError as grpc_error: + raise ApiClientError.from_grpc_error( + server_url=self.server_url, + operation=method_name, + grpc_error=grpc_error, + ) from grpc_error + + if response.HasField("valid_until_time"): + return conversion.to_datetime(response.valid_until_time) return None @@ -506,14 +544,11 @@ async def add_component_bounds( # noqa: DOC502 (Raises ApiClientError indirectl most likely a subclass of [GrpcError][frequenz.client.microgrid.GrpcError]. """ - extra_args = {} - if validity is not None: - extra_args["validity_duration"] = validity.value response = await client.call_stub_method( self, - lambda: self.stub.AddComponentBounds( - microgrid_pb2.AddComponentBoundsRequest( - component_id=_get_component_id(component), + lambda: self.stub.AugmentElectricalComponentBounds( + microgrid_pb2.AugmentElectricalComponentBoundsRequest( + electrical_component_id=_get_component_id(component), target_metric=_get_metric_value(target), bounds=( bounds_pb2.Bounds( @@ -522,15 +557,15 @@ async def add_component_bounds( # noqa: DOC502 (Raises ApiClientError indirectl ) for bound in bounds ), - **extra_args, + request_lifetime=validity.value if validity else None, ), timeout=DEFAULT_GRPC_CALL_TIMEOUT, ), method_name="AddComponentBounds", ) - if response.HasField("ts"): - return conversion.to_datetime(response.ts) + if response.HasField("valid_until_time"): + return conversion.to_datetime(response.valid_until_time) return None @@ -578,48 +613,43 @@ def receive_component_data_samples_stream( stream_name = f"microgrid-client-{client_id}-component-data-{key}" # Alias to avoid too long lines linter errors # pylint: disable-next=invalid-name - Request = microgrid_pb2.ReceiveComponentDataStreamRequest + Request = microgrid_pb2.ReceiveElectricalComponentTelemetryStreamRequest broadcaster = streaming.GrpcStreamBroadcaster( stream_name, lambda: aiter( - self.stub.ReceiveComponentDataStream( + self.stub.ReceiveElectricalComponentTelemetryStream( Request( - component_id=_get_component_id(component), - filter=Request.ComponentDataStreamFilter( + electrical_component_id=_get_component_id(component), + filter=Request.ComponentTelemetryStreamFilter( metrics=metrics_set ), ), timeout=DEFAULT_GRPC_CALL_TIMEOUT, ) ), - lambda msg: component_data_samples_from_proto(msg.data), + lambda msg: component_data_samples_from_proto(msg.telemetry), retry_strategy=self._retry_strategy, ) self._component_data_broadcasters[key] = broadcaster return broadcaster.new_receiver(maxsize=buffer_size) +# pylint: disable-next=fixme +# TODO: Remove this enum, now AugmentElectricalComponentBounds takes a simple timeout as +# an int. class Validity(enum.Enum): """The duration for which a given list of bounds will stay in effect.""" - FIVE_SECONDS = ( - microgrid_pb2.ComponentBoundsValidityDuration.COMPONENT_BOUNDS_VALIDITY_DURATION_5_SECONDS - ) + FIVE_SECONDS = 5 """The bounds will stay in effect for 5 seconds.""" - ONE_MINUTE = ( - microgrid_pb2.ComponentBoundsValidityDuration.COMPONENT_BOUNDS_VALIDITY_DURATION_1_MINUTE - ) + ONE_MINUTE = 60 """The bounds will stay in effect for 1 minute.""" - FIVE_MINUTES = ( - microgrid_pb2.ComponentBoundsValidityDuration.COMPONENT_BOUNDS_VALIDITY_DURATION_5_MINUTES - ) + FIVE_MINUTES = 60 * 5 """The bounds will stay in effect for 5 minutes.""" - FIFTEEN_MINUTES = ( - microgrid_pb2.ComponentBoundsValidityDuration.COMPONENT_BOUNDS_VALIDITY_DURATION_15_MINUTES - ) + FIFTEEN_MINUTES = 60 * 15 """The bounds will stay in effect for 15 minutes.""" @@ -634,26 +664,30 @@ def _get_component_id(component: ComponentId | Component) -> int: assert_never(unexpected) -def _get_metric_value(metric: Metric | int) -> metric_sample_pb2.Metric.ValueType: +def _get_metric_value(metric: Metric | int) -> metrics_pb2.Metric.ValueType: """Get the metric ID from a metric or metric ID.""" match metric: case Metric(): - return metric_sample_pb2.Metric.ValueType(metric.value) + return metrics_pb2.Metric.ValueType(metric.value) case int(): - return metric_sample_pb2.Metric.ValueType(metric) + return metrics_pb2.Metric.ValueType(metric) case unexpected: assert_never(unexpected) def _get_category_value( category: ComponentCategory | int, -) -> components_pb2.ComponentCategory.ValueType: +) -> electrical_components_pb2.ElectricalComponentCategory.ValueType: """Get the category value from a component or component category.""" match category: case ComponentCategory(): - return components_pb2.ComponentCategory.ValueType(category.value) + return electrical_components_pb2.ElectricalComponentCategory.ValueType( + category.value + ) case int(): - return components_pb2.ComponentCategory.ValueType(category) + return electrical_components_pb2.ElectricalComponentCategory.ValueType( + category + ) case unexpected: assert_never(unexpected) diff --git a/src/frequenz/client/microgrid/_delivery_area.py b/src/frequenz/client/microgrid/_delivery_area.py index 1746f60..64994b2 100644 --- a/src/frequenz/client/microgrid/_delivery_area.py +++ b/src/frequenz/client/microgrid/_delivery_area.py @@ -6,7 +6,7 @@ import enum from dataclasses import dataclass -from frequenz.api.common.v1.grid import delivery_area_pb2 +from frequenz.api.common.v1alpha8.grid import delivery_area_pb2 @enum.unique diff --git a/src/frequenz/client/microgrid/_delivery_area_proto.py b/src/frequenz/client/microgrid/_delivery_area_proto.py index 7824757..4b99e0b 100644 --- a/src/frequenz/client/microgrid/_delivery_area_proto.py +++ b/src/frequenz/client/microgrid/_delivery_area_proto.py @@ -5,7 +5,7 @@ import logging -from frequenz.api.common.v1.grid import delivery_area_pb2 +from frequenz.api.common.v1alpha8.grid import delivery_area_pb2 from ._delivery_area import DeliveryArea, EnergyMarketCodeType from ._util import enum_from_proto diff --git a/src/frequenz/client/microgrid/_lifetime_proto.py b/src/frequenz/client/microgrid/_lifetime_proto.py index c466763..37ae45f 100644 --- a/src/frequenz/client/microgrid/_lifetime_proto.py +++ b/src/frequenz/client/microgrid/_lifetime_proto.py @@ -3,7 +3,7 @@ """Loading of Lifetime objects from protobuf messages.""" -from frequenz.api.common.v1.microgrid import lifetime_pb2 +from frequenz.api.common.v1alpha8.microgrid import lifetime_pb2 from frequenz.client.base.conversion import to_datetime from ._lifetime import Lifetime diff --git a/src/frequenz/client/microgrid/_location_proto.py b/src/frequenz/client/microgrid/_location_proto.py index 301fada..ee20787 100644 --- a/src/frequenz/client/microgrid/_location_proto.py +++ b/src/frequenz/client/microgrid/_location_proto.py @@ -5,7 +5,7 @@ import logging -from frequenz.api.common.v1 import location_pb2 +from frequenz.api.common.v1alpha8.types import location_pb2 from ._location import Location diff --git a/src/frequenz/client/microgrid/_microgrid_info.py b/src/frequenz/client/microgrid/_microgrid_info.py index b1f65c9..8fbe328 100644 --- a/src/frequenz/client/microgrid/_microgrid_info.py +++ b/src/frequenz/client/microgrid/_microgrid_info.py @@ -9,7 +9,7 @@ from dataclasses import dataclass from functools import cached_property -from frequenz.api.common.v1.microgrid import microgrid_pb2 +from frequenz.api.common.v1alpha8.microgrid import microgrid_pb2 from frequenz.client.common.microgrid import EnterpriseId, MicrogridId from ._delivery_area import DeliveryArea diff --git a/src/frequenz/client/microgrid/_microgrid_info_proto.py b/src/frequenz/client/microgrid/_microgrid_info_proto.py index 0640cde..c2f74dc 100644 --- a/src/frequenz/client/microgrid/_microgrid_info_proto.py +++ b/src/frequenz/client/microgrid/_microgrid_info_proto.py @@ -6,7 +6,7 @@ import logging -from frequenz.api.common.v1.microgrid import microgrid_pb2 +from frequenz.api.common.v1alpha8.microgrid import microgrid_pb2 from frequenz.client.base import conversion from frequenz.client.common.microgrid import EnterpriseId, MicrogridId diff --git a/src/frequenz/client/microgrid/component/_battery.py b/src/frequenz/client/microgrid/component/_battery.py index d6f4bf1..72c52ee 100644 --- a/src/frequenz/client/microgrid/component/_battery.py +++ b/src/frequenz/client/microgrid/component/_battery.py @@ -7,7 +7,9 @@ import enum from typing import Any, Literal, Self, TypeAlias -from frequenz.api.common.v1.microgrid.components import battery_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) from ._category import ComponentCategory from ._component import Component @@ -17,13 +19,13 @@ class BatteryType(enum.Enum): """The known types of batteries.""" - UNSPECIFIED = battery_pb2.BATTERY_TYPE_UNSPECIFIED + UNSPECIFIED = electrical_components_pb2.BATTERY_TYPE_UNSPECIFIED """The battery type is unspecified.""" - LI_ION = battery_pb2.BATTERY_TYPE_LI_ION + LI_ION = electrical_components_pb2.BATTERY_TYPE_LI_ION """Lithium-ion (Li-ion) battery.""" - NA_ION = battery_pb2.BATTERY_TYPE_NA_ION + NA_ION = electrical_components_pb2.BATTERY_TYPE_NA_ION """Sodium-ion (Na-ion) battery.""" diff --git a/src/frequenz/client/microgrid/component/_category.py b/src/frequenz/client/microgrid/component/_category.py index 20eb139..507479e 100644 --- a/src/frequenz/client/microgrid/component/_category.py +++ b/src/frequenz/client/microgrid/component/_category.py @@ -5,44 +5,57 @@ import enum -from frequenz.api.common.v1.microgrid.components import components_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) -@enum.unique +# @enum.unique class ComponentCategory(enum.Enum): """The known categories of components that can be present in a microgrid.""" - UNSPECIFIED = components_pb2.COMPONENT_CATEGORY_UNSPECIFIED + UNSPECIFIED = electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_UNSPECIFIED """The component category is unspecified, probably due to an error in the message.""" - GRID = components_pb2.COMPONENT_CATEGORY_GRID + GRID_CONNECTION_POINT = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_GRID_CONNECTION_POINT + ) """The point where the local microgrid is connected to the grid.""" - METER = components_pb2.COMPONENT_CATEGORY_METER + GRID = electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_GRID_CONNECTION_POINT + """The point where the local microgrid is connected to the grid (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use + [`GRID_CONNECTION_POINT`][frequenz.client.microgrid.component.ComponentCategory.GRID_CONNECTION_POINT] + instead. + """ + + METER = electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_METER """A meter, for measuring electrical metrics, e.g., current, voltage, etc.""" - INVERTER = components_pb2.COMPONENT_CATEGORY_INVERTER + INVERTER = electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_INVERTER """An electricity generator, with batteries or solar energy.""" - CONVERTER = components_pb2.COMPONENT_CATEGORY_CONVERTER + CONVERTER = electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_CONVERTER """A DC-DC converter.""" - BATTERY = components_pb2.COMPONENT_CATEGORY_BATTERY + BATTERY = electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_BATTERY """A storage system for electrical energy, used by inverters.""" - EV_CHARGER = components_pb2.COMPONENT_CATEGORY_EV_CHARGER + EV_CHARGER = electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_EV_CHARGER """A station for charging electrical vehicles.""" - CRYPTO_MINER = components_pb2.COMPONENT_CATEGORY_CRYPTO_MINER + CRYPTO_MINER = electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_CRYPTO_MINER """A crypto miner.""" - ELECTROLYZER = components_pb2.COMPONENT_CATEGORY_ELECTROLYZER + ELECTROLYZER = electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_ELECTROLYZER """An electrolyzer for converting water into hydrogen and oxygen.""" - CHP = components_pb2.COMPONENT_CATEGORY_CHP + CHP = electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_CHP """A heat and power combustion plant (CHP stands for combined heat and power).""" - RELAY = components_pb2.COMPONENT_CATEGORY_RELAY + RELAY = electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_BREAKER """A relay. Relays generally have two states: open (connected) and closed (disconnected). @@ -50,7 +63,7 @@ class ComponentCategory(enum.Enum): control whether the component is connected to the grid or not. """ - PRECHARGER = components_pb2.COMPONENT_CATEGORY_PRECHARGER + PRECHARGER = electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_PRECHARGER """A precharge module. Precharging involves gradually ramping up the DC voltage to prevent any @@ -61,17 +74,30 @@ class ComponentCategory(enum.Enum): external precharging modules. """ - VOLTAGE_TRANSFORMER = components_pb2.COMPONENT_CATEGORY_VOLTAGE_TRANSFORMER - """A voltage transformer. + POWER_TRANSFORMER = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_POWER_TRANSFORMER + ) + """A power transformer. + + A power transformer is designed for the bulk transfer of electrical energy. Its main + job is to "step-up" or "step-down" voltage levels for efficient transmission and + distribution of power. + + Since power transformers try to keep the output power same as the input + power (ignoring losses), when they step-up the voltage, the current gets + proportionally reduced, and vice versa. + """ - Voltage transformers are used to step up or step down the voltage, keeping - the power somewhat constant by increasing or decreasing the current. If voltage is - stepped up, current is stepped down, and vice versa. + VOLTAGE_TRANSFORMER = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_POWER_TRANSFORMER + ) + """A voltage transformer (deprecated). - Note: - Voltage transformers have efficiency losses, so the output power is - always less than the input power. + Deprecated: Deprecated in v0.18.0 + Use + [`POWER_TRANSFORMER`][frequenz.client.microgrid.component.ComponentCategory.POWER_TRANSFORMER] + instead. """ - HVAC = components_pb2.COMPONENT_CATEGORY_HVAC + HVAC = electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_HVAC """A Heating, Ventilation, and Air Conditioning (HVAC) system.""" diff --git a/src/frequenz/client/microgrid/component/_component_proto.py b/src/frequenz/client/microgrid/component/_component_proto.py index dafef34..eefb072 100644 --- a/src/frequenz/client/microgrid/component/_component_proto.py +++ b/src/frequenz/client/microgrid/component/_component_proto.py @@ -7,7 +7,9 @@ from collections.abc import Sequence from typing import Any, NamedTuple, assert_never -from frequenz.api.common.v1.microgrid.components import components_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) from frequenz.client.common.microgrid import MicrogridId from frequenz.client.common.microgrid.components import ComponentId from google.protobuf.json_format import MessageToDict @@ -67,7 +69,9 @@ # pylint: disable=too-many-arguments -def component_from_proto(message: components_pb2.Component) -> ComponentTypes: +def component_from_proto( + message: electrical_components_pb2.ElectricalComponent, +) -> ComponentTypes: """Convert a protobuf message to a `Component` instance. Args: @@ -110,12 +114,12 @@ class ComponentBaseData(NamedTuple): category: ComponentCategory | int lifetime: Lifetime rated_bounds: dict[Metric | int, Bounds] - category_specific_metadata: dict[str, Any] + category_specific_info: dict[str, Any] category_mismatched: bool = False def component_base_from_proto_with_issues( - message: components_pb2.Component, + message: electrical_components_pb2.ElectricalComponent, *, major_issues: list[str], minor_issues: list[str], @@ -161,19 +165,19 @@ def component_base_from_proto_with_issues( elif isinstance(category, int): major_issues.append(f"category {category} is unrecognized") - metadata_category = message.category_type.WhichOneof("metadata") - category_specific_metadata: dict[str, Any] = {} - if metadata_category is not None: - category_specific_metadata = MessageToDict( - getattr(message.category_type, metadata_category), + category_specific_info_kind = message.category_specific_info.WhichOneof("kind") + category_specific_info: dict[str, Any] = {} + if category_specific_info_kind is not None: + category_specific_info = MessageToDict( + getattr(message.category_specific_info, category_specific_info_kind), always_print_fields_with_no_presence=True, ) category_mismatched = False if ( - metadata_category + category_specific_info_kind and isinstance(category, ComponentCategory) - and category.name.lower() != metadata_category + and category.name.lower() != category_specific_info_kind ): major_issues.append("category_type.metadata does not match the category_type") category_mismatched = True @@ -187,14 +191,14 @@ def component_base_from_proto_with_issues( category, lifetime, rated_bounds, - category_specific_metadata, + category_specific_info, category_mismatched, ) # pylint: disable-next=too-many-locals def component_from_proto_with_issues( - message: components_pb2.Component, + message: electrical_components_pb2.ElectricalComponent, *, major_issues: list[str], minor_issues: list[str], @@ -222,7 +226,7 @@ def component_from_proto_with_issues( model_name=base_data.model_name, category=base_data.category, operational_lifetime=base_data.lifetime, - category_specific_metadata=base_data.category_specific_metadata, + category_specific_metadata=base_data.category_specific_info, rated_bounds=base_data.rated_bounds, ) @@ -267,7 +271,7 @@ def component_from_proto_with_issues( BatteryType.NA_ION: NaIonBattery, } battery_type = enum_from_proto( - message.category_type.battery.type, BatteryType + message.category_specific_info.battery.type, BatteryType ) match battery_type: case BatteryType.UNSPECIFIED | BatteryType.LI_ION | BatteryType.NA_ION: @@ -309,7 +313,7 @@ def component_from_proto_with_issues( EvChargerType.HYBRID: HybridEvCharger, } ev_charger_type = enum_from_proto( - message.category_type.ev_charger.type, EvChargerType + message.category_specific_info.ev_charger.type, EvChargerType ) match ev_charger_type: case ( @@ -345,8 +349,10 @@ def component_from_proto_with_issues( ) case unexpected_ev_charger_type: assert_never(unexpected_ev_charger_type) - case ComponentCategory.GRID: - rated_fuse_current = message.category_type.grid.rated_fuse_current + case ComponentCategory.GRID_CONNECTION_POINT | ComponentCategory.GRID: + rated_fuse_current = ( + message.category_specific_info.grid_connection_point.rated_fuse_current + ) # No need to check for negatives because the protobuf type is uint32. return GridConnectionPoint( id=base_data.component_id, @@ -374,7 +380,7 @@ def component_from_proto_with_issues( InverterType.HYBRID: HybridInverter, } inverter_type = enum_from_proto( - message.category_type.inverter.type, InverterType + message.category_specific_info.inverter.type, InverterType ) match inverter_type: case ( @@ -410,7 +416,9 @@ def component_from_proto_with_issues( ) case unexpected_inverter_type: assert_never(unexpected_inverter_type) - case ComponentCategory.VOLTAGE_TRANSFORMER: + case ( + ComponentCategory.POWER_TRANSFORMER | ComponentCategory.VOLTAGE_TRANSFORMER + ): return VoltageTransformer( id=base_data.component_id, microgrid_id=base_data.microgrid_id, @@ -419,8 +427,8 @@ def component_from_proto_with_issues( model_name=base_data.model_name, operational_lifetime=base_data.lifetime, rated_bounds=base_data.rated_bounds, - primary_voltage=message.category_type.voltage_transformer.primary, - secondary_voltage=message.category_type.voltage_transformer.secondary, + primary_voltage=message.category_specific_info.power_transformer.primary, + secondary_voltage=message.category_specific_info.power_transformer.secondary, ) case unexpected_category: assert_never(unexpected_category) @@ -454,7 +462,7 @@ def _trivial_category_to_class( def _metric_config_bounds_from_proto( - message: Sequence[components_pb2.MetricConfigBounds], + message: Sequence[electrical_components_pb2.MetricConfigBounds], *, major_issues: list[str], minor_issues: list[str], # pylint: disable=unused-argument @@ -506,7 +514,7 @@ def _metric_config_bounds_from_proto( def _get_operational_lifetime_from_proto( - message: components_pb2.Component, + message: electrical_components_pb2.ElectricalComponent, *, major_issues: list[str], minor_issues: list[str], diff --git a/src/frequenz/client/microgrid/component/_connection_proto.py b/src/frequenz/client/microgrid/component/_connection_proto.py index 7f7e97b..c8bb101 100644 --- a/src/frequenz/client/microgrid/component/_connection_proto.py +++ b/src/frequenz/client/microgrid/component/_connection_proto.py @@ -5,7 +5,9 @@ import logging -from frequenz.api.common.v1.microgrid.components import components_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) from frequenz.client.common.microgrid.components import ComponentId from .._lifetime import Lifetime @@ -16,7 +18,7 @@ def component_connection_from_proto( - message: components_pb2.ComponentConnection, + message: electrical_components_pb2.ElectricalComponentConnection, ) -> ComponentConnection | None: """Create a `ComponentConnection` from a protobuf message.""" major_issues: list[str] = [] @@ -43,7 +45,7 @@ def component_connection_from_proto( def component_connection_from_proto_with_issues( - message: components_pb2.ComponentConnection, + message: electrical_components_pb2.ElectricalComponentConnection, *, major_issues: list[str], minor_issues: list[str], @@ -63,8 +65,8 @@ def component_connection_from_proto_with_issues( `None` if the protobuf message is completely invalid and a `ComponentConnection` cannot be created. """ - source_component_id = ComponentId(message.source_component_id) - destination_component_id = ComponentId(message.destination_component_id) + source_component_id = ComponentId(message.source_electrical_component_id) + destination_component_id = ComponentId(message.destination_electrical_component_id) if source_component_id == destination_component_id: major_issues.append( f"connection ignored: source and destination are the same ({source_component_id})", @@ -83,7 +85,7 @@ def component_connection_from_proto_with_issues( def _get_operational_lifetime_from_proto( - message: components_pb2.ComponentConnection, + message: electrical_components_pb2.ElectricalComponentConnection, *, major_issues: list[str], minor_issues: list[str], diff --git a/src/frequenz/client/microgrid/component/_data_samples_proto.py b/src/frequenz/client/microgrid/component/_data_samples_proto.py index 326e98f..e483855 100644 --- a/src/frequenz/client/microgrid/component/_data_samples_proto.py +++ b/src/frequenz/client/microgrid/component/_data_samples_proto.py @@ -7,7 +7,9 @@ import logging from functools import partial -from frequenz.api.common.v1.microgrid.components import components_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) from frequenz.client.common.microgrid.components import ComponentId from ..metrics._sample_proto import metric_sample_from_proto_with_issues @@ -18,7 +20,7 @@ def component_data_samples_from_proto( - message: components_pb2.ComponentData, + message: electrical_components_pb2.ElectricalComponentTelemetry, ) -> ComponentDataSamples: """Convert a protobuf component data message to a component data object. @@ -57,7 +59,7 @@ def component_data_samples_from_proto( def component_data_samples_from_proto_with_issues( - message: components_pb2.ComponentData, + message: electrical_components_pb2.ElectricalComponentTelemetry, *, major_issues: list[str], minor_issues: list[str], @@ -73,7 +75,7 @@ def component_data_samples_from_proto_with_issues( The resulting `ComponentDataSamples` object. """ return ComponentDataSamples( - component_id=ComponentId(message.component_id), + component_id=ComponentId(message.electrical_component_id), metric_samples=list( map( partial( @@ -84,5 +86,5 @@ def component_data_samples_from_proto_with_issues( message.metric_samples, ) ), - states=list(map(component_state_sample_from_proto, message.states)), + states=list(map(component_state_sample_from_proto, message.state_snapshots)), ) diff --git a/src/frequenz/client/microgrid/component/_ev_charger.py b/src/frequenz/client/microgrid/component/_ev_charger.py index 8e1605e..5a7deb3 100644 --- a/src/frequenz/client/microgrid/component/_ev_charger.py +++ b/src/frequenz/client/microgrid/component/_ev_charger.py @@ -7,7 +7,9 @@ import enum from typing import Any, Literal, Self, TypeAlias -from frequenz.api.common.v1.microgrid.components import ev_charger_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) from ._category import ComponentCategory from ._component import Component @@ -17,16 +19,16 @@ class EvChargerType(enum.Enum): """The known types of electric vehicle (EV) chargers.""" - UNSPECIFIED = ev_charger_pb2.EV_CHARGER_TYPE_UNSPECIFIED + UNSPECIFIED = electrical_components_pb2.EV_CHARGER_TYPE_UNSPECIFIED """The type of the EV charger is unspecified.""" - AC = ev_charger_pb2.EV_CHARGER_TYPE_AC + AC = electrical_components_pb2.EV_CHARGER_TYPE_AC """The EV charging station supports AC charging only.""" - DC = ev_charger_pb2.EV_CHARGER_TYPE_DC + DC = electrical_components_pb2.EV_CHARGER_TYPE_DC """The EV charging station supports DC charging only.""" - HYBRID = ev_charger_pb2.EV_CHARGER_TYPE_HYBRID + HYBRID = electrical_components_pb2.EV_CHARGER_TYPE_HYBRID """The EV charging station supports both AC and DC.""" diff --git a/src/frequenz/client/microgrid/component/_inverter.py b/src/frequenz/client/microgrid/component/_inverter.py index 8f7001c..a49395d 100644 --- a/src/frequenz/client/microgrid/component/_inverter.py +++ b/src/frequenz/client/microgrid/component/_inverter.py @@ -7,7 +7,9 @@ import enum from typing import Any, Literal, Self, TypeAlias -from frequenz.api.common.v1.microgrid.components import inverter_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) from ._category import ComponentCategory from ._component import Component @@ -17,16 +19,16 @@ class InverterType(enum.Enum): """The known types of inverters.""" - UNSPECIFIED = inverter_pb2.INVERTER_TYPE_UNSPECIFIED + UNSPECIFIED = electrical_components_pb2.INVERTER_TYPE_UNSPECIFIED """The type of the inverter is unspecified.""" - BATTERY = inverter_pb2.INVERTER_TYPE_BATTERY + BATTERY = electrical_components_pb2.INVERTER_TYPE_BATTERY """The inverter is a battery inverter.""" - SOLAR = inverter_pb2.INVERTER_TYPE_SOLAR + SOLAR = electrical_components_pb2.INVERTER_TYPE_PV """The inverter is a solar inverter.""" - HYBRID = inverter_pb2.INVERTER_TYPE_HYBRID + HYBRID = electrical_components_pb2.INVERTER_TYPE_HYBRID """The inverter is a hybrid inverter.""" diff --git a/src/frequenz/client/microgrid/component/_state_sample.py b/src/frequenz/client/microgrid/component/_state_sample.py index c69381c..36bcbaa 100644 --- a/src/frequenz/client/microgrid/component/_state_sample.py +++ b/src/frequenz/client/microgrid/component/_state_sample.py @@ -7,223 +7,287 @@ from dataclasses import dataclass from datetime import datetime -from frequenz.api.common.v1.microgrid.components import components_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) @enum.unique class ComponentStateCode(enum.Enum): """The various states that a component can be in.""" - UNSPECIFIED = components_pb2.COMPONENT_STATE_CODE_UNSPECIFIED + UNSPECIFIED = electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_UNSPECIFIED """The state is unspecified (this should not be normally used).""" - UNKNOWN = components_pb2.COMPONENT_STATE_CODE_UNKNOWN + UNKNOWN = electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_UNKNOWN """The component is in an unknown or undefined condition. This is used when the state can be retrieved from the component but it doesn't match any known state. """ - UNAVAILABLE = components_pb2.COMPONENT_STATE_CODE_UNAVAILABLE + UNAVAILABLE = electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_UNAVAILABLE """The component is temporarily unavailable for operation.""" - SWITCHING_OFF = components_pb2.COMPONENT_STATE_CODE_SWITCHING_OFF + SWITCHING_OFF = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_SWITCHING_OFF + ) """The component is in the process of switching off.""" - OFF = components_pb2.COMPONENT_STATE_CODE_OFF + OFF = electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_OFF """The component has successfully switched off.""" - SWITCHING_ON = components_pb2.COMPONENT_STATE_CODE_SWITCHING_ON + SWITCHING_ON = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_SWITCHING_ON + ) """The component is in the process of switching on.""" - STANDBY = components_pb2.COMPONENT_STATE_CODE_STANDBY + STANDBY = electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_STANDBY """The component is in standby mode and not immediately ready for operation.""" - READY = components_pb2.COMPONENT_STATE_CODE_READY + READY = electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_READY """The component is fully operational and ready for use.""" - CHARGING = components_pb2.COMPONENT_STATE_CODE_CHARGING + CHARGING = electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_CHARGING """The component is actively consuming energy.""" - DISCHARGING = components_pb2.COMPONENT_STATE_CODE_DISCHARGING + DISCHARGING = electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_DISCHARGING """The component is actively producing or releasing energy.""" - ERROR = components_pb2.COMPONENT_STATE_CODE_ERROR + ERROR = electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_ERROR """The component is in an error state and may need attention.""" EV_CHARGING_CABLE_UNPLUGGED = ( - components_pb2.COMPONENT_STATE_CODE_EV_CHARGING_CABLE_UNPLUGGED + electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_EV_CHARGING_CABLE_UNPLUGGED ) """The EV charging cable is unplugged from the charging station.""" EV_CHARGING_CABLE_PLUGGED_AT_STATION = ( - components_pb2.COMPONENT_STATE_CODE_EV_CHARGING_CABLE_PLUGGED_AT_STATION + electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_EV_CHARGING_CABLE_PLUGGED_AT_STATION # noqa: E501 ) """The EV charging cable is plugged into the charging station.""" EV_CHARGING_CABLE_PLUGGED_AT_EV = ( - components_pb2.COMPONENT_STATE_CODE_EV_CHARGING_CABLE_PLUGGED_AT_EV + electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_EV_CHARGING_CABLE_PLUGGED_AT_EV ) """The EV charging cable is plugged into the vehicle.""" EV_CHARGING_CABLE_LOCKED_AT_STATION = ( - components_pb2.COMPONENT_STATE_CODE_EV_CHARGING_CABLE_LOCKED_AT_STATION + electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_EV_CHARGING_CABLE_LOCKED_AT_STATION # noqa: E501 ) """The EV charging cable is locked at the charging station end.""" EV_CHARGING_CABLE_LOCKED_AT_EV = ( - components_pb2.COMPONENT_STATE_CODE_EV_CHARGING_CABLE_LOCKED_AT_EV + electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_EV_CHARGING_CABLE_LOCKED_AT_EV ) """The EV charging cable is locked at the vehicle end.""" - RELAY_OPEN = components_pb2.COMPONENT_STATE_CODE_RELAY_OPEN + RELAY_OPEN = electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_RELAY_OPEN """The relay is in an open state, meaning no current can flow through.""" - RELAY_CLOSED = components_pb2.COMPONENT_STATE_CODE_RELAY_CLOSED + RELAY_CLOSED = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_RELAY_CLOSED + ) """The relay is in a closed state, allowing current to flow.""" - PRECHARGER_OPEN = components_pb2.COMPONENT_STATE_CODE_PRECHARGER_OPEN + PRECHARGER_OPEN = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_PRECHARGER_OPEN + ) """The precharger circuit is open, meaning it's not currently active.""" - PRECHARGER_PRECHARGING = components_pb2.COMPONENT_STATE_CODE_PRECHARGER_PRECHARGING + PRECHARGER_PRECHARGING = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_PRECHARGER_PRECHARGING + ) """The precharger is in a precharging state, preparing the main circuit for activation.""" - PRECHARGER_CLOSED = components_pb2.COMPONENT_STATE_CODE_PRECHARGER_CLOSED + PRECHARGER_CLOSED = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_PRECHARGER_CLOSED + ) """The precharger circuit is closed, allowing full current to flow to the main circuit.""" -@enum.unique +# @enum.unique class ComponentErrorCode(enum.Enum): """The various errors that a component can report.""" - UNSPECIFIED = components_pb2.COMPONENT_ERROR_CODE_UNSPECIFIED + UNSPECIFIED = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_UNSPECIFIED + ) """The error is unspecified (this should not be normally used).""" - UNKNOWN = components_pb2.COMPONENT_ERROR_CODE_UNKNOWN + UNKNOWN = electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_UNKNOWN """The component is reporting an unknown or undefined error. This is used when the error can be retrieved from the component but it doesn't match any known error. """ - SWITCH_ON_FAULT = components_pb2.COMPONENT_ERROR_CODE_SWITCH_ON_FAULT + SWITCH_ON_FAULT = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_SWITCH_ON_FAULT + ) """The component could not be switched on.""" - UNDERVOLTAGE = components_pb2.COMPONENT_ERROR_CODE_UNDERVOLTAGE + UNDERVOLTAGE = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_UNDERVOLTAGE + ) """The component is operating under the minimum rated voltage.""" - OVERVOLTAGE = components_pb2.COMPONENT_ERROR_CODE_OVERVOLTAGE + OVERVOLTAGE = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_OVERVOLTAGE + ) """The component is operating over the maximum rated voltage.""" - OVERCURRENT = components_pb2.COMPONENT_ERROR_CODE_OVERCURRENT + OVERCURRENT = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_OVERCURRENT + ) """The component is drawing more current than the maximum rated value.""" - OVERCURRENT_CHARGING = components_pb2.COMPONENT_ERROR_CODE_OVERCURRENT_CHARGING + OVERCURRENT_CHARGING = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_OVERCURRENT_CHARGING + ) """The component's consumption current is over the maximum rated value during charging.""" OVERCURRENT_DISCHARGING = ( - components_pb2.COMPONENT_ERROR_CODE_OVERCURRENT_DISCHARGING + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_OVERCURRENT_DISCHARGING ) """The component's production current is over the maximum rated value during discharging.""" - OVERTEMPERATURE = components_pb2.COMPONENT_ERROR_CODE_OVERTEMPERATURE + OVERTEMPERATURE = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_OVERTEMPERATURE + ) """The component is operating over the maximum rated temperature.""" - UNDERTEMPERATURE = components_pb2.COMPONENT_ERROR_CODE_UNDERTEMPERATURE + UNDERTEMPERATURE = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_UNDERTEMPERATURE + ) """The component is operating under the minimum rated temperature.""" - HIGH_HUMIDITY = components_pb2.COMPONENT_ERROR_CODE_HIGH_HUMIDITY + HIGH_HUMIDITY = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_HIGH_HUMIDITY + ) """The component is exposed to high humidity levels over the maximum rated value.""" - FUSE_ERROR = components_pb2.COMPONENT_ERROR_CODE_FUSE_ERROR + FUSE_ERROR = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_FUSE_ERROR + ) """The component's fuse has blown.""" - PRECHARGE_ERROR = components_pb2.COMPONENT_ERROR_CODE_PRECHARGE_ERROR + PRECHARGE_ERROR = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_PRECHARGE_ERROR + ) """The component's precharge unit has failed.""" - PLAUSIBILITY_ERROR = components_pb2.COMPONENT_ERROR_CODE_PLAUSIBILITY_ERROR + PLAUSIBILITY_ERROR = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_PLAUSIBILITY_ERROR + ) """Plausibility issues within the system involving this component.""" - UNDERVOLTAGE_SHUTDOWN = components_pb2.COMPONENT_ERROR_CODE_UNDERVOLTAGE_SHUTDOWN - """System shutdown due to undervoltage involving this component.""" + UNDERVOLTAGE_SHUTDOWN = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_UNDERVOLTAGE + ) + """System shutdown due to undervoltage involving this component. + + Deprecated: Deprecated in v0.18.0 + Use + [`UNDERVOLTAGE`][frequenz.client.microgrid.component.ComponentErrorCode.UNDERVOLTAGE] + instead. + """ EV_UNEXPECTED_PILOT_FAILURE = ( - components_pb2.COMPONENT_ERROR_CODE_EV_UNEXPECTED_PILOT_FAILURE + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_EV_UNEXPECTED_PILOT_FAILURE ) """Unexpected pilot failure in an electric vehicle component.""" - FAULT_CURRENT = components_pb2.COMPONENT_ERROR_CODE_FAULT_CURRENT + FAULT_CURRENT = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_FAULT_CURRENT + ) """Fault current detected in the component.""" - SHORT_CIRCUIT = components_pb2.COMPONENT_ERROR_CODE_SHORT_CIRCUIT + SHORT_CIRCUIT = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_SHORT_CIRCUIT + ) """Short circuit detected in the component.""" - CONFIG_ERROR = components_pb2.COMPONENT_ERROR_CODE_CONFIG_ERROR + CONFIG_ERROR = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_CONFIG_ERROR + ) """Configuration error related to the component.""" - ILLEGAL_COMPONENT_STATE_CODE_REQUESTED = ( - components_pb2.COMPONENT_ERROR_CODE_ILLEGAL_COMPONENT_STATE_CODE_REQUESTED + ILLEGAL_ELECTRICAL_COMPONENT_STATE_CODE_REQUESTED = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_ILLEGAL_COMPONENT_STATE_CODE_REQUESTED # noqa: E501 ) """Illegal state requested for the component.""" - HARDWARE_INACCESSIBLE = components_pb2.COMPONENT_ERROR_CODE_HARDWARE_INACCESSIBLE + HARDWARE_INACCESSIBLE = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_HARDWARE_INACCESSIBLE + ) """Hardware of the component is inaccessible.""" - INTERNAL = components_pb2.COMPONENT_ERROR_CODE_INTERNAL + INTERNAL = electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_INTERNAL """Internal error within the component.""" - UNAUTHORIZED = components_pb2.COMPONENT_ERROR_CODE_UNAUTHORIZED + UNAUTHORIZED = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_UNAUTHORIZED + ) """The component is unauthorized to perform the last requested action.""" EV_CHARGING_CABLE_UNPLUGGED_FROM_STATION = ( - components_pb2.COMPONENT_ERROR_CODE_EV_CHARGING_CABLE_UNPLUGGED_FROM_STATION + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_EV_CHARGING_CABLE_UNPLUGGED_FROM_STATION # noqa: E501 ) """EV cable was abruptly unplugged from the charging station.""" EV_CHARGING_CABLE_UNPLUGGED_FROM_EV = ( - components_pb2.COMPONENT_ERROR_CODE_EV_CHARGING_CABLE_UNPLUGGED_FROM_EV + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_EV_CHARGING_CABLE_UNPLUGGED_FROM_EV # noqa: E501 ) """EV cable was abruptly unplugged from the vehicle.""" EV_CHARGING_CABLE_LOCK_FAILED = ( - components_pb2.COMPONENT_ERROR_CODE_EV_CHARGING_CABLE_LOCK_FAILED + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_EV_CHARGING_CABLE_LOCK_FAILED ) """EV cable lock failure.""" EV_CHARGING_CABLE_INVALID = ( - components_pb2.COMPONENT_ERROR_CODE_EV_CHARGING_CABLE_INVALID + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_EV_CHARGING_CABLE_INVALID ) """Invalid EV cable.""" EV_CONSUMER_INCOMPATIBLE = ( - components_pb2.COMPONENT_ERROR_CODE_EV_CONSUMER_INCOMPATIBLE + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_EV_CONSUMER_INCOMPATIBLE ) """Incompatible EV plug.""" - BATTERY_IMBALANCE = components_pb2.COMPONENT_ERROR_CODE_BATTERY_IMBALANCE + BATTERY_IMBALANCE = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_BATTERY_IMBALANCE + ) """Battery system imbalance.""" - BATTERY_LOW_SOH = components_pb2.COMPONENT_ERROR_CODE_BATTERY_LOW_SOH + BATTERY_LOW_SOH = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_BATTERY_LOW_SOH + ) """Low state of health (SOH) detected in the battery.""" - BATTERY_BLOCK_ERROR = components_pb2.COMPONENT_ERROR_CODE_BATTERY_BLOCK_ERROR + BATTERY_BLOCK_ERROR = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_BATTERY_BLOCK_ERROR + ) """Battery block error.""" BATTERY_CONTROLLER_ERROR = ( - components_pb2.COMPONENT_ERROR_CODE_BATTERY_CONTROLLER_ERROR + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_BATTERY_CONTROLLER_ERROR ) """Battery controller error.""" - BATTERY_RELAY_ERROR = components_pb2.COMPONENT_ERROR_CODE_BATTERY_RELAY_ERROR + BATTERY_RELAY_ERROR = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_BATTERY_RELAY_ERROR + ) """Battery relay error.""" BATTERY_CALIBRATION_NEEDED = ( - components_pb2.COMPONENT_ERROR_CODE_BATTERY_CALIBRATION_NEEDED + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_BATTERY_CALIBRATION_NEEDED ) """Battery calibration is needed.""" RELAY_CYCLE_LIMIT_REACHED = ( - components_pb2.COMPONENT_ERROR_CODE_RELAY_CYCLE_LIMIT_REACHED + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_RELAY_CYCLE_LIMIT_REACHED ) """Relays have been cycled for the maximum number of times.""" diff --git a/src/frequenz/client/microgrid/component/_state_sample_proto.py b/src/frequenz/client/microgrid/component/_state_sample_proto.py index bfdf122..efba45b 100644 --- a/src/frequenz/client/microgrid/component/_state_sample_proto.py +++ b/src/frequenz/client/microgrid/component/_state_sample_proto.py @@ -5,7 +5,9 @@ from functools import partial -from frequenz.api.common.v1.microgrid.components import components_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) from frequenz.client.base import conversion from .._util import enum_from_proto @@ -16,7 +18,7 @@ def component_state_sample_from_proto( - message: components_pb2.ComponentState, + message: electrical_components_pb2.ElectricalComponentStateSnapshot, ) -> ComponentStateSample: """Convert a protobuf message to a `ComponentStateSample` object. @@ -27,8 +29,14 @@ def component_state_sample_from_proto( The resulting `ComponentStateSample` object. """ return ComponentStateSample( - sampled_at=conversion.to_datetime(message.sampled_at), + sampled_at=conversion.to_datetime(message.origin_time), states=frozenset(map(_state_from_proto, message.states)), - warnings=frozenset(map(_error_from_proto, message.warnings)), - errors=frozenset(map(_error_from_proto, message.errors)), + # pylint: disable-next=fixme + # TODO: Wrap the full diagnostic object. + warnings=frozenset( + map(_error_from_proto, (w.diagnostic_code for w in message.warnings)) + ), + errors=frozenset( + map(_error_from_proto, (e.diagnostic_code for e in message.errors)) + ), ) diff --git a/src/frequenz/client/microgrid/metrics/_bounds_proto.py b/src/frequenz/client/microgrid/metrics/_bounds_proto.py index 2a40f64..e446618 100644 --- a/src/frequenz/client/microgrid/metrics/_bounds_proto.py +++ b/src/frequenz/client/microgrid/metrics/_bounds_proto.py @@ -4,7 +4,7 @@ """Loading of Bounds objects from protobuf messages.""" -from frequenz.api.common.v1.metrics import bounds_pb2 +from frequenz.api.common.v1alpha8.metrics import bounds_pb2 from ._bounds import Bounds diff --git a/src/frequenz/client/microgrid/metrics/_metric.py b/src/frequenz/client/microgrid/metrics/_metric.py index 4754e88..8b82e7c 100644 --- a/src/frequenz/client/microgrid/metrics/_metric.py +++ b/src/frequenz/client/microgrid/metrics/_metric.py @@ -6,7 +6,7 @@ import enum -from frequenz.api.common.v1.metrics import metric_sample_pb2 +from frequenz.api.common.v1alpha8.metrics import metrics_pb2 @enum.unique @@ -26,239 +26,237 @@ class Metric(enum.Enum): period,and therefore can be inconsistent. """ - UNSPECIFIED = metric_sample_pb2.METRIC_UNSPECIFIED + UNSPECIFIED = metrics_pb2.METRIC_UNSPECIFIED """The metric is unspecified (this should not be used).""" - DC_VOLTAGE = metric_sample_pb2.METRIC_DC_VOLTAGE + DC_VOLTAGE = metrics_pb2.METRIC_DC_VOLTAGE """The direct current voltage.""" - DC_CURRENT = metric_sample_pb2.METRIC_DC_CURRENT + DC_CURRENT = metrics_pb2.METRIC_DC_CURRENT """The direct current current.""" - DC_POWER = metric_sample_pb2.METRIC_DC_POWER + DC_POWER = metrics_pb2.METRIC_DC_POWER """The direct current power.""" - AC_FREQUENCY = metric_sample_pb2.METRIC_AC_FREQUENCY + AC_FREQUENCY = metrics_pb2.METRIC_AC_FREQUENCY """The alternating current frequency.""" - AC_VOLTAGE = metric_sample_pb2.METRIC_AC_VOLTAGE + AC_VOLTAGE = metrics_pb2.METRIC_AC_VOLTAGE """The alternating current electric potential difference.""" - AC_VOLTAGE_PHASE_1_N = metric_sample_pb2.METRIC_AC_VOLTAGE_PHASE_1_N + AC_VOLTAGE_PHASE_1_N = metrics_pb2.METRIC_AC_VOLTAGE_PHASE_1_N """The alternating current electric potential difference between phase 1 and neutral.""" - AC_VOLTAGE_PHASE_2_N = metric_sample_pb2.METRIC_AC_VOLTAGE_PHASE_2_N + AC_VOLTAGE_PHASE_2_N = metrics_pb2.METRIC_AC_VOLTAGE_PHASE_2_N """The alternating current electric potential difference between phase 2 and neutral.""" - AC_VOLTAGE_PHASE_3_N = metric_sample_pb2.METRIC_AC_VOLTAGE_PHASE_3_N + AC_VOLTAGE_PHASE_3_N = metrics_pb2.METRIC_AC_VOLTAGE_PHASE_3_N """The alternating current electric potential difference between phase 3 and neutral.""" - AC_VOLTAGE_PHASE_1_PHASE_2 = metric_sample_pb2.METRIC_AC_VOLTAGE_PHASE_1_PHASE_2 + AC_VOLTAGE_PHASE_1_PHASE_2 = metrics_pb2.METRIC_AC_VOLTAGE_PHASE_1_PHASE_2 """The alternating current electric potential difference between phase 1 and phase 2.""" - AC_VOLTAGE_PHASE_2_PHASE_3 = metric_sample_pb2.METRIC_AC_VOLTAGE_PHASE_2_PHASE_3 + AC_VOLTAGE_PHASE_2_PHASE_3 = metrics_pb2.METRIC_AC_VOLTAGE_PHASE_2_PHASE_3 """The alternating current electric potential difference between phase 2 and phase 3.""" - AC_VOLTAGE_PHASE_3_PHASE_1 = metric_sample_pb2.METRIC_AC_VOLTAGE_PHASE_3_PHASE_1 + AC_VOLTAGE_PHASE_3_PHASE_1 = metrics_pb2.METRIC_AC_VOLTAGE_PHASE_3_PHASE_1 """The alternating current electric potential difference between phase 3 and phase 1.""" - AC_CURRENT = metric_sample_pb2.METRIC_AC_CURRENT + AC_CURRENT = metrics_pb2.METRIC_AC_CURRENT """The alternating current current.""" - AC_CURRENT_PHASE_1 = metric_sample_pb2.METRIC_AC_CURRENT_PHASE_1 + AC_CURRENT_PHASE_1 = metrics_pb2.METRIC_AC_CURRENT_PHASE_1 """The alternating current current in phase 1.""" - AC_CURRENT_PHASE_2 = metric_sample_pb2.METRIC_AC_CURRENT_PHASE_2 + AC_CURRENT_PHASE_2 = metrics_pb2.METRIC_AC_CURRENT_PHASE_2 """The alternating current current in phase 2.""" - AC_CURRENT_PHASE_3 = metric_sample_pb2.METRIC_AC_CURRENT_PHASE_3 + AC_CURRENT_PHASE_3 = metrics_pb2.METRIC_AC_CURRENT_PHASE_3 """The alternating current current in phase 3.""" - AC_APPARENT_POWER = metric_sample_pb2.METRIC_AC_APPARENT_POWER + AC_APPARENT_POWER = metrics_pb2.METRIC_AC_POWER_APPARENT """The alternating current apparent power.""" - AC_APPARENT_POWER_PHASE_1 = metric_sample_pb2.METRIC_AC_APPARENT_POWER_PHASE_1 + AC_APPARENT_POWER_PHASE_1 = metrics_pb2.METRIC_AC_POWER_APPARENT_PHASE_1 """The alternating current apparent power in phase 1.""" - AC_APPARENT_POWER_PHASE_2 = metric_sample_pb2.METRIC_AC_APPARENT_POWER_PHASE_2 + AC_APPARENT_POWER_PHASE_2 = metrics_pb2.METRIC_AC_POWER_APPARENT_PHASE_2 """The alternating current apparent power in phase 2.""" - AC_APPARENT_POWER_PHASE_3 = metric_sample_pb2.METRIC_AC_APPARENT_POWER_PHASE_3 + AC_APPARENT_POWER_PHASE_3 = metrics_pb2.METRIC_AC_POWER_APPARENT_PHASE_3 """The alternating current apparent power in phase 3.""" - AC_ACTIVE_POWER = metric_sample_pb2.METRIC_AC_ACTIVE_POWER + AC_ACTIVE_POWER = metrics_pb2.METRIC_AC_POWER_ACTIVE """The alternating current active power.""" - AC_ACTIVE_POWER_PHASE_1 = metric_sample_pb2.METRIC_AC_ACTIVE_POWER_PHASE_1 + AC_ACTIVE_POWER_PHASE_1 = metrics_pb2.METRIC_AC_POWER_ACTIVE_PHASE_1 """The alternating current active power in phase 1.""" - AC_ACTIVE_POWER_PHASE_2 = metric_sample_pb2.METRIC_AC_ACTIVE_POWER_PHASE_2 + AC_ACTIVE_POWER_PHASE_2 = metrics_pb2.METRIC_AC_POWER_ACTIVE_PHASE_2 """The alternating current active power in phase 2.""" - AC_ACTIVE_POWER_PHASE_3 = metric_sample_pb2.METRIC_AC_ACTIVE_POWER_PHASE_3 + AC_ACTIVE_POWER_PHASE_3 = metrics_pb2.METRIC_AC_POWER_ACTIVE_PHASE_3 """The alternating current active power in phase 3.""" - AC_REACTIVE_POWER = metric_sample_pb2.METRIC_AC_REACTIVE_POWER + AC_REACTIVE_POWER = metrics_pb2.METRIC_AC_POWER_REACTIVE """The alternating current reactive power.""" - AC_REACTIVE_POWER_PHASE_1 = metric_sample_pb2.METRIC_AC_REACTIVE_POWER_PHASE_1 + AC_REACTIVE_POWER_PHASE_1 = metrics_pb2.METRIC_AC_POWER_REACTIVE_PHASE_1 """The alternating current reactive power in phase 1.""" - AC_REACTIVE_POWER_PHASE_2 = metric_sample_pb2.METRIC_AC_REACTIVE_POWER_PHASE_2 + AC_REACTIVE_POWER_PHASE_2 = metrics_pb2.METRIC_AC_POWER_REACTIVE_PHASE_2 """The alternating current reactive power in phase 2.""" - AC_REACTIVE_POWER_PHASE_3 = metric_sample_pb2.METRIC_AC_REACTIVE_POWER_PHASE_3 + AC_REACTIVE_POWER_PHASE_3 = metrics_pb2.METRIC_AC_POWER_REACTIVE_PHASE_3 """The alternating current reactive power in phase 3.""" - AC_POWER_FACTOR = metric_sample_pb2.METRIC_AC_POWER_FACTOR + AC_POWER_FACTOR = metrics_pb2.METRIC_AC_POWER_FACTOR """The alternating current power factor.""" - AC_POWER_FACTOR_PHASE_1 = metric_sample_pb2.METRIC_AC_POWER_FACTOR_PHASE_1 + AC_POWER_FACTOR_PHASE_1 = metrics_pb2.METRIC_AC_POWER_FACTOR_PHASE_1 """The alternating current power factor in phase 1.""" - AC_POWER_FACTOR_PHASE_2 = metric_sample_pb2.METRIC_AC_POWER_FACTOR_PHASE_2 + AC_POWER_FACTOR_PHASE_2 = metrics_pb2.METRIC_AC_POWER_FACTOR_PHASE_2 """The alternating current power factor in phase 2.""" - AC_POWER_FACTOR_PHASE_3 = metric_sample_pb2.METRIC_AC_POWER_FACTOR_PHASE_3 + AC_POWER_FACTOR_PHASE_3 = metrics_pb2.METRIC_AC_POWER_FACTOR_PHASE_3 """The alternating current power factor in phase 3.""" - AC_APPARENT_ENERGY = metric_sample_pb2.METRIC_AC_APPARENT_ENERGY + AC_APPARENT_ENERGY = metrics_pb2.METRIC_AC_ENERGY_APPARENT """The alternating current apparent energy.""" - AC_APPARENT_ENERGY_PHASE_1 = metric_sample_pb2.METRIC_AC_APPARENT_ENERGY_PHASE_1 + AC_APPARENT_ENERGY_PHASE_1 = metrics_pb2.METRIC_AC_ENERGY_APPARENT_PHASE_1 """The alternating current apparent energy in phase 1.""" - AC_APPARENT_ENERGY_PHASE_2 = metric_sample_pb2.METRIC_AC_APPARENT_ENERGY_PHASE_2 + AC_APPARENT_ENERGY_PHASE_2 = metrics_pb2.METRIC_AC_ENERGY_APPARENT_PHASE_2 """The alternating current apparent energy in phase 2.""" - AC_APPARENT_ENERGY_PHASE_3 = metric_sample_pb2.METRIC_AC_APPARENT_ENERGY_PHASE_3 + AC_APPARENT_ENERGY_PHASE_3 = metrics_pb2.METRIC_AC_ENERGY_APPARENT_PHASE_3 """The alternating current apparent energy in phase 3.""" - AC_ACTIVE_ENERGY = metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY + AC_ACTIVE_ENERGY = metrics_pb2.METRIC_AC_ENERGY_ACTIVE """The alternating current active energy.""" - AC_ACTIVE_ENERGY_PHASE_1 = metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY_PHASE_1 + AC_ACTIVE_ENERGY_PHASE_1 = metrics_pb2.METRIC_AC_ENERGY_ACTIVE_PHASE_1 """The alternating current active energy in phase 1.""" - AC_ACTIVE_ENERGY_PHASE_2 = metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY_PHASE_2 + AC_ACTIVE_ENERGY_PHASE_2 = metrics_pb2.METRIC_AC_ENERGY_ACTIVE_PHASE_2 """The alternating current active energy in phase 2.""" - AC_ACTIVE_ENERGY_PHASE_3 = metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY_PHASE_3 + AC_ACTIVE_ENERGY_PHASE_3 = metrics_pb2.METRIC_AC_ENERGY_ACTIVE_PHASE_3 """The alternating current active energy in phase 3.""" - AC_ACTIVE_ENERGY_CONSUMED = metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY_CONSUMED + AC_ACTIVE_ENERGY_CONSUMED = metrics_pb2.METRIC_AC_ENERGY_ACTIVE_CONSUMED """The alternating current active energy consumed.""" AC_ACTIVE_ENERGY_CONSUMED_PHASE_1 = ( - metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY_CONSUMED_PHASE_1 + metrics_pb2.METRIC_AC_ENERGY_ACTIVE_CONSUMED_PHASE_1 ) """The alternating current active energy consumed in phase 1.""" AC_ACTIVE_ENERGY_CONSUMED_PHASE_2 = ( - metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY_CONSUMED_PHASE_2 + metrics_pb2.METRIC_AC_ENERGY_ACTIVE_CONSUMED_PHASE_2 ) """The alternating current active energy consumed in phase 2.""" AC_ACTIVE_ENERGY_CONSUMED_PHASE_3 = ( - metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY_CONSUMED_PHASE_3 + metrics_pb2.METRIC_AC_ENERGY_ACTIVE_CONSUMED_PHASE_3 ) """The alternating current active energy consumed in phase 3.""" - AC_ACTIVE_ENERGY_DELIVERED = metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY_DELIVERED + AC_ACTIVE_ENERGY_DELIVERED = metrics_pb2.METRIC_AC_ENERGY_ACTIVE_DELIVERED """The alternating current active energy delivered.""" AC_ACTIVE_ENERGY_DELIVERED_PHASE_1 = ( - metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY_DELIVERED_PHASE_1 + metrics_pb2.METRIC_AC_ENERGY_ACTIVE_DELIVERED_PHASE_1 ) """The alternating current active energy delivered in phase 1.""" AC_ACTIVE_ENERGY_DELIVERED_PHASE_2 = ( - metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY_DELIVERED_PHASE_2 + metrics_pb2.METRIC_AC_ENERGY_ACTIVE_DELIVERED_PHASE_2 ) """The alternating current active energy delivered in phase 2.""" AC_ACTIVE_ENERGY_DELIVERED_PHASE_3 = ( - metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY_DELIVERED_PHASE_3 + metrics_pb2.METRIC_AC_ENERGY_ACTIVE_DELIVERED_PHASE_3 ) """The alternating current active energy delivered in phase 3.""" - AC_REACTIVE_ENERGY = metric_sample_pb2.METRIC_AC_REACTIVE_ENERGY + AC_REACTIVE_ENERGY = metrics_pb2.METRIC_AC_ENERGY_REACTIVE """The alternating current reactive energy.""" - AC_REACTIVE_ENERGY_PHASE_1 = metric_sample_pb2.METRIC_AC_REACTIVE_ENERGY_PHASE_1 + AC_REACTIVE_ENERGY_PHASE_1 = metrics_pb2.METRIC_AC_ENERGY_REACTIVE_PHASE_1 """The alternating current reactive energy in phase 1.""" - AC_REACTIVE_ENERGY_PHASE_2 = metric_sample_pb2.METRIC_AC_REACTIVE_ENERGY_PHASE_2 + AC_REACTIVE_ENERGY_PHASE_2 = metrics_pb2.METRIC_AC_ENERGY_REACTIVE_PHASE_2 """The alternating current reactive energy in phase 2.""" - AC_REACTIVE_ENERGY_PHASE_3 = metric_sample_pb2.METRIC_AC_REACTIVE_ENERGY_PHASE_3 + AC_REACTIVE_ENERGY_PHASE_3 = metrics_pb2.METRIC_AC_ENERGY_REACTIVE_PHASE_3 """The alternating current reactive energy in phase 3.""" AC_TOTAL_HARMONIC_DISTORTION_CURRENT = ( - metric_sample_pb2.METRIC_AC_TOTAL_HARMONIC_DISTORTION_CURRENT + metrics_pb2.METRIC_AC_TOTAL_HARMONIC_DISTORTION_CURRENT ) """The alternating current total harmonic distortion current.""" AC_TOTAL_HARMONIC_DISTORTION_CURRENT_PHASE_1 = ( - metric_sample_pb2.METRIC_AC_TOTAL_HARMONIC_DISTORTION_CURRENT_PHASE_1 + metrics_pb2.METRIC_AC_TOTAL_HARMONIC_DISTORTION_CURRENT_PHASE_1 ) """The alternating current total harmonic distortion current in phase 1.""" AC_TOTAL_HARMONIC_DISTORTION_CURRENT_PHASE_2 = ( - metric_sample_pb2.METRIC_AC_TOTAL_HARMONIC_DISTORTION_CURRENT_PHASE_2 + metrics_pb2.METRIC_AC_TOTAL_HARMONIC_DISTORTION_CURRENT_PHASE_2 ) """The alternating current total harmonic distortion current in phase 2.""" AC_TOTAL_HARMONIC_DISTORTION_CURRENT_PHASE_3 = ( - metric_sample_pb2.METRIC_AC_TOTAL_HARMONIC_DISTORTION_CURRENT_PHASE_3 + metrics_pb2.METRIC_AC_TOTAL_HARMONIC_DISTORTION_CURRENT_PHASE_3 ) """The alternating current total harmonic distortion current in phase 3.""" - BATTERY_CAPACITY = metric_sample_pb2.METRIC_BATTERY_CAPACITY + BATTERY_CAPACITY = metrics_pb2.METRIC_BATTERY_CAPACITY """The capacity of the battery.""" - BATTERY_SOC_PCT = metric_sample_pb2.METRIC_BATTERY_SOC_PCT + BATTERY_SOC_PCT = metrics_pb2.METRIC_BATTERY_SOC_PCT """The state of charge of the battery as a percentage.""" - BATTERY_TEMPERATURE = metric_sample_pb2.METRIC_BATTERY_TEMPERATURE + BATTERY_TEMPERATURE = metrics_pb2.METRIC_BATTERY_TEMPERATURE """The temperature of the battery.""" - INVERTER_TEMPERATURE = metric_sample_pb2.METRIC_INVERTER_TEMPERATURE + INVERTER_TEMPERATURE = metrics_pb2.METRIC_INVERTER_TEMPERATURE """The temperature of the inverter.""" - INVERTER_TEMPERATURE_CABINET = metric_sample_pb2.METRIC_INVERTER_TEMPERATURE_CABINET + INVERTER_TEMPERATURE_CABINET = metrics_pb2.METRIC_INVERTER_TEMPERATURE_CABINET """The temperature of the inverter cabinet.""" - INVERTER_TEMPERATURE_HEATSINK = ( - metric_sample_pb2.METRIC_INVERTER_TEMPERATURE_HEATSINK - ) + INVERTER_TEMPERATURE_HEATSINK = metrics_pb2.METRIC_INVERTER_TEMPERATURE_HEATSINK """The temperature of the inverter heatsink.""" INVERTER_TEMPERATURE_TRANSFORMER = ( - metric_sample_pb2.METRIC_INVERTER_TEMPERATURE_TRANSFORMER + metrics_pb2.METRIC_INVERTER_TEMPERATURE_TRANSFORMER ) """The temperature of the inverter transformer.""" - EV_CHARGER_TEMPERATURE = metric_sample_pb2.METRIC_EV_CHARGER_TEMPERATURE + EV_CHARGER_TEMPERATURE = metrics_pb2.METRIC_EV_CHARGER_TEMPERATURE """The temperature of the EV charger.""" - SENSOR_WIND_SPEED = metric_sample_pb2.METRIC_SENSOR_WIND_SPEED + SENSOR_WIND_SPEED = metrics_pb2.METRIC_SENSOR_WIND_SPEED """The speed of the wind measured.""" - SENSOR_WIND_DIRECTION = metric_sample_pb2.METRIC_SENSOR_WIND_DIRECTION + SENSOR_WIND_DIRECTION = metrics_pb2.METRIC_SENSOR_WIND_DIRECTION """The direction of the wind measured.""" - SENSOR_TEMPERATURE = metric_sample_pb2.METRIC_SENSOR_TEMPERATURE + SENSOR_TEMPERATURE = metrics_pb2.METRIC_SENSOR_TEMPERATURE """The temperature measured.""" - SENSOR_RELATIVE_HUMIDITY = metric_sample_pb2.METRIC_SENSOR_RELATIVE_HUMIDITY + SENSOR_RELATIVE_HUMIDITY = metrics_pb2.METRIC_SENSOR_RELATIVE_HUMIDITY """The relative humidity measured.""" - SENSOR_DEW_POINT = metric_sample_pb2.METRIC_SENSOR_DEW_POINT + SENSOR_DEW_POINT = metrics_pb2.METRIC_SENSOR_DEW_POINT """The dew point measured.""" - SENSOR_AIR_PRESSURE = metric_sample_pb2.METRIC_SENSOR_AIR_PRESSURE + SENSOR_AIR_PRESSURE = metrics_pb2.METRIC_SENSOR_AIR_PRESSURE """The air pressure measured.""" - SENSOR_IRRADIANCE = metric_sample_pb2.METRIC_SENSOR_IRRADIANCE + SENSOR_IRRADIANCE = metrics_pb2.METRIC_SENSOR_IRRADIANCE """The irradiance measured.""" diff --git a/src/frequenz/client/microgrid/metrics/_sample_proto.py b/src/frequenz/client/microgrid/metrics/_sample_proto.py index 314555c..def7ce4 100644 --- a/src/frequenz/client/microgrid/metrics/_sample_proto.py +++ b/src/frequenz/client/microgrid/metrics/_sample_proto.py @@ -5,7 +5,7 @@ from collections.abc import Sequence -from frequenz.api.common.v1.metrics import bounds_pb2, metric_sample_pb2 +from frequenz.api.common.v1alpha8.metrics import bounds_pb2, metrics_pb2 from frequenz.client.base import conversion from .._util import enum_from_proto @@ -16,7 +16,7 @@ def aggregated_metric_sample_from_proto( - message: metric_sample_pb2.AggregatedMetricValue, + message: metrics_pb2.AggregatedMetricValue, ) -> AggregatedMetricValue: """Convert a protobuf message to a `AggregatedMetricValue` object. @@ -35,7 +35,7 @@ def aggregated_metric_sample_from_proto( def metric_sample_from_proto_with_issues( - message: metric_sample_pb2.MetricSample, + message: metrics_pb2.MetricSample, *, major_issues: list[str], minor_issues: list[str], @@ -63,7 +63,7 @@ def metric_sample_from_proto_with_issues( metric = enum_from_proto(message.metric, Metric) return MetricSample( - sampled_at=conversion.to_datetime(message.sampled_at), + sampled_at=conversion.to_datetime(message.sample_time), metric=metric, value=value, bounds=_metric_bounds_from_proto( @@ -72,7 +72,9 @@ def metric_sample_from_proto_with_issues( major_issues=major_issues, minor_issues=minor_issues, ), - connection=message.source or None, + # pylint: disable-next=fixme + # TODO: Wrap the full connection object + connection=(message.connection.name or None) if message.connection else None, ) diff --git a/tests/client_test_cases/add_component_bounds/no_validity_case.py b/tests/client_test_cases/add_component_bounds/no_validity_case.py index bff849b..562d39c 100644 --- a/tests/client_test_cases/add_component_bounds/no_validity_case.py +++ b/tests/client_test_cases/add_component_bounds/no_validity_case.py @@ -5,8 +5,8 @@ from typing import Any -from frequenz.api.common.v1.metrics import bounds_pb2, metric_sample_pb2 -from frequenz.api.microgrid.v1 import microgrid_pb2 +from frequenz.api.common.v1alpha8.metrics import bounds_pb2, metrics_pb2 +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2 from frequenz.client.common.microgrid.components import ComponentId from frequenz.client.microgrid.metrics import Bounds, Metric @@ -17,9 +17,9 @@ def assert_stub_method_call(stub_method: Any) -> None: """Assert that the gRPC request matches the expected request.""" stub_method.assert_called_once_with( - microgrid_pb2.AddComponentBoundsRequest( - component_id=1, - target_metric=metric_sample_pb2.Metric.METRIC_AC_VOLTAGE, + microgrid_pb2.AugmentElectricalComponentBoundsRequest( + electrical_component_id=1, + target_metric=metrics_pb2.Metric.METRIC_AC_VOLTAGE, bounds=[bounds_pb2.Bounds(lower=200.0, upper=250.0)], # No validity field ), @@ -27,7 +27,7 @@ def assert_stub_method_call(stub_method: Any) -> None: ) -grpc_response = microgrid_pb2.AddComponentBoundsResponse() +grpc_response = microgrid_pb2.AugmentElectricalComponentBoundsResponse() def assert_client_result(result: Any) -> None: diff --git a/tests/client_test_cases/add_component_bounds/success_case.py b/tests/client_test_cases/add_component_bounds/success_case.py index 2374904..9ab4760 100644 --- a/tests/client_test_cases/add_component_bounds/success_case.py +++ b/tests/client_test_cases/add_component_bounds/success_case.py @@ -6,8 +6,8 @@ from datetime import datetime, timezone from typing import Any -from frequenz.api.common.v1.metrics import bounds_pb2, metric_sample_pb2 -from frequenz.api.microgrid.v1 import microgrid_pb2 +from frequenz.api.common.v1alpha8.metrics import bounds_pb2, metrics_pb2 +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2 from frequenz.client.base.conversion import to_timestamp from frequenz.client.common.microgrid.components import ComponentId @@ -24,25 +24,25 @@ "validity": Validity.FIFTEEN_MINUTES, } -PbValidity = microgrid_pb2.ComponentBoundsValidityDuration - valid_until = datetime(2023, 1, 1, 12, 0, 0, tzinfo=timezone.utc) def assert_stub_method_call(stub_method: Any) -> None: """Assert that the gRPC request matches the expected request.""" stub_method.assert_called_once_with( - microgrid_pb2.AddComponentBoundsRequest( - component_id=1, - target_metric=metric_sample_pb2.Metric.METRIC_DC_VOLTAGE, + microgrid_pb2.AugmentElectricalComponentBoundsRequest( + electrical_component_id=1, + target_metric=metrics_pb2.Metric.METRIC_DC_VOLTAGE, bounds=[bounds_pb2.Bounds(lower=200.0, upper=250.0)], - validity_duration=PbValidity.COMPONENT_BOUNDS_VALIDITY_DURATION_15_MINUTES, + request_lifetime=60 * 15, ), timeout=DEFAULT_GRPC_CALL_TIMEOUT, ) -grpc_response = microgrid_pb2.AddComponentBoundsResponse(ts=to_timestamp(valid_until)) +grpc_response = microgrid_pb2.AugmentElectricalComponentBoundsResponse( + valid_until_time=to_timestamp(valid_until) +) def assert_client_result(result: datetime) -> None: diff --git a/tests/client_test_cases/get_microgrid_info/defaults_case.py b/tests/client_test_cases/get_microgrid_info/defaults_case.py index 5776eef..40b4cd8 100644 --- a/tests/client_test_cases/get_microgrid_info/defaults_case.py +++ b/tests/client_test_cases/get_microgrid_info/defaults_case.py @@ -7,8 +7,8 @@ from typing import Any from unittest.mock import AsyncMock -from frequenz.api.common.v1.microgrid import microgrid_pb2 as microgrid_common_pb2 -from frequenz.api.microgrid.v1 import microgrid_pb2 +from frequenz.api.common.v1alpha8.microgrid import microgrid_pb2 as microgrid_common_pb2 +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2 from frequenz.client.common.microgrid import EnterpriseId, MicrogridId from google.protobuf.empty_pb2 import Empty @@ -23,7 +23,7 @@ def assert_stub_method_call(stub_method: AsyncMock) -> None: create_timestamp = datetime(2023, 1, 1, tzinfo=timezone.utc) -grpc_response = microgrid_pb2.GetMicrogridMetadataResponse( +grpc_response = microgrid_pb2.GetMicrogridResponse( microgrid=microgrid_common_pb2.Microgrid() ) diff --git a/tests/client_test_cases/get_microgrid_info/full_case.py b/tests/client_test_cases/get_microgrid_info/full_case.py index 4f1e9f9..12a9d3b 100644 --- a/tests/client_test_cases/get_microgrid_info/full_case.py +++ b/tests/client_test_cases/get_microgrid_info/full_case.py @@ -8,10 +8,10 @@ from unittest.mock import AsyncMock import pytest -from frequenz.api.common.v1 import location_pb2 -from frequenz.api.common.v1.grid import delivery_area_pb2 -from frequenz.api.common.v1.microgrid import microgrid_pb2 as microgrid_common_pb2 -from frequenz.api.microgrid.v1 import microgrid_pb2 +from frequenz.api.common.v1alpha8.grid import delivery_area_pb2 +from frequenz.api.common.v1alpha8.microgrid import microgrid_pb2 as microgrid_common_pb2 +from frequenz.api.common.v1alpha8.types import location_pb2 +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2 from frequenz.client.base.conversion import to_timestamp from frequenz.client.common.microgrid import EnterpriseId, MicrogridId from google.protobuf.empty_pb2 import Empty @@ -33,7 +33,7 @@ def assert_stub_method_call(stub_method: AsyncMock) -> None: create_timestamp = datetime(2023, 1, 1, tzinfo=timezone.utc) -grpc_response = microgrid_pb2.GetMicrogridMetadataResponse( +grpc_response = microgrid_pb2.GetMicrogridResponse( microgrid=microgrid_common_pb2.Microgrid( id=1234, enterprise_id=5678, diff --git a/tests/client_test_cases/list_components/diverse_component_types_case.py b/tests/client_test_cases/list_components/diverse_component_types_case.py index 8bc7755..99fe4ea 100644 --- a/tests/client_test_cases/list_components/diverse_component_types_case.py +++ b/tests/client_test_cases/list_components/diverse_component_types_case.py @@ -5,14 +5,10 @@ from typing import Any -from frequenz.api.common.v1.microgrid.components import ( - battery_pb2, - components_pb2, - ev_charger_pb2, - grid_pb2, - inverter_pb2, +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2 as ec_pb2, ) -from frequenz.api.microgrid.v1 import microgrid_pb2 +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2 from frequenz.client.common.microgrid import MicrogridId from frequenz.client.common.microgrid.components import ComponentId @@ -59,199 +55,194 @@ def assert_stub_method_call(stub_method: Any) -> None: """Assert that the gRPC request matches the expected request.""" stub_method.assert_called_once_with( - microgrid_pb2.ListComponentsRequest(component_ids=[], categories=[]), + microgrid_pb2.ListElectricalComponentsRequest( + electrical_component_ids=[], electrical_component_categories=[] + ), timeout=60.0, ) -grpc_response = microgrid_pb2.ListComponentsResponse( - components=[ - components_pb2.Component( +grpc_response = microgrid_pb2.ListElectricalComponentsResponse( + electrical_components=[ + ec_pb2.ElectricalComponent( id=1, microgrid_id=1, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_GRID, - category_type=components_pb2.ComponentCategoryMetadataVariant( - grid=grid_pb2.GridConnectionPoint(rated_fuse_current=10_000) + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_GRID_CONNECTION_POINT, + category_specific_info=ec_pb2.ElectricalComponentCategorySpecificInfo( + grid_connection_point=ec_pb2.GridConnectionPoint( + rated_fuse_current=10_000 + ) ), ), - components_pb2.Component( + ec_pb2.ElectricalComponent( id=2, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_INVERTER, - category_type=components_pb2.ComponentCategoryMetadataVariant( - inverter=inverter_pb2.Inverter( - type=inverter_pb2.InverterType.INVERTER_TYPE_SOLAR - ) + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_INVERTER, + category_specific_info=ec_pb2.ElectricalComponentCategorySpecificInfo( + inverter=ec_pb2.Inverter(type=ec_pb2.InverterType.INVERTER_TYPE_PV) ), ), - components_pb2.Component( + ec_pb2.ElectricalComponent( id=3, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_BATTERY, - category_type=components_pb2.ComponentCategoryMetadataVariant( - battery=battery_pb2.Battery( - type=battery_pb2.BatteryType.BATTERY_TYPE_LI_ION - ) + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_BATTERY, + category_specific_info=ec_pb2.ElectricalComponentCategorySpecificInfo( + battery=ec_pb2.Battery(type=ec_pb2.BatteryType.BATTERY_TYPE_LI_ION) ), ), - components_pb2.Component( - id=4, category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_CONVERTER + ec_pb2.ElectricalComponent( + id=4, + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_CONVERTER, ), - components_pb2.Component( - id=5, category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_METER + ec_pb2.ElectricalComponent( + id=5, + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_METER, ), - components_pb2.Component( + ec_pb2.ElectricalComponent( id=6, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_EV_CHARGER, - category_type=components_pb2.ComponentCategoryMetadataVariant( - ev_charger=ev_charger_pb2.EvCharger( - type=ev_charger_pb2.EvChargerType.EV_CHARGER_TYPE_AC + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_EV_CHARGER, + category_specific_info=ec_pb2.ElectricalComponentCategorySpecificInfo( + ev_charger=ec_pb2.EvCharger( + type=ec_pb2.EvChargerType.EV_CHARGER_TYPE_AC ) ), ), - components_pb2.Component( - id=8, category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_HVAC + ec_pb2.ElectricalComponent( + id=8, + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_HVAC, ), # Additional battery types - components_pb2.Component( + ec_pb2.ElectricalComponent( id=9, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_BATTERY, - category_type=components_pb2.ComponentCategoryMetadataVariant( - battery=battery_pb2.Battery( - type=battery_pb2.BatteryType.BATTERY_TYPE_UNSPECIFIED - ) + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_BATTERY, + category_specific_info=ec_pb2.ElectricalComponentCategorySpecificInfo( + battery=ec_pb2.Battery(type=ec_pb2.BatteryType.BATTERY_TYPE_UNSPECIFIED) ), ), - components_pb2.Component( + ec_pb2.ElectricalComponent( id=10, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_BATTERY, - category_type=components_pb2.ComponentCategoryMetadataVariant( - battery=battery_pb2.Battery( - type=battery_pb2.BatteryType.BATTERY_TYPE_NA_ION - ) + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_BATTERY, + category_specific_info=ec_pb2.ElectricalComponentCategorySpecificInfo( + battery=ec_pb2.Battery(type=ec_pb2.BatteryType.BATTERY_TYPE_NA_ION) ), ), - components_pb2.Component( + ec_pb2.ElectricalComponent( id=11, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_BATTERY, - category_type=components_pb2.ComponentCategoryMetadataVariant( - battery=battery_pb2.Battery( + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_BATTERY, + category_specific_info=ec_pb2.ElectricalComponentCategorySpecificInfo( + battery=ec_pb2.Battery( type=666, # type: ignore[arg-type] ) ), ), # Additional inverter types - components_pb2.Component( + ec_pb2.ElectricalComponent( id=12, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_INVERTER, - category_type=components_pb2.ComponentCategoryMetadataVariant( - inverter=inverter_pb2.Inverter( - type=inverter_pb2.InverterType.INVERTER_TYPE_UNSPECIFIED + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_INVERTER, + category_specific_info=ec_pb2.ElectricalComponentCategorySpecificInfo( + inverter=ec_pb2.Inverter( + type=ec_pb2.InverterType.INVERTER_TYPE_UNSPECIFIED ) ), ), - components_pb2.Component( + ec_pb2.ElectricalComponent( id=13, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_INVERTER, - category_type=components_pb2.ComponentCategoryMetadataVariant( - inverter=inverter_pb2.Inverter( - type=inverter_pb2.InverterType.INVERTER_TYPE_BATTERY - ) + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_INVERTER, + category_specific_info=ec_pb2.ElectricalComponentCategorySpecificInfo( + inverter=ec_pb2.Inverter(type=ec_pb2.InverterType.INVERTER_TYPE_BATTERY) ), ), - components_pb2.Component( + ec_pb2.ElectricalComponent( id=14, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_INVERTER, - category_type=components_pb2.ComponentCategoryMetadataVariant( - inverter=inverter_pb2.Inverter( - type=inverter_pb2.InverterType.INVERTER_TYPE_HYBRID - ) + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_INVERTER, + category_specific_info=ec_pb2.ElectricalComponentCategorySpecificInfo( + inverter=ec_pb2.Inverter(type=ec_pb2.InverterType.INVERTER_TYPE_HYBRID) ), ), - components_pb2.Component( + ec_pb2.ElectricalComponent( id=15, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_INVERTER, - category_type=components_pb2.ComponentCategoryMetadataVariant( - inverter=inverter_pb2.Inverter( + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_INVERTER, + category_specific_info=ec_pb2.ElectricalComponentCategorySpecificInfo( + inverter=ec_pb2.Inverter( type=777, # type: ignore[arg-type] ) ), ), # Additional EV charger types - components_pb2.Component( + ec_pb2.ElectricalComponent( id=16, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_EV_CHARGER, - category_type=components_pb2.ComponentCategoryMetadataVariant( - ev_charger=ev_charger_pb2.EvCharger( - type=ev_charger_pb2.EvChargerType.EV_CHARGER_TYPE_UNSPECIFIED + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_EV_CHARGER, + category_specific_info=ec_pb2.ElectricalComponentCategorySpecificInfo( + ev_charger=ec_pb2.EvCharger( + type=ec_pb2.EvChargerType.EV_CHARGER_TYPE_UNSPECIFIED ) ), ), - components_pb2.Component( + ec_pb2.ElectricalComponent( id=17, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_EV_CHARGER, - category_type=components_pb2.ComponentCategoryMetadataVariant( - ev_charger=ev_charger_pb2.EvCharger( - type=ev_charger_pb2.EvChargerType.EV_CHARGER_TYPE_DC + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_EV_CHARGER, + category_specific_info=ec_pb2.ElectricalComponentCategorySpecificInfo( + ev_charger=ec_pb2.EvCharger( + type=ec_pb2.EvChargerType.EV_CHARGER_TYPE_DC ) ), ), - components_pb2.Component( + ec_pb2.ElectricalComponent( id=18, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_EV_CHARGER, - category_type=components_pb2.ComponentCategoryMetadataVariant( - ev_charger=ev_charger_pb2.EvCharger( - type=ev_charger_pb2.EvChargerType.EV_CHARGER_TYPE_HYBRID + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_EV_CHARGER, + category_specific_info=ec_pb2.ElectricalComponentCategorySpecificInfo( + ev_charger=ec_pb2.EvCharger( + type=ec_pb2.EvChargerType.EV_CHARGER_TYPE_HYBRID ) ), ), - components_pb2.Component( + ec_pb2.ElectricalComponent( id=19, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_EV_CHARGER, - category_type=components_pb2.ComponentCategoryMetadataVariant( - ev_charger=ev_charger_pb2.EvCharger( + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_EV_CHARGER, + category_specific_info=ec_pb2.ElectricalComponentCategorySpecificInfo( + ev_charger=ec_pb2.EvCharger( type=888, # type: ignore[arg-type] ) ), ), # Additional component categories - components_pb2.Component( - id=20, category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_CHP + ec_pb2.ElectricalComponent( + id=20, + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_CHP, ), - components_pb2.Component( + ec_pb2.ElectricalComponent( id=21, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_CRYPTO_MINER, + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_CRYPTO_MINER, ), - components_pb2.Component( + ec_pb2.ElectricalComponent( id=22, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_ELECTROLYZER, + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_ELECTROLYZER, ), - components_pb2.Component( + ec_pb2.ElectricalComponent( id=23, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_PRECHARGER, + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_PRECHARGER, ), - components_pb2.Component( - id=24, category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_RELAY + ec_pb2.ElectricalComponent( + id=24, + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_BREAKER, ), - components_pb2.Component( + ec_pb2.ElectricalComponent( id=25, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_VOLTAGE_TRANSFORMER, + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_POWER_TRANSFORMER, ), # Problematic components - components_pb2.Component( + ec_pb2.ElectricalComponent( id=26, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_UNSPECIFIED, + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_UNSPECIFIED, ), - components_pb2.Component( + ec_pb2.ElectricalComponent( id=27, category=999, # type: ignore[arg-type] ), - components_pb2.Component( + ec_pb2.ElectricalComponent( id=28, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_BATTERY, - category_type=components_pb2.ComponentCategoryMetadataVariant( + category=ec_pb2.ELECTRICAL_COMPONENT_CATEGORY_BATTERY, + category_specific_info=ec_pb2.ElectricalComponentCategorySpecificInfo( # Mismatched: battery category with inverter metadata - inverter=inverter_pb2.Inverter( - type=inverter_pb2.InverterType.INVERTER_TYPE_SOLAR - ) + inverter=ec_pb2.Inverter(type=ec_pb2.InverterType.INVERTER_TYPE_PV) ), ), ] @@ -311,7 +302,7 @@ def assert_client_result(result: Any) -> None: microgrid_id=MicrogridId(0), category=ComponentCategory.BATTERY, category_specific_metadata={ - "type": "INVERTER_TYPE_SOLAR", + "type": "INVERTER_TYPE_PV", }, ), ] diff --git a/tests/client_test_cases/list_components/empty_case.py b/tests/client_test_cases/list_components/empty_case.py index a5bfe70..688eeae 100644 --- a/tests/client_test_cases/list_components/empty_case.py +++ b/tests/client_test_cases/list_components/empty_case.py @@ -5,7 +5,7 @@ from typing import Any -from frequenz.api.microgrid.v1 import microgrid_pb2 +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2 # No client_args or client_kwargs needed for this call @@ -13,12 +13,14 @@ def assert_stub_method_call(stub_method: Any) -> None: """Assert that the gRPC request matches the expected request.""" stub_method.assert_called_once_with( - microgrid_pb2.ListComponentsRequest(component_ids=[], categories=[]), + microgrid_pb2.ListElectricalComponentsRequest( + electrical_component_ids=[], electrical_component_categories=[] + ), timeout=60.0, ) -grpc_response = microgrid_pb2.ListComponentsResponse(components=[]) +grpc_response = microgrid_pb2.ListElectricalComponentsResponse(electrical_components=[]) def assert_client_result(result: Any) -> None: # noqa: D103 diff --git a/tests/client_test_cases/list_components/error_case.py b/tests/client_test_cases/list_components/error_case.py index b1b28f0..a3833aa 100644 --- a/tests/client_test_cases/list_components/error_case.py +++ b/tests/client_test_cases/list_components/error_case.py @@ -5,7 +5,7 @@ from typing import Any -from frequenz.api.microgrid.v1 import microgrid_pb2 +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2 from grpc import StatusCode from frequenz.client.microgrid import PermissionDenied @@ -17,7 +17,9 @@ def assert_stub_method_call(stub_method: Any) -> None: """Assert that the gRPC request matches the expected request.""" stub_method.assert_called_once_with( - microgrid_pb2.ListComponentsRequest(component_ids=[], categories=[]), + microgrid_pb2.ListElectricalComponentsRequest( + electrical_component_ids=[], electrical_component_categories=[] + ), timeout=60.0, ) diff --git a/tests/client_test_cases/list_components/filter_by_categories_case.py b/tests/client_test_cases/list_components/filter_by_categories_case.py index f30a412..71b54c0 100644 --- a/tests/client_test_cases/list_components/filter_by_categories_case.py +++ b/tests/client_test_cases/list_components/filter_by_categories_case.py @@ -3,14 +3,12 @@ """Test list_components with category filtering.""" -from typing import Any +from typing import Any, TypeAlias -from frequenz.api.common.v1.microgrid.components import ( - battery_pb2, - components_pb2, - inverter_pb2, +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, ) -from frequenz.api.microgrid.v1 import microgrid_pb2 +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2 from frequenz.client.common.microgrid import MicrogridId from frequenz.client.common.microgrid.components import ComponentId @@ -22,38 +20,42 @@ client_kwargs = {"categories": [ComponentCategory.BATTERY, ComponentCategory.INVERTER]} +_CategorySpecificInfo: TypeAlias = ( + electrical_components_pb2.ElectricalComponentCategorySpecificInfo +) + def assert_stub_method_call(stub_method: Any) -> None: """Assert that the gRPC request matches the expected request.""" stub_method.assert_called_once_with( - microgrid_pb2.ListComponentsRequest( - component_ids=[], - categories=[ - components_pb2.ComponentCategory.COMPONENT_CATEGORY_BATTERY, - components_pb2.ComponentCategory.COMPONENT_CATEGORY_INVERTER, + microgrid_pb2.ListElectricalComponentsRequest( + electrical_component_ids=[], + electrical_component_categories=[ + electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_BATTERY, + electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_INVERTER, ], ), timeout=60.0, ) -grpc_response = microgrid_pb2.ListComponentsResponse( - components=[ - components_pb2.Component( +grpc_response = microgrid_pb2.ListElectricalComponentsResponse( + electrical_components=[ + electrical_components_pb2.ElectricalComponent( id=2, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_INVERTER, - category_type=components_pb2.ComponentCategoryMetadataVariant( - inverter=inverter_pb2.Inverter( - type=inverter_pb2.InverterType.INVERTER_TYPE_SOLAR + category=electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_INVERTER, + category_specific_info=_CategorySpecificInfo( + inverter=electrical_components_pb2.Inverter( + type=electrical_components_pb2.INVERTER_TYPE_PV ) ), ), - components_pb2.Component( + electrical_components_pb2.ElectricalComponent( id=3, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_BATTERY, - category_type=components_pb2.ComponentCategoryMetadataVariant( - battery=battery_pb2.Battery( - type=battery_pb2.BatteryType.BATTERY_TYPE_LI_ION + category=electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_BATTERY, + category_specific_info=_CategorySpecificInfo( + battery=electrical_components_pb2.Battery( + type=electrical_components_pb2.BATTERY_TYPE_LI_ION ) ), ), diff --git a/tests/client_test_cases/list_components/filter_by_component_ids_case.py b/tests/client_test_cases/list_components/filter_by_component_ids_case.py index d0a3f19..9b301ec 100644 --- a/tests/client_test_cases/list_components/filter_by_component_ids_case.py +++ b/tests/client_test_cases/list_components/filter_by_component_ids_case.py @@ -3,14 +3,12 @@ """Test list_components with component ID filtering.""" -from typing import Any +from typing import Any, TypeAlias -from frequenz.api.common.v1.microgrid.components import ( - battery_pb2, - components_pb2, - grid_pb2, +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, ) -from frequenz.api.microgrid.v1 import microgrid_pb2 +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2 from frequenz.client.common.microgrid import MicrogridId from frequenz.client.common.microgrid.components import ComponentId @@ -19,30 +17,39 @@ client_kwargs = {"components": [ComponentId(1), ComponentId(3)]} +_CategorySpecificInfo: TypeAlias = ( + electrical_components_pb2.ElectricalComponentCategorySpecificInfo +) + + def assert_stub_method_call(stub_method: Any) -> None: """Assert that the gRPC request matches the expected request.""" stub_method.assert_called_once_with( - microgrid_pb2.ListComponentsRequest(component_ids=[1, 3], categories=[]), + microgrid_pb2.ListElectricalComponentsRequest( + electrical_component_ids=[1, 3], electrical_component_categories=[] + ), timeout=60.0, ) -grpc_response = microgrid_pb2.ListComponentsResponse( - components=[ - components_pb2.Component( +grpc_response = microgrid_pb2.ListElectricalComponentsResponse( + electrical_components=[ + electrical_components_pb2.ElectricalComponent( id=1, microgrid_id=1, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_GRID, - category_type=components_pb2.ComponentCategoryMetadataVariant( - grid=grid_pb2.GridConnectionPoint(rated_fuse_current=10_000) + category=electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_GRID_CONNECTION_POINT, + category_specific_info=_CategorySpecificInfo( + grid_connection_point=electrical_components_pb2.GridConnectionPoint( + rated_fuse_current=10_000 + ) ), ), - components_pb2.Component( + electrical_components_pb2.ElectricalComponent( id=3, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_BATTERY, - category_type=components_pb2.ComponentCategoryMetadataVariant( - battery=battery_pb2.Battery( - type=battery_pb2.BatteryType.BATTERY_TYPE_LI_ION + category=electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_BATTERY, + category_specific_info=_CategorySpecificInfo( + battery=electrical_components_pb2.Battery( + type=electrical_components_pb2.BatteryType.BATTERY_TYPE_LI_ION ) ), ), diff --git a/tests/client_test_cases/list_components/filter_by_component_objects_case.py b/tests/client_test_cases/list_components/filter_by_component_objects_case.py index 0209fe8..62b8894 100644 --- a/tests/client_test_cases/list_components/filter_by_component_objects_case.py +++ b/tests/client_test_cases/list_components/filter_by_component_objects_case.py @@ -3,14 +3,12 @@ """Test list_components with Component objects as filters.""" -from typing import Any +from typing import Any, TypeAlias -from frequenz.api.common.v1.microgrid.components import ( - battery_pb2, - components_pb2, - grid_pb2, +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, ) -from frequenz.api.microgrid.v1 import microgrid_pb2 +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2 from frequenz.client.common.microgrid import MicrogridId from frequenz.client.common.microgrid.components import ComponentId @@ -23,34 +21,40 @@ client_kwargs = {"components": [grid_component, battery_component]} +_CategorySpecificInfo: TypeAlias = ( + electrical_components_pb2.ElectricalComponentCategorySpecificInfo +) + def assert_stub_method_call(stub_method: Any) -> None: """Assert that the gRPC request matches the expected request.""" stub_method.assert_called_once_with( - microgrid_pb2.ListComponentsRequest(component_ids=[1, 3], categories=[]), + microgrid_pb2.ListElectricalComponentsRequest( + electrical_component_ids=[1, 3], electrical_component_categories=[] + ), timeout=60.0, ) -grpc_response = microgrid_pb2.ListComponentsResponse( - components=[ - components_pb2.Component( +grpc_response = microgrid_pb2.ListElectricalComponentsResponse( + electrical_components=[ + electrical_components_pb2.ElectricalComponent( id=int(grid_component.id), microgrid_id=int(grid_component.microgrid_id), - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_GRID, - category_type=components_pb2.ComponentCategoryMetadataVariant( - grid=grid_pb2.GridConnectionPoint( + category=electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_GRID_CONNECTION_POINT, + category_specific_info=_CategorySpecificInfo( + grid_connection_point=electrical_components_pb2.GridConnectionPoint( rated_fuse_current=grid_component.rated_fuse_current ) ), ), - components_pb2.Component( + electrical_components_pb2.ElectricalComponent( id=int(battery_component.id), microgrid_id=int(battery_component.microgrid_id), - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_BATTERY, - category_type=components_pb2.ComponentCategoryMetadataVariant( - battery=battery_pb2.Battery( - type=battery_pb2.BatteryType.BATTERY_TYPE_LI_ION + category=electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_BATTERY, + category_specific_info=_CategorySpecificInfo( + battery=electrical_components_pb2.Battery( + type=electrical_components_pb2.BatteryType.BATTERY_TYPE_LI_ION ) ), ), diff --git a/tests/client_test_cases/list_components/filter_by_integer_category_case.py b/tests/client_test_cases/list_components/filter_by_integer_category_case.py index 2b95ccd..cb1e3e3 100644 --- a/tests/client_test_cases/list_components/filter_by_integer_category_case.py +++ b/tests/client_test_cases/list_components/filter_by_integer_category_case.py @@ -5,8 +5,10 @@ from typing import Any -from frequenz.api.common.v1.microgrid.components import components_pb2 -from frequenz.api.microgrid.v1 import microgrid_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2 from frequenz.client.common.microgrid import MicrogridId from frequenz.client.common.microgrid.components import ComponentId @@ -18,17 +20,17 @@ def assert_stub_method_call(stub_method: Any) -> None: """Assert that the gRPC request matches the expected request.""" stub_method.assert_called_once_with( - microgrid_pb2.ListComponentsRequest( - component_ids=[], - categories=[999], # type: ignore[list-item] + microgrid_pb2.ListElectricalComponentsRequest( + electrical_component_ids=[], + electrical_component_categories=[999], # type: ignore[list-item] ), timeout=60.0, ) -grpc_response = microgrid_pb2.ListComponentsResponse( - components=[ - components_pb2.Component( +grpc_response = microgrid_pb2.ListElectricalComponentsResponse( + electrical_components=[ + electrical_components_pb2.ElectricalComponent( id=4, microgrid_id=1, category=999, # type: ignore[arg-type] diff --git a/tests/client_test_cases/list_components/filter_combined_case.py b/tests/client_test_cases/list_components/filter_combined_case.py index 908d01d..f74049c 100644 --- a/tests/client_test_cases/list_components/filter_combined_case.py +++ b/tests/client_test_cases/list_components/filter_combined_case.py @@ -3,10 +3,12 @@ """Test list_components with combined component ID and category filtering.""" -from typing import Any +from typing import Any, TypeAlias -from frequenz.api.common.v1.microgrid.components import battery_pb2, components_pb2 -from frequenz.api.microgrid.v1 import microgrid_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2 from frequenz.client.common.microgrid import MicrogridId from frequenz.client.common.microgrid.components import ComponentId @@ -20,13 +22,18 @@ } +_CategorySpecificInfo: TypeAlias = ( + electrical_components_pb2.ElectricalComponentCategorySpecificInfo +) + + def assert_stub_method_call(stub_method: Any) -> None: """Assert that the gRPC request matches the expected request.""" stub_method.assert_called_once_with( - microgrid_pb2.ListComponentsRequest( - component_ids=[3, 5], - categories=[ - components_pb2.ComponentCategory.COMPONENT_CATEGORY_BATTERY, + microgrid_pb2.ListElectricalComponentsRequest( + electrical_component_ids=[3, 5], + electrical_component_categories=[ + electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_BATTERY, 999, # type: ignore[list-item] ], ), @@ -34,14 +41,14 @@ def assert_stub_method_call(stub_method: Any) -> None: ) -grpc_response = microgrid_pb2.ListComponentsResponse( - components=[ - components_pb2.Component( +grpc_response = microgrid_pb2.ListElectricalComponentsResponse( + electrical_components=[ + electrical_components_pb2.ElectricalComponent( id=3, - category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_BATTERY, - category_type=components_pb2.ComponentCategoryMetadataVariant( - battery=battery_pb2.Battery( - type=battery_pb2.BatteryType.BATTERY_TYPE_LI_ION + category=electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_BATTERY, + category_specific_info=_CategorySpecificInfo( + battery=electrical_components_pb2.Battery( + type=electrical_components_pb2.BATTERY_TYPE_LI_ION ) ), ), diff --git a/tests/client_test_cases/list_connections/empty_case.py b/tests/client_test_cases/list_connections/empty_case.py index ad36194..22a65a6 100644 --- a/tests/client_test_cases/list_connections/empty_case.py +++ b/tests/client_test_cases/list_connections/empty_case.py @@ -5,7 +5,7 @@ from typing import Any -from frequenz.api.microgrid.v1 import microgrid_pb2 +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2 # No client_args or client_kwargs needed for this call @@ -13,11 +13,16 @@ def assert_stub_method_call(stub_method: Any) -> None: """Assert that the gRPC request matches the expected request.""" stub_method.assert_called_once_with( - microgrid_pb2.ListConnectionsRequest(starts=[], ends=[]), timeout=60.0 + microgrid_pb2.ListElectricalComponentConnectionsRequest( + source_electrical_component_ids=[], destination_electrical_component_ids=[] + ), + timeout=60.0, ) -grpc_response = microgrid_pb2.ListConnectionsResponse(connections=[]) +grpc_response = microgrid_pb2.ListElectricalComponentConnectionsResponse( + electrical_component_connections=[] +) def assert_client_result(result: Any) -> None: # noqa: D103 diff --git a/tests/client_test_cases/list_connections/error_case.py b/tests/client_test_cases/list_connections/error_case.py index 6091bc6..5ef6724 100644 --- a/tests/client_test_cases/list_connections/error_case.py +++ b/tests/client_test_cases/list_connections/error_case.py @@ -5,7 +5,7 @@ from typing import Any -from frequenz.api.microgrid.v1 import microgrid_pb2 +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2 from grpc import StatusCode from frequenz.client.microgrid import PermissionDenied @@ -17,7 +17,8 @@ def assert_stub_method_call(stub_method: Any) -> None: """Assert that the gRPC request matches the expected request.""" stub_method.assert_called_once_with( - microgrid_pb2.ListConnectionsRequest(starts=[], ends=[]), timeout=60.0 + microgrid_pb2.ListElectricalComponentConnectionsRequest(), + timeout=60.0, ) diff --git a/tests/client_test_cases/list_connections/mixed_filters_case.py b/tests/client_test_cases/list_connections/mixed_filters_case.py index 56afa09..e11e86d 100644 --- a/tests/client_test_cases/list_connections/mixed_filters_case.py +++ b/tests/client_test_cases/list_connections/mixed_filters_case.py @@ -6,14 +6,11 @@ from datetime import datetime, timezone from typing import Any -from frequenz.api.microgrid.v1 import microgrid_pb2 +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2 from frequenz.client.common.microgrid import MicrogridId from frequenz.client.common.microgrid.components import ComponentId -from frequenz.client.microgrid.component import ( - GridConnectionPoint, - Meter, -) +from frequenz.client.microgrid.component import GridConnectionPoint, Meter # Mix ComponentId and Component objects grid_component = GridConnectionPoint( @@ -30,14 +27,20 @@ def assert_stub_method_call(stub_method: Any) -> None: """Assert that the gRPC request matches the expected request.""" stub_method.assert_called_once_with( - microgrid_pb2.ListConnectionsRequest(starts=[1, 2], ends=[3, 4]), timeout=60.0 + microgrid_pb2.ListElectricalComponentConnectionsRequest( + source_electrical_component_ids=[1, 2], + destination_electrical_component_ids=[3, 4], + ), + timeout=60.0, ) lifetime_start = datetime(2023, 1, 1, 0, 0, 0, tzinfo=timezone.utc) -grpc_response = microgrid_pb2.ListConnectionsResponse(connections=[]) +grpc_response = microgrid_pb2.ListElectricalComponentConnectionsResponse( + electrical_component_connections=[] +) def assert_client_result(actual_result: Any) -> None: """Assert that the client result matches the expected connections list.""" - assert list(actual_result) == [] + assert not list(actual_result) diff --git a/tests/client_test_cases/list_connections/success_case.py b/tests/client_test_cases/list_connections/success_case.py index 9013373..b532d41 100644 --- a/tests/client_test_cases/list_connections/success_case.py +++ b/tests/client_test_cases/list_connections/success_case.py @@ -6,9 +6,11 @@ from datetime import datetime, timezone from typing import Any -from frequenz.api.common.v1.microgrid import lifetime_pb2 -from frequenz.api.common.v1.microgrid.components import components_pb2 -from frequenz.api.microgrid.v1 import microgrid_pb2 +from frequenz.api.common.v1alpha8.microgrid import lifetime_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2 from frequenz.client.base.conversion import to_timestamp from frequenz.client.common.microgrid.components import ComponentId @@ -21,19 +23,22 @@ def assert_stub_method_call(stub_method: Any) -> None: """Assert that the gRPC request matches the expected request.""" stub_method.assert_called_once_with( - microgrid_pb2.ListConnectionsRequest(starts=[], ends=[]), timeout=60.0 + microgrid_pb2.ListElectricalComponentConnectionsRequest( + source_electrical_component_ids=[], destination_electrical_component_ids=[] + ), + timeout=60.0, ) lifetime_start = datetime(2023, 1, 1, 0, 0, 0, tzinfo=timezone.utc) -grpc_response = microgrid_pb2.ListConnectionsResponse( - connections=[ - components_pb2.ComponentConnection( - source_component_id=1, destination_component_id=2 +grpc_response = microgrid_pb2.ListElectricalComponentConnectionsResponse( + electrical_component_connections=[ + electrical_components_pb2.ElectricalComponentConnection( + source_electrical_component_id=1, destination_electrical_component_id=2 ), - components_pb2.ComponentConnection( - source_component_id=2, - destination_component_id=3, + electrical_components_pb2.ElectricalComponentConnection( + source_electrical_component_id=2, + destination_electrical_component_id=3, operational_lifetime=lifetime_pb2.Lifetime( start_timestamp=to_timestamp(lifetime_start) ), diff --git a/tests/client_test_cases/receive_component_data_samples_stream/empty_case.py b/tests/client_test_cases/receive_component_data_samples_stream/empty_case.py index e5341ca..d614a81 100644 --- a/tests/client_test_cases/receive_component_data_samples_stream/empty_case.py +++ b/tests/client_test_cases/receive_component_data_samples_stream/empty_case.py @@ -3,36 +3,42 @@ """Test data for empty component data stream.""" -from typing import Any +from typing import Any, TypeAlias import pytest -from frequenz.api.common.v1.metrics import metric_sample_pb2 -from frequenz.api.common.v1.microgrid.components import components_pb2 -from frequenz.api.microgrid.v1 import microgrid_pb2 +from frequenz.api.common.v1alpha8.metrics import metrics_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2 from frequenz.channels import Receiver, ReceiverStoppedError from frequenz.client.common.microgrid.components import ComponentId from frequenz.client.microgrid.component import ComponentDataSamples -client_args = (ComponentId(1), [metric_sample_pb2.Metric.METRIC_AC_CURRENT]) +client_args = (ComponentId(1), [metrics_pb2.Metric.METRIC_AC_CURRENT]) + +_Filter: TypeAlias = ( + microgrid_pb2.ReceiveElectricalComponentTelemetryStreamRequest.ComponentTelemetryStreamFilter +) def assert_stub_method_call(stub_method: Any) -> None: """Assert that the gRPC request matches the expected request.""" stub_method.assert_called_once_with( - microgrid_pb2.ReceiveComponentDataStreamRequest( - component_id=1, - filter=microgrid_pb2.ReceiveComponentDataStreamRequest.ComponentDataStreamFilter( - metrics=[metric_sample_pb2.Metric.METRIC_AC_CURRENT] - ), + microgrid_pb2.ReceiveElectricalComponentTelemetryStreamRequest( + electrical_component_id=1, + filter=_Filter(metrics=[metrics_pb2.Metric.METRIC_AC_CURRENT]), ), timeout=60.0, ) # The mock response from the server -grpc_response = microgrid_pb2.ReceiveComponentDataStreamResponse( - data=components_pb2.ComponentData(component_id=1, metric_samples=[], states=[]), +grpc_response = microgrid_pb2.ReceiveElectricalComponentTelemetryStreamResponse( + telemetry=electrical_components_pb2.ElectricalComponentTelemetry( + electrical_component_id=1, metric_samples=[], state_snapshots=[] + ), ) diff --git a/tests/client_test_cases/receive_component_data_samples_stream/error_case.py b/tests/client_test_cases/receive_component_data_samples_stream/error_case.py index d0a7e44..4f59cbe 100644 --- a/tests/client_test_cases/receive_component_data_samples_stream/error_case.py +++ b/tests/client_test_cases/receive_component_data_samples_stream/error_case.py @@ -5,12 +5,14 @@ import enum from collections.abc import AsyncIterator -from typing import Any +from typing import Any, TypeAlias import pytest -from frequenz.api.common.v1.metrics import metric_sample_pb2 -from frequenz.api.common.v1.microgrid.components import components_pb2 -from frequenz.api.microgrid.v1 import microgrid_pb2 +from frequenz.api.common.v1alpha8.metrics import metrics_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2 from frequenz.channels import Receiver, ReceiverStoppedError from frequenz.client.common.microgrid.components import ComponentId from grpc import StatusCode @@ -18,17 +20,19 @@ from frequenz.client.microgrid.component import ComponentDataSamples from tests.util import make_grpc_error -client_args = (ComponentId(1), [metric_sample_pb2.Metric.METRIC_DC_VOLTAGE]) +client_args = (ComponentId(1), [metrics_pb2.Metric.METRIC_DC_VOLTAGE]) + +_Filter: TypeAlias = ( + microgrid_pb2.ReceiveElectricalComponentTelemetryStreamRequest.ComponentTelemetryStreamFilter +) def assert_stub_method_call(stub_method: Any) -> None: """Assert that the gRPC request matches the expected request.""" stub_method.assert_called_once_with( - microgrid_pb2.ReceiveComponentDataStreamRequest( - component_id=1, - filter=microgrid_pb2.ReceiveComponentDataStreamRequest.ComponentDataStreamFilter( - metrics=[metric_sample_pb2.Metric.METRIC_DC_VOLTAGE] - ), + microgrid_pb2.ReceiveElectricalComponentTelemetryStreamRequest( + electrical_component_id=1, + filter=_Filter(metrics=[metrics_pb2.Metric.METRIC_DC_VOLTAGE]), ), timeout=60.0, ) @@ -43,7 +47,7 @@ class _State(enum.Enum): RECEIVING = "receiving" -_iterations = 0 +_iterations: int = 0 _state: _State = _State.INITIAL @@ -58,9 +62,9 @@ async def grpc_response() -> AsyncIterator[Any]: _state = _State.RECEIVING for _ in range(3): - yield microgrid_pb2.ReceiveComponentDataStreamResponse( - data=components_pb2.ComponentData( - component_id=1, metric_samples=[], states=[] + yield microgrid_pb2.ReceiveElectricalComponentTelemetryStreamResponse( + telemetry=electrical_components_pb2.ElectricalComponentTelemetry( + electrical_component_id=1, metric_samples=[], state_snapshots=[] ), ) diff --git a/tests/client_test_cases/receive_component_data_samples_stream/many_case.py b/tests/client_test_cases/receive_component_data_samples_stream/many_case.py index f5eae1b..e178ef7 100644 --- a/tests/client_test_cases/receive_component_data_samples_stream/many_case.py +++ b/tests/client_test_cases/receive_component_data_samples_stream/many_case.py @@ -4,12 +4,14 @@ """Test data for successful component data stream.""" from datetime import datetime, timezone -from typing import Any +from typing import Any, TypeAlias import pytest -from frequenz.api.common.v1.metrics import metric_sample_pb2 -from frequenz.api.common.v1.microgrid.components import components_pb2 -from frequenz.api.microgrid.v1 import microgrid_pb2 +from frequenz.api.common.v1alpha8.metrics import metrics_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2 from frequenz.channels import Receiver, ReceiverStoppedError from frequenz.client.base.conversion import to_timestamp from frequenz.client.common.microgrid.components import ComponentId @@ -21,21 +23,25 @@ client_args = ( ComponentId(1), [ - metric_sample_pb2.Metric.METRIC_DC_VOLTAGE, - metric_sample_pb2.Metric.METRIC_DC_CURRENT, + metrics_pb2.Metric.METRIC_DC_VOLTAGE, + metrics_pb2.Metric.METRIC_DC_CURRENT, ], ) +_Filter: TypeAlias = ( + microgrid_pb2.ReceiveElectricalComponentTelemetryStreamRequest.ComponentTelemetryStreamFilter +) + def assert_stub_method_call(stub_method: Any) -> None: """Assert that the gRPC request matches the expected request.""" stub_method.assert_called_once_with( - microgrid_pb2.ReceiveComponentDataStreamRequest( - component_id=1, - filter=microgrid_pb2.ReceiveComponentDataStreamRequest.ComponentDataStreamFilter( + microgrid_pb2.ReceiveElectricalComponentTelemetryStreamRequest( + electrical_component_id=1, + filter=_Filter( metrics=[ - metric_sample_pb2.Metric.METRIC_DC_VOLTAGE, - metric_sample_pb2.Metric.METRIC_DC_CURRENT, + metrics_pb2.Metric.METRIC_DC_VOLTAGE, + metrics_pb2.Metric.METRIC_DC_CURRENT, ] ), ), @@ -46,22 +52,22 @@ def assert_stub_method_call(stub_method: Any) -> None: timestamp = datetime(2023, 10, 1, 12, 0, 0, tzinfo=timezone.utc) timestamp_proto = to_timestamp(timestamp) grpc_response = [ - microgrid_pb2.ReceiveComponentDataStreamResponse( - data=components_pb2.ComponentData( - component_id=1, + microgrid_pb2.ReceiveElectricalComponentTelemetryStreamResponse( + telemetry=electrical_components_pb2.ElectricalComponentTelemetry( + electrical_component_id=1, metric_samples=[ - metric_sample_pb2.MetricSample( - metric=metric_sample_pb2.Metric.METRIC_DC_VOLTAGE, - sampled_at=timestamp_proto, - value=metric_sample_pb2.MetricValueVariant( - simple_metric=metric_sample_pb2.SimpleMetricValue(value=230.5), + metrics_pb2.MetricSample( + metric=metrics_pb2.Metric.METRIC_DC_VOLTAGE, + sample_time=timestamp_proto, + value=metrics_pb2.MetricValueVariant( + simple_metric=metrics_pb2.SimpleMetricValue(value=230.5), ), ), - metric_sample_pb2.MetricSample( - metric=metric_sample_pb2.Metric.METRIC_DC_CURRENT, - sampled_at=timestamp_proto, - value=metric_sample_pb2.MetricValueVariant( - aggregated_metric=metric_sample_pb2.AggregatedMetricValue( + metrics_pb2.MetricSample( + metric=metrics_pb2.Metric.METRIC_DC_CURRENT, + sample_time=timestamp_proto, + value=metrics_pb2.MetricValueVariant( + aggregated_metric=metrics_pb2.AggregatedMetricValue( min_value=10.0, max_value=10.5, avg_value=10.2, @@ -70,25 +76,25 @@ def assert_stub_method_call(stub_method: Any) -> None: ), ), ], - states=[], + state_snapshots=[], ), ), - microgrid_pb2.ReceiveComponentDataStreamResponse( - data=components_pb2.ComponentData( - component_id=1, + microgrid_pb2.ReceiveElectricalComponentTelemetryStreamResponse( + telemetry=electrical_components_pb2.ElectricalComponentTelemetry( + electrical_component_id=1, metric_samples=[ - metric_sample_pb2.MetricSample( - metric=metric_sample_pb2.Metric.METRIC_DC_VOLTAGE, - sampled_at=timestamp_proto, - value=metric_sample_pb2.MetricValueVariant( - simple_metric=metric_sample_pb2.SimpleMetricValue(value=231.5), + metrics_pb2.MetricSample( + metric=metrics_pb2.Metric.METRIC_DC_VOLTAGE, + sample_time=timestamp_proto, + value=metrics_pb2.MetricValueVariant( + simple_metric=metrics_pb2.SimpleMetricValue(value=231.5), ), ), - metric_sample_pb2.MetricSample( - metric=metric_sample_pb2.Metric.METRIC_DC_CURRENT, - sampled_at=timestamp_proto, - value=metric_sample_pb2.MetricValueVariant( - aggregated_metric=metric_sample_pb2.AggregatedMetricValue( + metrics_pb2.MetricSample( + metric=metrics_pb2.Metric.METRIC_DC_CURRENT, + sample_time=timestamp_proto, + value=metrics_pb2.MetricValueVariant( + aggregated_metric=metrics_pb2.AggregatedMetricValue( min_value=12.0, max_value=12.5, avg_value=12.2, @@ -97,7 +103,7 @@ def assert_stub_method_call(stub_method: Any) -> None: ), ), ], - states=[], + state_snapshots=[], ), ), ] diff --git a/tests/client_test_cases/set_component_power_active/_config.py b/tests/client_test_cases/set_component_power_active/_config.py index 8584ad4..f58fb1d 100644 --- a/tests/client_test_cases/set_component_power_active/_config.py +++ b/tests/client_test_cases/set_component_power_active/_config.py @@ -4,6 +4,6 @@ """Configuration for `SetComponentPowerActive` test cases.""" -from frequenz.api.microgrid.v1 import microgrid_pb2 +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2 -RESPONSE_CLASS = microgrid_pb2.SetComponentPowerActiveResponse +RESPONSE_CLASS = microgrid_pb2.SetElectricalComponentPowerResponse diff --git a/tests/client_test_cases/set_component_power_active/invalid_power_no_validate_case.py b/tests/client_test_cases/set_component_power_active/invalid_power_no_validate_case.py index 7bd473b..32cd963 100644 --- a/tests/client_test_cases/set_component_power_active/invalid_power_no_validate_case.py +++ b/tests/client_test_cases/set_component_power_active/invalid_power_no_validate_case.py @@ -26,7 +26,7 @@ def assert_stub_method_call(stub_method: Any) -> None: # and then check the arguments manually stub_method.assert_called_once() request = stub_method.call_args[0][0] - assert request.component_id == 1 + assert request.electrical_component_id == 1 assert math.isnan(request.power) assert request.request_lifetime == 60 assert stub_method.call_args[1]["timeout"] == 60.0 diff --git a/tests/client_test_cases/set_component_power_active/no_lifetime_case.py b/tests/client_test_cases/set_component_power_active/no_lifetime_case.py index 8185583..a89e3cd 100644 --- a/tests/client_test_cases/set_component_power_active/no_lifetime_case.py +++ b/tests/client_test_cases/set_component_power_active/no_lifetime_case.py @@ -21,7 +21,7 @@ def assert_stub_method_call(stub_method: Any) -> None: """Assert that the gRPC request matches the expected request.""" stub_method.assert_called_once() request = stub_method.call_args[0][0] - assert request.component_id == 1 + assert request.electrical_component_id == 1 assert request.power == pytest.approx(1000.0) assert stub_method.call_args[1]["timeout"] == 60.0 diff --git a/tests/client_test_cases/set_component_power_active/success_case.py b/tests/client_test_cases/set_component_power_active/success_case.py index e24d0f8..7f86ca8 100644 --- a/tests/client_test_cases/set_component_power_active/success_case.py +++ b/tests/client_test_cases/set_component_power_active/success_case.py @@ -21,14 +21,14 @@ def assert_stub_method_call(stub_method: Any) -> None: """Assert that the gRPC request matches the expected request.""" stub_method.assert_called_once() request = stub_method.call_args[0][0] - assert request.component_id == 1 + assert request.electrical_component_id == 1 assert request.power == pytest.approx(1000.0) assert request.request_lifetime == pytest.approx(60.0 * 9.0) assert stub_method.call_args[1]["timeout"] == 60.0 expiry_time = datetime(2023, 1, 1, 12, 0, 0, tzinfo=timezone.utc) -grpc_response = RESPONSE_CLASS(valid_until=conversion.to_timestamp(expiry_time)) +grpc_response = RESPONSE_CLASS(valid_until_time=conversion.to_timestamp(expiry_time)) def assert_client_result(result: datetime) -> None: diff --git a/tests/client_test_cases/set_component_power_reactive/_config.py b/tests/client_test_cases/set_component_power_reactive/_config.py index cf80d63..3d6270b 100644 --- a/tests/client_test_cases/set_component_power_reactive/_config.py +++ b/tests/client_test_cases/set_component_power_reactive/_config.py @@ -4,6 +4,6 @@ """Configuration for `SetComponentPowerReactive` test cases.""" -from frequenz.api.microgrid.v1 import microgrid_pb2 +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2 -RESPONSE_CLASS = microgrid_pb2.SetComponentPowerReactiveResponse +RESPONSE_CLASS = microgrid_pb2.SetElectricalComponentPowerResponse diff --git a/tests/component/component_proto/conftest.py b/tests/component/component_proto/conftest.py index f8a68e0..f5b8471 100644 --- a/tests/component/component_proto/conftest.py +++ b/tests/component/component_proto/conftest.py @@ -6,9 +6,11 @@ from datetime import datetime, timezone import pytest -from frequenz.api.common.v1.metrics import bounds_pb2 -from frequenz.api.common.v1.microgrid import lifetime_pb2 -from frequenz.api.common.v1.microgrid.components import components_pb2 +from frequenz.api.common.v1alpha8.metrics import bounds_pb2 +from frequenz.api.common.v1alpha8.microgrid import lifetime_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) from frequenz.client.base.conversion import to_timestamp from frequenz.client.common.microgrid import MicrogridId from frequenz.client.common.microgrid.components import ComponentId @@ -56,7 +58,7 @@ def default_component_base_data( category=ComponentCategory.UNSPECIFIED, lifetime=DEFAULT_LIFETIME, rated_bounds={Metric.AC_ACTIVE_ENERGY: Bounds(lower=0, upper=100)}, - category_specific_metadata={}, + category_specific_info={}, category_mismatched=False, ) @@ -71,12 +73,14 @@ def assert_base_data(base_data: ComponentBaseData, other: Component) -> None: assert base_data.category == other.category assert base_data.lifetime == other.operational_lifetime assert base_data.rated_bounds == other.rated_bounds - assert base_data.category_specific_metadata == other.category_specific_metadata + assert base_data.category_specific_info == other.category_specific_metadata -def base_data_as_proto(base_data: ComponentBaseData) -> components_pb2.Component: +def base_data_as_proto( + base_data: ComponentBaseData, +) -> electrical_components_pb2.ElectricalComponent: """Convert this ComponentBaseData to a protobuf Component.""" - proto = components_pb2.Component( + proto = electrical_components_pb2.ElectricalComponent( id=int(base_data.component_id), microgrid_id=int(base_data.microgrid_id), name=base_data.name or "", @@ -104,7 +108,7 @@ def base_data_as_proto(base_data: ComponentBaseData) -> components_pb2.Component bounds_dict["upper"] = bounds.upper metric_value = metric.value if isinstance(metric, Metric) else metric proto.metric_config_bounds.append( - components_pb2.MetricConfigBounds( + electrical_components_pb2.MetricConfigBounds( metric=metric_value, # type: ignore[arg-type] config_bounds=bounds_pb2.Bounds(**bounds_dict), ) diff --git a/tests/component/component_proto/test_base.py b/tests/component/component_proto/test_base.py index 5fc0d4d..bfffdf1 100644 --- a/tests/component/component_proto/test_base.py +++ b/tests/component/component_proto/test_base.py @@ -4,7 +4,9 @@ """Tests for protobuf conversion of the base/common part of Component objects.""" -from frequenz.api.common.v1.microgrid.components import battery_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) from google.protobuf.timestamp_pb2 import Timestamp from frequenz.client.microgrid import Lifetime @@ -37,7 +39,7 @@ def test_complete(default_component_base_data: ComponentBaseData) -> None: def test_missing_category_specific_info( default_component_base_data: ComponentBaseData, ) -> None: - """Test parsing with missing optional metadata.""" + """Test parsing with missing optional category specific info.""" major_issues: list[str] = [] minor_issues: list[str] = [] base_data = default_component_base_data._replace( @@ -47,7 +49,7 @@ def test_missing_category_specific_info( category=ComponentCategory.UNSPECIFIED, lifetime=Lifetime(), rated_bounds={}, - category_specific_metadata={}, + category_specific_info={}, ) proto = base_data_as_proto(base_data) proto.ClearField("operational_lifetime") @@ -69,19 +71,21 @@ def test_missing_category_specific_info( assert parsed == base_data -def test_category_metadata_mismatch( +def test_category_specific_info_mismatch( default_component_base_data: ComponentBaseData, ) -> None: - """Test category and metadata mismatch.""" + """Test category and category specific info mismatch.""" major_issues: list[str] = [] minor_issues: list[str] = [] base_data = default_component_base_data._replace( - category=ComponentCategory.GRID, - category_specific_metadata={"type": "BATTERY_TYPE_LI_ION"}, + category=ComponentCategory.GRID_CONNECTION_POINT, + category_specific_info={"type": "BATTERY_TYPE_LI_ION"}, category_mismatched=True, ) proto = base_data_as_proto(base_data) - proto.category_type.battery.type = battery_pb2.BATTERY_TYPE_LI_ION + proto.category_specific_info.battery.type = ( + electrical_components_pb2.BATTERY_TYPE_LI_ION + ) parsed = component_base_from_proto_with_issues( proto, major_issues=major_issues, minor_issues=minor_issues diff --git a/tests/component/component_proto/test_simple.py b/tests/component/component_proto/test_simple.py index 9ff5bff..11bd6c9 100644 --- a/tests/component/component_proto/test_simple.py +++ b/tests/component/component_proto/test_simple.py @@ -8,7 +8,9 @@ from unittest.mock import Mock, patch import pytest -from frequenz.api.common.v1.microgrid.components import battery_pb2, components_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) from frequenz.client.microgrid.component import ( Chp, @@ -72,16 +74,18 @@ def test_unrecognized(default_component_base_data: ComponentBaseData) -> None: def test_category_mismatch(default_component_base_data: ComponentBaseData) -> None: - """Test MismatchedCategoryComponent for category GRID and battery metadata.""" + """Test MismatchedCategoryComponent for category GRID and battery specific info.""" major_issues: list[str] = [] minor_issues: list[str] = [] base_data = default_component_base_data._replace( - category=ComponentCategory.GRID, - category_specific_metadata={"type": "BATTERY_TYPE_LI_ION"}, + category=ComponentCategory.GRID_CONNECTION_POINT, + category_specific_info={"type": "BATTERY_TYPE_LI_ION"}, category_mismatched=True, ) proto = base_data_as_proto(base_data) - proto.category_type.battery.type = battery_pb2.BATTERY_TYPE_LI_ION + proto.category_specific_info.battery.type = ( + electrical_components_pb2.BATTERY_TYPE_LI_ION + ) component = component_from_proto_with_issues( proto, major_issues=major_issues, minor_issues=minor_issues @@ -92,7 +96,7 @@ def test_category_mismatch(default_component_base_data: ComponentBaseData) -> No assert not minor_issues assert isinstance(component, MismatchedCategoryComponent) assert_base_data(base_data, component) - assert component.category == ComponentCategory.GRID + assert component.category == ComponentCategory.GRID_CONNECTION_POINT @pytest.mark.parametrize( @@ -139,14 +143,14 @@ def test_voltage_transformer( major_issues: list[str] = [] minor_issues: list[str] = [] base_data = default_component_base_data._replace( - category=ComponentCategory.VOLTAGE_TRANSFORMER + category=ComponentCategory.POWER_TRANSFORMER ) proto = base_data_as_proto(base_data) if primary is not None: - proto.category_type.voltage_transformer.primary = primary + proto.category_specific_info.power_transformer.primary = primary if secondary is not None: - proto.category_type.voltage_transformer.secondary = secondary + proto.category_specific_info.power_transformer.secondary = secondary component = component_from_proto_with_issues( proto, major_issues=major_issues, minor_issues=minor_issues @@ -172,11 +176,15 @@ def test_grid( """Test GridConnectionPoint component with default values.""" major_issues: list[str] = [] minor_issues: list[str] = [] - base_data = default_component_base_data._replace(category=ComponentCategory.GRID) + base_data = default_component_base_data._replace( + category=ComponentCategory.GRID_CONNECTION_POINT + ) proto = base_data_as_proto(base_data) if rated_fuse_current is not None: - proto.category_type.grid.rated_fuse_current = rated_fuse_current + proto.category_specific_info.grid_connection_point.rated_fuse_current = ( + rated_fuse_current + ) component = component_from_proto_with_issues( proto, major_issues=major_issues, minor_issues=minor_issues @@ -205,7 +213,7 @@ def test_issues_logging( mock_component = Mock(name="component", spec=Component) def _fake_from_proto_with_issues( - _: components_pb2.Component, + _: electrical_components_pb2.ElectricalComponent, *, major_issues: list[str], minor_issues: list[str], @@ -217,7 +225,7 @@ def _fake_from_proto_with_issues( mock_from_proto_with_issues.side_effect = _fake_from_proto_with_issues - mock_proto = Mock(name="proto", spec=components_pb2.Component) + mock_proto = Mock(name="proto", spec=electrical_components_pb2.ElectricalComponent) component = component_from_proto(mock_proto) assert component is mock_component diff --git a/tests/component/component_proto/test_with_type.py b/tests/component/component_proto/test_with_type.py index 99640d5..f7ba810 100644 --- a/tests/component/component_proto/test_with_type.py +++ b/tests/component/component_proto/test_with_type.py @@ -4,10 +4,8 @@ """Tests for protobuf conversion of components with a type.""" import pytest -from frequenz.api.common.v1.microgrid.components import ( - battery_pb2, - ev_charger_pb2, - inverter_pb2, +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, ) from frequenz.client.microgrid.component import ( @@ -47,21 +45,21 @@ pytest.param( LiIonBattery, BatteryType.LI_ION, - battery_pb2.BATTERY_TYPE_LI_ION, + electrical_components_pb2.BATTERY_TYPE_LI_ION, [], id="LI_ION", ), pytest.param( NaIonBattery, BatteryType.NA_ION, - battery_pb2.BATTERY_TYPE_NA_ION, + electrical_components_pb2.BATTERY_TYPE_NA_ION, [], id="NA_ION", ), pytest.param( UnspecifiedBattery, BatteryType.UNSPECIFIED, - battery_pb2.BATTERY_TYPE_UNSPECIFIED, + electrical_components_pb2.BATTERY_TYPE_UNSPECIFIED, ["battery type is unspecified"], id="UNSPECIFIED", ), @@ -86,7 +84,7 @@ def test_battery( minor_issues: list[str] = [] base_data = default_component_base_data._replace(category=ComponentCategory.BATTERY) proto = base_data_as_proto(base_data) - proto.category_type.battery.type = pb_battery_type # type: ignore[assignment] + proto.category_specific_info.battery.type = pb_battery_type # type: ignore[assignment] component = component_from_proto_with_issues( proto, major_issues=major_issues, minor_issues=minor_issues @@ -105,28 +103,28 @@ def test_battery( pytest.param( AcEvCharger, EvChargerType.AC, - ev_charger_pb2.EV_CHARGER_TYPE_AC, + electrical_components_pb2.EV_CHARGER_TYPE_AC, [], id="AC", ), pytest.param( DcEvCharger, EvChargerType.DC, - ev_charger_pb2.EV_CHARGER_TYPE_DC, + electrical_components_pb2.EV_CHARGER_TYPE_DC, [], id="DC", ), pytest.param( HybridEvCharger, EvChargerType.HYBRID, - ev_charger_pb2.EV_CHARGER_TYPE_HYBRID, + electrical_components_pb2.EV_CHARGER_TYPE_HYBRID, [], id="HYBRID", ), pytest.param( UnspecifiedEvCharger, EvChargerType.UNSPECIFIED, - ev_charger_pb2.EV_CHARGER_TYPE_UNSPECIFIED, + electrical_components_pb2.EV_CHARGER_TYPE_UNSPECIFIED, ["ev_charger type is unspecified"], id="UNSPECIFIED", ), @@ -153,7 +151,7 @@ def test_ev_charger( category=ComponentCategory.EV_CHARGER ) proto = base_data_as_proto(base_data) - proto.category_type.ev_charger.type = pb_ev_charger_type # type: ignore[assignment] + proto.category_specific_info.ev_charger.type = pb_ev_charger_type # type: ignore[assignment] component = component_from_proto_with_issues( proto, major_issues=major_issues, minor_issues=minor_issues @@ -172,28 +170,28 @@ def test_ev_charger( pytest.param( BatteryInverter, InverterType.BATTERY, - inverter_pb2.INVERTER_TYPE_BATTERY, + electrical_components_pb2.INVERTER_TYPE_BATTERY, [], id="BATTERY", ), pytest.param( SolarInverter, InverterType.SOLAR, - inverter_pb2.INVERTER_TYPE_SOLAR, + electrical_components_pb2.INVERTER_TYPE_PV, [], id="SOLAR", ), pytest.param( HybridInverter, InverterType.HYBRID, - inverter_pb2.INVERTER_TYPE_HYBRID, + electrical_components_pb2.INVERTER_TYPE_HYBRID, [], id="HYBRID", ), pytest.param( UnspecifiedInverter, InverterType.UNSPECIFIED, - inverter_pb2.INVERTER_TYPE_UNSPECIFIED, + electrical_components_pb2.INVERTER_TYPE_UNSPECIFIED, ["inverter type is unspecified"], id="UNSPECIFIED", ), @@ -220,7 +218,7 @@ def test_inverter( category=ComponentCategory.INVERTER ) proto = base_data_as_proto(base_data) - proto.category_type.inverter.type = pb_inverter_type # type: ignore[assignment] + proto.category_specific_info.inverter.type = pb_inverter_type # type: ignore[assignment] component = component_from_proto_with_issues( proto, major_issues=major_issues, minor_issues=minor_issues diff --git a/tests/component/test_connection_proto.py b/tests/component/test_connection_proto.py index 90b7ef2..bad7eb6 100644 --- a/tests/component/test_connection_proto.py +++ b/tests/component/test_connection_proto.py @@ -9,8 +9,10 @@ from unittest.mock import Mock, patch import pytest -from frequenz.api.common.v1.microgrid import lifetime_pb2 -from frequenz.api.common.v1.microgrid.components import components_pb2 +from frequenz.api.common.v1alpha8.microgrid import lifetime_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) from frequenz.client.common.microgrid.components import ComponentId from google.protobuf import timestamp_pb2 @@ -26,8 +28,8 @@ [ pytest.param( { - "source_component_id": 1, - "destination_component_id": 2, + "source_electrical_component_id": 1, + "destination_electrical_component_id": 2, "has_lifetime": True, }, [], @@ -35,8 +37,8 @@ ), pytest.param( { - "source_component_id": 1, - "destination_component_id": 2, + "source_electrical_component_id": 1, + "destination_electrical_component_id": 2, "has_lifetime": False, }, ["missing operational lifetime, considering it always operational"], @@ -46,9 +48,11 @@ ) def test_success(proto_data: dict[str, Any], expected_minor_issues: list[str]) -> None: """Test successful conversion from protobuf message to ComponentConnection.""" - proto = components_pb2.ComponentConnection( - source_component_id=proto_data["source_component_id"], - destination_component_id=proto_data["destination_component_id"], + proto = electrical_components_pb2.ElectricalComponentConnection( + source_electrical_component_id=proto_data["source_electrical_component_id"], + destination_electrical_component_id=proto_data[ + "destination_electrical_component_id" + ], ) if proto_data["has_lifetime"]: @@ -70,14 +74,18 @@ def test_success(proto_data: dict[str, Any], expected_minor_issues: list[str]) - assert connection is not None assert not major_issues assert minor_issues == expected_minor_issues - assert connection.source == ComponentId(proto_data["source_component_id"]) - assert connection.destination == ComponentId(proto_data["destination_component_id"]) + assert connection.source == ComponentId( + proto_data["source_electrical_component_id"] + ) + assert connection.destination == ComponentId( + proto_data["destination_electrical_component_id"] + ) def test_error_same_ids() -> None: """Test proto conversion with same source and destination returns None.""" - proto = components_pb2.ComponentConnection( - source_component_id=1, destination_component_id=1 + proto = electrical_components_pb2.ElectricalComponentConnection( + source_electrical_component_id=1, destination_electrical_component_id=1 ) major_issues: list[str] = [] @@ -103,8 +111,8 @@ def test_invalid_lifetime(mock_lifetime_from_proto: Mock) -> None: """Test proto conversion with invalid lifetime data.""" mock_lifetime_from_proto.side_effect = ValueError("Invalid lifetime") - proto = components_pb2.ComponentConnection( - source_component_id=1, destination_component_id=2 + proto = electrical_components_pb2.ElectricalComponentConnection( + source_electrical_component_id=1, destination_electrical_component_id=2 ) now = datetime.now(timezone.utc) start_time = timestamp_pb2.Timestamp() @@ -143,7 +151,7 @@ def test_issues_logging( # mypy needs the explicit return def _fake_from_proto_with_issues( # pylint: disable=useless-return - _: components_pb2.ComponentConnection, + _: electrical_components_pb2.ElectricalComponentConnection, *, major_issues: list[str], minor_issues: list[str], @@ -155,7 +163,9 @@ def _fake_from_proto_with_issues( # pylint: disable=useless-return mock_from_proto_with_issues.side_effect = _fake_from_proto_with_issues - mock_proto = Mock(name="proto", spec=components_pb2.ComponentConnection) + mock_proto = Mock( + name="proto", spec=electrical_components_pb2.ElectricalComponentConnection + ) connection = component_connection_from_proto(mock_proto) assert connection is None diff --git a/tests/component/test_data_samples.py b/tests/component/test_data_samples.py index 052b89c..d6c4645 100644 --- a/tests/component/test_data_samples.py +++ b/tests/component/test_data_samples.py @@ -7,8 +7,10 @@ from datetime import datetime, timezone import pytest -from frequenz.api.common.v1.metrics import bounds_pb2, metric_sample_pb2 -from frequenz.api.common.v1.microgrid.components import components_pb2 +from frequenz.api.common.v1alpha8.metrics import bounds_pb2, metrics_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) from frequenz.client.common.microgrid.components import ComponentId from google.protobuf.timestamp_pb2 import Timestamp @@ -31,6 +33,12 @@ DATETIME = datetime(2025, 3, 1, 12, 0, 0, tzinfo=timezone.utc) TIMESTAMP = Timestamp(seconds=int(DATETIME.timestamp())) +# Some aliases to avoid max line length issues +HARDWARE_INACCESSIBLE = ( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_HARDWARE_INACCESSIBLE +) +OVERCURRENT = electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_OVERCURRENT + @pytest.fixture def component_id() -> ComponentId: @@ -134,7 +142,7 @@ class _ComponentDataSamplesConversionTestCase: name: str """The description of the test case.""" - message: components_pb2.ComponentData + message: electrical_components_pb2.ElectricalComponentTelemetry """The input protobuf message.""" expected_samples: ComponentDataSamples @@ -152,23 +160,23 @@ class _ComponentDataSamplesConversionTestCase: [ _ComponentDataSamplesConversionTestCase( name="empty", - message=components_pb2.ComponentData(component_id=1), + message=electrical_components_pb2.ElectricalComponentTelemetry( + electrical_component_id=1 + ), expected_samples=ComponentDataSamples( component_id=ComponentId(1), metric_samples=[], states=[] ), ), _ComponentDataSamplesConversionTestCase( name="metrics_only_valid", - message=components_pb2.ComponentData( - component_id=2, + message=electrical_components_pb2.ElectricalComponentTelemetry( + electrical_component_id=2, metric_samples=[ - metric_sample_pb2.MetricSample( - sampled_at=TIMESTAMP, + metrics_pb2.MetricSample( + sample_time=TIMESTAMP, metric=Metric.AC_ACTIVE_POWER.value, - value=metric_sample_pb2.MetricValueVariant( - simple_metric=metric_sample_pb2.SimpleMetricValue( - value=100.0 - ) + value=metrics_pb2.MetricValueVariant( + simple_metric=metrics_pb2.SimpleMetricValue(value=100.0) ), ) ], @@ -188,12 +196,14 @@ class _ComponentDataSamplesConversionTestCase: ), _ComponentDataSamplesConversionTestCase( name="states_only_valid", - message=components_pb2.ComponentData( - component_id=3, - states=[ - components_pb2.ComponentState( - sampled_at=TIMESTAMP, - states=[components_pb2.COMPONENT_STATE_CODE_READY], + message=electrical_components_pb2.ElectricalComponentTelemetry( + electrical_component_id=3, + state_snapshots=[ + electrical_components_pb2.ElectricalComponentStateSnapshot( + origin_time=TIMESTAMP, + states=[ + electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_READY + ], ) ], ), @@ -212,16 +222,14 @@ class _ComponentDataSamplesConversionTestCase: ), _ComponentDataSamplesConversionTestCase( name="metric_with_invalid_bounds", - message=components_pb2.ComponentData( - component_id=4, + message=electrical_components_pb2.ElectricalComponentTelemetry( + electrical_component_id=4, metric_samples=[ - metric_sample_pb2.MetricSample( - sampled_at=TIMESTAMP, + metrics_pb2.MetricSample( + sample_time=TIMESTAMP, metric=Metric.DC_CURRENT.value, - value=metric_sample_pb2.MetricValueVariant( - simple_metric=metric_sample_pb2.SimpleMetricValue( - value=50.0 - ) + value=metrics_pb2.MetricValueVariant( + simple_metric=metrics_pb2.SimpleMetricValue(value=50.0) ), bounds=[bounds_pb2.Bounds(lower=10.0, upper=5.0)], # Invalid ) @@ -246,19 +254,17 @@ class _ComponentDataSamplesConversionTestCase: ), _ComponentDataSamplesConversionTestCase( name="metric_with_valid_bounds_and_source", - message=components_pb2.ComponentData( - component_id=5, + message=electrical_components_pb2.ElectricalComponentTelemetry( + electrical_component_id=5, metric_samples=[ - metric_sample_pb2.MetricSample( - sampled_at=TIMESTAMP, + metrics_pb2.MetricSample( + sample_time=TIMESTAMP, metric=Metric.AC_FREQUENCY.value, - value=metric_sample_pb2.MetricValueVariant( - simple_metric=metric_sample_pb2.SimpleMetricValue( - value=50.0 - ) + value=metrics_pb2.MetricValueVariant( + simple_metric=metrics_pb2.SimpleMetricValue(value=50.0) ), bounds=[bounds_pb2.Bounds(lower=49.0, upper=51.0)], - source="sensor_A", + connection=metrics_pb2.MetricConnection(name="sensor_A"), ) ], ), @@ -278,23 +284,21 @@ class _ComponentDataSamplesConversionTestCase: ), _ComponentDataSamplesConversionTestCase( name="full_example_with_issues", - message=components_pb2.ComponentData( - component_id=6, + message=electrical_components_pb2.ElectricalComponentTelemetry( + electrical_component_id=6, metric_samples=[ - metric_sample_pb2.MetricSample( # Simple metric - sampled_at=TIMESTAMP, + metrics_pb2.MetricSample( # Simple metric + sample_time=TIMESTAMP, metric=Metric.AC_ACTIVE_POWER.value, - value=metric_sample_pb2.MetricValueVariant( - simple_metric=metric_sample_pb2.SimpleMetricValue( - value=150.0 - ) + value=metrics_pb2.MetricValueVariant( + simple_metric=metrics_pb2.SimpleMetricValue(value=150.0) ), ), - metric_sample_pb2.MetricSample( # Aggregated metric - sampled_at=TIMESTAMP, + metrics_pb2.MetricSample( # Aggregated metric + sample_time=TIMESTAMP, metric=Metric.AC_REACTIVE_POWER.value, - value=metric_sample_pb2.MetricValueVariant( - aggregated_metric=metric_sample_pb2.AggregatedMetricValue( + value=metrics_pb2.MetricValueVariant( + aggregated_metric=metrics_pb2.AggregatedMetricValue( avg_value=75.0, min_value=70.0, max_value=80.0, @@ -302,25 +306,31 @@ class _ComponentDataSamplesConversionTestCase: ) ), ), - metric_sample_pb2.MetricSample( # Metric with invalid bounds - sampled_at=TIMESTAMP, + metrics_pb2.MetricSample( # Metric with invalid bounds + sample_time=TIMESTAMP, metric=Metric.AC_VOLTAGE.value, - value=metric_sample_pb2.MetricValueVariant( - simple_metric=metric_sample_pb2.SimpleMetricValue( - value=230.0 - ) + value=metrics_pb2.MetricValueVariant( + simple_metric=metrics_pb2.SimpleMetricValue(value=230.0) ), bounds=[bounds_pb2.Bounds(lower=250.0, upper=220.0)], # Invalid ), ], - states=[ - components_pb2.ComponentState( - sampled_at=TIMESTAMP, - states=[components_pb2.COMPONENT_STATE_CODE_READY], + state_snapshots=[ + electrical_components_pb2.ElectricalComponentStateSnapshot( + origin_time=TIMESTAMP, + states=[ + electrical_components_pb2.ELECTRICAL_COMPONENT_STATE_CODE_READY + ], warnings=[ - components_pb2.COMPONENT_ERROR_CODE_HARDWARE_INACCESSIBLE + electrical_components_pb2.ElectricalComponentDiagnostic( + diagnostic_code=HARDWARE_INACCESSIBLE + ) + ], + errors=[ + electrical_components_pb2.ElectricalComponentDiagnostic( + diagnostic_code=OVERCURRENT + ) ], - errors=[components_pb2.COMPONENT_ERROR_CODE_OVERCURRENT], ) ], ), diff --git a/tests/component/test_state_sample.py b/tests/component/test_state_sample.py index 4152f00..70660a5 100644 --- a/tests/component/test_state_sample.py +++ b/tests/component/test_state_sample.py @@ -8,7 +8,9 @@ from unittest.mock import patch import pytest -from frequenz.api.common.v1.microgrid.components import components_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) from frequenz.client.base.conversion import to_timestamp from frequenz.client.microgrid.component import ( @@ -158,22 +160,30 @@ def test_from_proto( timestamp: datetime, ) -> None: """Test conversion from proto message to ComponentStateSample.""" - proto = components_pb2.ComponentState( - sampled_at=to_timestamp(timestamp), + proto = electrical_components_pb2.ElectricalComponentStateSnapshot( + origin_time=to_timestamp(timestamp), states=( state.value if isinstance(state, ComponentStateCode) else state # type: ignore[misc] for state in case.states ), warnings=( - ( - warning.value # type: ignore[misc] - if isinstance(warning, ComponentErrorCode) - else warning + electrical_components_pb2.ElectricalComponentDiagnostic( + diagnostic_code=( + warning.value # type: ignore[arg-type] + if isinstance(warning, ComponentErrorCode) + else warning + ) ) for warning in case.warnings ), errors=( - error.value if isinstance(error, ComponentErrorCode) else error # type: ignore[misc] + electrical_components_pb2.ElectricalComponentDiagnostic( + diagnostic_code=( + error.value # type: ignore[arg-type] + if isinstance(error, ComponentErrorCode) + else error + ) + ) for error in case.errors ), ) diff --git a/tests/metrics/test_bounds.py b/tests/metrics/test_bounds.py index cf78302..383f229 100644 --- a/tests/metrics/test_bounds.py +++ b/tests/metrics/test_bounds.py @@ -7,7 +7,7 @@ from dataclasses import dataclass import pytest -from frequenz.api.common.v1.metrics import bounds_pb2 +from frequenz.api.common.v1alpha8.metrics import bounds_pb2 from frequenz.client.microgrid.metrics import Bounds from frequenz.client.microgrid.metrics._bounds_proto import bounds_from_proto diff --git a/tests/metrics/test_sample.py b/tests/metrics/test_sample.py index 2c427d4..42ec03e 100644 --- a/tests/metrics/test_sample.py +++ b/tests/metrics/test_sample.py @@ -8,7 +8,7 @@ from typing import Final import pytest -from frequenz.api.common.v1.metrics import bounds_pb2, metric_sample_pb2 +from frequenz.api.common.v1alpha8.metrics import bounds_pb2, metrics_pb2 from google.protobuf.timestamp_pb2 import Timestamp from frequenz.client.microgrid.metrics import ( @@ -61,7 +61,7 @@ class _MetricSampleConversionTestCase: name: str """The description of the test case.""" - proto_message: metric_sample_pb2.MetricSample + proto_message: metrics_pb2.MetricSample """The input protobuf message.""" expected_sample: MetricSample @@ -279,7 +279,7 @@ def test_metric_sample_multiple_bounds(now: datetime) -> None: ) def test_aggregated_metric_value_from_proto(case: _AggregatedValueTestCase) -> None: """Test conversion from protobuf message to AggregatedMetricValue.""" - proto = metric_sample_pb2.AggregatedMetricValue( + proto = metrics_pb2.AggregatedMetricValue( avg_value=case.avg_value, ) if case.has_min and case.min_value is not None: @@ -302,11 +302,11 @@ def test_aggregated_metric_value_from_proto(case: _AggregatedValueTestCase) -> N [ _MetricSampleConversionTestCase( name="simple_value", - proto_message=metric_sample_pb2.MetricSample( - sampled_at=TIMESTAMP, + proto_message=metrics_pb2.MetricSample( + sample_time=TIMESTAMP, metric=Metric.AC_ACTIVE_POWER.value, - value=metric_sample_pb2.MetricValueVariant( - simple_metric=metric_sample_pb2.SimpleMetricValue(value=5.0) + value=metrics_pb2.MetricValueVariant( + simple_metric=metrics_pb2.SimpleMetricValue(value=5.0) ), ), expected_sample=MetricSample( @@ -319,11 +319,11 @@ def test_aggregated_metric_value_from_proto(case: _AggregatedValueTestCase) -> N ), _MetricSampleConversionTestCase( name="aggregated_value", - proto_message=metric_sample_pb2.MetricSample( - sampled_at=TIMESTAMP, + proto_message=metrics_pb2.MetricSample( + sample_time=TIMESTAMP, metric=Metric.AC_ACTIVE_POWER.value, - value=metric_sample_pb2.MetricValueVariant( - aggregated_metric=metric_sample_pb2.AggregatedMetricValue( + value=metrics_pb2.MetricValueVariant( + aggregated_metric=metrics_pb2.AggregatedMetricValue( avg_value=5.0, min_value=1.0, max_value=10.0 ) ), @@ -338,8 +338,8 @@ def test_aggregated_metric_value_from_proto(case: _AggregatedValueTestCase) -> N ), _MetricSampleConversionTestCase( name="no_value", - proto_message=metric_sample_pb2.MetricSample( - sampled_at=TIMESTAMP, + proto_message=metrics_pb2.MetricSample( + sample_time=TIMESTAMP, metric=Metric.AC_ACTIVE_POWER.value, ), expected_sample=MetricSample( @@ -352,11 +352,11 @@ def test_aggregated_metric_value_from_proto(case: _AggregatedValueTestCase) -> N ), _MetricSampleConversionTestCase( name="unrecognized_metric", - proto_message=metric_sample_pb2.MetricSample( - sampled_at=TIMESTAMP, + proto_message=metrics_pb2.MetricSample( + sample_time=TIMESTAMP, metric=999, # type: ignore[arg-type] - value=metric_sample_pb2.MetricValueVariant( - simple_metric=metric_sample_pb2.SimpleMetricValue(value=5.0) + value=metrics_pb2.MetricValueVariant( + simple_metric=metrics_pb2.SimpleMetricValue(value=5.0) ), ), expected_sample=MetricSample( @@ -365,11 +365,11 @@ def test_aggregated_metric_value_from_proto(case: _AggregatedValueTestCase) -> N ), _MetricSampleConversionTestCase( name="with_valid_bounds", - proto_message=metric_sample_pb2.MetricSample( - sampled_at=TIMESTAMP, + proto_message=metrics_pb2.MetricSample( + sample_time=TIMESTAMP, metric=Metric.AC_ACTIVE_POWER.value, - value=metric_sample_pb2.MetricValueVariant( - simple_metric=metric_sample_pb2.SimpleMetricValue(value=5.0) + value=metrics_pb2.MetricValueVariant( + simple_metric=metrics_pb2.SimpleMetricValue(value=5.0) ), bounds=[bounds_pb2.Bounds(lower=-10.0, upper=10.0)], ), @@ -383,11 +383,11 @@ def test_aggregated_metric_value_from_proto(case: _AggregatedValueTestCase) -> N ), _MetricSampleConversionTestCase( name="with_invalid_bounds", - proto_message=metric_sample_pb2.MetricSample( - sampled_at=TIMESTAMP, + proto_message=metrics_pb2.MetricSample( + sample_time=TIMESTAMP, metric=Metric.AC_ACTIVE_POWER.value, - value=metric_sample_pb2.MetricValueVariant( - simple_metric=metric_sample_pb2.SimpleMetricValue(value=5.0) + value=metrics_pb2.MetricValueVariant( + simple_metric=metrics_pb2.SimpleMetricValue(value=5.0) ), bounds=[ bounds_pb2.Bounds(lower=-10.0, upper=10.0), @@ -410,13 +410,13 @@ def test_aggregated_metric_value_from_proto(case: _AggregatedValueTestCase) -> N ), _MetricSampleConversionTestCase( name="with_source", - proto_message=metric_sample_pb2.MetricSample( - sampled_at=TIMESTAMP, + proto_message=metrics_pb2.MetricSample( + sample_time=TIMESTAMP, metric=Metric.AC_ACTIVE_POWER.value, - value=metric_sample_pb2.MetricValueVariant( - simple_metric=metric_sample_pb2.SimpleMetricValue(value=5.0) + value=metrics_pb2.MetricValueVariant( + simple_metric=metrics_pb2.SimpleMetricValue(value=5.0) ), - source="dc_battery_0", + connection=metrics_pb2.MetricConnection(name="dc_battery_0"), ), expected_sample=MetricSample( sampled_at=DATETIME, diff --git a/tests/test_client.py b/tests/test_client.py index 0605478..0635c80 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -9,7 +9,7 @@ from pathlib import Path import pytest -from frequenz.api.microgrid.v1 import microgrid_pb2_grpc +from frequenz.api.microgrid.v1alpha18 import microgrid_pb2_grpc from frequenz.client.base.channel import ChannelOptions, KeepAliveOptions, SslOptions from frequenz.client.base.retry import LinearBackoff @@ -95,7 +95,7 @@ async def test_get_microgrid_info( client: MicrogridApiClient, spec: ApiClientTestCaseSpec ) -> None: """Test get_microgrid_info method.""" - await spec.test_unary_unary_call(client, "GetMicrogridMetadata") + await spec.test_unary_unary_call(client, "GetMicrogrid") @pytest.mark.asyncio @@ -108,7 +108,7 @@ async def test_list_components( client: MicrogridApiClient, spec: ApiClientTestCaseSpec ) -> None: """Test list_components method.""" - await spec.test_unary_unary_call(client, "ListComponents") + await spec.test_unary_unary_call(client, "ListElectricalComponents") @pytest.mark.asyncio @@ -121,7 +121,7 @@ async def test_list_connections( client: MicrogridApiClient, spec: ApiClientTestCaseSpec ) -> None: """Test list_connections method.""" - await spec.test_unary_unary_call(client, "ListConnections") + await spec.test_unary_unary_call(client, "ListElectricalComponentConnections") @pytest.mark.asyncio @@ -134,7 +134,7 @@ async def test_set_component_power_active( client: MicrogridApiClient, spec: ApiClientTestCaseSpec ) -> None: """Test set_component_power_active method.""" - await spec.test_unary_unary_call(client, "SetComponentPowerActive") + await spec.test_unary_stream_call(client, "SetElectricalComponentPower") @pytest.mark.asyncio @@ -147,7 +147,7 @@ async def test_set_component_power_reactive( client: MicrogridApiClient, spec: ApiClientTestCaseSpec ) -> None: """Test set_component_power_reactive method.""" - await spec.test_unary_unary_call(client, "SetComponentPowerReactive") + await spec.test_unary_stream_call(client, "SetElectricalComponentPower") @pytest.mark.asyncio @@ -160,7 +160,7 @@ async def test_add_bounds( client: MicrogridApiClient, spec: ApiClientTestCaseSpec ) -> None: """Test add_bounds method.""" - await spec.test_unary_unary_call(client, "AddComponentBounds") + await spec.test_unary_unary_call(client, "AugmentElectricalComponentBounds") @pytest.mark.asyncio @@ -176,4 +176,6 @@ async def test_receive_component_data_samples_stream( client: MicrogridApiClient, spec: ApiClientTestCaseSpec ) -> None: """Test receive_component_data_samples_stream method.""" - await spec.test_unary_stream_call(client, "ReceiveComponentDataStream") + await spec.test_unary_stream_call( + client, "ReceiveElectricalComponentTelemetryStream" + ) diff --git a/tests/test_delivery_area.py b/tests/test_delivery_area.py index 2d9fbb4..72504ed 100644 --- a/tests/test_delivery_area.py +++ b/tests/test_delivery_area.py @@ -6,7 +6,7 @@ from dataclasses import dataclass import pytest -from frequenz.api.common.v1.grid import delivery_area_pb2 +from frequenz.api.common.v1alpha8.grid import delivery_area_pb2 from frequenz.client.microgrid import DeliveryArea, EnergyMarketCodeType from frequenz.client.microgrid._delivery_area_proto import delivery_area_from_proto diff --git a/tests/test_lifetime.py b/tests/test_lifetime.py index 0de6d0e..2040286 100644 --- a/tests/test_lifetime.py +++ b/tests/test_lifetime.py @@ -9,7 +9,7 @@ from typing import Any import pytest -from frequenz.api.common.v1.microgrid import lifetime_pb2 +from frequenz.api.common.v1alpha8.microgrid import lifetime_pb2 from google.protobuf import timestamp_pb2 from frequenz.client.microgrid import Lifetime diff --git a/tests/test_location.py b/tests/test_location.py index 15450ed..abf4dd8 100644 --- a/tests/test_location.py +++ b/tests/test_location.py @@ -6,7 +6,7 @@ from dataclasses import dataclass import pytest -from frequenz.api.common.v1 import location_pb2 +from frequenz.api.common.v1alpha8.types import location_pb2 from frequenz.client.microgrid import Location from frequenz.client.microgrid._location_proto import location_from_proto diff --git a/tests/test_microgrid_info.py b/tests/test_microgrid_info.py index 8b9a90f..b1f27f3 100644 --- a/tests/test_microgrid_info.py +++ b/tests/test_microgrid_info.py @@ -8,8 +8,8 @@ from unittest.mock import Mock, patch import pytest -from frequenz.api.common.v1.grid import delivery_area_pb2 -from frequenz.api.common.v1.microgrid import microgrid_pb2 +from frequenz.api.common.v1alpha8.grid import delivery_area_pb2 +from frequenz.api.common.v1alpha8.microgrid import microgrid_pb2 from frequenz.client.common.microgrid import EnterpriseId, MicrogridId from frequenz.client.microgrid import ( From 214d0e43ae6e54b2f5ba78c2f56f9fdb1ee9e3c9 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Wed, 24 Sep 2025 15:03:29 +0200 Subject: [PATCH 07/10] Use deprecate-aware `enum` from `frequenz-core` With this we can enable `@unique` again, as we can explicitly mark members as deprecated and deprecated members are not checked for duplicates. We also replace the internal uses of the deprecated names with the new names. Signed-off-by: Leandro Lucarella --- pyproject.toml | 1 + .../client/microgrid/component/_category.py | 15 +++++++++------ .../microgrid/component/_grid_connection_point.py | 4 +++- .../client/microgrid/component/_state_sample.py | 9 +++++---- .../microgrid/component/_voltage_transformer.py | 4 ++-- tests/component/test_grid_connection_point.py | 2 +- tests/component/test_voltage_transformer.py | 2 +- 7 files changed, 22 insertions(+), 15 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 692ee72..551ca21 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,6 +41,7 @@ dependencies = [ "frequenz-channels >= 1.6.1, < 2.0.0", "frequenz-client-base >= 0.10.0, < 0.12.0", "frequenz-client-common >= 0.3.6, < 0.4.0", + "frequenz-core >= 1.3.0, < 2.0.0", "grpcio >= 1.72.1, < 2", "protobuf >= 6.31.1, < 7", "typing-extensions >= 4.13.0, < 5", diff --git a/src/frequenz/client/microgrid/component/_category.py b/src/frequenz/client/microgrid/component/_category.py index 507479e..e3e4b4c 100644 --- a/src/frequenz/client/microgrid/component/_category.py +++ b/src/frequenz/client/microgrid/component/_category.py @@ -3,14 +3,13 @@ """The component categories that can be used in a microgrid.""" -import enum - from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( electrical_components_pb2, ) +from frequenz.core import enum -# @enum.unique +@enum.unique class ComponentCategory(enum.Enum): """The known categories of components that can be present in a microgrid.""" @@ -22,7 +21,10 @@ class ComponentCategory(enum.Enum): ) """The point where the local microgrid is connected to the grid.""" - GRID = electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_GRID_CONNECTION_POINT + GRID = enum.deprecated_member( + electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_GRID_CONNECTION_POINT, + "GRID is deprecated, use GRID_CONNECTION_POINT instead", + ) """The point where the local microgrid is connected to the grid (deprecated). Deprecated: Deprecated in v0.18.0 @@ -88,8 +90,9 @@ class ComponentCategory(enum.Enum): proportionally reduced, and vice versa. """ - VOLTAGE_TRANSFORMER = ( - electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_POWER_TRANSFORMER + VOLTAGE_TRANSFORMER = enum.deprecated_member( + electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_POWER_TRANSFORMER, + "VOLTAGE_TRANSFORMER is deprecated, use POWER_TRANSFORMER instead", ) """A voltage transformer (deprecated). diff --git a/src/frequenz/client/microgrid/component/_grid_connection_point.py b/src/frequenz/client/microgrid/component/_grid_connection_point.py index 24c72c0..bf463c8 100644 --- a/src/frequenz/client/microgrid/component/_grid_connection_point.py +++ b/src/frequenz/client/microgrid/component/_grid_connection_point.py @@ -34,7 +34,9 @@ class GridConnectionPoint(Component): Note that this may also be the PCC in some cases. """ - category: Literal[ComponentCategory.GRID] = ComponentCategory.GRID + category: Literal[ComponentCategory.GRID_CONNECTION_POINT] = ( + ComponentCategory.GRID_CONNECTION_POINT + ) """The category of this component.""" rated_fuse_current: int diff --git a/src/frequenz/client/microgrid/component/_state_sample.py b/src/frequenz/client/microgrid/component/_state_sample.py index 36bcbaa..5829f8a 100644 --- a/src/frequenz/client/microgrid/component/_state_sample.py +++ b/src/frequenz/client/microgrid/component/_state_sample.py @@ -3,13 +3,13 @@ """Definition of component states.""" -import enum from dataclasses import dataclass from datetime import datetime from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( electrical_components_pb2, ) +from frequenz.core import enum @enum.unique @@ -106,7 +106,7 @@ class ComponentStateCode(enum.Enum): """The precharger circuit is closed, allowing full current to flow to the main circuit.""" -# @enum.unique +@enum.unique class ComponentErrorCode(enum.Enum): """The various errors that a component can report.""" @@ -182,8 +182,9 @@ class ComponentErrorCode(enum.Enum): ) """Plausibility issues within the system involving this component.""" - UNDERVOLTAGE_SHUTDOWN = ( - electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_UNDERVOLTAGE + UNDERVOLTAGE_SHUTDOWN = enum.deprecated_member( + electrical_components_pb2.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_UNDERVOLTAGE, + "UNDERVOLTAGE_SHUTDOWN is deprecated, use UNDERVOLTAGE instead", ) """System shutdown due to undervoltage involving this component. diff --git a/src/frequenz/client/microgrid/component/_voltage_transformer.py b/src/frequenz/client/microgrid/component/_voltage_transformer.py index af9f367..d32d66b 100644 --- a/src/frequenz/client/microgrid/component/_voltage_transformer.py +++ b/src/frequenz/client/microgrid/component/_voltage_transformer.py @@ -24,8 +24,8 @@ class VoltageTransformer(Component): than the input power. """ - category: Literal[ComponentCategory.VOLTAGE_TRANSFORMER] = ( - ComponentCategory.VOLTAGE_TRANSFORMER + category: Literal[ComponentCategory.POWER_TRANSFORMER] = ( + ComponentCategory.POWER_TRANSFORMER ) """The category of this component.""" diff --git a/tests/component/test_grid_connection_point.py b/tests/component/test_grid_connection_point.py index b8adfa0..7ee88c3 100644 --- a/tests/component/test_grid_connection_point.py +++ b/tests/component/test_grid_connection_point.py @@ -41,7 +41,7 @@ def test_creation_ok( assert grid_point.name == "test_grid_point" assert grid_point.manufacturer == "test_manufacturer" assert grid_point.model_name == "test_model" - assert grid_point.category == ComponentCategory.GRID + assert grid_point.category == ComponentCategory.GRID_CONNECTION_POINT assert grid_point.rated_fuse_current == rated_fuse_current diff --git a/tests/component/test_voltage_transformer.py b/tests/component/test_voltage_transformer.py index 6d1d44f..0240bac 100644 --- a/tests/component/test_voltage_transformer.py +++ b/tests/component/test_voltage_transformer.py @@ -47,6 +47,6 @@ def test_creation_ok( assert voltage_transformer.name == "test_voltage_transformer" assert voltage_transformer.manufacturer == "test_manufacturer" assert voltage_transformer.model_name == "test_model" - assert voltage_transformer.category == ComponentCategory.VOLTAGE_TRANSFORMER + assert voltage_transformer.category == ComponentCategory.POWER_TRANSFORMER assert voltage_transformer.primary_voltage == pytest.approx(primary) assert voltage_transformer.secondary_voltage == pytest.approx(secondary) From 7ed1f14c49b6497fc0435b707090fec048517bc1 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Wed, 24 Sep 2025 15:10:14 +0200 Subject: [PATCH 08/10] Improve the mismatched category issue message Signed-off-by: Leandro Lucarella --- src/frequenz/client/microgrid/component/_component_proto.py | 5 ++++- tests/component/component_proto/test_base.py | 4 +++- tests/component/component_proto/test_simple.py | 4 +++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/frequenz/client/microgrid/component/_component_proto.py b/src/frequenz/client/microgrid/component/_component_proto.py index eefb072..4da31fc 100644 --- a/src/frequenz/client/microgrid/component/_component_proto.py +++ b/src/frequenz/client/microgrid/component/_component_proto.py @@ -179,7 +179,10 @@ def component_base_from_proto_with_issues( and isinstance(category, ComponentCategory) and category.name.lower() != category_specific_info_kind ): - major_issues.append("category_type.metadata does not match the category_type") + major_issues.append( + f"category_specific_info.kind ({category_specific_info_kind}) does not " + f"match the category ({category.name.lower()})", + ) category_mismatched = True return ComponentBaseData( diff --git a/tests/component/component_proto/test_base.py b/tests/component/component_proto/test_base.py index bfffdf1..8d0e189 100644 --- a/tests/component/component_proto/test_base.py +++ b/tests/component/component_proto/test_base.py @@ -91,7 +91,9 @@ def test_category_specific_info_mismatch( proto, major_issues=major_issues, minor_issues=minor_issues ) # Actual message from _component_base_from_proto_with_issues - assert major_issues == ["category_type.metadata does not match the category_type"] + assert major_issues == [ + "category_specific_info.kind (battery) does not match the category (grid_connection_point)" + ] assert not minor_issues assert parsed == base_data diff --git a/tests/component/component_proto/test_simple.py b/tests/component/component_proto/test_simple.py index 11bd6c9..ec755f4 100644 --- a/tests/component/component_proto/test_simple.py +++ b/tests/component/component_proto/test_simple.py @@ -92,7 +92,9 @@ def test_category_mismatch(default_component_base_data: ComponentBaseData) -> No ) # The actual message from component_from_proto_with_issues via # _component_base_from_proto_with_issues - assert major_issues == ["category_type.metadata does not match the category_type"] + assert major_issues == [ + "category_specific_info.kind (battery) does not match the category (grid_connection_point)" + ] assert not minor_issues assert isinstance(component, MismatchedCategoryComponent) assert_base_data(base_data, component) From aa619df6990551a76776f1a0e69bad83f9ee2d98 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Wed, 24 Sep 2025 15:13:21 +0200 Subject: [PATCH 09/10] Fix wrong test description Signed-off-by: Leandro Lucarella --- tests/component/component_proto/test_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/component/component_proto/test_base.py b/tests/component/component_proto/test_base.py index 8d0e189..31143b7 100644 --- a/tests/component/component_proto/test_base.py +++ b/tests/component/component_proto/test_base.py @@ -99,7 +99,7 @@ def test_category_specific_info_mismatch( def test_invalid_lifetime(default_component_base_data: ComponentBaseData) -> None: - """Test parsing with missing optional metadata.""" + """Test invalid lifetime (start after end).""" major_issues: list[str] = [] minor_issues: list[str] = [] base_data = default_component_base_data._replace( From 98d8d5ced1b951b1916e164fbcdf444ff87dffc3 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Thu, 25 Sep 2025 14:03:16 +0200 Subject: [PATCH 10/10] Rename old POWER and ENERGY metric members We still keep the old names but we mark them as deprecated. We need to disable the max line check in flake8 for the whole file because the symbol names are too long, and we can't use per-line overrides because this happens inside a docstring. Signed-off-by: Leandro Lucarella --- pyproject.toml | 4 + .../client/microgrid/metrics/_metric.py | 387 +++++++++++++----- tests/component/component_proto/conftest.py | 2 +- tests/component/test_component.py | 6 +- tests/component/test_data_samples.py | 14 +- tests/metrics/test_sample.py | 34 +- 6 files changed, 318 insertions(+), 129 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 551ca21..b7eb64c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -131,6 +131,10 @@ check-yield-types = false arg-type-hints-in-docstring = false arg-type-hints-in-signature = true allow-init-docstring = true +per-file-ignores = [ + # Ignore the max-line-length (E501) because enum values are just too long + "src/frequenz/client/microgrid/metrics/_metric.py:E501", +] [tool.pylint.similarities] ignore-comments = ['yes'] diff --git a/src/frequenz/client/microgrid/metrics/_metric.py b/src/frequenz/client/microgrid/metrics/_metric.py index 8b82e7c..61bc4a7 100644 --- a/src/frequenz/client/microgrid/metrics/_metric.py +++ b/src/frequenz/client/microgrid/metrics/_metric.py @@ -4,9 +4,8 @@ """Supported metrics for microgrid components.""" -import enum - from frequenz.api.common.v1alpha8.metrics import metrics_pb2 +from frequenz.core import enum @enum.unique @@ -74,42 +73,174 @@ class Metric(enum.Enum): AC_CURRENT_PHASE_3 = metrics_pb2.METRIC_AC_CURRENT_PHASE_3 """The alternating current current in phase 3.""" - AC_APPARENT_POWER = metrics_pb2.METRIC_AC_POWER_APPARENT + AC_POWER_APPARENT = metrics_pb2.METRIC_AC_POWER_APPARENT """The alternating current apparent power.""" - AC_APPARENT_POWER_PHASE_1 = metrics_pb2.METRIC_AC_POWER_APPARENT_PHASE_1 + AC_APPARENT_POWER = enum.deprecated_member( + metrics_pb2.METRIC_AC_POWER_APPARENT, + "AC_APPARENT_POWER is deprecated, user AC_POWER_APPARENT instead", + ) + """The alternating current apparent power (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use [`AC_POWER_APPARENT`][frequenz.client.microgrid.metrics.Metric.AC_POWER_APPARENT] + instead. + """ + + AC_POWER_APPARENT_PHASE_1 = metrics_pb2.METRIC_AC_POWER_APPARENT_PHASE_1 """The alternating current apparent power in phase 1.""" - AC_APPARENT_POWER_PHASE_2 = metrics_pb2.METRIC_AC_POWER_APPARENT_PHASE_2 + AC_APPARENT_POWER_PHASE_1 = enum.deprecated_member( + metrics_pb2.METRIC_AC_POWER_APPARENT_PHASE_1, + "AC_APPARENT_POWER_PHASE_1 is deprecated, user AC_POWER_APPARENT_PHASE_1 instead", + ) + """The alternating current apparent power in phase 1 (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use [`AC_POWER_APPARENT_PHASE_1`][frequenz.client.microgrid.metrics.Metric.AC_POWER_APPARENT_PHASE_1] + instead. + """ + + AC_POWER_APPARENT_PHASE_2 = metrics_pb2.METRIC_AC_POWER_APPARENT_PHASE_2 """The alternating current apparent power in phase 2.""" - AC_APPARENT_POWER_PHASE_3 = metrics_pb2.METRIC_AC_POWER_APPARENT_PHASE_3 + AC_APPARENT_POWER_PHASE_2 = enum.deprecated_member( + metrics_pb2.METRIC_AC_POWER_APPARENT_PHASE_2, + "AC_APPARENT_POWER_PHASE_2 is deprecated, user AC_POWER_APPARENT_PHASE_2 instead", + ) + """The alternating current apparent power in phase 2 (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use [`AC_POWER_APPARENT_PHASE_2`][frequenz.client.microgrid.metrics.Metric.AC_POWER_APPARENT_PHASE_2] + instead. + """ + + AC_POWER_APPARENT_PHASE_3 = metrics_pb2.METRIC_AC_POWER_APPARENT_PHASE_3 """The alternating current apparent power in phase 3.""" - AC_ACTIVE_POWER = metrics_pb2.METRIC_AC_POWER_ACTIVE + AC_APPARENT_POWER_PHASE_3 = enum.deprecated_member( + metrics_pb2.METRIC_AC_POWER_APPARENT_PHASE_3, + "AC_APPARENT_POWER_PHASE_3 is deprecated, user AC_POWER_APPARENT_PHASE_3 instead", + ) + """The alternating current apparent power in phase 3 (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use [`AC_POWER_APPARENT_PHASE_3`][frequenz.client.microgrid.metrics.Metric.AC_POWER_APPARENT_PHASE_3] + instead. + """ + + AC_POWER_ACTIVE = metrics_pb2.METRIC_AC_POWER_ACTIVE """The alternating current active power.""" - AC_ACTIVE_POWER_PHASE_1 = metrics_pb2.METRIC_AC_POWER_ACTIVE_PHASE_1 + AC_ACTIVE_POWER = enum.deprecated_member( + metrics_pb2.METRIC_AC_POWER_ACTIVE, + "AC_ACTIVE_POWER is deprecated, user AC_POWER_ACTIVE instead", + ) + """The alternating current active power (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use [`AC_POWER_ACTIVE`][frequenz.client.microgrid.metrics.Metric.AC_POWER_ACTIVE] + instead. + """ + + AC_POWER_ACTIVE_PHASE_1 = metrics_pb2.METRIC_AC_POWER_ACTIVE_PHASE_1 """The alternating current active power in phase 1.""" - AC_ACTIVE_POWER_PHASE_2 = metrics_pb2.METRIC_AC_POWER_ACTIVE_PHASE_2 + AC_ACTIVE_POWER_PHASE_1 = enum.deprecated_member( + metrics_pb2.METRIC_AC_POWER_ACTIVE_PHASE_1, + "AC_ACTIVE_POWER_PHASE_1 is deprecated, user AC_POWER_ACTIVE_PHASE_1 instead", + ) + """The alternating current active power in phase 1 (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use [`AC_POWER_ACTIVE_PHASE_1`][frequenz.client.microgrid.metrics.Metric.AC_POWER_ACTIVE_PHASE_1] + instead. + """ + + AC_POWER_ACTIVE_PHASE_2 = metrics_pb2.METRIC_AC_POWER_ACTIVE_PHASE_2 """The alternating current active power in phase 2.""" - AC_ACTIVE_POWER_PHASE_3 = metrics_pb2.METRIC_AC_POWER_ACTIVE_PHASE_3 + AC_ACTIVE_POWER_PHASE_2 = enum.deprecated_member( + metrics_pb2.METRIC_AC_POWER_ACTIVE_PHASE_2, + "AC_ACTIVE_POWER_PHASE_2 is deprecated, user AC_POWER_ACTIVE_PHASE_2 instead", + ) + """The alternating current active power in phase 2 (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use [`AC_POWER_ACTIVE_PHASE_2`][frequenz.client.microgrid.metrics.Metric.AC_POWER_ACTIVE_PHASE_2] + instead. + """ + + AC_POWER_ACTIVE_PHASE_3 = metrics_pb2.METRIC_AC_POWER_ACTIVE_PHASE_3 """The alternating current active power in phase 3.""" - AC_REACTIVE_POWER = metrics_pb2.METRIC_AC_POWER_REACTIVE + AC_ACTIVE_POWER_PHASE_3 = enum.deprecated_member( + metrics_pb2.METRIC_AC_POWER_ACTIVE_PHASE_3, + "AC_ACTIVE_POWER_PHASE_3 is deprecated, user AC_POWER_ACTIVE_PHASE_3 instead", + ) + """The alternating current active power in phase 3 (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use [`AC_POWER_ACTIVE_PHASE_3`][frequenz.client.microgrid.metrics.Metric.AC_POWER_ACTIVE_PHASE_3] + instead. + """ + + AC_POWER_REACTIVE = metrics_pb2.METRIC_AC_POWER_REACTIVE """The alternating current reactive power.""" - AC_REACTIVE_POWER_PHASE_1 = metrics_pb2.METRIC_AC_POWER_REACTIVE_PHASE_1 + AC_REACTIVE_POWER = enum.deprecated_member( + metrics_pb2.METRIC_AC_POWER_REACTIVE, + "AC_REACTIVE_POWER is deprecated, user AC_POWER_REACTIVE instead", + ) + """The alternating current reactive power (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use [`AC_POWER_REACTIVE`][frequenz.client.microgrid.metrics.Metric.AC_POWER_REACTIVE] + instead. + """ + + AC_POWER_REACTIVE_PHASE_1 = metrics_pb2.METRIC_AC_POWER_REACTIVE_PHASE_1 """The alternating current reactive power in phase 1.""" - AC_REACTIVE_POWER_PHASE_2 = metrics_pb2.METRIC_AC_POWER_REACTIVE_PHASE_2 + AC_REACTIVE_POWER_PHASE_1 = enum.deprecated_member( + metrics_pb2.METRIC_AC_POWER_REACTIVE_PHASE_1, + "AC_REACTIVE_POWER_PHASE_1 is deprecated, user AC_POWER_REACTIVE_PHASE_1 instead", + ) + """The alternating current reactive power in phase 1 (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use [`AC_POWER_REACTIVE_PHASE_1`][frequenz.client.microgrid.metrics.Metric.AC_POWER_REACTIVE_PHASE_1] + instead. + """ + + AC_POWER_REACTIVE_PHASE_2 = metrics_pb2.METRIC_AC_POWER_REACTIVE_PHASE_2 """The alternating current reactive power in phase 2.""" - AC_REACTIVE_POWER_PHASE_3 = metrics_pb2.METRIC_AC_POWER_REACTIVE_PHASE_3 + AC_REACTIVE_POWER_PHASE_2 = enum.deprecated_member( + metrics_pb2.METRIC_AC_POWER_REACTIVE_PHASE_2, + "AC_REACTIVE_POWER_PHASE_2 is deprecated, user AC_POWER_REACTIVE_PHASE_2 instead", + ) + """The alternating current reactive power in phase 2 (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use [`AC_POWER_REACTIVE_PHASE_2`][frequenz.client.microgrid.metrics.Metric.AC_POWER_REACTIVE_PHASE_2] + instead. + """ + + AC_POWER_REACTIVE_PHASE_3 = metrics_pb2.METRIC_AC_POWER_REACTIVE_PHASE_3 """The alternating current reactive power in phase 3.""" + AC_REACTIVE_POWER_PHASE_3 = enum.deprecated_member( + metrics_pb2.METRIC_AC_POWER_REACTIVE_PHASE_3, + "AC_REACTIVE_POWER_PHASE_3 is deprecated, user AC_POWER_REACTIVE_PHASE_3 instead", + ) + """The alternating current reactive power in phase 3 (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use [`AC_POWER_REACTIVE_PHASE_3`][frequenz.client.microgrid.metrics.Metric.AC_POWER_REACTIVE_PHASE_3] + instead. + """ + AC_POWER_FACTOR = metrics_pb2.METRIC_AC_POWER_FACTOR """The alternating current power factor.""" @@ -122,141 +253,195 @@ class Metric(enum.Enum): AC_POWER_FACTOR_PHASE_3 = metrics_pb2.METRIC_AC_POWER_FACTOR_PHASE_3 """The alternating current power factor in phase 3.""" - AC_APPARENT_ENERGY = metrics_pb2.METRIC_AC_ENERGY_APPARENT + AC_ENERGY_APPARENT = metrics_pb2.METRIC_AC_ENERGY_APPARENT """The alternating current apparent energy.""" - AC_APPARENT_ENERGY_PHASE_1 = metrics_pb2.METRIC_AC_ENERGY_APPARENT_PHASE_1 + AC_APPARENT_ENERGY = enum.deprecated_member( + metrics_pb2.METRIC_AC_ENERGY_APPARENT, + "AC_APPARENT_ENERGY is deprecated, user AC_ENERGY_APPARENT instead", + ) + """The alternating current apparent energy (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use [`AC_ENERGY_APPARENT`][frequenz.client.microgrid.metrics.Metric.AC_ENERGY_APPARENT] + instead. + """ + + AC_ENERGY_APPARENT_PHASE_1 = metrics_pb2.METRIC_AC_ENERGY_APPARENT_PHASE_1 """The alternating current apparent energy in phase 1.""" - AC_APPARENT_ENERGY_PHASE_2 = metrics_pb2.METRIC_AC_ENERGY_APPARENT_PHASE_2 + AC_APPARENT_ENERGY_PHASE_1 = enum.deprecated_member( + metrics_pb2.METRIC_AC_ENERGY_APPARENT_PHASE_1, + "AC_APPARENT_ENERGY_PHASE_1 is deprecated, user AC_ENERGY_APPARENT_PHASE_1 instead", + ) + """The alternating current apparent energy in phase 1 (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use [`AC_ENERGY_APPARENT_PHASE_1`][frequenz.client.microgrid.metrics.Metric.AC_ENERGY_APPARENT_PHASE_1] + instead. + """ + + AC_ENERGY_APPARENT_PHASE_2 = metrics_pb2.METRIC_AC_ENERGY_APPARENT_PHASE_2 """The alternating current apparent energy in phase 2.""" - AC_APPARENT_ENERGY_PHASE_3 = metrics_pb2.METRIC_AC_ENERGY_APPARENT_PHASE_3 + AC_APPARENT_ENERGY_PHASE_2 = enum.deprecated_member( + metrics_pb2.METRIC_AC_ENERGY_APPARENT_PHASE_2, + "AC_APPARENT_ENERGY_PHASE_2 is deprecated, user AC_ENERGY_APPARENT_PHASE_2 instead", + ) + """The alternating current apparent energy in phase 2 (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use [`AC_ENERGY_APPARENT_PHASE_2`][frequenz.client.microgrid.metrics.Metric.AC_ENERGY_APPARENT_PHASE_2] + instead. + """ + + AC_ENERGY_APPARENT_PHASE_3 = metrics_pb2.METRIC_AC_ENERGY_APPARENT_PHASE_3 """The alternating current apparent energy in phase 3.""" - AC_ACTIVE_ENERGY = metrics_pb2.METRIC_AC_ENERGY_ACTIVE + AC_APPARENT_ENERGY_PHASE_3 = enum.deprecated_member( + metrics_pb2.METRIC_AC_ENERGY_APPARENT_PHASE_3, + "AC_APPARENT_ENERGY_PHASE_3 is deprecated, user AC_ENERGY_APPARENT_PHASE_3 instead", + ) + """The alternating current apparent energy in phase 3 (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use [`AC_ENERGY_APPARENT_PHASE_3`][frequenz.client.microgrid.metrics.Metric.AC_ENERGY_APPARENT_PHASE_3] + instead. + """ + + AC_ENERGY_ACTIVE = metrics_pb2.METRIC_AC_ENERGY_ACTIVE """The alternating current active energy.""" - AC_ACTIVE_ENERGY_PHASE_1 = metrics_pb2.METRIC_AC_ENERGY_ACTIVE_PHASE_1 + AC_ACTIVE_ENERGY = enum.deprecated_member( + metrics_pb2.METRIC_AC_ENERGY_ACTIVE, + "AC_ACTIVE_ENERGY is deprecated, user AC_ENERGY_ACTIVE instead", + ) + """The alternating current active energy (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use [`AC_ENERGY_ACTIVE`][frequenz.client.microgrid.metrics.Metric.AC_ENERGY_ACTIVE] + instead. + """ + + AC_ENERGY_ACTIVE_PHASE_1 = metrics_pb2.METRIC_AC_ENERGY_ACTIVE_PHASE_1 """The alternating current active energy in phase 1.""" - AC_ACTIVE_ENERGY_PHASE_2 = metrics_pb2.METRIC_AC_ENERGY_ACTIVE_PHASE_2 + AC_ACTIVE_ENERGY_PHASE_1 = enum.deprecated_member( + metrics_pb2.METRIC_AC_ENERGY_ACTIVE_PHASE_1, + "AC_ACTIVE_ENERGY_PHASE_1 is deprecated, user AC_ENERGY_ACTIVE_PHASE_1 instead", + ) + """The alternating current active energy in phase 1 (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use [`AC_ENERGY_ACTIVE_PHASE_1`][frequenz.client.microgrid.metrics.Metric.AC_ENERGY_ACTIVE_PHASE_1] + instead. + """ + + AC_ENERGY_ACTIVE_PHASE_2 = metrics_pb2.METRIC_AC_ENERGY_ACTIVE_PHASE_2 """The alternating current active energy in phase 2.""" - AC_ACTIVE_ENERGY_PHASE_3 = metrics_pb2.METRIC_AC_ENERGY_ACTIVE_PHASE_3 + AC_ACTIVE_ENERGY_PHASE_2 = enum.deprecated_member( + metrics_pb2.METRIC_AC_ENERGY_ACTIVE_PHASE_2, + "AC_ACTIVE_ENERGY_PHASE_2 is deprecated, user AC_ENERGY_ACTIVE_PHASE_2 instead", + ) + """The alternating current active energy in phase 2 (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use [`AC_ENERGY_ACTIVE_PHASE_2`][frequenz.client.microgrid.metrics.Metric.AC_ENERGY_ACTIVE_PHASE_2] + instead. + """ + + AC_ENERGY_ACTIVE_PHASE_3 = metrics_pb2.METRIC_AC_ENERGY_ACTIVE_PHASE_3 """The alternating current active energy in phase 3.""" - AC_ACTIVE_ENERGY_CONSUMED = metrics_pb2.METRIC_AC_ENERGY_ACTIVE_CONSUMED + AC_ACTIVE_ENERGY_PHASE_3 = enum.deprecated_member( + metrics_pb2.METRIC_AC_ENERGY_ACTIVE_PHASE_3, + "AC_ACTIVE_ENERGY_PHASE_3 is deprecated, user AC_ENERGY_ACTIVE_PHASE_3 instead", + ) + """The alternating current active energy in phase 3 (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use [`AC_ENERGY_ACTIVE_PHASE_3`][frequenz.client.microgrid.metrics.Metric.AC_ENERGY_ACTIVE_PHASE_3] + instead. + """ + + AC_ENERGY_ACTIVE_CONSUMED = metrics_pb2.METRIC_AC_ENERGY_ACTIVE_CONSUMED """The alternating current active energy consumed.""" - AC_ACTIVE_ENERGY_CONSUMED_PHASE_1 = ( + AC_ACTIVE_ENERGY_CONSUMED = enum.deprecated_member( + metrics_pb2.METRIC_AC_ENERGY_ACTIVE_CONSUMED, + "AC_ACTIVE_ENERGY_CONSUMED is deprecated, user AC_ENERGY_ACTIVE_CONSUMED instead", + ) + """The alternating current active energy consumed (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use [`AC_ENERGY_ACTIVE_CONSUMED`][frequenz.client.microgrid.metrics.Metric.AC_ENERGY_ACTIVE_CONSUMED] + instead. + """ + + AC_ENERGY_ACTIVE_CONSUMED_PHASE_1 = ( metrics_pb2.METRIC_AC_ENERGY_ACTIVE_CONSUMED_PHASE_1 ) """The alternating current active energy consumed in phase 1.""" - AC_ACTIVE_ENERGY_CONSUMED_PHASE_2 = ( + AC_ENERGY_ACTIVE_CONSUMED_PHASE_2 = ( metrics_pb2.METRIC_AC_ENERGY_ACTIVE_CONSUMED_PHASE_2 ) """The alternating current active energy consumed in phase 2.""" - AC_ACTIVE_ENERGY_CONSUMED_PHASE_3 = ( + AC_ENERGY_ACTIVE_CONSUMED_PHASE_3 = ( metrics_pb2.METRIC_AC_ENERGY_ACTIVE_CONSUMED_PHASE_3 ) """The alternating current active energy consumed in phase 3.""" - AC_ACTIVE_ENERGY_DELIVERED = metrics_pb2.METRIC_AC_ENERGY_ACTIVE_DELIVERED + AC_ENERGY_ACTIVE_DELIVERED = metrics_pb2.METRIC_AC_ENERGY_ACTIVE_DELIVERED """The alternating current active energy delivered.""" - AC_ACTIVE_ENERGY_DELIVERED_PHASE_1 = ( + AC_ACTIVE_ENERGY_DELIVERED = enum.deprecated_member( + metrics_pb2.METRIC_AC_ENERGY_ACTIVE_DELIVERED, + "AC_ACTIVE_ENERGY_DELIVERED is deprecated, user AC_ENERGY_ACTIVE_DELIVERED instead", + ) + """The alternating current active energy delivered (deprecated). + + Deprecated: Deprecated in v0.18.0 + Use [`AC_ENERGY_ACTIVE_DELIVERED`][frequenz.client.microgrid.metrics.Metric.AC_ENERGY_ACTIVE_DELIVERED] + instead. + """ + + AC_ENERGY_ACTIVE_DELIVERED_PHASE_1 = ( metrics_pb2.METRIC_AC_ENERGY_ACTIVE_DELIVERED_PHASE_1 ) """The alternating current active energy delivered in phase 1.""" - AC_ACTIVE_ENERGY_DELIVERED_PHASE_2 = ( + AC_ENERGY_ACTIVE_DELIVERED_PHASE_2 = ( metrics_pb2.METRIC_AC_ENERGY_ACTIVE_DELIVERED_PHASE_2 ) """The alternating current active energy delivered in phase 2.""" - AC_ACTIVE_ENERGY_DELIVERED_PHASE_3 = ( + AC_ENERGY_ACTIVE_DELIVERED_PHASE_3 = ( metrics_pb2.METRIC_AC_ENERGY_ACTIVE_DELIVERED_PHASE_3 ) """The alternating current active energy delivered in phase 3.""" - AC_REACTIVE_ENERGY = metrics_pb2.METRIC_AC_ENERGY_REACTIVE + AC_ENERGY_REACTIVE = metrics_pb2.METRIC_AC_ENERGY_REACTIVE """The alternating current reactive energy.""" - AC_REACTIVE_ENERGY_PHASE_1 = metrics_pb2.METRIC_AC_ENERGY_REACTIVE_PHASE_1 - """The alternating current reactive energy in phase 1.""" - - AC_REACTIVE_ENERGY_PHASE_2 = metrics_pb2.METRIC_AC_ENERGY_REACTIVE_PHASE_2 - """The alternating current reactive energy in phase 2.""" - - AC_REACTIVE_ENERGY_PHASE_3 = metrics_pb2.METRIC_AC_ENERGY_REACTIVE_PHASE_3 - """The alternating current reactive energy in phase 3.""" - - AC_TOTAL_HARMONIC_DISTORTION_CURRENT = ( - metrics_pb2.METRIC_AC_TOTAL_HARMONIC_DISTORTION_CURRENT + AC_REACTIVE_ENERGY = enum.deprecated_member( + metrics_pb2.METRIC_AC_ENERGY_REACTIVE, + "AC_REACTIVE_ENERGY is deprecated, user AC_ENERGY_REACTIVE instead", ) - """The alternating current total harmonic distortion current.""" - - AC_TOTAL_HARMONIC_DISTORTION_CURRENT_PHASE_1 = ( - metrics_pb2.METRIC_AC_TOTAL_HARMONIC_DISTORTION_CURRENT_PHASE_1 - ) - """The alternating current total harmonic distortion current in phase 1.""" - - AC_TOTAL_HARMONIC_DISTORTION_CURRENT_PHASE_2 = ( - metrics_pb2.METRIC_AC_TOTAL_HARMONIC_DISTORTION_CURRENT_PHASE_2 - ) - """The alternating current total harmonic distortion current in phase 2.""" - - AC_TOTAL_HARMONIC_DISTORTION_CURRENT_PHASE_3 = ( - metrics_pb2.METRIC_AC_TOTAL_HARMONIC_DISTORTION_CURRENT_PHASE_3 - ) - """The alternating current total harmonic distortion current in phase 3.""" - - BATTERY_CAPACITY = metrics_pb2.METRIC_BATTERY_CAPACITY - """The capacity of the battery.""" - - BATTERY_SOC_PCT = metrics_pb2.METRIC_BATTERY_SOC_PCT - """The state of charge of the battery as a percentage.""" + """The alternating current reactive energy (deprecated). - BATTERY_TEMPERATURE = metrics_pb2.METRIC_BATTERY_TEMPERATURE - """The temperature of the battery.""" - - INVERTER_TEMPERATURE = metrics_pb2.METRIC_INVERTER_TEMPERATURE - """The temperature of the inverter.""" - - INVERTER_TEMPERATURE_CABINET = metrics_pb2.METRIC_INVERTER_TEMPERATURE_CABINET - """The temperature of the inverter cabinet.""" - - INVERTER_TEMPERATURE_HEATSINK = metrics_pb2.METRIC_INVERTER_TEMPERATURE_HEATSINK - """The temperature of the inverter heatsink.""" - - INVERTER_TEMPERATURE_TRANSFORMER = ( - metrics_pb2.METRIC_INVERTER_TEMPERATURE_TRANSFORMER - ) - """The temperature of the inverter transformer.""" - - EV_CHARGER_TEMPERATURE = metrics_pb2.METRIC_EV_CHARGER_TEMPERATURE - """The temperature of the EV charger.""" - - SENSOR_WIND_SPEED = metrics_pb2.METRIC_SENSOR_WIND_SPEED - """The speed of the wind measured.""" - - SENSOR_WIND_DIRECTION = metrics_pb2.METRIC_SENSOR_WIND_DIRECTION - """The direction of the wind measured.""" - - SENSOR_TEMPERATURE = metrics_pb2.METRIC_SENSOR_TEMPERATURE - """The temperature measured.""" - - SENSOR_RELATIVE_HUMIDITY = metrics_pb2.METRIC_SENSOR_RELATIVE_HUMIDITY - """The relative humidity measured.""" + Deprecated: Deprecated in v0.18.0 + Use [`AC_ENERGY_REACTIVE`][frequenz.client.microgrid.metrics.Metric.AC_ENERGY_REACTIVE] + instead. + """ - SENSOR_DEW_POINT = metrics_pb2.METRIC_SENSOR_DEW_POINT - """The dew point measured.""" + AC_ENERGY_REACTIVE_PHASE_1 = metrics_pb2.METRIC_AC_ENERGY_REACTIVE_PHASE_1 + """The alternating current reactive energy in phase 1.""" - SENSOR_AIR_PRESSURE = metrics_pb2.METRIC_SENSOR_AIR_PRESSURE - """The air pressure measured.""" + AC_ENERGY_REACTIVE_PHASE_2 = metrics_pb2.METRIC_AC_ENERGY_REACTIVE_PHASE_2 + """The alternating current reactive energy in phase 2.""" - SENSOR_IRRADIANCE = metrics_pb2.METRIC_SENSOR_IRRADIANCE - """The irradiance measured.""" + AC_ENERGY_REACTIVE_PHASE_3 = metrics_pb2.METRIC_AC_ENERGY_REACTIVE_PHASE_3 + """The alternating current reactive energy in phase 3.""" diff --git a/tests/component/component_proto/conftest.py b/tests/component/component_proto/conftest.py index f5b8471..2e9d4a7 100644 --- a/tests/component/component_proto/conftest.py +++ b/tests/component/component_proto/conftest.py @@ -57,7 +57,7 @@ def default_component_base_data( model_name=DEFAULT_MODEL_NAME, category=ComponentCategory.UNSPECIFIED, lifetime=DEFAULT_LIFETIME, - rated_bounds={Metric.AC_ACTIVE_ENERGY: Bounds(lower=0, upper=100)}, + rated_bounds={Metric.AC_ENERGY_ACTIVE: Bounds(lower=0, upper=100)}, category_specific_info={}, category_mismatched=False, ) diff --git a/tests/component/test_component.py b/tests/component/test_component.py index 6fb8228..9fcd5ea 100644 --- a/tests/component/test_component.py +++ b/tests/component/test_component.py @@ -53,7 +53,7 @@ def test_creation_with_defaults() -> None: def test_creation_full() -> None: """Test component creation with all attributes.""" bounds = Bounds(lower=-100.0, upper=100.0) - rated_bounds: dict[Metric | int, Bounds] = {Metric.AC_ACTIVE_POWER: bounds} + rated_bounds: dict[Metric | int, Bounds] = {Metric.AC_POWER_ACTIVE: bounds} metadata = {"key1": "value1", "key2": 42} component = _TestComponent( @@ -140,7 +140,7 @@ def test_is_operational_now(mock_datetime: Mock) -> None: name="test", manufacturer="Test Mfg", model_name="Model A", - rated_bounds={Metric.AC_ACTIVE_POWER: Bounds(lower=-100.0, upper=100.0)}, + rated_bounds={Metric.AC_POWER_ACTIVE: Bounds(lower=-100.0, upper=100.0)}, category_specific_metadata={"key": "value"}, ) @@ -151,7 +151,7 @@ def test_is_operational_now(mock_datetime: Mock) -> None: name=COMPONENT.name, manufacturer=COMPONENT.manufacturer, model_name=COMPONENT.model_name, - rated_bounds={Metric.AC_ACTIVE_POWER: Bounds(lower=-200.0, upper=200.0)}, + rated_bounds={Metric.AC_POWER_ACTIVE: Bounds(lower=-200.0, upper=200.0)}, category_specific_metadata={"different": "metadata"}, ) diff --git a/tests/component/test_data_samples.py b/tests/component/test_data_samples.py index d6c4645..b689569 100644 --- a/tests/component/test_data_samples.py +++ b/tests/component/test_data_samples.py @@ -56,7 +56,7 @@ def timestamp() -> datetime: def metric_sample(timestamp: datetime) -> MetricSample: """Provide a test metric sample.""" return MetricSample( - metric=Metric.AC_ACTIVE_POWER, + metric=Metric.AC_POWER_ACTIVE, value=100.0, bounds=[], sampled_at=timestamp, @@ -174,7 +174,7 @@ class _ComponentDataSamplesConversionTestCase: metric_samples=[ metrics_pb2.MetricSample( sample_time=TIMESTAMP, - metric=Metric.AC_ACTIVE_POWER.value, + metric=Metric.AC_POWER_ACTIVE.value, value=metrics_pb2.MetricValueVariant( simple_metric=metrics_pb2.SimpleMetricValue(value=100.0) ), @@ -186,7 +186,7 @@ class _ComponentDataSamplesConversionTestCase: metric_samples=[ MetricSample( sampled_at=DATETIME, - metric=Metric.AC_ACTIVE_POWER, + metric=Metric.AC_POWER_ACTIVE, value=100.0, bounds=[], ) @@ -289,14 +289,14 @@ class _ComponentDataSamplesConversionTestCase: metric_samples=[ metrics_pb2.MetricSample( # Simple metric sample_time=TIMESTAMP, - metric=Metric.AC_ACTIVE_POWER.value, + metric=Metric.AC_POWER_ACTIVE.value, value=metrics_pb2.MetricValueVariant( simple_metric=metrics_pb2.SimpleMetricValue(value=150.0) ), ), metrics_pb2.MetricSample( # Aggregated metric sample_time=TIMESTAMP, - metric=Metric.AC_REACTIVE_POWER.value, + metric=Metric.AC_POWER_REACTIVE.value, value=metrics_pb2.MetricValueVariant( aggregated_metric=metrics_pb2.AggregatedMetricValue( avg_value=75.0, @@ -339,13 +339,13 @@ class _ComponentDataSamplesConversionTestCase: metric_samples=[ MetricSample( sampled_at=DATETIME, - metric=Metric.AC_ACTIVE_POWER, + metric=Metric.AC_POWER_ACTIVE, value=150.0, bounds=[], ), MetricSample( sampled_at=DATETIME, - metric=Metric.AC_REACTIVE_POWER, + metric=Metric.AC_POWER_REACTIVE, value=AggregatedMetricValue( avg=75.0, min=70.0, max=80.0, raw_values=[70.0, 75.0, 80.0] ), diff --git a/tests/metrics/test_sample.py b/tests/metrics/test_sample.py index 42ec03e..538430e 100644 --- a/tests/metrics/test_sample.py +++ b/tests/metrics/test_sample.py @@ -163,13 +163,13 @@ def test_metric_sample_creation( bounds = [Bounds(lower=-10.0, upper=10.0)] sample = MetricSample( sampled_at=now, - metric=Metric.AC_ACTIVE_POWER, + metric=Metric.AC_POWER_ACTIVE, value=value, bounds=bounds, connection=connection, ) assert sample.sampled_at == now - assert sample.metric == Metric.AC_ACTIVE_POWER + assert sample.metric == Metric.AC_POWER_ACTIVE assert sample.value == value assert sample.bounds == bounds assert sample.connection == connection @@ -222,7 +222,7 @@ def test_metric_sample_as_single_value( sample = MetricSample( sampled_at=now, - metric=Metric.AC_ACTIVE_POWER, + metric=Metric.AC_POWER_ACTIVE, value=value, bounds=bounds, ) @@ -239,7 +239,7 @@ def test_metric_sample_multiple_bounds(now: datetime) -> None: ] sample = MetricSample( sampled_at=now, - metric=Metric.AC_ACTIVE_POWER, + metric=Metric.AC_POWER_ACTIVE, value=7.0, bounds=bounds, ) @@ -304,14 +304,14 @@ def test_aggregated_metric_value_from_proto(case: _AggregatedValueTestCase) -> N name="simple_value", proto_message=metrics_pb2.MetricSample( sample_time=TIMESTAMP, - metric=Metric.AC_ACTIVE_POWER.value, + metric=Metric.AC_POWER_ACTIVE.value, value=metrics_pb2.MetricValueVariant( simple_metric=metrics_pb2.SimpleMetricValue(value=5.0) ), ), expected_sample=MetricSample( sampled_at=DATETIME, - metric=Metric.AC_ACTIVE_POWER, + metric=Metric.AC_POWER_ACTIVE, value=5.0, bounds=[], connection=None, @@ -321,7 +321,7 @@ def test_aggregated_metric_value_from_proto(case: _AggregatedValueTestCase) -> N name="aggregated_value", proto_message=metrics_pb2.MetricSample( sample_time=TIMESTAMP, - metric=Metric.AC_ACTIVE_POWER.value, + metric=Metric.AC_POWER_ACTIVE.value, value=metrics_pb2.MetricValueVariant( aggregated_metric=metrics_pb2.AggregatedMetricValue( avg_value=5.0, min_value=1.0, max_value=10.0 @@ -330,7 +330,7 @@ def test_aggregated_metric_value_from_proto(case: _AggregatedValueTestCase) -> N ), expected_sample=MetricSample( sampled_at=DATETIME, - metric=Metric.AC_ACTIVE_POWER, + metric=Metric.AC_POWER_ACTIVE, value=AggregatedMetricValue(avg=5.0, min=1.0, max=10.0, raw_values=[]), bounds=[], connection=None, @@ -340,11 +340,11 @@ def test_aggregated_metric_value_from_proto(case: _AggregatedValueTestCase) -> N name="no_value", proto_message=metrics_pb2.MetricSample( sample_time=TIMESTAMP, - metric=Metric.AC_ACTIVE_POWER.value, + metric=Metric.AC_POWER_ACTIVE.value, ), expected_sample=MetricSample( sampled_at=DATETIME, - metric=Metric.AC_ACTIVE_POWER, + metric=Metric.AC_POWER_ACTIVE, value=None, bounds=[], connection=None, @@ -367,7 +367,7 @@ def test_aggregated_metric_value_from_proto(case: _AggregatedValueTestCase) -> N name="with_valid_bounds", proto_message=metrics_pb2.MetricSample( sample_time=TIMESTAMP, - metric=Metric.AC_ACTIVE_POWER.value, + metric=Metric.AC_POWER_ACTIVE.value, value=metrics_pb2.MetricValueVariant( simple_metric=metrics_pb2.SimpleMetricValue(value=5.0) ), @@ -375,7 +375,7 @@ def test_aggregated_metric_value_from_proto(case: _AggregatedValueTestCase) -> N ), expected_sample=MetricSample( sampled_at=DATETIME, - metric=Metric.AC_ACTIVE_POWER, + metric=Metric.AC_POWER_ACTIVE, value=5.0, bounds=[Bounds(lower=-10.0, upper=10.0)], connection=None, @@ -385,7 +385,7 @@ def test_aggregated_metric_value_from_proto(case: _AggregatedValueTestCase) -> N name="with_invalid_bounds", proto_message=metrics_pb2.MetricSample( sample_time=TIMESTAMP, - metric=Metric.AC_ACTIVE_POWER.value, + metric=Metric.AC_POWER_ACTIVE.value, value=metrics_pb2.MetricValueVariant( simple_metric=metrics_pb2.SimpleMetricValue(value=5.0) ), @@ -396,14 +396,14 @@ def test_aggregated_metric_value_from_proto(case: _AggregatedValueTestCase) -> N ), expected_sample=MetricSample( sampled_at=DATETIME, - metric=Metric.AC_ACTIVE_POWER, + metric=Metric.AC_POWER_ACTIVE, value=5.0, bounds=[Bounds(lower=-10.0, upper=10.0)], # Invalid bounds are ignored connection=None, ), expected_major_issues=[ ( - "bounds for AC_ACTIVE_POWER is invalid (Lower bound (10.0) must be " + "bounds for AC_POWER_ACTIVE is invalid (Lower bound (10.0) must be " "less than or equal to upper bound (-10.0)), ignoring these bounds" ) ], @@ -412,7 +412,7 @@ def test_aggregated_metric_value_from_proto(case: _AggregatedValueTestCase) -> N name="with_source", proto_message=metrics_pb2.MetricSample( sample_time=TIMESTAMP, - metric=Metric.AC_ACTIVE_POWER.value, + metric=Metric.AC_POWER_ACTIVE.value, value=metrics_pb2.MetricValueVariant( simple_metric=metrics_pb2.SimpleMetricValue(value=5.0) ), @@ -420,7 +420,7 @@ def test_aggregated_metric_value_from_proto(case: _AggregatedValueTestCase) -> N ), expected_sample=MetricSample( sampled_at=DATETIME, - metric=Metric.AC_ACTIVE_POWER, + metric=Metric.AC_POWER_ACTIVE, value=5.0, bounds=[], connection="dc_battery_0",