1
1
# License: MIT
2
2
# Copyright © 2022 Frequenz Energy-as-a-Service GmbH
3
3
4
- """Actor to distribute power between batteries .
4
+ """Actor to distribute power between components .
5
5
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.
10
7
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.
12
10
"""
13
11
14
12
32
30
33
31
class PowerDistributingActor (Actor ):
34
32
# 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.
36
34
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 .
40
38
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.
47
42
48
43
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.
57
55
"""
58
56
59
57
def __init__ ( # pylint: disable=too-many-arguments
@@ -67,7 +65,7 @@ def __init__( # pylint: disable=too-many-arguments
67
65
component_type : ComponentType | None = None ,
68
66
name : str | None = None ,
69
67
) -> None :
70
- """Create class instance.
68
+ """Create actor instance.
71
69
72
70
Args:
73
71
requests_receiver: Receiver for receiving power requests from the power
@@ -121,13 +119,17 @@ def __init__( # pylint: disable=too-many-arguments
121
119
)
122
120
123
121
@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.
126
131
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
131
133
as broken for some time.
132
134
"""
133
135
await self ._component_manager .start ()
0 commit comments