Skip to content

Commit 57d539d

Browse files
committed
Add system bounds tracking for components in an EVChargerPool
This is exposed through the private `_system_power_bounds` method in the EVChargerPool. Signed-off-by: Sahas Subramanian <[email protected]>
1 parent 9df881a commit 57d539d

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

src/frequenz/sdk/microgrid/_data_pipeline.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ def __init__(
9292
self._battery_power_wrapper = PowerWrapper(
9393
ComponentCategory.BATTERY, self._channel_registry
9494
)
95+
self._ev_power_wrapper = PowerWrapper(
96+
ComponentCategory.EV_CHARGER, self._channel_registry
97+
)
9598

9699
self._logical_meter: LogicalMeter | None = None
97100
self._consumer: Consumer | None = None
@@ -173,6 +176,9 @@ def ev_charger_pool(
173176
"""
174177
from ..timeseries.ev_charger_pool import EVChargerPool
175178

179+
if not self._ev_power_wrapper.started:
180+
self._ev_power_wrapper.start()
181+
176182
# We use frozenset to make a hashable key from the input set.
177183
key: frozenset[int] = frozenset()
178184
if ev_charger_ids is not None:
@@ -182,6 +188,9 @@ def ev_charger_pool(
182188
self._ev_charger_pools[key] = EVChargerPool(
183189
channel_registry=self._channel_registry,
184190
resampler_subscription_sender=self._resampling_request_sender(),
191+
status_receiver=self._ev_power_wrapper.status_channel.new_receiver(
192+
limit=1
193+
),
185194
component_ids=ev_charger_ids,
186195
)
187196
return self._ev_charger_pools[key]

src/frequenz/sdk/timeseries/ev_charger_pool/_ev_charger_pool.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@
77
import uuid
88
from collections import abc
99

10-
from frequenz.channels import Sender
10+
from frequenz.channels import Broadcast, Receiver, Sender
1111
from frequenz.client.microgrid import ComponentCategory
1212

13+
from ..._internal._channels import ReceiverFetcher
1314
from ...actor import ChannelRegistry, ComponentMetricRequest
15+
from ...actor.power_distributing import ComponentPoolStatus
1416
from ...microgrid import connection_manager
17+
from .._base_types import SystemBounds
1518
from .._quantities import Current, Power
1619
from ..formula_engine import FormulaEngine, FormulaEngine3Phase
1720
from ..formula_engine._formula_engine_pool import FormulaEnginePool
@@ -20,6 +23,7 @@
2023
EVChargerPowerFormula,
2124
FormulaGeneratorConfig,
2225
)
26+
from ._system_bounds_tracker import EVCSystemBoundsTracker
2327

2428

2529
class EVChargerPoolError(Exception):
@@ -41,10 +45,11 @@ class EVChargerPool:
4145
measurements of the EV Chargers in the pool.
4246
"""
4347

44-
def __init__(
48+
def __init__( # pylint: disable=too-many-arguments
4549
self,
4650
channel_registry: ChannelRegistry,
4751
resampler_subscription_sender: Sender[ComponentMetricRequest],
52+
status_receiver: Receiver[ComponentPoolStatus],
4853
component_ids: abc.Set[int] | None = None,
4954
) -> None:
5055
"""Create an `EVChargerPool` instance.
@@ -59,6 +64,8 @@ def __init__(
5964
actor.
6065
resampler_subscription_sender: A sender for sending metric requests to the
6166
resampling actor.
67+
status_receiver: A receiver that streams the status of the EV Chargers in
68+
the pool.
6269
component_ids: An optional list of component_ids belonging to this pool. If
6370
not specified, IDs of all EV Chargers in the microgrid will be fetched
6471
from the component graph.
@@ -67,6 +74,7 @@ def __init__(
6774
self._resampler_subscription_sender: Sender[ComponentMetricRequest] = (
6875
resampler_subscription_sender
6976
)
77+
self._status_receiver: Receiver[ComponentPoolStatus] = status_receiver
7078
self._component_ids: abc.Set[int] = set()
7179
if component_ids is not None:
7280
self._component_ids = component_ids
@@ -85,6 +93,14 @@ def __init__(
8593
self._resampler_subscription_sender,
8694
)
8795

96+
self._bounds_channel: Broadcast[SystemBounds] = Broadcast(
97+
name=f"System Bounds for EV Chargers: {component_ids}"
98+
)
99+
self._bounds_tracker: EVCSystemBoundsTracker = EVCSystemBoundsTracker(
100+
self.component_ids, self._status_receiver, self._bounds_channel.new_sender()
101+
)
102+
self._bounds_tracker.start()
103+
88104
@property
89105
def component_ids(self) -> abc.Set[int]:
90106
"""Return component IDs of all EV Chargers managed by this EVChargerPool.
@@ -147,3 +163,8 @@ def power(self) -> FormulaEngine[Power]:
147163
async def stop(self) -> None:
148164
"""Stop all tasks and channels owned by the EVChargerPool."""
149165
await self._formula_pool.stop()
166+
167+
@property
168+
def _system_power_bounds(self) -> ReceiverFetcher[SystemBounds]:
169+
"""Return a receiver for the system power bounds."""
170+
return self._bounds_channel

0 commit comments

Comments
 (0)