21
21
from frequenz .quantities import Power
22
22
from typing_extensions import override
23
23
24
- from ...._internal ._math import is_close_to_zero
25
24
from ... import connection_manager
26
25
from .._component_pool_status_tracker import ComponentPoolStatusTracker
27
26
from .._component_status import BatteryStatusTracker , ComponentPoolStatus
@@ -264,14 +263,12 @@ async def _distribute_power(
264
263
Returns:
265
264
Result from the microgrid API.
266
265
"""
267
- distributed_power_value = (
268
- request .power .as_watts () - distribution .remaining_power
269
- )
270
- battery_distribution : dict [int , float ] = {}
266
+ distributed_power_value = request .power - distribution .remaining_power
267
+ battery_distribution : dict [int , Power ] = {}
271
268
for inverter_id , dist in distribution .distribution .items ():
272
269
for battery_id in self ._inv_bats_map [inverter_id ]:
273
270
battery_distribution [battery_id ] = (
274
- battery_distribution .get (battery_id , 0.0 ) + dist
271
+ battery_distribution .get (battery_id , Power . zero () ) + dist
275
272
)
276
273
_logger .debug (
277
274
"Distributing power %d between the batteries %s" ,
@@ -288,21 +285,19 @@ async def _distribute_power(
288
285
succeed_batteries = set (battery_distribution .keys ()) - failed_batteries
289
286
response = PartialFailure (
290
287
request = request ,
291
- succeeded_power = Power .from_watts (
292
- distributed_power_value - failed_power
293
- ),
288
+ succeeded_power = distributed_power_value - failed_power ,
294
289
succeeded_components = succeed_batteries ,
295
- failed_power = Power . from_watts ( failed_power ) ,
290
+ failed_power = failed_power ,
296
291
failed_components = failed_batteries ,
297
- excess_power = Power . from_watts ( distribution .remaining_power ) ,
292
+ excess_power = distribution .remaining_power ,
298
293
)
299
294
else :
300
295
succeed_batteries = set (battery_distribution .keys ())
301
296
response = Success (
302
297
request = request ,
303
- succeeded_power = Power . from_watts ( distributed_power_value ) ,
298
+ succeeded_power = distributed_power_value ,
304
299
succeeded_components = succeed_batteries ,
305
- excess_power = Power . from_watts ( distribution .remaining_power ) ,
300
+ excess_power = distribution .remaining_power ,
306
301
)
307
302
308
303
await asyncio .gather (
@@ -346,39 +341,59 @@ def _get_bounds(
346
341
"""
347
342
return PowerBounds (
348
343
inclusion_lower = sum (
349
- max (
350
- battery .power_bounds .inclusion_lower ,
351
- sum (
352
- inverter .active_power_inclusion_lower_bound
353
- for inverter in inverters
354
- ),
355
- )
356
- for battery , inverters in pairs_data
344
+ (
345
+ max (
346
+ battery .power_bounds .inclusion_lower ,
347
+ Power .from_watts (
348
+ sum (
349
+ inverter .active_power_inclusion_lower_bound
350
+ for inverter in inverters
351
+ )
352
+ ),
353
+ )
354
+ for battery , inverters in pairs_data
355
+ ),
356
+ start = Power .zero (),
357
357
),
358
358
inclusion_upper = sum (
359
- min (
360
- battery .power_bounds .inclusion_upper ,
361
- sum (
362
- inverter .active_power_inclusion_upper_bound
363
- for inverter in inverters
364
- ),
365
- )
366
- for battery , inverters in pairs_data
359
+ (
360
+ min (
361
+ battery .power_bounds .inclusion_upper ,
362
+ Power .from_watts (
363
+ sum (
364
+ inverter .active_power_inclusion_upper_bound
365
+ for inverter in inverters
366
+ )
367
+ ),
368
+ )
369
+ for battery , inverters in pairs_data
370
+ ),
371
+ start = Power .zero (),
367
372
),
368
373
exclusion_lower = min (
369
- sum (battery .power_bounds .exclusion_lower for battery , _ in pairs_data ),
370
374
sum (
371
- inverter .active_power_exclusion_lower_bound
372
- for _ , inverters in pairs_data
373
- for inverter in inverters
375
+ (battery .power_bounds .exclusion_lower for battery , _ in pairs_data ),
376
+ start = Power .zero (),
377
+ ),
378
+ Power .from_watts (
379
+ sum (
380
+ inverter .active_power_exclusion_lower_bound
381
+ for _ , inverters in pairs_data
382
+ for inverter in inverters
383
+ )
374
384
),
375
385
),
376
386
exclusion_upper = max (
377
- sum (battery .power_bounds .exclusion_upper for battery , _ in pairs_data ),
378
387
sum (
379
- inverter .active_power_exclusion_upper_bound
380
- for _ , inverters in pairs_data
381
- for inverter in inverters
388
+ (battery .power_bounds .exclusion_upper for battery , _ in pairs_data ),
389
+ start = Power .zero (),
390
+ ),
391
+ Power .from_watts (
392
+ sum (
393
+ inverter .active_power_exclusion_upper_bound
394
+ for _ , inverters in pairs_data
395
+ for inverter in inverters
396
+ )
382
397
),
383
398
),
384
399
)
@@ -410,11 +425,11 @@ def _check_request(
410
425
411
426
bounds = self ._get_bounds (pairs_data )
412
427
413
- power = request .power . as_watts ()
428
+ power = request .power
414
429
415
430
# Zero power requests are always forwarded to the microgrid API, even if they
416
431
# are outside the exclusion bounds.
417
- if is_close_to_zero ( power ):
432
+ if power . isclose ( Power . zero () ):
418
433
return None
419
434
420
435
if request .adjust_power :
@@ -599,7 +614,7 @@ def _get_power_distribution(
599
614
unavailable_inv_ids = unavailable_inv_ids .union (inverter_ids )
600
615
601
616
result = self ._distribution_algorithm .distribute_power (
602
- request .power . as_watts () , inv_bat_pairs
617
+ request .power , inv_bat_pairs
603
618
)
604
619
605
620
return result
@@ -608,7 +623,7 @@ async def _set_distributed_power(
608
623
self ,
609
624
distribution : DistributionResult ,
610
625
timeout : timedelta ,
611
- ) -> tuple [float , set [int ]]:
626
+ ) -> tuple [Power , set [int ]]:
612
627
"""Send distributed power to the inverters.
613
628
614
629
Args:
@@ -622,7 +637,9 @@ async def _set_distributed_power(
622
637
api = connection_manager .get ().api_client
623
638
624
639
tasks = {
625
- inverter_id : asyncio .create_task (api .set_power (inverter_id , power ))
640
+ inverter_id : asyncio .create_task (
641
+ api .set_power (inverter_id , power .as_watts ())
642
+ )
626
643
for inverter_id , power in distribution .distribution .items ()
627
644
}
628
645
@@ -639,9 +656,9 @@ async def _set_distributed_power(
639
656
def _parse_result (
640
657
self ,
641
658
tasks : dict [int , asyncio .Task [None ]],
642
- distribution : dict [int , float ],
659
+ distribution : dict [int , Power ],
643
660
request_timeout : timedelta ,
644
- ) -> tuple [float , set [int ]]:
661
+ ) -> tuple [Power , set [int ]]:
645
662
"""Parse the results of `set_power` requests.
646
663
647
664
Check if any task has failed and determine the reason for failure.
@@ -658,7 +675,7 @@ def _parse_result(
658
675
A tuple where the first element is the total failed power, and the second element is
659
676
the set of batteries that failed.
660
677
"""
661
- failed_power : float = 0.0
678
+ failed_power : Power = Power . zero ()
662
679
failed_batteries : set [int ] = set ()
663
680
664
681
for inverter_id , aws in tasks .items ():
0 commit comments