diff --git a/pyproject.toml b/pyproject.toml index 7e8ca2d4..b7eb64cc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,10 +36,12 @@ 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", + "frequenz-core >= 1.3.0, < 2.0.0", "grpcio >= 1.72.1, < 2", "protobuf >= 6.31.1, < 7", "typing-extensions >= 4.13.0, < 5", @@ -129,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/_client.py b/src/frequenz/client/microgrid/_client.py index 5477d0c0..072db2e4 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 1746f608..64994b2c 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 7824757c..4b99e0b8 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 c4667634..37ae45ff 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 301fadaf..ee207870 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 b1f65c9a..8fbe328d 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 0640cdeb..c2f74dc4 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/__init__.py b/src/frequenz/client/microgrid/component/__init__.py index 3341da06..e6dee160 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 ( @@ -52,7 +51,6 @@ ) from ._relay import Relay from ._state_sample import ComponentErrorCode, ComponentStateCode, ComponentStateSample -from ._status import ComponentStatus from ._types import ( ComponentTypes, ProblematicComponentTypes, @@ -75,7 +73,6 @@ "ComponentErrorCode", "ComponentStateCode", "ComponentStateSample", - "ComponentStatus", "ComponentTypes", "Converter", "CryptoMiner", @@ -84,7 +81,6 @@ "EvCharger", "EvChargerType", "EvChargerTypes", - "Fuse", "GridConnectionPoint", "Hvac", "HybridEvCharger", diff --git a/src/frequenz/client/microgrid/component/_battery.py b/src/frequenz/client/microgrid/component/_battery.py index d6f4bf1a..72c52eeb 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 1f5bff0e..e3e4b4cc 100644 --- a/src/frequenz/client/microgrid/component/_category.py +++ b/src/frequenz/client/microgrid/component/_category.py @@ -3,46 +3,61 @@ """The component categories that can be used in a microgrid.""" -import enum - -from frequenz.api.common.v1.microgrid.components import components_pb2 +from frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_pb2, +) +from frequenz.core import enum @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 = 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 + 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 +65,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,20 +76,31 @@ class ComponentCategory(enum.Enum): external precharging modules. """ - FUSE = components_pb2.COMPONENT_CATEGORY_FUSE - """A fuse.""" + 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. - VOLTAGE_TRANSFORMER = components_pb2.COMPONENT_CATEGORY_VOLTAGE_TRANSFORMER - """A voltage transformer. + 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 = enum.deprecated_member( + electrical_components_pb2.ELECTRICAL_COMPONENT_CATEGORY_POWER_TRANSFORMER, + "VOLTAGE_TRANSFORMER is deprecated, use POWER_TRANSFORMER instead", + ) + """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.py b/src/frequenz/client/microgrid/component/_component.py index d4a8d535..40954b20 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 21e9c697..4da31fc9 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 @@ -38,7 +40,6 @@ UnrecognizedEvCharger, UnspecifiedEvCharger, ) -from ._fuse import Fuse from ._grid_connection_point import GridConnectionPoint from ._hvac import Hvac from ._inverter import ( @@ -57,7 +58,6 @@ UnspecifiedComponent, ) from ._relay import Relay -from ._status import ComponentStatus from ._types import ComponentTypes from ._voltage_transformer import VoltageTransformer @@ -69,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,15 +112,14 @@ 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] + 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], @@ -148,12 +149,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 ) @@ -170,21 +165,24 @@ 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") + 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( @@ -194,17 +192,16 @@ def component_base_from_proto_with_issues( manufacturer, model_name, category, - status, 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], @@ -230,10 +227,9 @@ 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, + category_specific_metadata=base_data.category_specific_info, rated_bounds=base_data.rated_bounds, ) @@ -245,7 +241,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, @@ -267,7 +262,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, ) @@ -280,7 +274,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: @@ -292,7 +286,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, ) @@ -304,7 +297,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, @@ -324,7 +316,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 ( @@ -341,7 +333,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, ) @@ -355,29 +346,16 @@ 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, ) 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_CONNECTION_POINT | ComponentCategory.GRID: + rated_fuse_current = ( + message.category_specific_info.grid_connection_point.rated_fuse_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. return GridConnectionPoint( id=base_data.component_id, @@ -385,7 +363,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, @@ -406,7 +383,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 ( @@ -423,7 +400,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, ) @@ -437,25 +413,25 @@ 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, ) 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, 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, - 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) @@ -489,7 +465,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 @@ -541,7 +517,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 7f7e97b3..c8bb1013 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 326e98f7..e4838550 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 8e1605e7..5a7deb34 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/_fuse.py b/src/frequenz/client/microgrid/component/_fuse.py deleted file mode 100644 index fc4455b1..00000000 --- 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/_grid_connection_point.py b/src/frequenz/client/microgrid/component/_grid_connection_point.py index 24c72c0c..bf463c8c 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/_inverter.py b/src/frequenz/client/microgrid/component/_inverter.py index 8f7001c6..a49395df 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 c69381c1..5829f8ac 100644 --- a/src/frequenz/client/microgrid/component/_state_sample.py +++ b/src/frequenz/client/microgrid/component/_state_sample.py @@ -3,92 +3,106 @@ """Definition of component states.""" -import enum 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, +) +from frequenz.core import enum @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.""" @@ -96,134 +110,185 @@ class ComponentStateCode(enum.Enum): 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 = 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. + + 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 bfdf122d..efba45bd 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/component/_status.py b/src/frequenz/client/microgrid/component/_status.py deleted file mode 100644 index 727ee248..00000000 --- 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/src/frequenz/client/microgrid/component/_types.py b/src/frequenz/client/microgrid/component/_types.py index e362ab73..043a7bed 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/src/frequenz/client/microgrid/component/_voltage_transformer.py b/src/frequenz/client/microgrid/component/_voltage_transformer.py index af9f367f..d32d66b3 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/src/frequenz/client/microgrid/metrics/_bounds_proto.py b/src/frequenz/client/microgrid/metrics/_bounds_proto.py index 2a40f64a..e4466187 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 4754e88c..61bc4a76 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.v1.metrics import metric_sample_pb2 +from frequenz.api.common.v1alpha8.metrics import metrics_pb2 +from frequenz.core import enum @enum.unique @@ -26,239 +25,423 @@ 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_POWER_APPARENT = 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 = 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 = metric_sample_pb2.METRIC_AC_APPARENT_POWER_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 = metric_sample_pb2.METRIC_AC_APPARENT_POWER_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 = metric_sample_pb2.METRIC_AC_ACTIVE_POWER + 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 = metric_sample_pb2.METRIC_AC_ACTIVE_POWER_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 = metric_sample_pb2.METRIC_AC_ACTIVE_POWER_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 = metric_sample_pb2.METRIC_AC_ACTIVE_POWER_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 = metric_sample_pb2.METRIC_AC_REACTIVE_POWER + 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 = metric_sample_pb2.METRIC_AC_REACTIVE_POWER_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 = metric_sample_pb2.METRIC_AC_REACTIVE_POWER_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 = metric_sample_pb2.METRIC_AC_REACTIVE_POWER_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_POWER_FACTOR = metric_sample_pb2.METRIC_AC_POWER_FACTOR + 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.""" - 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_ENERGY_APPARENT = 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 = 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 = metric_sample_pb2.METRIC_AC_APPARENT_ENERGY_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 = metric_sample_pb2.METRIC_AC_APPARENT_ENERGY_PHASE_3 - """The alternating current apparent energy in 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). - AC_ACTIVE_ENERGY = metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY - """The alternating current active energy.""" + Deprecated: Deprecated in v0.18.0 + Use [`AC_ENERGY_APPARENT_PHASE_2`][frequenz.client.microgrid.metrics.Metric.AC_ENERGY_APPARENT_PHASE_2] + instead. + """ - AC_ACTIVE_ENERGY_PHASE_1 = metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY_PHASE_1 - """The alternating current active energy in phase 1.""" + AC_ENERGY_APPARENT_PHASE_3 = metrics_pb2.METRIC_AC_ENERGY_APPARENT_PHASE_3 + """The alternating current apparent energy in phase 3.""" - AC_ACTIVE_ENERGY_PHASE_2 = metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY_PHASE_2 - """The alternating current active energy in phase 2.""" + 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). - AC_ACTIVE_ENERGY_PHASE_3 = metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY_PHASE_3 - """The alternating current active energy in phase 3.""" + Deprecated: Deprecated in v0.18.0 + Use [`AC_ENERGY_APPARENT_PHASE_3`][frequenz.client.microgrid.metrics.Metric.AC_ENERGY_APPARENT_PHASE_3] + instead. + """ - AC_ACTIVE_ENERGY_CONSUMED = metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY_CONSUMED - """The alternating current active energy consumed.""" + AC_ENERGY_ACTIVE = metrics_pb2.METRIC_AC_ENERGY_ACTIVE + """The alternating current active energy.""" - AC_ACTIVE_ENERGY_CONSUMED_PHASE_1 = ( - metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY_CONSUMED_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 consumed in phase 1.""" + """The alternating current active energy (deprecated). - AC_ACTIVE_ENERGY_CONSUMED_PHASE_2 = ( - metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY_CONSUMED_PHASE_2 - ) - """The alternating current active energy consumed in phase 2.""" + 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_CONSUMED_PHASE_3 = ( - metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY_CONSUMED_PHASE_3 + 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 consumed in phase 3.""" + """The alternating current active energy in phase 1 (deprecated). - AC_ACTIVE_ENERGY_DELIVERED = metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY_DELIVERED - """The alternating current active energy delivered.""" + Deprecated: Deprecated in v0.18.0 + Use [`AC_ENERGY_ACTIVE_PHASE_1`][frequenz.client.microgrid.metrics.Metric.AC_ENERGY_ACTIVE_PHASE_1] + instead. + """ - AC_ACTIVE_ENERGY_DELIVERED_PHASE_1 = ( - metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY_DELIVERED_PHASE_1 - ) - """The alternating current active energy delivered in phase 1.""" + AC_ENERGY_ACTIVE_PHASE_2 = metrics_pb2.METRIC_AC_ENERGY_ACTIVE_PHASE_2 + """The alternating current active energy in phase 2.""" - AC_ACTIVE_ENERGY_DELIVERED_PHASE_2 = ( - metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY_DELIVERED_PHASE_2 + 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 delivered in phase 2.""" + """The alternating current active energy in phase 2 (deprecated). - AC_ACTIVE_ENERGY_DELIVERED_PHASE_3 = ( - metric_sample_pb2.METRIC_AC_ACTIVE_ENERGY_DELIVERED_PHASE_3 - ) - """The alternating current active energy delivered in phase 3.""" + Deprecated: Deprecated in v0.18.0 + Use [`AC_ENERGY_ACTIVE_PHASE_2`][frequenz.client.microgrid.metrics.Metric.AC_ENERGY_ACTIVE_PHASE_2] + instead. + """ - AC_REACTIVE_ENERGY = metric_sample_pb2.METRIC_AC_REACTIVE_ENERGY - """The alternating current reactive energy.""" + AC_ENERGY_ACTIVE_PHASE_3 = metrics_pb2.METRIC_AC_ENERGY_ACTIVE_PHASE_3 + """The alternating current active energy in phase 3.""" - AC_REACTIVE_ENERGY_PHASE_1 = metric_sample_pb2.METRIC_AC_REACTIVE_ENERGY_PHASE_1 - """The alternating current reactive energy in phase 1.""" + 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). - AC_REACTIVE_ENERGY_PHASE_2 = metric_sample_pb2.METRIC_AC_REACTIVE_ENERGY_PHASE_2 - """The alternating current reactive energy in phase 2.""" + Deprecated: Deprecated in v0.18.0 + Use [`AC_ENERGY_ACTIVE_PHASE_3`][frequenz.client.microgrid.metrics.Metric.AC_ENERGY_ACTIVE_PHASE_3] + instead. + """ - AC_REACTIVE_ENERGY_PHASE_3 = metric_sample_pb2.METRIC_AC_REACTIVE_ENERGY_PHASE_3 - """The alternating current reactive energy in phase 3.""" + AC_ENERGY_ACTIVE_CONSUMED = metrics_pb2.METRIC_AC_ENERGY_ACTIVE_CONSUMED + """The alternating current active energy consumed.""" - AC_TOTAL_HARMONIC_DISTORTION_CURRENT = ( - metric_sample_pb2.METRIC_AC_TOTAL_HARMONIC_DISTORTION_CURRENT + 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 total harmonic distortion current.""" + """The alternating current active energy consumed (deprecated). - AC_TOTAL_HARMONIC_DISTORTION_CURRENT_PHASE_1 = ( - metric_sample_pb2.METRIC_AC_TOTAL_HARMONIC_DISTORTION_CURRENT_PHASE_1 - ) - """The alternating current total harmonic distortion current in phase 1.""" + Deprecated: Deprecated in v0.18.0 + Use [`AC_ENERGY_ACTIVE_CONSUMED`][frequenz.client.microgrid.metrics.Metric.AC_ENERGY_ACTIVE_CONSUMED] + instead. + """ - AC_TOTAL_HARMONIC_DISTORTION_CURRENT_PHASE_2 = ( - metric_sample_pb2.METRIC_AC_TOTAL_HARMONIC_DISTORTION_CURRENT_PHASE_2 + AC_ENERGY_ACTIVE_CONSUMED_PHASE_1 = ( + metrics_pb2.METRIC_AC_ENERGY_ACTIVE_CONSUMED_PHASE_1 ) - """The alternating current total harmonic distortion current in phase 2.""" + """The alternating current active energy consumed in phase 1.""" - AC_TOTAL_HARMONIC_DISTORTION_CURRENT_PHASE_3 = ( - metric_sample_pb2.METRIC_AC_TOTAL_HARMONIC_DISTORTION_CURRENT_PHASE_3 + AC_ENERGY_ACTIVE_CONSUMED_PHASE_2 = ( + metrics_pb2.METRIC_AC_ENERGY_ACTIVE_CONSUMED_PHASE_2 ) - """The alternating current total harmonic distortion current in phase 3.""" - - BATTERY_CAPACITY = metric_sample_pb2.METRIC_BATTERY_CAPACITY - """The capacity of the battery.""" + """The alternating current active energy consumed in phase 2.""" - BATTERY_SOC_PCT = metric_sample_pb2.METRIC_BATTERY_SOC_PCT - """The state of charge of the battery as a percentage.""" + AC_ENERGY_ACTIVE_CONSUMED_PHASE_3 = ( + metrics_pb2.METRIC_AC_ENERGY_ACTIVE_CONSUMED_PHASE_3 + ) + """The alternating current active energy consumed in phase 3.""" - BATTERY_TEMPERATURE = metric_sample_pb2.METRIC_BATTERY_TEMPERATURE - """The temperature of the battery.""" + AC_ENERGY_ACTIVE_DELIVERED = metrics_pb2.METRIC_AC_ENERGY_ACTIVE_DELIVERED + """The alternating current active energy delivered.""" - INVERTER_TEMPERATURE = metric_sample_pb2.METRIC_INVERTER_TEMPERATURE - """The temperature of the inverter.""" + 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). - INVERTER_TEMPERATURE_CABINET = metric_sample_pb2.METRIC_INVERTER_TEMPERATURE_CABINET - """The temperature of the inverter cabinet.""" + Deprecated: Deprecated in v0.18.0 + Use [`AC_ENERGY_ACTIVE_DELIVERED`][frequenz.client.microgrid.metrics.Metric.AC_ENERGY_ACTIVE_DELIVERED] + instead. + """ - INVERTER_TEMPERATURE_HEATSINK = ( - metric_sample_pb2.METRIC_INVERTER_TEMPERATURE_HEATSINK + AC_ENERGY_ACTIVE_DELIVERED_PHASE_1 = ( + metrics_pb2.METRIC_AC_ENERGY_ACTIVE_DELIVERED_PHASE_1 ) - """The temperature of the inverter heatsink.""" + """The alternating current active energy delivered in phase 1.""" - INVERTER_TEMPERATURE_TRANSFORMER = ( - metric_sample_pb2.METRIC_INVERTER_TEMPERATURE_TRANSFORMER + AC_ENERGY_ACTIVE_DELIVERED_PHASE_2 = ( + metrics_pb2.METRIC_AC_ENERGY_ACTIVE_DELIVERED_PHASE_2 ) - """The temperature of the inverter transformer.""" - - EV_CHARGER_TEMPERATURE = metric_sample_pb2.METRIC_EV_CHARGER_TEMPERATURE - """The temperature of the EV charger.""" + """The alternating current active energy delivered in phase 2.""" - SENSOR_WIND_SPEED = metric_sample_pb2.METRIC_SENSOR_WIND_SPEED - """The speed of the wind measured.""" + AC_ENERGY_ACTIVE_DELIVERED_PHASE_3 = ( + metrics_pb2.METRIC_AC_ENERGY_ACTIVE_DELIVERED_PHASE_3 + ) + """The alternating current active energy delivered in phase 3.""" - SENSOR_WIND_DIRECTION = metric_sample_pb2.METRIC_SENSOR_WIND_DIRECTION - """The direction of the wind measured.""" + AC_ENERGY_REACTIVE = metrics_pb2.METRIC_AC_ENERGY_REACTIVE + """The alternating current reactive energy.""" - SENSOR_TEMPERATURE = metric_sample_pb2.METRIC_SENSOR_TEMPERATURE - """The temperature measured.""" + 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 reactive energy (deprecated). - SENSOR_RELATIVE_HUMIDITY = metric_sample_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 = metric_sample_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 = metric_sample_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 = metric_sample_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/src/frequenz/client/microgrid/metrics/_sample_proto.py b/src/frequenz/client/microgrid/metrics/_sample_proto.py index 314555c5..def7ce4e 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 bff849b0..562d39c5 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 23749044..9ab47605 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 5776eef8..40b4cd81 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 4f1e9f98..12a9d3b7 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 ae554445..99fe4ea0 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,15 +5,10 @@ from typing import Any -from frequenz.api.common.v1.microgrid.components import ( - battery_pb2, - components_pb2, - ev_charger_pb2, - fuse_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 @@ -30,7 +25,6 @@ Electrolyzer, EvCharger, EvChargerType, - Fuse, GridConnectionPoint, Hvac, HybridEvCharger, @@ -61,206 +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=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 + 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) ), ), ] @@ -279,7 +261,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)), @@ -321,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 a5bfe70a..688eeae3 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 b1b28f0a..a3833aa7 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 f30a412c..71b54c07 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 d0a3f194..9b301ec4 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 0209fe8c..62b88941 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 2b95ccdd..cb1e3e36 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 908d01d9..f74049c0 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 ad36194e..22a65a65 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 6091bc6b..5ef67247 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 56afa09b..e11e86db 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 90133739..b532d419 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 e5341ca8..d614a815 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 d0a7e44c..4f59cbe0 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 f5eae1b7..e178ef75 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 8584ad4a..f58fb1d9 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 7bd473ba..32cd963f 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 81855837..a89e3cdb 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 e24d0f8d..7f86ca89 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 cf80d632..3d6270b3 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 b1d2a09f..2e9d4a75 100644 --- a/tests/component/component_proto/conftest.py +++ b/tests/component/component_proto/conftest.py @@ -6,20 +6,18 @@ 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 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,10 +56,9 @@ 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={}, + rated_bounds={Metric.AC_ENERGY_ACTIVE: Bounds(lower=0, upper=100)}, + category_specific_info={}, category_mismatched=False, ) @@ -74,25 +71,21 @@ 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 + 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 "", 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) @@ -115,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 4c20ae97..31143b79 100644 --- a/tests/component/component_proto/test_base.py +++ b/tests/component/component_proto/test_base.py @@ -4,12 +4,13 @@ """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 frequenz.api.common.v1alpha8.microgrid.electrical_components import ( + electrical_components_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,11 +36,10 @@ 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.""" + """Test parsing with missing optional category specific info.""" major_issues: list[str] = [] minor_issues: list[str] = [] base_data = default_component_base_data._replace( @@ -47,10 +47,9 @@ def test_missing_metadata( manufacturer=None, model_name=None, category=ComponentCategory.UNSPECIFIED, - status=status, lifetime=Lifetime(), rated_bounds={}, - category_specific_metadata={}, + category_specific_info={}, ) proto = base_data_as_proto(base_data) proto.ClearField("operational_lifetime") @@ -60,12 +59,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", @@ -77,31 +71,35 @@ def test_missing_metadata( 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 ) # 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 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( diff --git a/tests/component/component_proto/test_simple.py b/tests/component/component_proto/test_simple.py index 960a27d6..ec755f43 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, @@ -17,7 +19,6 @@ Converter, CryptoMiner, Electrolyzer, - Fuse, GridConnectionPoint, Hvac, Meter, @@ -73,27 +74,31 @@ 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 ) # 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) - assert component.category == ComponentCategory.GRID + assert component.category == ComponentCategory.GRID_CONNECTION_POINT @pytest.mark.parametrize( @@ -140,14 +145,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 @@ -165,33 +170,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, @@ -200,11 +178,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 @@ -233,7 +215,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], @@ -245,7 +227,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 99640d5b..f7ba8107 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_battery.py b/tests/component/test_battery.py index 828aa9bf..b9ddfc01 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 c16ff5d5..5a5ea77c 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 4b2b2532..9fcd5ea1 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 @@ -55,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( @@ -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,11 +137,10 @@ 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", - 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"}, ) @@ -165,31 +148,17 @@ 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, - 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"}, ) -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_connection_proto.py b/tests/component/test_connection_proto.py index 90b7ef27..bad7eb67 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_converter.py b/tests/component/test_converter.py index 29a284ef..fee15fa2 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 9a3a2bd6..95b17858 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_data_samples.py b/tests/component/test_data_samples.py index 052b89c9..b689569d 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: @@ -48,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, @@ -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, - metric=Metric.AC_ACTIVE_POWER.value, - value=metric_sample_pb2.MetricValueVariant( - simple_metric=metric_sample_pb2.SimpleMetricValue( - value=100.0 - ) + metrics_pb2.MetricSample( + sample_time=TIMESTAMP, + metric=Metric.AC_POWER_ACTIVE.value, + value=metrics_pb2.MetricValueVariant( + simple_metric=metrics_pb2.SimpleMetricValue(value=100.0) ), ) ], @@ -178,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=[], ) @@ -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, - metric=Metric.AC_ACTIVE_POWER.value, - value=metric_sample_pb2.MetricValueVariant( - simple_metric=metric_sample_pb2.SimpleMetricValue( - value=150.0 - ) + metrics_pb2.MetricSample( # Simple metric + sample_time=TIMESTAMP, + metric=Metric.AC_POWER_ACTIVE.value, + value=metrics_pb2.MetricValueVariant( + simple_metric=metrics_pb2.SimpleMetricValue(value=150.0) ), ), - metric_sample_pb2.MetricSample( # Aggregated metric - sampled_at=TIMESTAMP, - metric=Metric.AC_REACTIVE_POWER.value, - value=metric_sample_pb2.MetricValueVariant( - aggregated_metric=metric_sample_pb2.AggregatedMetricValue( + metrics_pb2.MetricSample( # Aggregated metric + sample_time=TIMESTAMP, + metric=Metric.AC_POWER_REACTIVE.value, + 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], ) ], ), @@ -329,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/component/test_electrolyzer.py b/tests/component/test_electrolyzer.py index 61eeb1e5..0a107378 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 5b9eaf40..705970b9 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_fuse.py b/tests/component/test_fuse.py deleted file mode 100644 index e1ae2cd5..00000000 --- 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, - ) diff --git a/tests/component/test_grid_connection_point.py b/tests/component/test_grid_connection_point.py index 3f102f10..7ee88c3f 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,8 +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.status == ComponentStatus.ACTIVE - assert grid_point.category == ComponentCategory.GRID + assert grid_point.category == ComponentCategory.GRID_CONNECTION_POINT 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 ff398797..3fca3d52 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 c598ce42..db1b356b 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 80ed02f6..90f6c3f2 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 16edfd0d..413e3727 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 8ab8feba..63002c47 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 2ad82df8..0cfd1b64 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_state_sample.py b/tests/component/test_state_sample.py index 4152f00e..70660a5f 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/component/test_voltage_transformer.py b/tests/component/test_voltage_transformer.py index ca70a481..0240bac8 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.category == ComponentCategory.POWER_TRANSFORMER assert voltage_transformer.primary_voltage == pytest.approx(primary) assert voltage_transformer.secondary_voltage == pytest.approx(secondary) diff --git a/tests/metrics/test_bounds.py b/tests/metrics/test_bounds.py index cf783028..383f229b 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 2c427d4c..538430eb 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 @@ -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, ) @@ -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,16 +302,16 @@ def test_aggregated_metric_value_from_proto(case: _AggregatedValueTestCase) -> N [ _MetricSampleConversionTestCase( name="simple_value", - proto_message=metric_sample_pb2.MetricSample( - sampled_at=TIMESTAMP, - metric=Metric.AC_ACTIVE_POWER.value, - value=metric_sample_pb2.MetricValueVariant( - simple_metric=metric_sample_pb2.SimpleMetricValue(value=5.0) + proto_message=metrics_pb2.MetricSample( + sample_time=TIMESTAMP, + 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, @@ -319,18 +319,18 @@ def test_aggregated_metric_value_from_proto(case: _AggregatedValueTestCase) -> N ), _MetricSampleConversionTestCase( name="aggregated_value", - proto_message=metric_sample_pb2.MetricSample( - sampled_at=TIMESTAMP, - metric=Metric.AC_ACTIVE_POWER.value, - value=metric_sample_pb2.MetricValueVariant( - aggregated_metric=metric_sample_pb2.AggregatedMetricValue( + proto_message=metrics_pb2.MetricSample( + sample_time=TIMESTAMP, + 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 ) ), ), 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, @@ -338,13 +338,13 @@ def test_aggregated_metric_value_from_proto(case: _AggregatedValueTestCase) -> N ), _MetricSampleConversionTestCase( name="no_value", - proto_message=metric_sample_pb2.MetricSample( - sampled_at=TIMESTAMP, - metric=Metric.AC_ACTIVE_POWER.value, + proto_message=metrics_pb2.MetricSample( + sample_time=TIMESTAMP, + 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, @@ -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,17 +365,17 @@ def test_aggregated_metric_value_from_proto(case: _AggregatedValueTestCase) -> N ), _MetricSampleConversionTestCase( name="with_valid_bounds", - proto_message=metric_sample_pb2.MetricSample( - sampled_at=TIMESTAMP, - metric=Metric.AC_ACTIVE_POWER.value, - value=metric_sample_pb2.MetricValueVariant( - simple_metric=metric_sample_pb2.SimpleMetricValue(value=5.0) + proto_message=metrics_pb2.MetricSample( + sample_time=TIMESTAMP, + metric=Metric.AC_POWER_ACTIVE.value, + value=metrics_pb2.MetricValueVariant( + simple_metric=metrics_pb2.SimpleMetricValue(value=5.0) ), bounds=[bounds_pb2.Bounds(lower=-10.0, upper=10.0)], ), 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, @@ -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, - metric=Metric.AC_ACTIVE_POWER.value, - value=metric_sample_pb2.MetricValueVariant( - simple_metric=metric_sample_pb2.SimpleMetricValue(value=5.0) + proto_message=metrics_pb2.MetricSample( + sample_time=TIMESTAMP, + metric=Metric.AC_POWER_ACTIVE.value, + value=metrics_pb2.MetricValueVariant( + simple_metric=metrics_pb2.SimpleMetricValue(value=5.0) ), bounds=[ bounds_pb2.Bounds(lower=-10.0, upper=10.0), @@ -396,31 +396,31 @@ 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" ) ], ), _MetricSampleConversionTestCase( name="with_source", - proto_message=metric_sample_pb2.MetricSample( - sampled_at=TIMESTAMP, - metric=Metric.AC_ACTIVE_POWER.value, - value=metric_sample_pb2.MetricValueVariant( - simple_metric=metric_sample_pb2.SimpleMetricValue(value=5.0) + proto_message=metrics_pb2.MetricSample( + sample_time=TIMESTAMP, + metric=Metric.AC_POWER_ACTIVE.value, + 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, - metric=Metric.AC_ACTIVE_POWER, + metric=Metric.AC_POWER_ACTIVE, value=5.0, bounds=[], connection="dc_battery_0", diff --git a/tests/test_client.py b/tests/test_client.py index 06054785..0635c805 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 2d9fbb4c..72504ed2 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 0de6d0e5..2040286a 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 15450edf..abf4dd83 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 8b9a90f6..b1f27f32 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 ( diff --git a/tests/util.py b/tests/util.py index 05c42d0c..5787cc07 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) @@ -1243,7 +1247,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: