diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 373c3e00f..d8b82fdb9 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -16,4 +16,4 @@ ## Bug Fixes - +- When the PowerDistributor receives a zero power request for PV inverters, it now correctly sets zero power to the inverters, and no longer crashes. diff --git a/src/frequenz/sdk/actor/power_distributing/_component_managers/_pv_inverter_manager/_pv_inverter_manager.py b/src/frequenz/sdk/actor/power_distributing/_component_managers/_pv_inverter_manager/_pv_inverter_manager.py index 2a2f77852..716f57739 100644 --- a/src/frequenz/sdk/actor/power_distributing/_component_managers/_pv_inverter_manager/_pv_inverter_manager.py +++ b/src/frequenz/sdk/actor/power_distributing/_component_managers/_pv_inverter_manager/_pv_inverter_manager.py @@ -136,7 +136,8 @@ async def distribute_power(self, request: Request) -> None: if remaining_power > Power.zero() or is_close_to_zero( remaining_power.as_watts() ): - break + allocations[inv_id] = Power.zero() + continue distribution = remaining_power / float(num_components - idx) inv_data = self._component_data_caches[inv_id] if not inv_data.has_value(): diff --git a/tests/timeseries/_pv_pool/test_pv_pool_control_methods.py b/tests/timeseries/_pv_pool/test_pv_pool_control_methods.py index 8cd5a5c68..034953814 100644 --- a/tests/timeseries/_pv_pool/test_pv_pool_control_methods.py +++ b/tests/timeseries/_pv_pool/test_pv_pool_control_methods.py @@ -131,7 +131,7 @@ async def _recv_reports_until( if check(report): break - async def test_setting_power( + async def test_setting_power( # pylint: disable=too-many-statements self, mocks: _Mocks, mocker: MockerFixture, @@ -260,3 +260,24 @@ async def test_setting_power( mocker.call(inv_ids[2], -30000.0), mocker.call(inv_ids[3], -30000.0), ] + + # Setting 0 power should set all inverters to 0 + set_power.reset_mock() + await pv_pool.propose_power(Power.zero()) + await self._recv_reports_until( + bounds_rx, + lambda x: x.target_power is not None and x.target_power.as_watts() == 0.0, + ) + self._assert_report( + await bounds_rx.receive(), power=0.0, lower=-100000.0, upper=0.0 + ) + await asyncio.sleep(0.0) + + assert set_power.call_count == 4 + inv_ids = mocks.microgrid.pv_inverter_ids + assert sorted(set_power.call_args_list, key=lambda x: x.args[0]) == [ + mocker.call(inv_ids[0], 0.0), + mocker.call(inv_ids[1], 0.0), + mocker.call(inv_ids[2], 0.0), + mocker.call(inv_ids[3], 0.0), + ]