11# License: MIT
22# Copyright © 2022 Frequenz Energy-as-a-Service GmbH
33
4- """Actor to distribute power between batteries .
4+ """Actor to distribute power between components .
55
6- When charge/discharge method is called the power should be distributed so that
7- the SoC in batteries stays at the same level. That way of distribution
8- prevents using only one battery, increasing temperature, and maximize the total
9- amount power to charge/discharge.
6+ The purpose of this actor is to distribute power between components in a microgrid.
107
11- Purpose of this actor is to keep SoC level of each component at the equal level.
8+ The actor receives power requests from the power manager, process them by
9+ distributing the power between the components and sends the results back to it.
1210"""
1311
1412
3230
3331class PowerDistributingActor (Actor ):
3432 # pylint: disable=too-many-instance-attributes
35- """Actor to distribute the power between batteries in a microgrid.
33+ """Actor to distribute the power between components in a microgrid.
3634
37- The purpose of this tool is to keep an equal SoC level in all batteries.
38- The PowerDistributingActor can have many concurrent users which at this time
39- need to be known at construction time .
35+ One instance of the actor can handle only one component category and type,
36+ which needs to be specified at actor startup and it will setup the correct
37+ component manager based on the given category and type .
4038
41- For each user a bidirectional channel needs to be created through which
42- they can send and receive requests and responses.
43-
44- It is recommended to wait for PowerDistributingActor output with timeout. Otherwise if
45- the processing function fails then the response will never come.
46- The timeout should be Result:request_timeout + time for processing the request.
39+ Only one power request is processed at a time to prevent from sending
40+ multiple requests for the same components to the microgrid API at the
41+ same time.
4742
4843 Edge cases:
49- * If there are 2 requests to be processed for the same subset of batteries, then
50- only the latest request will be processed. Older request will be ignored. User with
51- older request will get response with Result.Status.IGNORED.
52-
53- * If there are 2 requests and their subset of batteries is different but they
54- overlap (they have at least one common battery), then then both batteries
55- will be processed. However it is not expected so the proper error log will be
56- printed.
44+ * If a new power request is received while a power request with the same
45+ set of components is being processed, the new request will be added to
46+ the pending requests. Then the pending request will be processed after the
47+ request with the same set of components being processed is done. Only one
48+ pending request is kept for each set of components, the latest request will
49+ overwrite the previous one if there is any.
50+
51+ * If there are 2 requests and their set of components is different but they
52+ overlap (they have at least one common component), then both requests will
53+ be processed concurrently. Though, the power manager will make sure this
54+ doesn't happen as overlapping component IDs are not possible at the moment.
5755 """
5856
5957 def __init__ ( # pylint: disable=too-many-arguments
@@ -67,7 +65,7 @@ def __init__( # pylint: disable=too-many-arguments
6765 component_type : ComponentType | None = None ,
6866 name : str | None = None ,
6967 ) -> None :
70- """Create class instance.
68+ """Create actor instance.
7169
7270 Args:
7371 requests_receiver: Receiver for receiving power requests from the power
@@ -121,13 +119,17 @@ def __init__( # pylint: disable=too-many-arguments
121119 )
122120
123121 @override
124- async def _run (self ) -> None : # pylint: disable=too-many-locals
125- """Run actor main function.
122+ async def _run (self ) -> None :
123+ """Run this actor's logic.
124+
125+ It waits for new power requests and process them. Only one power request
126+ can be processed at a time to prevent from sending multiple requests for
127+ the same components to the microgrid API at the same time.
128+
129+ A new power request will be ignored if a power request with the same
130+ components is currently being processed.
126131
127- It waits for new requests in task_queue and process it, and send
128- `set_power` request with distributed power.
129- The output of the `set_power` method is processed.
130- Every battery and inverter that failed or didn't respond in time will be marked
132+ Every component that failed or didn't respond in time will be marked
131133 as broken for some time.
132134 """
133135 await self ._component_manager .start ()
0 commit comments