Skip to content

Commit 41d4543

Browse files
committed
Use Power instead of float in PowerDistributor's battery manager
The PV manager and the EV Charger manager of the PowerDistributor are already using `Power` and not `float`. Signed-off-by: Sahas Subramanian <[email protected]>
1 parent 5aa87ab commit 41d4543

File tree

6 files changed

+1496
-581
lines changed

6 files changed

+1496
-581
lines changed

src/frequenz/sdk/microgrid/_power_distributing/_component_managers/_battery_manager.py

Lines changed: 62 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
from frequenz.quantities import Power
2222
from typing_extensions import override
2323

24-
from ...._internal._math import is_close_to_zero
2524
from ... import connection_manager
2625
from .._component_pool_status_tracker import ComponentPoolStatusTracker
2726
from .._component_status import BatteryStatusTracker, ComponentPoolStatus
@@ -264,14 +263,12 @@ async def _distribute_power(
264263
Returns:
265264
Result from the microgrid API.
266265
"""
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] = {}
271268
for inverter_id, dist in distribution.distribution.items():
272269
for battery_id in self._inv_bats_map[inverter_id]:
273270
battery_distribution[battery_id] = (
274-
battery_distribution.get(battery_id, 0.0) + dist
271+
battery_distribution.get(battery_id, Power.zero()) + dist
275272
)
276273
_logger.debug(
277274
"Distributing power %d between the batteries %s",
@@ -288,21 +285,19 @@ async def _distribute_power(
288285
succeed_batteries = set(battery_distribution.keys()) - failed_batteries
289286
response = PartialFailure(
290287
request=request,
291-
succeeded_power=Power.from_watts(
292-
distributed_power_value - failed_power
293-
),
288+
succeeded_power=distributed_power_value - failed_power,
294289
succeeded_components=succeed_batteries,
295-
failed_power=Power.from_watts(failed_power),
290+
failed_power=failed_power,
296291
failed_components=failed_batteries,
297-
excess_power=Power.from_watts(distribution.remaining_power),
292+
excess_power=distribution.remaining_power,
298293
)
299294
else:
300295
succeed_batteries = set(battery_distribution.keys())
301296
response = Success(
302297
request=request,
303-
succeeded_power=Power.from_watts(distributed_power_value),
298+
succeeded_power=distributed_power_value,
304299
succeeded_components=succeed_batteries,
305-
excess_power=Power.from_watts(distribution.remaining_power),
300+
excess_power=distribution.remaining_power,
306301
)
307302

308303
await asyncio.gather(
@@ -346,39 +341,59 @@ def _get_bounds(
346341
"""
347342
return PowerBounds(
348343
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(),
357357
),
358358
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(),
367372
),
368373
exclusion_lower=min(
369-
sum(battery.power_bounds.exclusion_lower for battery, _ in pairs_data),
370374
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+
)
374384
),
375385
),
376386
exclusion_upper=max(
377-
sum(battery.power_bounds.exclusion_upper for battery, _ in pairs_data),
378387
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+
)
382397
),
383398
),
384399
)
@@ -410,11 +425,11 @@ def _check_request(
410425

411426
bounds = self._get_bounds(pairs_data)
412427

413-
power = request.power.as_watts()
428+
power = request.power
414429

415430
# Zero power requests are always forwarded to the microgrid API, even if they
416431
# are outside the exclusion bounds.
417-
if is_close_to_zero(power):
432+
if power.isclose(Power.zero()):
418433
return None
419434

420435
if request.adjust_power:
@@ -599,7 +614,7 @@ def _get_power_distribution(
599614
unavailable_inv_ids = unavailable_inv_ids.union(inverter_ids)
600615

601616
result = self._distribution_algorithm.distribute_power(
602-
request.power.as_watts(), inv_bat_pairs
617+
request.power, inv_bat_pairs
603618
)
604619

605620
return result
@@ -608,7 +623,7 @@ async def _set_distributed_power(
608623
self,
609624
distribution: DistributionResult,
610625
timeout: timedelta,
611-
) -> tuple[float, set[int]]:
626+
) -> tuple[Power, set[int]]:
612627
"""Send distributed power to the inverters.
613628
614629
Args:
@@ -622,7 +637,9 @@ async def _set_distributed_power(
622637
api = connection_manager.get().api_client
623638

624639
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+
)
626643
for inverter_id, power in distribution.distribution.items()
627644
}
628645

@@ -639,9 +656,9 @@ async def _set_distributed_power(
639656
def _parse_result(
640657
self,
641658
tasks: dict[int, asyncio.Task[None]],
642-
distribution: dict[int, float],
659+
distribution: dict[int, Power],
643660
request_timeout: timedelta,
644-
) -> tuple[float, set[int]]:
661+
) -> tuple[Power, set[int]]:
645662
"""Parse the results of `set_power` requests.
646663
647664
Check if any task has failed and determine the reason for failure.
@@ -658,7 +675,7 @@ def _parse_result(
658675
A tuple where the first element is the total failed power, and the second element is
659676
the set of batteries that failed.
660677
"""
661-
failed_power: float = 0.0
678+
failed_power: Power = Power.zero()
662679
failed_batteries: set[int] = set()
663680

664681
for inverter_id, aws in tasks.items():

0 commit comments

Comments
 (0)