3232from frequenz .channels import Bidirectional , Peekable , Receiver
3333from google .protobuf .empty_pb2 import Empty # pylint: disable=no-name-in-module
3434
35+ from ... import microgrid
3536from ...actor ._decorator import actor
3637from ...microgrid import ComponentGraph
3738from ...microgrid .client import MicrogridApiClient
4142 ComponentCategory ,
4243 InverterData ,
4344)
44- from ...power import DistributionAlgorithm , InvBatPair
45+ from ...power import DistributionAlgorithm , DistributionResult , InvBatPair
4546from ._battery_pool_status import BatteryPoolStatus
4647from .request import Request
4748from .result import Error , Ignored , OutOfBound , PartialFailure , Result , Success
@@ -140,22 +141,17 @@ class PowerDistributingActor:
140141
141142 def __init__ (
142143 self ,
143- microgrid_api : MicrogridApiClient ,
144- component_graph : ComponentGraph ,
145144 users_channels : Dict [str , Bidirectional .Handle [Result , Request ]],
146145 wait_for_data_sec : float = 2 ,
147146 ) -> None :
148147 """Create class instance.
149148
150149 Args:
151- microgrid_api: api for sending the requests.
152- component_graph: component graph of the given microgrid api.
153150 users_channels: BidirectionalHandle for each user. Key should be
154151 user id and value should be BidirectionalHandle.
155152 wait_for_data_sec: How long actor should wait before processing first
156153 request. It is a time needed to collect first components data.
157154 """
158- self ._api = microgrid_api
159155 self ._wait_for_data_sec = wait_for_data_sec
160156
161157 # NOTE: power_distributor_exponent should be received from ConfigManager
@@ -164,19 +160,16 @@ def __init__(
164160 self .power_distributor_exponent
165161 )
166162
167- batteries = component_graph .components (
168- component_category = {ComponentCategory .BATTERY }
169- )
163+ graph = microgrid .get ().component_graph
164+ batteries = graph .components (component_category = {ComponentCategory .BATTERY })
170165
171166 self ._battery_pool = BatteryPoolStatus (
172167 battery_ids = {battery .component_id for battery in batteries },
173168 max_blocking_duration_sec = 30.0 ,
174169 max_data_age_sec = 10.0 ,
175170 )
176171
177- self ._bat_inv_map , self ._inv_bat_map = self ._get_components_pairs (
178- component_graph
179- )
172+ self ._bat_inv_map , self ._inv_bat_map = self ._get_components_pairs (graph )
180173 self ._battery_receivers : Dict [int , Peekable [BatteryData ]] = {}
181174 self ._inverter_receivers : Dict [int , Peekable [InverterData ]] = {}
182175
@@ -250,6 +243,7 @@ async def run(self) -> None:
250243 """
251244 await self ._create_channels ()
252245 await self ._battery_pool .async_init ()
246+ api = microgrid .get ().api_client
253247
254248 # Wait few seconds to get data from the channels created above.
255249 await asyncio .sleep (self ._wait_for_data_sec )
@@ -291,20 +285,10 @@ async def run(self) -> None:
291285 str (battery_distribution ),
292286 )
293287
294- tasks = {
295- inverter_id : asyncio .create_task (
296- self ._api .set_power (inverter_id , power )
297- )
298- for inverter_id , power in distribution .distribution .items ()
299- }
300-
301- _ , pending = await asyncio .wait (
302- tasks .values (),
303- timeout = request .request_timeout_sec ,
304- return_when = ALL_COMPLETED ,
288+ tasks = await self ._set_distributed_power (
289+ api , distribution , request .request_timeout_sec
305290 )
306291
307- await self ._cancel_tasks (pending )
308292 failed_power , failed_batteries = self ._parse_result (
309293 tasks , distribution .distribution , request .request_timeout_sec
310294 )
@@ -330,6 +314,36 @@ async def run(self) -> None:
330314 self ._battery_pool .update_last_request_status (response )
331315 await user .channel .send (response )
332316
317+ async def _set_distributed_power (
318+ self ,
319+ api : MicrogridApiClient ,
320+ distribution : DistributionResult ,
321+ timeout_sec : float ,
322+ ) -> Dict [int , asyncio .Task [Empty ]]:
323+ """Send distributed power to the inverters.
324+
325+ Args:
326+ api: Microgrid api client
327+ distribution: Distribution result
328+ timeout_sec: How long wait for the response
329+
330+ Returns:
331+ Dict with finished or cancelled task for each inverter.
332+ """
333+ tasks = {
334+ inverter_id : asyncio .create_task (api .set_power (inverter_id , power ))
335+ for inverter_id , power in distribution .distribution .items ()
336+ }
337+
338+ _ , pending = await asyncio .wait (
339+ tasks .values (),
340+ timeout = timeout_sec ,
341+ return_when = ALL_COMPLETED ,
342+ )
343+
344+ await self ._cancel_tasks (pending )
345+ return tasks
346+
333347 def _check_request (self , request : Request ) -> Optional [Result ]:
334348 """Check whether the given request if correct.
335349
@@ -546,13 +560,12 @@ def _get_components_data(self, batteries: Set[int]) -> List[InvBatPair]:
546560
547561 async def _create_channels (self ) -> None :
548562 """Create channels to get data of components in microgrid."""
563+ api = microgrid .get ().api_client
549564 for battery_id , inverter_id in self ._bat_inv_map .items ():
550- bat_recv : Receiver [BatteryData ] = await self . _api .battery_data (battery_id )
565+ bat_recv : Receiver [BatteryData ] = await api .battery_data (battery_id )
551566 self ._battery_receivers [battery_id ] = bat_recv .into_peekable ()
552567
553- inv_recv : Receiver [InverterData ] = await self ._api .inverter_data (
554- inverter_id
555- )
568+ inv_recv : Receiver [InverterData ] = await api .inverter_data (inverter_id )
556569 self ._inverter_receivers [inverter_id ] = inv_recv .into_peekable ()
557570
558571 def _parse_result (
0 commit comments