Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@

## Bug Fixes

<!-- Here goes notable bug fixes that are worth a special mention or explanation -->
- When the PowerDistributor receives a zero power request for PV inverters, it now correctly sets zero power to the inverters, and no longer crashes.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't it be ... receives a positive or zero power request ...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would never receive a positive power, because that's filtered in the pv pool:

if power is not None and power > Power.zero():
raise PVPoolError("Charge powers for PV inverters is not supported.")

Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ async def distribute_power(self, request: Request) -> None:
if remaining_power > Power.zero() or is_close_to_zero(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The stop is outdated in the comment above.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is still correct, because when we set 0 power to the remaining inverters, we're no longer allocating, but the comment could provide further details: #960

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():
Expand Down
23 changes: 22 additions & 1 deletion tests/timeseries/_pv_pool/test_pv_pool_control_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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),
]