Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix consumer_power() not working certain configurations. #589

Merged
merged 3 commits into from
Aug 22, 2023
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
3 changes: 3 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@
component.
So far we only had configurations like this: Meter -> Inverter -> PV. However
the scenario with Inverter -> PV is also possible and now handled correctly.
- Fix `consumer_power()` not working certain configurations.
In microgrids without consumers and no main meter, the formula
would never return any values.
2 changes: 1 addition & 1 deletion benchmarks/timeseries/benchmark_datasourcing.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ async def benchmark_data_sourcing(
num_ev_chargers * len(COMPONENT_METRIC_IDS) * num_msgs_per_battery
)
mock_grid = MockMicrogrid(
grid_side_meter=False, num_values=num_msgs_per_battery, sample_rate_s=0.0
grid_meter=False, num_values=num_msgs_per_battery, sample_rate_s=0.0
)

mock_grid.add_ev_chargers(num_ev_chargers)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,21 @@

from __future__ import annotations

import logging
from collections import abc

from ....microgrid import connection_manager
from ....microgrid.component import Component, ComponentCategory, ComponentMetricId
from ..._quantities import Power
from .._formula_engine import FormulaEngine
from .._resampled_formula_builder import ResampledFormulaBuilder
from ._formula_generator import ComponentNotFound, FormulaGenerator
from ._formula_generator import (
NON_EXISTING_COMPONENT_ID,
ComponentNotFound,
FormulaGenerator,
)

_logger = logging.getLogger(__name__)


