Skip to content

Commit d22eba3

Browse files
Update PowerDistributor to use use frequenz.sdk.microgrid
...instead of taking them in constructor. Signed-off-by: ela-kotulska-frequenz <[email protected]>
1 parent 44c93e7 commit d22eba3

File tree

5 files changed

+137
-132
lines changed

5 files changed

+137
-132
lines changed

RELEASE_NOTES.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@
2121
- Add a formula generator for SoC in the LogicalMeter
2222
https://github.com/frequenz-floss/frequenz-sdk-python/pull/137
2323

24-
2524
## Bug Fixes
2625

2726
- Formulas with repeated operators like `#1 - #2 - #3` were getting
2827
calculated incorrectly as `#1 - (#2 - #3)`. This has been fixed in
2928
https://github.com/frequenz-floss/frequenz-sdk-python/pull/141
29+
30+
- Remove `microgrid_api` and `component_graph` arguments from PowerDistributingActor constructor
31+
https://github.com/frequenz-floss/frequenz-sdk-python/pull/156

benchmarks/power_distribution/power_distributor.py

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
from dataclasses import dataclass
1111
from typing import Any, Coroutine, Dict, List, Set # pylint: disable=unused-import
1212

13-
import grpc.aio as grpcaio
1413
from frequenz.channels import Bidirectional
1514

15+
from frequenz.sdk import microgrid
1616
from frequenz.sdk.actor.power_distributing import (
1717
Error,
1818
Ignored,
@@ -23,12 +23,9 @@
2323
Result,
2424
Success,
2525
)
26-
from frequenz.sdk.microgrid import ComponentGraph
27-
from frequenz.sdk.microgrid._graph import _MicrogridComponentGraph
28-
from frequenz.sdk.microgrid.client import MicrogridApiClient, MicrogridGrpcClient
2926
from frequenz.sdk.microgrid.component import Component, ComponentCategory
3027

31-
HOST = "157.90.243.180"
28+
HOST = "microgrid.sandbox.api.frequenz.io"
3229
PORT = 61060
3330

3431

@@ -104,16 +101,13 @@ async def run_test( # pylint: disable=too-many-locals
104101
users_num: int,
105102
requests_per_user: int,
106103
batteries: Set[int],
107-
api: MicrogridApiClient,
108-
graph: ComponentGraph,
109104
) -> Dict[str, Any]:
110105
"""Run test.
111106
112107
Args:
113108
users_num: Number of users to register
114109
requests_per_user: How many request user should send.
115110
batteries: Set of batteries for each request.
116-
distributor: PowerDistributingActor instance.
117111
118112
Returns:
119113
Dictionary with statistics.
@@ -129,7 +123,7 @@ async def run_test( # pylint: disable=too-many-locals
129123
user_id: channel.service_handle for user_id, channel in channels.items()
130124
}
131125

132-
distributor = PowerDistributingActor(api, graph, service_channels)
126+
distributor = PowerDistributingActor(service_channels)
133127

134128
tasks: List[Coroutine[Any, Any, List[Result]]] = []
135129
for user_id, channel in channels.items():
@@ -152,25 +146,22 @@ async def run_test( # pylint: disable=too-many-locals
152146
async def run() -> None:
153147
"""Create microgrid api and run tests."""
154148
# pylint: disable=protected-access
155-
grpc_channel = grpcaio.insecure_channel(f"{HOST}:{PORT}")
156-
api = MicrogridGrpcClient(grpc_channel, target=f"{HOST}:{PORT}")
157149

158-
graph = _MicrogridComponentGraph()
159-
await graph.refresh_from_api(api)
150+
await microgrid.initialize(HOST, PORT)
160151

161-
all_batteries: Set[Component] = graph.components(
152+
all_batteries: Set[Component] = microgrid.get().component_graph.components(
162153
component_category={ComponentCategory.BATTERY}
163154
)
164155
batteries_ids = {c.component_id for c in all_batteries}
165156
# Take some time to get data from components
166157
await asyncio.sleep(4)
167158
with open("/dev/stdout", "w", encoding="utf-8") as csvfile:
168-
fields = await run_test(0, 0, batteries_ids, api, graph)
159+
fields = await run_test(0, 0, batteries_ids)
169160
out = csv.DictWriter(csvfile, fields.keys())
170161
out.writeheader()
171-
out.writerow(await run_test(1, 1, batteries_ids, api, graph))
172-
out.writerow(await run_test(1, 10, batteries_ids, api, graph))
173-
out.writerow(await run_test(10, 10, batteries_ids, api, graph))
162+
out.writerow(await run_test(1, 1, batteries_ids))
163+
out.writerow(await run_test(1, 10, batteries_ids))
164+
out.writerow(await run_test(10, 10, batteries_ids))
174165

175166

176167
async def main() -> None:

examples/power_distribution.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,6 @@ async def run() -> None:
184184
}
185185

186186
power_distributor = PowerDistributingActor(
187-
microgrid_api=microgrid.get().api_client,
188-
# microgrid_api=microgrid_api.microgrid_api, in v0.8.0
189-
component_graph=microgrid.get().component_graph,
190187
users_channels={
191188
key: channel.service_handle
192189
for key, channel in power_distributor_channels.items()

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

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
from frequenz.channels import Bidirectional, Peekable, Receiver
3333
from google.protobuf.empty_pb2 import Empty # pylint: disable=no-name-in-module
3434

35+
from ... import microgrid
3536
from ...actor._decorator import actor
3637
from ...microgrid import ComponentGraph
3738
from ...microgrid.client import MicrogridApiClient
@@ -41,7 +42,7 @@
4142
ComponentCategory,
4243
InverterData,
4344
)
44-
from ...power import DistributionAlgorithm, InvBatPair
45+
from ...power import DistributionAlgorithm, DistributionResult, InvBatPair
4546
from ._battery_pool_status import BatteryPoolStatus
4647
from .request import Request
4748
from .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

Comments
 (0)