mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2025-04-19 08:55:15 +00:00
inverter test: Mock SelfConsumptionProbabilityInterpolator
This commit is contained in:
parent
e8a47af04e
commit
b386c4be70
@ -10,7 +10,6 @@ from scipy.interpolate import RegularGridInterpolator
|
|||||||
class SelfConsumptionPropabilityInterpolator:
|
class SelfConsumptionPropabilityInterpolator:
|
||||||
def __init__(self, filepath: str | Path):
|
def __init__(self, filepath: str | Path):
|
||||||
self.filepath = filepath
|
self.filepath = filepath
|
||||||
# self.interpolator = None
|
|
||||||
# Load the RegularGridInterpolator
|
# Load the RegularGridInterpolator
|
||||||
with open(self.filepath, "rb") as file:
|
with open(self.filepath, "rb") as file:
|
||||||
self.interpolator: RegularGridInterpolator = pickle.load(file)
|
self.interpolator: RegularGridInterpolator = pickle.load(file)
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
from pathlib import Path
|
|
||||||
from unittest.mock import Mock
|
from unittest.mock import Mock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from akkudoktoreos.devices.inverter import Inverter, InverterParameters
|
from akkudoktoreos.devices.inverter import Inverter, InverterParameters
|
||||||
from akkudoktoreos.prediction.interpolator import SelfConsumptionPropabilityInterpolator
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@ -17,37 +15,61 @@ def mock_battery():
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def inverter(mock_battery):
|
def inverter(mock_battery):
|
||||||
sc = SelfConsumptionPropabilityInterpolator(
|
mock_self_consumption_predictor = Mock()
|
||||||
Path(__file__).parent.resolve()
|
mock_self_consumption_predictor.calculate_self_consumption.return_value = 1.0
|
||||||
/ ".."
|
return Inverter(
|
||||||
/ "src"
|
mock_self_consumption_predictor,
|
||||||
/ "akkudoktoreos"
|
InverterParameters(max_power_wh=500.0),
|
||||||
/ "data"
|
battery=mock_battery,
|
||||||
/ "regular_grid_interpolator.pkl"
|
|
||||||
)
|
)
|
||||||
return Inverter(sc, InverterParameters(max_power_wh=500.0), battery=mock_battery)
|
|
||||||
|
|
||||||
|
|
||||||
def test_process_energy_excess_generation(inverter, mock_battery):
|
def test_process_energy_excess_generation(inverter, mock_battery):
|
||||||
# Battery charges 100 Wh with 10 Wh loss
|
# Battery charges 100 Wh with 10 Wh loss
|
||||||
|
mock_battery.charge_energy.return_value = (100.0, 10.0)
|
||||||
generation = 600.0
|
generation = 600.0
|
||||||
consumption = 200.0
|
consumption = 200.0
|
||||||
hour = 12
|
hour = 12
|
||||||
|
|
||||||
|
grid_export, grid_import, losses, self_consumption = inverter.process_energy(
|
||||||
|
generation, consumption, hour
|
||||||
|
)
|
||||||
|
|
||||||
|
assert grid_export == pytest.approx(290.0, rel=1e-2) # 290 Wh feed-in after battery charges
|
||||||
|
assert grid_import == 0.0 # No grid draw
|
||||||
|
assert losses == 10.0 # Battery charging losses
|
||||||
|
assert self_consumption == 200.0 # All consumption is met
|
||||||
|
mock_battery.charge_energy.assert_called_once_with(400.0, hour)
|
||||||
|
mock_battery.discharge_energy.assert_not_called()
|
||||||
|
inverter.self_consumption_predictor.calculate_self_consumption.assert_called_once_with(
|
||||||
|
consumption, generation
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_process_energy_excess_generation_interpolator(inverter, mock_battery):
|
||||||
|
# Battery charges 100 Wh with 10 Wh loss
|
||||||
mock_battery.charge_energy.return_value = (100.0, 10.0)
|
mock_battery.charge_energy.return_value = (100.0, 10.0)
|
||||||
|
mock_battery.discharge_energy.return_value = (20.0, 2.0)
|
||||||
|
inverter.self_consumption_predictor.calculate_self_consumption.return_value = 0.95
|
||||||
|
|
||||||
|
generation = 600.0
|
||||||
|
consumption = 200.0
|
||||||
|
hour = 12
|
||||||
|
|
||||||
grid_export, grid_import, losses, self_consumption = inverter.process_energy(
|
grid_export, grid_import, losses, self_consumption = inverter.process_energy(
|
||||||
generation, consumption, hour
|
generation, consumption, hour
|
||||||
)
|
)
|
||||||
|
|
||||||
assert grid_export == pytest.approx(
|
assert grid_export == pytest.approx(
|
||||||
286.1737223461208, rel=1e-2
|
270.0, rel=1e-2
|
||||||
) # 290 Wh feed-in after battery charges
|
) # 290 Wh feed-in - 5% of generation-consumption self consumption after battery charges
|
||||||
assert grid_import == pytest.approx(3.826277653879151, rel=1e-2) # Little grid draw
|
assert grid_import == pytest.approx(0.0, rel=1e-2) # No grid draw
|
||||||
assert losses == 10.0 # Battery charging losses
|
assert losses == 12.0 # Battery charging losses
|
||||||
assert self_consumption == 200.0 # All consumption is met
|
assert self_consumption == 220.0 # All consumption is met
|
||||||
mock_battery.charge_energy.assert_called_once_with(
|
mock_battery.charge_energy.assert_called_once_with(pytest.approx(380.0, rel=1e-2), hour)
|
||||||
pytest.approx(396.1737223461208, rel=1e-2), hour
|
mock_battery.discharge_energy.assert_called_once_with(pytest.approx(20.0, rel=1e-2), hour)
|
||||||
|
inverter.self_consumption_predictor.calculate_self_consumption.assert_called_once_with(
|
||||||
|
consumption, generation
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -67,6 +89,9 @@ def test_process_energy_generation_equals_consumption(inverter, mock_battery):
|
|||||||
|
|
||||||
mock_battery.charge_energy.assert_not_called()
|
mock_battery.charge_energy.assert_not_called()
|
||||||
mock_battery.discharge_energy.assert_not_called()
|
mock_battery.discharge_energy.assert_not_called()
|
||||||
|
inverter.self_consumption_predictor.calculate_self_consumption.assert_called_once_with(
|
||||||
|
consumption, generation
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_process_energy_battery_discharges(inverter, mock_battery):
|
def test_process_energy_battery_discharges(inverter, mock_battery):
|
||||||
@ -86,7 +111,9 @@ def test_process_energy_battery_discharges(inverter, mock_battery):
|
|||||||
) # Grid supplies remaining shortfall after battery discharge
|
) # Grid supplies remaining shortfall after battery discharge
|
||||||
assert losses == 10.0 # Discharge losses
|
assert losses == 10.0 # Discharge losses
|
||||||
assert self_consumption == 200.0 # Generation + battery discharge
|
assert self_consumption == 200.0 # Generation + battery discharge
|
||||||
|
mock_battery.charge_energy.assert_not_called()
|
||||||
mock_battery.discharge_energy.assert_called_once_with(150.0, hour)
|
mock_battery.discharge_energy.assert_called_once_with(150.0, hour)
|
||||||
|
inverter.self_consumption_predictor.calculate_self_consumption.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
def test_process_energy_battery_empty(inverter, mock_battery):
|
def test_process_energy_battery_empty(inverter, mock_battery):
|
||||||
@ -104,7 +131,9 @@ def test_process_energy_battery_empty(inverter, mock_battery):
|
|||||||
assert grid_import == pytest.approx(200.0, rel=1e-2) # Grid has to cover the full shortfall
|
assert grid_import == pytest.approx(200.0, rel=1e-2) # Grid has to cover the full shortfall
|
||||||
assert losses == 0.0 # No losses as the battery didn't discharge
|
assert losses == 0.0 # No losses as the battery didn't discharge
|
||||||
assert self_consumption == 100.0 # Only generation is consumed
|
assert self_consumption == 100.0 # Only generation is consumed
|
||||||
|
mock_battery.charge_energy.assert_not_called()
|
||||||
mock_battery.discharge_energy.assert_called_once_with(200.0, hour)
|
mock_battery.discharge_energy.assert_called_once_with(200.0, hour)
|
||||||
|
inverter.self_consumption_predictor.calculate_self_consumption.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
def test_process_energy_battery_full_at_start(inverter, mock_battery):
|
def test_process_energy_battery_full_at_start(inverter, mock_battery):
|
||||||
@ -119,13 +148,15 @@ def test_process_energy_battery_full_at_start(inverter, mock_battery):
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert grid_export == pytest.approx(
|
assert grid_export == pytest.approx(
|
||||||
296.39026480502736, rel=1e-2
|
300.0, rel=1e-2
|
||||||
) # All excess energy should be fed into the grid
|
) # All excess energy should be fed into the grid
|
||||||
assert grid_import == pytest.approx(3.609735194972663, rel=1e-2) # Almost no grid draw
|
assert grid_import == 0.0 # No grid draw
|
||||||
assert losses == 0.0 # No losses
|
assert losses == 0.0 # No losses
|
||||||
assert self_consumption == 200.0 # Only consumption is met
|
assert self_consumption == 200.0 # Only consumption is met
|
||||||
mock_battery.charge_energy.assert_called_once_with(
|
mock_battery.charge_energy.assert_called_once_with(300.0, hour)
|
||||||
pytest.approx(296.39026480502736, rel=1e-2), hour
|
mock_battery.discharge_energy.assert_not_called()
|
||||||
|
inverter.self_consumption_predictor.calculate_self_consumption.assert_called_once_with(
|
||||||
|
consumption, generation
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -144,7 +175,9 @@ def test_process_energy_insufficient_generation_no_battery(inverter, mock_batter
|
|||||||
assert grid_import == pytest.approx(400.0, rel=1e-2) # Grid supplies the shortfall
|
assert grid_import == pytest.approx(400.0, rel=1e-2) # Grid supplies the shortfall
|
||||||
assert losses == 0.0 # No losses
|
assert losses == 0.0 # No losses
|
||||||
assert self_consumption == 100.0 # Only generation is consumed
|
assert self_consumption == 100.0 # Only generation is consumed
|
||||||
|
mock_battery.charge_energy.assert_not_called()
|
||||||
mock_battery.discharge_energy.assert_called_once_with(400.0, hour)
|
mock_battery.discharge_energy.assert_called_once_with(400.0, hour)
|
||||||
|
inverter.self_consumption_predictor.calculate_self_consumption.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
def test_process_energy_insufficient_generation_battery_assists(inverter, mock_battery):
|
def test_process_energy_insufficient_generation_battery_assists(inverter, mock_battery):
|
||||||
@ -167,7 +200,9 @@ def test_process_energy_insufficient_generation_battery_assists(inverter, mock_b
|
|||||||
) # Grid supplies the remaining shortfall after battery discharge
|
) # Grid supplies the remaining shortfall after battery discharge
|
||||||
assert losses == 5.0 # Discharge losses
|
assert losses == 5.0 # Discharge losses
|
||||||
assert self_consumption == 250.0 # Generation + battery discharge
|
assert self_consumption == 250.0 # Generation + battery discharge
|
||||||
|
mock_battery.charge_energy.assert_not_called()
|
||||||
mock_battery.discharge_energy.assert_called_once_with(200.0, hour)
|
mock_battery.discharge_energy.assert_called_once_with(200.0, hour)
|
||||||
|
inverter.self_consumption_predictor.calculate_self_consumption.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
def test_process_energy_zero_generation(inverter, mock_battery):
|
def test_process_energy_zero_generation(inverter, mock_battery):
|
||||||
@ -188,7 +223,9 @@ def test_process_energy_zero_generation(inverter, mock_battery):
|
|||||||
assert grid_import == pytest.approx(200.0, rel=1e-2) # Grid supplies the remaining shortfall
|
assert grid_import == pytest.approx(200.0, rel=1e-2) # Grid supplies the remaining shortfall
|
||||||
assert losses == 5.0 # Discharge losses
|
assert losses == 5.0 # Discharge losses
|
||||||
assert self_consumption == 100.0 # Only battery discharge is consumed
|
assert self_consumption == 100.0 # Only battery discharge is consumed
|
||||||
|
mock_battery.charge_energy.assert_not_called()
|
||||||
mock_battery.discharge_energy.assert_called_once_with(300.0, hour)
|
mock_battery.discharge_energy.assert_called_once_with(300.0, hour)
|
||||||
|
inverter.self_consumption_predictor.calculate_self_consumption.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
def test_process_energy_zero_consumption(inverter, mock_battery):
|
def test_process_energy_zero_consumption(inverter, mock_battery):
|
||||||
@ -203,13 +240,13 @@ def test_process_energy_zero_consumption(inverter, mock_battery):
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert grid_export == pytest.approx(390.0, rel=1e-2) # Excess energy after battery charges
|
assert grid_export == pytest.approx(390.0, rel=1e-2) # Excess energy after battery charges
|
||||||
assert grid_import == pytest.approx(
|
assert grid_import == 0.0 # No grid draw as no consumption
|
||||||
0.022862368543430378, rel=1e-2
|
|
||||||
) # Almost no grid draw as no consumption
|
|
||||||
assert losses == 10.0 # Charging losses
|
assert losses == 10.0 # Charging losses
|
||||||
assert self_consumption == 0.0 # Zero consumption
|
assert self_consumption == 0.0 # Zero consumption
|
||||||
mock_battery.charge_energy.assert_called_once_with(
|
mock_battery.charge_energy.assert_called_once_with(500.0, hour)
|
||||||
pytest.approx(499.97713763145657, rel=1e-2), hour
|
mock_battery.discharge_energy.assert_not_called()
|
||||||
|
inverter.self_consumption_predictor.calculate_self_consumption.assert_called_once_with(
|
||||||
|
consumption, generation
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -226,6 +263,11 @@ def test_process_energy_zero_generation_zero_consumption(inverter, mock_battery)
|
|||||||
assert grid_import == 0.0 # No grid draw
|
assert grid_import == 0.0 # No grid draw
|
||||||
assert losses == 0.0 # No losses
|
assert losses == 0.0 # No losses
|
||||||
assert self_consumption == 0.0 # No consumption
|
assert self_consumption == 0.0 # No consumption
|
||||||
|
mock_battery.charge_energy.assert_not_called()
|
||||||
|
mock_battery.discharge_energy.assert_not_called()
|
||||||
|
inverter.self_consumption_predictor.calculate_self_consumption.assert_called_once_with(
|
||||||
|
consumption, generation
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_process_energy_partial_battery_discharge(inverter, mock_battery):
|
def test_process_energy_partial_battery_discharge(inverter, mock_battery):
|
||||||
@ -244,6 +286,9 @@ def test_process_energy_partial_battery_discharge(inverter, mock_battery):
|
|||||||
) # Grid supplies the shortfall after battery assist
|
) # Grid supplies the shortfall after battery assist
|
||||||
assert losses == 5.0 # Discharge losses
|
assert losses == 5.0 # Discharge losses
|
||||||
assert self_consumption == 250.0 # Generation + battery discharge
|
assert self_consumption == 250.0 # Generation + battery discharge
|
||||||
|
mock_battery.charge_energy.assert_not_called()
|
||||||
|
mock_battery.discharge_energy.assert_called_once_with(200.0, 12)
|
||||||
|
inverter.self_consumption_predictor.calculate_self_consumption.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
def test_process_energy_consumption_exceeds_max_no_battery(inverter, mock_battery):
|
def test_process_energy_consumption_exceeds_max_no_battery(inverter, mock_battery):
|
||||||
@ -261,7 +306,9 @@ def test_process_energy_consumption_exceeds_max_no_battery(inverter, mock_batter
|
|||||||
assert grid_import == pytest.approx(900.0, rel=1e-2) # Grid covers the remaining shortfall
|
assert grid_import == pytest.approx(900.0, rel=1e-2) # Grid covers the remaining shortfall
|
||||||
assert losses == 0.0 # No losses as the battery didn’t assist
|
assert losses == 0.0 # No losses as the battery didn’t assist
|
||||||
assert self_consumption == 100.0 # Only the generation is consumed, maxing out the inverter
|
assert self_consumption == 100.0 # Only the generation is consumed, maxing out the inverter
|
||||||
|
mock_battery.charge_energy.assert_not_called()
|
||||||
mock_battery.discharge_energy.assert_called_once_with(400.0, hour)
|
mock_battery.discharge_energy.assert_called_once_with(400.0, hour)
|
||||||
|
inverter.self_consumption_predictor.calculate_self_consumption.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
def test_process_energy_zero_generation_full_battery_high_consumption(inverter, mock_battery):
|
def test_process_energy_zero_generation_full_battery_high_consumption(inverter, mock_battery):
|
||||||
@ -281,4 +328,6 @@ def test_process_energy_zero_generation_full_battery_high_consumption(inverter,
|
|||||||
) # Grid covers remaining shortfall after battery discharge
|
) # Grid covers remaining shortfall after battery discharge
|
||||||
assert losses == 10.0 # Battery discharge losses
|
assert losses == 10.0 # Battery discharge losses
|
||||||
assert self_consumption == 500.0 # Battery fully discharges to meet consumption
|
assert self_consumption == 500.0 # Battery fully discharges to meet consumption
|
||||||
|
mock_battery.charge_energy.assert_not_called()
|
||||||
mock_battery.discharge_energy.assert_called_once_with(500.0, hour)
|
mock_battery.discharge_energy.assert_called_once_with(500.0, hour)
|
||||||
|
inverter.self_consumption_predictor.calculate_self_consumption.assert_not_called()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user