class ConsumerPowerFormula(FormulaGenerator[Power]):
Expand Down Expand Up @@ -121,4 +128,17 @@ def _gen_without_grid_meter(
is_first = False
builder.push_component_metric(successor.component_id, nones_are_zeros=False)

if len(builder.finalize()[0]) == 0:
# If there are no consumer components, we have to send 0 values at the same
# frequency as the other streams. So we subscribe with a non-existing
# component id, just to get a `None` message at the resampling interval.
builder.push_component_metric(
NON_EXISTING_COMPONENT_ID, nones_are_zeros=True
)
_logger.warning(
"Unable to find any consumers in the component graph. "
"Subscribing to the resampling actor with a non-existing "
"component id, so that `0` values are sent from the formula."
)

return builder.build()
2 changes: 1 addition & 1 deletion tests/actor/test_battery_pool_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ async def test_batteries_status(self, mocker: MockerFixture) -> None:
Args:
mock_microgrid: mock microgrid client
"""
mock_microgrid = MockMicrogrid(grid_side_meter=True)
mock_microgrid = MockMicrogrid(grid_meter=True)
mock_microgrid.add_batteries(3)
await mock_microgrid.start(mocker)

Expand Down
14 changes: 7 additions & 7 deletions tests/actor/test_battery_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ async def test_sync_update_status_with_messages(
Args:
mock_microgrid: mock_microgrid fixture
"""
mock_microgrid = MockMicrogrid(grid_side_meter=True)
mock_microgrid = MockMicrogrid(grid_meter=True)
mock_microgrid.add_batteries(3)
await mock_microgrid.start(mocker)

Expand Down Expand Up @@ -318,7 +318,7 @@ async def test_sync_blocking_feature(self, mocker: MockerFixture) -> None:
Args:
mock_microgrid: mock_microgrid fixture
"""
mock_microgrid = MockMicrogrid(grid_side_meter=True)
mock_microgrid = MockMicrogrid(grid_meter=True)
mock_microgrid.add_batteries(3)
await mock_microgrid.start(mocker)

Expand Down Expand Up @@ -435,7 +435,7 @@ async def test_sync_blocking_interrupted_with_with_max_data(
Args:
mock_microgrid: mock_microgrid fixture
"""
mock_microgrid = MockMicrogrid(grid_side_meter=True)
mock_microgrid = MockMicrogrid(grid_meter=True)
mock_microgrid.add_batteries(3)
await mock_microgrid.start(mocker)

Expand Down Expand Up @@ -486,7 +486,7 @@ async def test_sync_blocking_interrupted_with_invalid_message(
Args:
mock_microgrid: mock_microgrid fixture
"""
mock_microgrid = MockMicrogrid(grid_side_meter=True)
mock_microgrid = MockMicrogrid(grid_meter=True)
mock_microgrid.add_batteries(3)
await mock_microgrid.start(mocker)

Expand Down Expand Up @@ -547,7 +547,7 @@ async def test_timers(self, mocker: MockerFixture) -> None:
mock_microgrid: mock_microgrid fixture
mocker: pytest mocker instance
"""
mock_microgrid = MockMicrogrid(grid_side_meter=True)
mock_microgrid = MockMicrogrid(grid_meter=True)
mock_microgrid.add_batteries(3)
await mock_microgrid.start(mocker)

Expand Down Expand Up @@ -609,7 +609,7 @@ async def test_async_battery_status(self, mocker: MockerFixture) -> None:
Args:
mock_microgrid: mock_microgrid fixture
"""
mock_microgrid = MockMicrogrid(grid_side_meter=True)
mock_microgrid = MockMicrogrid(grid_meter=True)
mock_microgrid.add_batteries(3)
await mock_microgrid.start(mocker)

Expand Down Expand Up @@ -690,7 +690,7 @@ async def setup_tracker(
self, mocker: MockerFixture
) -> AsyncIterator[tuple[MockMicrogrid, Receiver[Status]]]:
"""Setup a BatteryStatusTracker instance to run tests with."""
mock_microgrid = MockMicrogrid(grid_side_meter=True)
mock_microgrid = MockMicrogrid(grid_meter=True)
mock_microgrid.add_batteries(1)
await mock_microgrid.start(mocker)

Expand Down
30 changes: 15 additions & 15 deletions tests/actor/test_power_distributing.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class TestPowerDistributingActor:

async def test_constructor(self, mocker: MockerFixture) -> None:
"""Test if gets all necessary data."""
mockgrid = MockMicrogrid(grid_side_meter=True)
mockgrid = MockMicrogrid(grid_meter=True)
mockgrid.add_batteries(2)
mockgrid.add_batteries(1, no_meter=True)
await mockgrid.start(mocker)
Expand All @@ -68,7 +68,7 @@ async def test_constructor(self, mocker: MockerFixture) -> None:
await mockgrid.cleanup()

# Test if it works without grid side meter
mockgrid = MockMicrogrid(grid_side_meter=False)
mockgrid = MockMicrogrid(grid_meter=False)
mockgrid.add_batteries(1)
mockgrid.add_batteries(2, no_meter=True)
await mockgrid.start(mocker)
Expand Down Expand Up @@ -108,7 +108,7 @@ async def init_component_data(self, mockgrid: MockMicrogrid) -> None:

async def test_power_distributor_one_user(self, mocker: MockerFixture) -> None:
"""Test if power distribution works with single user works."""
mockgrid = MockMicrogrid(grid_side_meter=False)
mockgrid = MockMicrogrid(grid_meter=False)
mockgrid.add_batteries(3)
await mockgrid.start(mocker)
await self.init_component_data(mockgrid)
Expand Down Expand Up @@ -157,7 +157,7 @@ async def test_power_distributor_one_user(self, mocker: MockerFixture) -> None:

async def test_battery_soc_nan(self, mocker: MockerFixture) -> None:
"""Test if battery with SoC==NaN is not used."""
mockgrid = MockMicrogrid(grid_side_meter=False)
mockgrid = MockMicrogrid(grid_meter=False)
mockgrid.add_batteries(3)
await mockgrid.start(mocker)
await self.init_component_data(mockgrid)
Expand Down Expand Up @@ -222,7 +222,7 @@ async def test_battery_soc_nan(self, mocker: MockerFixture) -> None:

async def test_battery_capacity_nan(self, mocker: MockerFixture) -> None:
"""Test battery with capacity set to NaN is not used."""
mockgrid = MockMicrogrid(grid_side_meter=False)
mockgrid = MockMicrogrid(grid_meter=False)
mockgrid.add_batteries(3)
await mockgrid.start(mocker)
await self.init_component_data(mockgrid)
Expand Down Expand Up @@ -280,7 +280,7 @@ async def test_battery_capacity_nan(self, mocker: MockerFixture) -> None:

async def test_battery_power_bounds_nan(self, mocker: MockerFixture) -> None:
"""Test battery with power bounds set to NaN is not used."""
mockgrid = MockMicrogrid(grid_side_meter=False)
mockgrid = MockMicrogrid(grid_meter=False)
mockgrid.add_batteries(3)
await mockgrid.start(mocker)
await self.init_component_data(mockgrid)
Expand Down Expand Up @@ -356,7 +356,7 @@ async def test_power_distributor_invalid_battery_id(
self, mocker: MockerFixture
) -> None:
"""Test if power distribution raises error if any battery id is invalid."""
mockgrid = MockMicrogrid(grid_side_meter=False)
mockgrid = MockMicrogrid(grid_meter=False)
mockgrid.add_batteries(3)
await mockgrid.start(mocker)
await self.init_component_data(mockgrid)
Expand Down Expand Up @@ -404,7 +404,7 @@ async def test_power_distributor_one_user_adjust_power_consume(
self, mocker: MockerFixture
) -> None:
"""Test if power distribution works with single user works."""
mockgrid = MockMicrogrid(grid_side_meter=False)
mockgrid = MockMicrogrid(grid_meter=False)
mockgrid.add_batteries(3)
await mockgrid.start(mocker)
await self.init_component_data(mockgrid)
Expand Down Expand Up @@ -457,7 +457,7 @@ async def test_power_distributor_one_user_adjust_power_supply(
self, mocker: MockerFixture
) -> None:
"""Test if power distribution works with single user works."""
mockgrid = MockMicrogrid(grid_side_meter=False)
mockgrid = MockMicrogrid(grid_meter=False)
mockgrid.add_batteries(3)
await mockgrid.start(mocker)
await self.init_component_data(mockgrid)
Expand Down Expand Up @@ -510,7 +510,7 @@ async def test_power_distributor_one_user_adjust_power_success(
self, mocker: MockerFixture
) -> None:
"""Test if power distribution works with single user works."""
mockgrid = MockMicrogrid(grid_side_meter=False)
mockgrid = MockMicrogrid(grid_meter=False)
mockgrid.add_batteries(3)
await mockgrid.start(mocker)
await self.init_component_data(mockgrid)
Expand Down Expand Up @@ -561,7 +561,7 @@ async def test_power_distributor_one_user_adjust_power_success(

async def test_not_all_batteries_are_working(self, mocker: MockerFixture) -> None:
"""Test if power distribution works if not all batteries are working."""
mockgrid = MockMicrogrid(grid_side_meter=False)
mockgrid = MockMicrogrid(grid_meter=False)
mockgrid.add_batteries(3)
await mockgrid.start(mocker)
await self.init_component_data(mockgrid)
Expand Down Expand Up @@ -615,7 +615,7 @@ async def test_use_all_batteries_none_is_working(
self, mocker: MockerFixture
) -> None:
"""Test all batteries are used if none of them works."""
mockgrid = MockMicrogrid(grid_side_meter=False)
mockgrid = MockMicrogrid(grid_meter=False)
mockgrid.add_batteries(3)
await mockgrid.start(mocker)
await self.init_component_data(mockgrid)
Expand Down Expand Up @@ -668,7 +668,7 @@ async def test_force_request_a_battery_is_not_working(
self, mocker: MockerFixture
) -> None:
"""Test force request when a battery is not working."""
mockgrid = MockMicrogrid(grid_side_meter=False)
mockgrid = MockMicrogrid(grid_meter=False)
mockgrid.add_batteries(3)
await mockgrid.start(mocker)
await self.init_component_data(mockgrid)
Expand Down Expand Up @@ -724,7 +724,7 @@ async def test_force_request_battery_nan_value_non_cached(
) -> None:
"""Test battery with NaN in SoC, capacity or power is used if request is forced."""
# pylint: disable=too-many-locals
mockgrid = MockMicrogrid(grid_side_meter=False)
mockgrid = MockMicrogrid(grid_meter=False)
mockgrid.add_batteries(3)
await mockgrid.start(mocker)
await self.init_component_data(mockgrid)
Expand Down Expand Up @@ -797,7 +797,7 @@ async def test_force_request_batteries_nan_values_cached(
self, mocker: MockerFixture
) -> None:
"""Test battery with NaN in SoC, capacity or power is used if request is forced."""
mockgrid = MockMicrogrid(grid_side_meter=False)
mockgrid = MockMicrogrid(grid_meter=False)
mockgrid.add_batteries(3)
await mockgrid.start(mocker)
await self.init_component_data(mockgrid)
Expand Down
2 changes: 1 addition & 1 deletion tests/timeseries/_battery_pool/test_battery_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ async def run_test_battery_status_channel( # pylint: disable=too-many-arguments

async def test_battery_pool_power(mocker: MockerFixture) -> None:
"""Test `BatteryPool.{,production,consumption}_power` methods."""
mockgrid = MockMicrogrid(grid_side_meter=True)
mockgrid = MockMicrogrid(grid_meter=True)
mockgrid.add_batteries(2)
await mockgrid.start(mocker)

Expand Down
24 changes: 10 additions & 14 deletions tests/timeseries/_formula_engine/test_formula_composition.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,17 @@ async def test_formula_composition( # pylint: disable=too-many-locals
mocker: MockerFixture,
) -> None:
"""Test the composition of formulas."""
mockgrid = MockMicrogrid(grid_side_meter=False)
mockgrid = MockMicrogrid(grid_meter=False)
mockgrid.add_consumer_meters()
mockgrid.add_batteries(3)
mockgrid.add_solar_inverters(2)
await mockgrid.start(mocker)

logical_meter = microgrid.logical_meter()
battery_pool = microgrid.battery_pool()
main_meter_recv = get_resampled_stream(
grid_meter_recv = get_resampled_stream(
logical_meter._namespace, # pylint: disable=protected-access
4,
mockgrid.meter_ids[0],
ComponentMetricId.ACTIVE_POWER,
Power.from_watts,
)
Expand All @@ -53,7 +54,7 @@ async def test_formula_composition( # pylint: disable=too-many-locals
grid_pow = await grid_power_recv.receive()
pv_pow = await pv_power_recv.receive()
bat_pow = await battery_power_recv.receive()
main_pow = await main_meter_recv.receive()
main_pow = await grid_meter_recv.receive()
inv_calc_pow = await inv_calc_recv.receive()

assert (
Expand Down Expand Up @@ -98,7 +99,7 @@ async def test_formula_composition( # pylint: disable=too-many-locals

async def test_formula_composition_missing_pv(self, mocker: MockerFixture) -> None:
"""Test the composition of formulas with missing PV power data."""
mockgrid = MockMicrogrid(grid_side_meter=False)
mockgrid = MockMicrogrid(grid_meter=False)
mockgrid.add_batteries(3)
await mockgrid.start(mocker)
battery_pool = microgrid.battery_pool()
Expand Down Expand Up @@ -136,7 +137,7 @@ async def test_formula_composition_missing_pv(self, mocker: MockerFixture) -> No

async def test_formula_composition_missing_bat(self, mocker: MockerFixture) -> None:
"""Test the composition of formulas with missing battery power data."""
mockgrid = MockMicrogrid(grid_side_meter=False)
mockgrid = MockMicrogrid(grid_meter=False)
mockgrid.add_solar_inverters(2)
await mockgrid.start(mocker)
battery_pool = microgrid.battery_pool()
Expand All @@ -149,9 +150,7 @@ async def test_formula_composition_missing_bat(self, mocker: MockerFixture) -> N

count = 0
for _ in range(10):
await mockgrid.mock_resampler.send_meter_power(
[10.0 + count, 12.0 + count, 14.0 + count]
)
await mockgrid.mock_resampler.send_meter_power([12.0 + count, 14.0 + count])
await mockgrid.mock_resampler.send_non_existing_component_value()
bat_pow = await battery_power_recv.receive()
pv_pow = await pv_power_recv.receive()
Expand All @@ -173,7 +172,7 @@ async def test_formula_composition_missing_bat(self, mocker: MockerFixture) -> N

async def test_formula_composition_constant(self, mocker: MockerFixture) -> None:
"""Test the composition of formulas with constant values."""
mockgrid = MockMicrogrid(grid_side_meter=True)
mockgrid = MockMicrogrid(grid_meter=True)
await mockgrid.start(mocker)

logical_meter = microgrid.logical_meter()
Expand Down Expand Up @@ -243,9 +242,7 @@ async def test_formula_composition_constant(self, mocker: MockerFixture) -> None

async def test_3_phase_formulas(self, mocker: MockerFixture) -> None:
"""Test 3 phase formulas current formulas and their composition."""
mockgrid = MockMicrogrid(
grid_side_meter=False, sample_rate_s=0.05, num_namespaces=2
)
mockgrid = MockMicrogrid(grid_meter=False, sample_rate_s=0.05, num_namespaces=2)
mockgrid.add_batteries(3)
mockgrid.add_ev_chargers(1)
await mockgrid.start(mocker)
Expand All @@ -266,7 +263,6 @@ async def test_3_phase_formulas(self, mocker: MockerFixture) -> None:
[10.0, 12.0, 14.0],
[10.0, 12.0, 14.0],
[10.0, 12.0, 14.0],
[10.0, 12.0, 14.0],
]
)
await mockgrid.mock_resampler.send_evc_current(
Expand Down
Loading