Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from dataclasses import dataclass
from datetime import datetime

from ...microgrid.component._component import ComponentMetricId
from ...microgrid.component._component import ComponentId, ComponentMetricId


@dataclass
Expand All @@ -24,7 +24,7 @@ class ComponentMetricRequest:
possible.
"""

component_id: int
component_id: ComponentId
"""The ID of the requested component."""

metric_id: ComponentMetricId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
BatteryData,
ComponentCategory,
ComponentData,
ComponentId,
InverterData,
)
from ._component_status import (
Expand All @@ -40,7 +41,7 @@

@dataclass
class _ComponentStreamStatus:
component_id: int
component_id: ComponentId
"""Component id."""

data_recv_timer: Timer
Expand Down Expand Up @@ -165,7 +166,7 @@ class BatteryStatusTracker(ComponentStatusTracker):
@override
def __init__( # pylint: disable=too-many-arguments
self,
component_id: int,
component_id: ComponentId,
max_data_age_sec: float,
max_blocking_duration_sec: float,
status_sender: Sender[ComponentStatus],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

from frequenz.channels import Receiver, Sender

from ...microgrid.component._component import ComponentId


@dataclass
class ComponentPoolStatus:
Expand Down Expand Up @@ -58,7 +60,7 @@ class ComponentStatusEnum(enum.Enum):
class ComponentStatus:
"""Status of a single component."""

component_id: int
component_id: ComponentId
"""Component ID."""

value: ComponentStatusEnum
Expand All @@ -82,7 +84,7 @@ class ComponentStatusTracker(ABC):
@abstractmethod
def __init__( # pylint: disable=too-many-arguments
self,
component_id: int,
component_id: ComponentId,
max_data_age_sec: float,
max_blocking_duration_sec: float,
status_sender: Sender[ComponentStatus],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from typing import NamedTuple, Sequence

from ...._internal._math import is_close_to_zero
from ....microgrid.component import BatteryData, InverterData
from ....microgrid.component import BatteryData, ComponentId, InverterData
from ..result import PowerBounds

_logger = logging.getLogger(__name__)
Expand All @@ -19,7 +19,7 @@
class AggregatedBatteryData:
"""Aggregated battery data."""

component_id: int
component_id: ComponentId
"""The component ID of the first battery.

