Skip to content

Commit 0c96cdd

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 fd93b32 commit 0c96cdd

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
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+
maxsize=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: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@
1515
from frequenz.channels import Broadcast, ChannelClosedError, Receiver, Sender
1616

1717
from ..._internal._asyncio import cancel_and_await
18+
from ..._internal._channels import ReceiverFetcher
1819
from ...actor import ChannelRegistry, ComponentMetricRequest
20+
from ...actor.power_distributing import ComponentPoolStatus
1921
from ...microgrid import connection_manager
2022
from ...microgrid.component import ComponentCategory, ComponentMetricId
2123
from .. import Sample, Sample3Phase
24+
from .._base_types import SystemBounds
2225
from .._quantities import Current, Power, Quantity
2326
from ..formula_engine import FormulaEngine, FormulaEngine3Phase
2427
from ..formula_engine._formula_engine_pool import FormulaEnginePool
@@ -29,6 +32,7 @@
2932
)
3033
from ._set_current_bounds import BoundsSetter, ComponentCurrentLimit
3134
from ._state_tracker import EVChargerState, StateTracker
35+
from ._system_bounds_tracker import EVCSystemBoundsTracker
3236

3337
_logger = logging.getLogger(__name__)
3438

@@ -73,10 +77,11 @@ class EVChargerPool:
7377
method for limiting the max current of individual EV Chargers in the pool.
7478
"""
7579

76-
def __init__(
80+
def __init__( # pylint: disable=too-many-arguments
7781
self,
7882
channel_registry: ChannelRegistry,
7983
resampler_subscription_sender: Sender[ComponentMetricRequest],
84+
status_receiver: Receiver[ComponentPoolStatus],
8085
component_ids: abc.Set[int] | None = None,
8186
repeat_interval: timedelta = timedelta(seconds=3.0),
8287
) -> None:
@@ -92,6 +97,8 @@ def __init__(
9297
actor.
9398
resampler_subscription_sender: A sender for sending metric requests to the
9499
resampling actor.
100+
status_receiver: A receiver that streams the status of the EV Chargers in
101+
the pool.
95102
component_ids: An optional list of component_ids belonging to this pool. If
96103
not specified, IDs of all EV Chargers in the microgrid will be fetched
97104
from the component graph.
@@ -103,6 +110,7 @@ def __init__(
103110
self._resampler_subscription_sender: Sender[ComponentMetricRequest] = (
104111
resampler_subscription_sender
105112
)
113+
self._status_receiver: Receiver[ComponentPoolStatus] = status_receiver
106114
self._component_ids: abc.Set[int] = set()
107115
if component_ids is not None:
108116
self._component_ids = component_ids
@@ -126,6 +134,14 @@ def __init__(
126134
)
127135
self._bounds_setter: BoundsSetter | None = None
128136

137+
self._bounds_channel: Broadcast[SystemBounds] = Broadcast(
138+
name=f"System Bounds for EV Chargers: {component_ids}"
139+
)
140+
self._bounds_tracker: EVCSystemBoundsTracker = EVCSystemBoundsTracker(
141+
self.component_ids, self._status_receiver, self._bounds_channel.new_sender()
142+
)
143+
self._bounds_tracker.start()
144+
129145
@property
130146
def component_ids(self) -> abc.Set[int]:
131147
"""Return component IDs of all EV Chargers managed by this EVChargerPool.
@@ -353,3 +369,8 @@ async def _stream_component_data(
353369
state=state,
354370
)
355371
)
372+
373+
@property
374+
def _system_power_bounds(self) -> ReceiverFetcher[SystemBounds]:
375+
"""Return a receiver for the system power bounds."""
376+
return self._bounds_channel

0 commit comments

Comments
 (0)