Skip to content

Commit 427e5eb

Browse files
committed
Send power distribution results from the component manager
Until now, the PowerDistributingActor has supported only distributing power to batteries. Batteries are (supposed to be) always available, so the distribution takes place once when the power distributor receives a request. This changes when distributing power to EV chargers, because power needs to be: - distributed when an EV is connected - redistributed to other EVs when an EV is disconnected - redistributed to other EVs if an EV appears to be not charging, etc. So a power distribution manager for EVs would be best implemented with its own `select` loop, where distribution happens. Because of this, a call to the `distribute_power` method on the EV charger manager can't immediately return a single distribution result, but that call is not the only thing that triggers the distribution, but other events too. So the manager needs to be what sends out the distribution results. Signed-off-by: Sahas Subramanian <[email protected]>
1 parent b1249e1 commit 427e5eb

File tree

3 files changed

+23
-12
lines changed

3 files changed

+23
-12
lines changed

src/frequenz/sdk/actor/power_distributing/_component_managers/_battery_manager.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,18 @@ class BatteryManager(ComponentManager):
127127
def __init__(
128128
self,
129129
component_pool_status_sender: Sender[ComponentPoolStatus],
130+
results_sender: Sender[Result],
130131
):
131-
"""Initialize the battery data manager."""
132+
"""Initialize the battery data manager.
133+
134+
Args:
135+
component_pool_status_sender: Channel sender to send the status of the
136+
battery pool to. This status is used by the battery pool metric
137+
streams, to dynamically adjust the values based on the health of the
138+
individual batteries.
139+
results_sender: Channel sender to send the power distribution results to.
140+
"""
141+
self._results_sender = results_sender
132142
self._batteries = connection_manager.get().component_graph.components(
133143
component_categories={ComponentCategory.BATTERY}
134144
)
@@ -181,20 +191,18 @@ async def stop(self) -> None:
181191
await self._component_pool_status_tracker.stop()
182192

183193
@override
184-
async def distribute_power(self, request: Request) -> Result:
194+
async def distribute_power(self, request: Request) -> None:
185195
"""Distribute the requested power to the components.
186196
187197
Args:
188198
request: Request to get the distribution for.
189-
190-
Returns:
191-
Result of the distribution.
192199
"""
193200
distribution_result = await self._get_distribution(request)
194201
if not isinstance(distribution_result, DistributionResult):
195-
return distribution_result
196-
result = await self._distribute_power(request, distribution_result)
197-
return result
202+
result = distribution_result
203+
else:
204+
result = await self._distribute_power(request, distribution_result)
205+
await self._results_sender.send(result)
198206

199207
async def _get_distribution(self, request: Request) -> DistributionResult | Result:
200208
"""Get the distribution of the batteries.

src/frequenz/sdk/actor/power_distributing/_component_managers/_component_manager.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@ class ComponentManager(abc.ABC):
2020
def __init__(
2121
self,
2222
component_pool_status_sender: Sender[ComponentPoolStatus],
23+
results_sender: Sender[Result],
2324
):
2425
"""Initialize the component data manager.
2526
2627
Args:
2728
component_pool_status_sender: Channel for sending information about which
2829
components are expected to be working.
30+
results_sender: Channel for sending the results of power distribution.
2931
"""
3032

3133
@abc.abstractmethod
@@ -37,7 +39,7 @@ async def start(self) -> None:
3739
"""Start the component data manager."""
3840

3941
@abc.abstractmethod
40-
async def distribute_power(self, request: Request) -> Result:
42+
async def distribute_power(self, request: Request) -> None:
4143
"""Distribute the requested power to the components.
4244
4345
Args:

src/frequenz/sdk/actor/power_distributing/power_distributing.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,9 @@ def __init__( # pylint: disable=too-many-arguments
8686

8787
self._component_manager: ComponentManager
8888
if component_category == ComponentCategory.BATTERY:
89-
self._component_manager = BatteryManager(component_pool_status_sender)
89+
self._component_manager = BatteryManager(
90+
component_pool_status_sender, results_sender
91+
)
9092
else:
9193
raise ValueError(
9294
f"PowerDistributor doesn't support controlling: {component_category}"
@@ -107,8 +109,7 @@ async def _run(self) -> None: # pylint: disable=too-many-locals
107109
await asyncio.sleep(self._wait_for_data_sec)
108110

109111
async for request in self._requests_receiver:
110-
result = await self._component_manager.distribute_power(request)
111-
await self._result_sender.send(result)
112+
await self._component_manager.distribute_power(request)
112113

113114
async def stop(self, msg: str | None = None) -> None:
114115
"""Stop this actor.

0 commit comments

Comments
 (0)