This is only used to identify the pair of battery and inverter.
Expand Down
33 changes: 18 additions & 15 deletions src/frequenz/sdk/microgrid/client/_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
BatteryData,
Component,
ComponentCategory,
ComponentId,
EVChargerData,
InverterData,
MeterData,
Expand Down Expand Up @@ -93,7 +94,7 @@ async def connections(
@abstractmethod
async def meter_data(
self,
component_id: int,
component_id: ComponentId,
maxsize: int = RECEIVER_MAX_SIZE,
) -> Receiver[MeterData]:
"""Return a channel receiver that provides a `MeterData` stream.
Expand All @@ -113,7 +114,7 @@ async def meter_data(
@abstractmethod
async def battery_data(
self,
component_id: int,
component_id: ComponentId,
maxsize: int = RECEIVER_MAX_SIZE,
) -> Receiver[BatteryData]:
"""Return a channel receiver that provides a `BatteryData` stream.
Expand All @@ -133,7 +134,7 @@ async def battery_data(
@abstractmethod
async def inverter_data(
self,
component_id: int,
component_id: ComponentId,
maxsize: int = RECEIVER_MAX_SIZE,
) -> Receiver[InverterData]:
"""Return a channel receiver that provides an `InverterData` stream.
Expand All @@ -153,7 +154,7 @@ async def inverter_data(
@abstractmethod
async def ev_charger_data(
self,
component_id: int,
component_id: ComponentId,
maxsize: int = RECEIVER_MAX_SIZE,
) -> Receiver[EVChargerData]:
"""Return a channel receiver that provides an `EvChargeData` stream.
Expand All @@ -171,7 +172,7 @@ async def ev_charger_data(
"""

@abstractmethod
async def set_power(self, component_id: int, power_w: float) -> None:
async def set_power(self, component_id: ComponentId, power_w: float) -> None:
"""Send request to the Microgrid to set power for component.

If power > 0, then component will be charged with this power.
Expand All @@ -185,7 +186,9 @@ async def set_power(self, component_id: int, power_w: float) -> None:
"""

@abstractmethod
async def set_bounds(self, component_id: int, lower: float, upper: float) -> None:
async def set_bounds(
self, component_id: ComponentId, lower: float, upper: float
) -> None:
"""Send `SetBoundsParam`s received from a channel to the Microgrid service.

Args:
Expand Down Expand Up @@ -367,7 +370,7 @@ async def connections(

async def _component_data_task(
self,
component_id: int,
component_id: ComponentId,
transform: Callable[[microgrid_pb.ComponentData], _GenericComponentData],
sender: Sender[_GenericComponentData],
) -> None:
Expand Down Expand Up @@ -421,7 +424,7 @@ async def _component_data_task(

def _get_component_data_channel(
self,
component_id: int,
component_id: ComponentId,
transform: Callable[[microgrid_pb.ComponentData], _GenericComponentData],
) -> Broadcast[_GenericComponentData]:
"""Return the broadcast channel for a given component_id.
Expand Down Expand Up @@ -456,7 +459,7 @@ def _get_component_data_channel(

async def _expect_category(
self,
component_id: int,
component_id: ComponentId,
expected_category: ComponentCategory,
) -> None:
"""Check if the given component_id is of the expected type.
Expand Down Expand Up @@ -488,7 +491,7 @@ async def _expect_category(

async def meter_data( # noqa: DOC502 (ValueError is raised indirectly by _expect_category)
self,
component_id: int,
component_id: ComponentId,
maxsize: int = RECEIVER_MAX_SIZE,
) -> Receiver[MeterData]:
"""Return a channel receiver that provides a `MeterData` stream.
Expand Down Expand Up @@ -518,7 +521,7 @@ async def meter_data( # noqa: DOC502 (ValueError is raised indirectly by _expec

async def battery_data( # noqa: DOC502 (ValueError is raised indirectly by _expect_category)
self,
component_id: int,
component_id: ComponentId,
maxsize: int = RECEIVER_MAX_SIZE,
) -> Receiver[BatteryData]:
"""Return a channel receiver that provides a `BatteryData` stream.
Expand Down Expand Up @@ -548,7 +551,7 @@ async def battery_data( # noqa: DOC502 (ValueError is raised indirectly by _exp

async def inverter_data( # noqa: DOC502 (ValueError is raised indirectly by _expect_category)
self,
component_id: int,
component_id: ComponentId,
maxsize: int = RECEIVER_MAX_SIZE,
) -> Receiver[InverterData]:
"""Return a channel receiver that provides an `InverterData` stream.
Expand Down Expand Up @@ -578,7 +581,7 @@ async def inverter_data( # noqa: DOC502 (ValueError is raised indirectly by _ex

async def ev_charger_data( # noqa: DOC502 (ValueError is raised indirectly by _expect_category)
self,
component_id: int,
component_id: ComponentId,
maxsize: int = RECEIVER_MAX_SIZE,
) -> Receiver[EVChargerData]:
"""Return a channel receiver that provides an `EvChargeData` stream.
Expand Down Expand Up @@ -606,7 +609,7 @@ async def ev_charger_data( # noqa: DOC502 (ValueError is raised indirectly by _
EVChargerData.from_proto,
).new_receiver(maxsize=maxsize)

async def set_power(self, component_id: int, power_w: float) -> None:
async def set_power(self, component_id: ComponentId, power_w: float) -> None:
"""Send request to the Microgrid to set power for component.

If power > 0, then component will be charged with this power.
Expand Down Expand Up @@ -644,7 +647,7 @@ async def set_power(self, component_id: int, power_w: float) -> None:

async def set_bounds(
self,
component_id: int,
component_id: ComponentId,
lower: float,
upper: float,
) -> None:
Expand Down
2 changes: 2 additions & 0 deletions src/frequenz/sdk/microgrid/component/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from ._component import (
Component,
ComponentCategory,
ComponentId,
ComponentMetadata,
ComponentMetricId,
GridMetadata,
Expand All @@ -27,6 +28,7 @@
"BatteryData",
"Component",
"ComponentData",
"ComponentId",
"ComponentCategory",
"ComponentMetadata",
"ComponentMetricId",
Expand Down
7 changes: 5 additions & 2 deletions src/frequenz/sdk/microgrid/component/_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from dataclasses import dataclass
from enum import Enum
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, NewType

import frequenz.api.common.components_pb2 as components_pb
import frequenz.api.microgrid.grid_pb2 as grid_pb
Expand All @@ -17,6 +17,9 @@
from ...timeseries import Fuse


ComponentId = NewType("ComponentId", int)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why NewType and not dataclass?

NewType allows this for example: ComponentId(1) + 2 and microgrid.battery_pool(priority=ComponentId(1)) which is just weird.

Also the str and repr looks just like a bare int, which might be good or not (I personally would like to at least have repr use ComponentId(1) instead of just 1.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly, no specific reason, I selected NewType after a quick research, I am not set on using it :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case I would use a dataclass, I see no benefits in using NewType and a few drawbacks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a data class with one member you mean?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup.



class ComponentType(Enum):
"""A base class from which individual component types are derived."""

Expand Down Expand Up @@ -157,7 +160,7 @@ def _component_metadata_from_protobuf(
class Component:
"""Metadata for a single microgrid component."""

component_id: int
component_id: ComponentId
"""The ID of this component."""

category: ComponentCategory
Expand Down
4 changes: 3 additions & 1 deletion src/frequenz/sdk/microgrid/component/_component_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@
import frequenz.api.microgrid.inverter_pb2 as inverter_pb
import frequenz.api.microgrid.microgrid_pb2 as microgrid_pb

from frequenz.sdk.microgrid.component import ComponentId

from ._component_states import EVChargerCableState, EVChargerComponentState


@dataclass(frozen=True)
class ComponentData(ABC):
"""A private base class for strongly typed component data classes."""

component_id: int
component_id: ComponentId
"""The ID identifying this component in the microgrid."""

timestamp: datetime
Expand Down
10 changes: 5 additions & 5 deletions src/frequenz/sdk/microgrid/component_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import networkx as nx

from .client import Connection, MicrogridApiClient
from .component import Component, ComponentCategory, InverterType
from .component import Component, ComponentCategory, ComponentId, InverterType

_logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -80,7 +80,7 @@ def connections(
"""

@abstractmethod
def predecessors(self, component_id: int) -> set[Component]:
def predecessors(self, component_id: ComponentId) -> set[Component]:
"""Fetch the graph predecessors of the specified component.

Args:
Expand All @@ -97,7 +97,7 @@ def predecessors(self, component_id: int) -> set[Component]:
"""

@abstractmethod
def successors(self, component_id: int) -> set[Component]:
def successors(self, component_id: ComponentId) -> set[Component]:
"""Fetch the graph successors of the specified component.

Args:
Expand Down Expand Up @@ -391,7 +391,7 @@ def connections(

return set(map(lambda c: Connection(c[0], c[1]), selection))

def predecessors(self, component_id: int) -> set[Component]:
def predecessors(self, component_id: ComponentId) -> set[Component]:
"""Fetch the graph predecessors of the specified component.

Args:
Expand All @@ -417,7 +417,7 @@ def predecessors(self, component_id: int) -> set[Component]:
map(lambda idx: Component(**self._graph.nodes[idx]), predecessors_ids)
)

def successors(self, component_id: int) -> set[Component]:
def successors(self, component_id: ComponentId) -> set[Component]:
"""Fetch the graph successors of the specified component.

Args:
Expand Down
4 changes: 3 additions & 1 deletion src/frequenz/sdk/timeseries/_grid_frequency.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

from frequenz.channels import Receiver, Sender

from frequenz.sdk.microgrid.component import ComponentId

from ..actor import ChannelRegistry
from ..microgrid import connection_manager
from ..microgrid.component import Component, ComponentCategory, ComponentMetricId
Expand All @@ -24,7 +26,7 @@
_logger = logging.getLogger(__name__)


def create_request(component_id: int) -> ComponentMetricRequest:
def create_request(component_id: ComponentId) -> ComponentMetricRequest:
"""Create a request for grid frequency.

Args:
Expand Down
Loading