|
| 1 | +"""Scenario tests for externally supplied grid-charge targets.""" |
| 2 | +import datetime |
| 3 | + |
| 4 | +import pytest |
| 5 | + |
| 6 | +from batcontrol.logic.default import DefaultLogic |
| 7 | +from batcontrol.logic.next import NextLogic |
| 8 | + |
| 9 | +from .helpers import CHEAP_PRICE, EXPENSIVE_PRICE, make_calc_input, make_logic |
| 10 | + |
| 11 | + |
| 12 | +def _calculate(logic_cls, min_grid_charge_soc): |
| 13 | + logic = make_logic(logic_cls, min_grid_charge_soc=min_grid_charge_soc) |
| 14 | + calc_input = make_calc_input( |
| 15 | + # Cheap current slot, then a moderate expensive block. Stored usable |
| 16 | + # energy covers most forecast need, so changing the target is visible. |
| 17 | + production=[0, 0, 0, 0, 0, 0, 0, 0], |
| 18 | + consumption=[1000, 600, 700, 700, 700, 700, 600, 0], |
| 19 | + prices=[CHEAP_PRICE] + [EXPENSIVE_PRICE] * 6 + [CHEAP_PRICE], |
| 20 | + soc=47.3, |
| 21 | + ) |
| 22 | + |
| 23 | + assert logic.calculate(calc_input, datetime.datetime( |
| 24 | + 2026, 4, 30, 14, 0, 0, tzinfo=datetime.timezone.utc)) |
| 25 | + return logic.get_inverter_control_settings(), logic.get_calculation_output() |
| 26 | + |
| 27 | + |
| 28 | +@pytest.mark.parametrize("logic_cls", [DefaultLogic, NextLogic]) |
| 29 | +def test_higher_grid_charge_target_requests_more_recharge(logic_cls): |
| 30 | + """A caller-provided higher target can prepare for a larger expensive window. |
| 31 | +
|
| 32 | + Dynamic target calculation can stay outside the logic layer: when the |
| 33 | + current cheap slot receives a higher min_grid_charge_soc, both logic |
| 34 | + implementations request more recharge before the future high-price block. |
| 35 | + """ |
| 36 | + low_target = _calculate(logic_cls, min_grid_charge_soc=0.55) |
| 37 | + high_target = _calculate(logic_cls, min_grid_charge_soc=0.84) |
| 38 | + |
| 39 | + low_result, low_output = low_target |
| 40 | + high_result, high_output = high_target |
| 41 | + |
| 42 | + assert low_result.charge_from_grid is True |
| 43 | + assert high_result.charge_from_grid is True |
| 44 | + assert high_output.reserved_energy > low_output.reserved_energy |
| 45 | + assert high_output.required_recharge_energy > low_output.required_recharge_energy |
| 46 | + assert high_result.charge_rate > low_result.charge_rate |
0 commit comments