Skip to content

Commit

Permalink
Test pv_power formula with fallback components
Browse files Browse the repository at this point in the history
Signed-off-by: Elzbieta Kotulska <[email protected]>
  • Loading branch information
ela-kotulska-frequenz committed Aug 16, 2024
1 parent e07a601 commit 7d77e83
Showing 1 changed file with 66 additions and 0 deletions.
66 changes: 66 additions & 0 deletions tests/timeseries/test_logical_meter.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,69 @@ async def test_pv_power_no_pv_components(self, mocker: MockerFixture) -> None:

await mockgrid.mock_resampler.send_non_existing_component_value()
assert (await pv_power_receiver.receive()).value == Power.zero()

async def test_pv_power_with_failing_meter(self, mocker: MockerFixture) -> None:
"""Test the pv power formula."""
mockgrid = MockMicrogrid(grid_meter=False, mocker=mocker)
mockgrid.add_solar_inverters(2)

async with mockgrid, AsyncExitStack() as stack:
pv_pool = microgrid.new_pv_pool(priority=5)
stack.push_async_callback(pv_pool.stop)
pv_power_receiver = pv_pool.power.new_receiver()
# Wait for mock resampler to create forward stream
await asyncio.sleep(0.01)

# Note: PvPowerFormula has a "nones-are-zero" rule, that says:
# * if the meter value is None, it should be treated as None.
# * for other components None is treated as 0.

expected_input_output: list[
tuple[list[float | None], list[float | None], Power | None]
] = [
# ([meter_power], [pv_inverter_power], expected_power)
#
# Case 1: Both meters are available, so inverters are not used.
([-1.0, -2.0], [None, -5.0], Power.from_watts(-3.0)),
([-1.0, -2.0], [-10.0, -20.0], Power.from_watts(-3.0)),
# Case 2: The first meter is unavailable (None).
# Subscribe to the fallback inverter, but return None as the result,
# according to the "nones-are-zero" rule
([None, -2.0], [-10.0, -20.0], None),
# Case 3: First meter is unavailable (None). Fallback inverter provides
# a value.
([None, -2.0], [-10.0, -20.0], Power.from_watts(-12.0)),
([None, -2.0], [-11.0, -20.0], Power.from_watts(-13.0)),
# Case 4: Both first meter and its fallback inverter are unavailable
# (None). Return 0 according to the "nones-are-zero" rule.
([None, -2.0], [None, -20.0], Power.from_watts(-2.0)),
([None, -2.0], [-11.0, -20.0], Power.from_watts(-13.0)),
# Case 5: Both meters are unavailable (None).
# Subscribe to the fallback inverter, but return None as the result,
# according "nones-are-zero" rule
([None, None], [-5.0, -20.0], None),
# Case 6: Both meters are unavailable (None). Fallback inverter provides
# a values.
([None, None], [-5.0, -20.0], Power.from_watts(-25.0)),
# Case 7: All components are unavailable (None).
# Return 0 according to the "nones-are-zero" rule.
([None, None], [None, None], Power.from_watts(0.0)),
([None, None], [-5.0, -20.0], Power.from_watts(-25.0)),
# Case 8: Meters becomes available and inverter values are not used.
([-10.0, None], [-5.0, -20.0], Power.from_watts(-30.0)),
([-10.0, -2.0], [-5.0, -20.0], Power.from_watts(-12.0)),
]

for idx, (meter_power, pv_inverter_power, expected_power) in enumerate(
expected_input_output
):
await mockgrid.mock_resampler.send_meter_power(meter_power)
await mockgrid.mock_resampler.send_pv_inverter_power(pv_inverter_power)
result = await pv_power_receiver.receive()
assert result.value == expected_power, (
f"Test case {idx} failed:"
+ f" meter_power: {meter_power}"
+ f" pv_inverter_power {pv_inverter_power}"
+ f" expected_power: {expected_power}"
+ f" actual_power: {result.value}"
)

0 comments on commit 7d77e83

Please sign in to comment.