mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2025-09-13 07:21:16 +00:00
translation of battery.py v3 (#262)
This commit is contained in:
219
tests/test_battery.py
Normal file
219
tests/test_battery.py
Normal file
@@ -0,0 +1,219 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from akkudoktoreos.devices.battery import Battery, SolarPanelBatteryParameters
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def setup_pv_battery():
|
||||
params = SolarPanelBatteryParameters(
|
||||
capacity_wh=10000,
|
||||
initial_soc_percentage=50,
|
||||
min_soc_percentage=20,
|
||||
max_soc_percentage=80,
|
||||
max_charge_power_w=8000,
|
||||
)
|
||||
battery = Battery(params, hours=24)
|
||||
battery.reset()
|
||||
return battery
|
||||
|
||||
|
||||
def test_initial_state_of_charge(setup_pv_battery):
|
||||
battery = setup_pv_battery
|
||||
assert battery.current_soc_percentage() == 50.0, "Initial SoC should be 50%"
|
||||
|
||||
|
||||
def test_battery_discharge_below_min_soc(setup_pv_battery):
|
||||
battery = setup_pv_battery
|
||||
discharged_wh, loss_wh = battery.discharge_energy(5000, 0)
|
||||
|
||||
# Ensure it discharges energy and stops at the min SOC
|
||||
assert discharged_wh > 0
|
||||
print(discharged_wh, loss_wh, battery.current_soc_percentage(), battery.min_soc_percentage)
|
||||
assert battery.current_soc_percentage() >= 20 # Ensure it's above min_soc_percentage
|
||||
assert loss_wh >= 0 # Losses should not be negative
|
||||
assert discharged_wh == 2640.0, "The energy discharged should be limited by min_soc"
|
||||
|
||||
|
||||
def test_battery_charge_above_max_soc(setup_pv_battery):
|
||||
battery = setup_pv_battery
|
||||
charged_wh, loss_wh = battery.charge_energy(5000, 0)
|
||||
|
||||
# Ensure it charges energy and stops at the max SOC
|
||||
assert charged_wh > 0
|
||||
assert battery.current_soc_percentage() <= 80 # Ensure it's below max_soc_percentage
|
||||
assert loss_wh >= 0 # Losses should not be negative
|
||||
assert charged_wh == 3000.0, "The energy charged should be limited by max_soc"
|
||||
|
||||
|
||||
def test_battery_charge_when_full(setup_pv_battery):
|
||||
battery = setup_pv_battery
|
||||
battery.soc_wh = battery.max_soc_wh # Set battery to full
|
||||
charged_wh, loss_wh = battery.charge_energy(5000, 0)
|
||||
|
||||
# No charging should happen if battery is full
|
||||
assert charged_wh == 0
|
||||
assert loss_wh == 0
|
||||
assert battery.current_soc_percentage() == 80, "SoC should remain at max_soc"
|
||||
|
||||
|
||||
def test_battery_discharge_when_empty(setup_pv_battery):
|
||||
battery = setup_pv_battery
|
||||
battery.soc_wh = battery.min_soc_wh # Set battery to minimum SOC
|
||||
discharged_wh, loss_wh = battery.discharge_energy(5000, 0)
|
||||
|
||||
# No discharge should happen if battery is at min SOC
|
||||
assert discharged_wh == 0
|
||||
assert loss_wh == 0
|
||||
assert battery.current_soc_percentage() == 20, "SoC should remain at min_soc"
|
||||
|
||||
|
||||
def test_battery_discharge_exactly_min_soc(setup_pv_battery):
|
||||
battery = setup_pv_battery
|
||||
battery.soc_wh = battery.min_soc_wh # Set battery to exactly min SOC
|
||||
discharged_wh, loss_wh = battery.discharge_energy(1000, 0)
|
||||
|
||||
# Battery should not go below the min SOC
|
||||
assert discharged_wh == 0
|
||||
assert battery.current_soc_percentage() == 20 # SOC should remain at min_SOC
|
||||
|
||||
|
||||
def test_battery_charge_exactly_max_soc(setup_pv_battery):
|
||||
battery = setup_pv_battery
|
||||
battery.soc_wh = battery.max_soc_wh # Set battery to exactly max SOC
|
||||
charged_wh, loss_wh = battery.charge_energy(1000, 0)
|
||||
|
||||
# Battery should not exceed the max SOC
|
||||
assert charged_wh == 0
|
||||
assert battery.current_soc_percentage() == 80 # SOC should remain at max_SOC
|
||||
|
||||
|
||||
def test_battery_reset_function(setup_pv_battery):
|
||||
battery = setup_pv_battery
|
||||
battery.soc_wh = 8000 # Change the SOC to some value
|
||||
battery.reset()
|
||||
|
||||
# After reset, SOC should be equal to the initial value
|
||||
assert battery.current_soc_percentage() == battery.initial_soc_percentage
|
||||
|
||||
|
||||
def test_soc_limits(setup_pv_battery):
|
||||
battery = setup_pv_battery
|
||||
|
||||
# Manually set SoC above max limit
|
||||
battery.soc_wh = battery.max_soc_wh + 1000
|
||||
battery.soc_wh = min(battery.soc_wh, battery.max_soc_wh)
|
||||
assert battery.current_soc_percentage() <= 80, "SoC should not exceed max_soc"
|
||||
|
||||
# Manually set SoC below min limit
|
||||
battery.soc_wh = battery.min_soc_wh - 1000
|
||||
battery.soc_wh = max(battery.soc_wh, battery.min_soc_wh)
|
||||
assert battery.current_soc_percentage() >= 20, "SoC should not drop below min_soc"
|
||||
|
||||
|
||||
def test_max_charge_power_w(setup_pv_battery):
|
||||
battery = setup_pv_battery
|
||||
battery.setup()
|
||||
assert (
|
||||
battery.parameters.max_charge_power_w == 8000
|
||||
), "Default max charge power should be 5000W, We ask for 8000W here"
|
||||
|
||||
|
||||
def test_charge_energy_within_limits(setup_pv_battery):
|
||||
battery = setup_pv_battery
|
||||
battery.setup()
|
||||
initial_soc_wh = battery.soc_wh
|
||||
|
||||
charged_wh, losses_wh = battery.charge_energy(wh=4000, hour=1)
|
||||
|
||||
assert charged_wh > 0, "Charging should add energy"
|
||||
assert losses_wh >= 0, "Losses should not be negative"
|
||||
assert battery.soc_wh > initial_soc_wh, "State of charge should increase after charging"
|
||||
assert battery.soc_wh <= battery.max_soc_wh, "SOC should not exceed max SOC"
|
||||
|
||||
|
||||
def test_charge_energy_exceeds_capacity(setup_pv_battery):
|
||||
battery = setup_pv_battery
|
||||
battery.setup()
|
||||
initial_soc_wh = battery.soc_wh
|
||||
|
||||
# Try to overcharge beyond max capacity
|
||||
charged_wh, losses_wh = battery.charge_energy(wh=20000, hour=2)
|
||||
|
||||
assert (
|
||||
charged_wh + initial_soc_wh <= battery.max_soc_wh
|
||||
), "Charging should not exceed max capacity"
|
||||
assert losses_wh >= 0, "Losses should not be negative"
|
||||
assert battery.soc_wh == battery.max_soc_wh, "SOC should be at max after overcharge attempt"
|
||||
|
||||
|
||||
def test_charge_energy_not_allowed_hour(setup_pv_battery):
|
||||
battery = setup_pv_battery
|
||||
battery.setup()
|
||||
|
||||
# Disable charging for all hours
|
||||
battery.set_charge_per_hour(np.zeros(battery.hours))
|
||||
|
||||
charged_wh, losses_wh = battery.charge_energy(wh=4000, hour=3)
|
||||
|
||||
assert charged_wh == 0, "No energy should be charged in disallowed hours"
|
||||
assert losses_wh == 0, "No losses should occur if charging is not allowed"
|
||||
assert (
|
||||
battery.soc_wh == (battery.parameters.initial_soc_percentage / 100) * battery.capacity_wh
|
||||
), "SOC should remain unchanged"
|
||||
|
||||
|
||||
def test_charge_energy_relative_power(setup_pv_battery):
|
||||
battery = setup_pv_battery
|
||||
battery.setup()
|
||||
|
||||
relative_power = 0.5 # 50% of max charge power
|
||||
charged_wh, losses_wh = battery.charge_energy(wh=None, hour=4, relative_power=relative_power)
|
||||
|
||||
assert charged_wh > 0, "Charging should occur with relative power"
|
||||
assert losses_wh >= 0, "Losses should not be negative"
|
||||
assert (
|
||||
charged_wh <= battery.max_charge_power_w * relative_power
|
||||
), "Charging should respect relative power limit"
|
||||
assert battery.soc_wh > 0, "SOC should increase after charging"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def setup_car_battery():
|
||||
from akkudoktoreos.devices.battery import ElectricVehicleParameters
|
||||
|
||||
params = ElectricVehicleParameters(
|
||||
capacity_wh=40000,
|
||||
initial_soc_percentage=60,
|
||||
min_soc_percentage=10,
|
||||
max_soc_percentage=90,
|
||||
max_charge_power_w=7000,
|
||||
)
|
||||
battery = Battery(params, hours=24)
|
||||
battery.reset()
|
||||
return battery
|
||||
|
||||
|
||||
def test_car_and_pv_battery_discharge_and_max_charge_power(setup_pv_battery, setup_car_battery):
|
||||
pv_battery = setup_pv_battery
|
||||
car_battery = setup_car_battery
|
||||
|
||||
# Test discharge for PV battery
|
||||
pv_discharged_wh, pv_loss_wh = pv_battery.discharge_energy(3000, 5)
|
||||
assert pv_discharged_wh > 0, "PV battery should discharge energy"
|
||||
assert (
|
||||
pv_battery.current_soc_percentage() >= pv_battery.parameters.min_soc_percentage
|
||||
), "PV battery SOC should stay above min SOC"
|
||||
assert (
|
||||
pv_battery.parameters.max_charge_power_w == 8000
|
||||
), "PV battery max charge power should remain as defined"
|
||||
|
||||
# Test discharge for car battery
|
||||
car_discharged_wh, car_loss_wh = car_battery.discharge_energy(5000, 10)
|
||||
assert car_discharged_wh > 0, "Car battery should discharge energy"
|
||||
assert (
|
||||
car_battery.current_soc_percentage() >= car_battery.parameters.min_soc_percentage
|
||||
), "Car battery SOC should stay above min SOC"
|
||||
assert (
|
||||
car_battery.parameters.max_charge_power_w == 7000
|
||||
), "Car battery max charge power should remain as defined"
|
@@ -1,143 +0,0 @@
|
||||
import unittest
|
||||
|
||||
from akkudoktoreos.devices.battery import PVAkku, PVAkkuParameters
|
||||
|
||||
|
||||
class TestPVAkku(unittest.TestCase):
|
||||
def setUp(self):
|
||||
# Initializing common parameters for tests
|
||||
self.kapazitaet_wh = 10000 # 10,000 Wh capacity
|
||||
self.lade_effizienz = 0.88
|
||||
self.entlade_effizienz = 0.88
|
||||
self.min_soc_prozent = 20 # Minimum SoC is 20%
|
||||
self.max_soc_prozent = 80 # Maximum SoC is 80%
|
||||
|
||||
def test_initial_state_of_charge(self):
|
||||
akku = PVAkku(
|
||||
PVAkkuParameters(
|
||||
kapazitaet_wh=self.kapazitaet_wh,
|
||||
start_soc_prozent=50,
|
||||
min_soc_prozent=self.min_soc_prozent,
|
||||
max_soc_prozent=self.max_soc_prozent,
|
||||
),
|
||||
hours=1,
|
||||
)
|
||||
self.assertEqual(akku.ladezustand_in_prozent(), 50.0, "Initial SoC should be 50%")
|
||||
|
||||
def test_discharge_below_min_soc(self):
|
||||
akku = PVAkku(
|
||||
PVAkkuParameters(
|
||||
kapazitaet_wh=self.kapazitaet_wh,
|
||||
start_soc_prozent=50,
|
||||
min_soc_prozent=self.min_soc_prozent,
|
||||
max_soc_prozent=self.max_soc_prozent,
|
||||
),
|
||||
hours=1,
|
||||
)
|
||||
akku.reset()
|
||||
# Try to discharge more energy than available above min_soc
|
||||
abgegeben_wh, verlust_wh = akku.energie_abgeben(5000, 0) # Try to discharge 5000 Wh
|
||||
expected_soc = self.min_soc_prozent # SoC should not drop below min_soc
|
||||
self.assertEqual(
|
||||
akku.ladezustand_in_prozent(),
|
||||
expected_soc,
|
||||
"SoC should not drop below min_soc after discharge",
|
||||
)
|
||||
self.assertEqual(abgegeben_wh, 2640.0, "The energy discharged should be limited by min_soc")
|
||||
|
||||
def test_charge_above_max_soc(self):
|
||||
akku = PVAkku(
|
||||
PVAkkuParameters(
|
||||
kapazitaet_wh=self.kapazitaet_wh,
|
||||
start_soc_prozent=50,
|
||||
min_soc_prozent=self.min_soc_prozent,
|
||||
max_soc_prozent=self.max_soc_prozent,
|
||||
),
|
||||
hours=1,
|
||||
)
|
||||
akku.reset()
|
||||
# Try to charge more energy than available up to max_soc
|
||||
geladen_wh, verlust_wh = akku.energie_laden(5000, 0) # Try to charge 5000 Wh
|
||||
expected_soc = self.max_soc_prozent # SoC should not exceed max_soc
|
||||
self.assertEqual(
|
||||
akku.ladezustand_in_prozent(),
|
||||
expected_soc,
|
||||
"SoC should not exceed max_soc after charge",
|
||||
)
|
||||
self.assertEqual(geladen_wh, 3000.0, "The energy charged should be limited by max_soc")
|
||||
|
||||
def test_charging_at_max_soc(self):
|
||||
akku = PVAkku(
|
||||
PVAkkuParameters(
|
||||
kapazitaet_wh=self.kapazitaet_wh,
|
||||
start_soc_prozent=80,
|
||||
min_soc_prozent=self.min_soc_prozent,
|
||||
max_soc_prozent=self.max_soc_prozent,
|
||||
),
|
||||
hours=1,
|
||||
)
|
||||
akku.reset()
|
||||
# Try to charge when SoC is already at max_soc
|
||||
geladen_wh, verlust_wh = akku.energie_laden(5000, 0)
|
||||
self.assertEqual(geladen_wh, 0.0, "No energy should be charged when at max_soc")
|
||||
self.assertEqual(
|
||||
akku.ladezustand_in_prozent(),
|
||||
self.max_soc_prozent,
|
||||
"SoC should remain at max_soc",
|
||||
)
|
||||
|
||||
def test_discharging_at_min_soc(self):
|
||||
akku = PVAkku(
|
||||
PVAkkuParameters(
|
||||
kapazitaet_wh=self.kapazitaet_wh,
|
||||
start_soc_prozent=20,
|
||||
min_soc_prozent=self.min_soc_prozent,
|
||||
max_soc_prozent=self.max_soc_prozent,
|
||||
),
|
||||
hours=1,
|
||||
)
|
||||
akku.reset()
|
||||
# Try to discharge when SoC is already at min_soc
|
||||
abgegeben_wh, verlust_wh = akku.energie_abgeben(5000, 0)
|
||||
self.assertEqual(abgegeben_wh, 0.0, "No energy should be discharged when at min_soc")
|
||||
self.assertEqual(
|
||||
akku.ladezustand_in_prozent(),
|
||||
self.min_soc_prozent,
|
||||
"SoC should remain at min_soc",
|
||||
)
|
||||
|
||||
def test_soc_limits(self):
|
||||
# Test to ensure that SoC never exceeds max_soc or drops below min_soc
|
||||
akku = PVAkku(
|
||||
PVAkkuParameters(
|
||||
kapazitaet_wh=self.kapazitaet_wh,
|
||||
start_soc_prozent=50,
|
||||
min_soc_prozent=self.min_soc_prozent,
|
||||
max_soc_prozent=self.max_soc_prozent,
|
||||
),
|
||||
hours=1,
|
||||
)
|
||||
akku.reset()
|
||||
akku.soc_wh = (
|
||||
self.max_soc_prozent / 100
|
||||
) * self.kapazitaet_wh + 1000 # Manually set SoC above max limit
|
||||
akku.soc_wh = min(akku.soc_wh, akku.max_soc_wh)
|
||||
self.assertLessEqual(
|
||||
akku.ladezustand_in_prozent(),
|
||||
self.max_soc_prozent,
|
||||
"SoC should not exceed max_soc",
|
||||
)
|
||||
|
||||
akku.soc_wh = (
|
||||
self.min_soc_prozent / 100
|
||||
) * self.kapazitaet_wh - 1000 # Manually set SoC below min limit
|
||||
akku.soc_wh = max(akku.soc_wh, akku.min_soc_wh)
|
||||
self.assertGreaterEqual(
|
||||
akku.ladezustand_in_prozent(),
|
||||
self.min_soc_prozent,
|
||||
"SoC should not drop below min_soc",
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
@@ -8,7 +8,11 @@ from akkudoktoreos.core.ems import (
|
||||
SimulationResult,
|
||||
get_ems,
|
||||
)
|
||||
from akkudoktoreos.devices.battery import EAutoParameters, PVAkku, PVAkkuParameters
|
||||
from akkudoktoreos.devices.battery import (
|
||||
Battery,
|
||||
ElectricVehicleParameters,
|
||||
SolarPanelBatteryParameters,
|
||||
)
|
||||
from akkudoktoreos.devices.generic import HomeAppliance, HomeApplianceParameters
|
||||
from akkudoktoreos.devices.inverter import Inverter, InverterParameters
|
||||
|
||||
@@ -25,8 +29,10 @@ def create_ems_instance() -> EnergieManagementSystem:
|
||||
assert config_eos.prediction_hours is not None
|
||||
|
||||
# Initialize the battery and the inverter
|
||||
akku = PVAkku(
|
||||
PVAkkuParameters(kapazitaet_wh=5000, start_soc_prozent=80, min_soc_prozent=10),
|
||||
akku = Battery(
|
||||
SolarPanelBatteryParameters(
|
||||
capacity_wh=5000, initial_soc_percentage=80, min_soc_percentage=10
|
||||
),
|
||||
hours=config_eos.prediction_hours,
|
||||
)
|
||||
akku.reset()
|
||||
@@ -43,8 +49,10 @@ def create_ems_instance() -> EnergieManagementSystem:
|
||||
home_appliance.set_starting_time(2)
|
||||
|
||||
# Example initialization of electric car battery
|
||||
eauto = PVAkku(
|
||||
EAutoParameters(kapazitaet_wh=26400, start_soc_prozent=10, min_soc_prozent=10),
|
||||
eauto = Battery(
|
||||
ElectricVehicleParameters(
|
||||
capacity_wh=26400, initial_soc_percentage=10, min_soc_percentage=10
|
||||
),
|
||||
hours=config_eos.prediction_hours,
|
||||
)
|
||||
eauto.set_charge_per_hour(np.full(config_eos.prediction_hours, 1))
|
||||
|
@@ -7,7 +7,11 @@ from akkudoktoreos.core.ems import (
|
||||
EnergieManagementSystemParameters,
|
||||
get_ems,
|
||||
)
|
||||
from akkudoktoreos.devices.battery import EAutoParameters, PVAkku, PVAkkuParameters
|
||||
from akkudoktoreos.devices.battery import (
|
||||
Battery,
|
||||
ElectricVehicleParameters,
|
||||
SolarPanelBatteryParameters,
|
||||
)
|
||||
from akkudoktoreos.devices.generic import HomeAppliance, HomeApplianceParameters
|
||||
from akkudoktoreos.devices.inverter import Inverter, InverterParameters
|
||||
|
||||
@@ -24,8 +28,10 @@ def create_ems_instance() -> EnergieManagementSystem:
|
||||
assert config_eos.prediction_hours is not None
|
||||
|
||||
# Initialize the battery and the inverter
|
||||
akku = PVAkku(
|
||||
PVAkkuParameters(kapazitaet_wh=5000, start_soc_prozent=80, min_soc_prozent=10),
|
||||
akku = Battery(
|
||||
SolarPanelBatteryParameters(
|
||||
capacity_wh=5000, initial_soc_percentage=80, min_soc_percentage=10
|
||||
),
|
||||
hours=config_eos.prediction_hours,
|
||||
)
|
||||
akku.reset()
|
||||
@@ -42,8 +48,10 @@ def create_ems_instance() -> EnergieManagementSystem:
|
||||
home_appliance.set_starting_time(2)
|
||||
|
||||
# Example initialization of electric car battery
|
||||
eauto = PVAkku(
|
||||
EAutoParameters(kapazitaet_wh=26400, start_soc_prozent=100, min_soc_prozent=100),
|
||||
eauto = Battery(
|
||||
ElectricVehicleParameters(
|
||||
capacity_wh=26400, initial_soc_percentage=100, min_soc_percentage=100
|
||||
),
|
||||
hours=config_eos.prediction_hours,
|
||||
)
|
||||
|
||||
|
@@ -8,8 +8,8 @@ from akkudoktoreos.devices.inverter import Inverter, InverterParameters
|
||||
@pytest.fixture
|
||||
def mock_battery():
|
||||
mock_battery = Mock()
|
||||
mock_battery.energie_laden = Mock(return_value=(0.0, 0.0))
|
||||
mock_battery.energie_abgeben = Mock(return_value=(0.0, 0.0))
|
||||
mock_battery.charge_energy = Mock(return_value=(0.0, 0.0))
|
||||
mock_battery.discharge_energy = Mock(return_value=(0.0, 0.0))
|
||||
return mock_battery
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ def inverter(mock_battery):
|
||||
|
||||
def test_process_energy_excess_generation(inverter, mock_battery):
|
||||
# Battery charges 100 Wh with 10 Wh loss
|
||||
mock_battery.energie_laden.return_value = (100.0, 10.0)
|
||||
mock_battery.charge_energy.return_value = (100.0, 10.0)
|
||||
generation = 600.0
|
||||
consumption = 200.0
|
||||
hour = 12
|
||||
@@ -33,7 +33,7 @@ def test_process_energy_excess_generation(inverter, mock_battery):
|
||||
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.energie_laden.assert_called_once_with(400.0, hour)
|
||||
mock_battery.charge_energy.assert_called_once_with(400.0, hour)
|
||||
|
||||
|
||||
def test_process_energy_generation_equals_consumption(inverter, mock_battery):
|
||||
@@ -50,12 +50,12 @@ def test_process_energy_generation_equals_consumption(inverter, mock_battery):
|
||||
assert losses == 0.0 # No losses
|
||||
assert self_consumption == 300.0 # All consumption is met with generation
|
||||
|
||||
mock_battery.energie_laden.assert_called_once_with(0.0, hour)
|
||||
mock_battery.charge_energy.assert_called_once_with(0.0, hour)
|
||||
|
||||
|
||||
def test_process_energy_battery_discharges(inverter, mock_battery):
|
||||
# Battery discharges 100 Wh with 10 Wh loss already accounted for in the discharge
|
||||
mock_battery.energie_abgeben.return_value = (100.0, 10.0)
|
||||
mock_battery.discharge_energy.return_value = (100.0, 10.0)
|
||||
generation = 100.0
|
||||
consumption = 250.0
|
||||
hour = 12
|
||||
@@ -70,12 +70,12 @@ def test_process_energy_battery_discharges(inverter, mock_battery):
|
||||
) # Grid supplies remaining shortfall after battery discharge
|
||||
assert losses == 10.0 # Discharge losses
|
||||
assert self_consumption == 200.0 # Generation + battery discharge
|
||||
mock_battery.energie_abgeben.assert_called_once_with(150.0, hour)
|
||||
mock_battery.discharge_energy.assert_called_once_with(150.0, hour)
|
||||
|
||||
|
||||
def test_process_energy_battery_empty(inverter, mock_battery):
|
||||
# Battery is empty, so no energy can be discharged
|
||||
mock_battery.energie_abgeben.return_value = (0.0, 0.0)
|
||||
mock_battery.discharge_energy.return_value = (0.0, 0.0)
|
||||
generation = 100.0
|
||||
consumption = 300.0
|
||||
hour = 12
|
||||
@@ -88,12 +88,12 @@ 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 losses == 0.0 # No losses as the battery didn't discharge
|
||||
assert self_consumption == 100.0 # Only generation is consumed
|
||||
mock_battery.energie_abgeben.assert_called_once_with(200.0, hour)
|
||||
mock_battery.discharge_energy.assert_called_once_with(200.0, hour)
|
||||
|
||||
|
||||
def test_process_energy_battery_full_at_start(inverter, mock_battery):
|
||||
# Battery is full, so no charging happens
|
||||
mock_battery.energie_laden.return_value = (0.0, 0.0)
|
||||
mock_battery.charge_energy.return_value = (0.0, 0.0)
|
||||
generation = 500.0
|
||||
consumption = 200.0
|
||||
hour = 12
|
||||
@@ -108,12 +108,12 @@ def test_process_energy_battery_full_at_start(inverter, mock_battery):
|
||||
assert grid_import == 0.0 # No grid draw
|
||||
assert losses == 0.0 # No losses
|
||||
assert self_consumption == 200.0 # Only consumption is met
|
||||
mock_battery.energie_laden.assert_called_once_with(300.0, hour)
|
||||
mock_battery.charge_energy.assert_called_once_with(300.0, hour)
|
||||
|
||||
|
||||
def test_process_energy_insufficient_generation_no_battery(inverter, mock_battery):
|
||||
# Insufficient generation and no battery discharge
|
||||
mock_battery.energie_abgeben.return_value = (0.0, 0.0)
|
||||
mock_battery.discharge_energy.return_value = (0.0, 0.0)
|
||||
generation = 100.0
|
||||
consumption = 500.0
|
||||
hour = 12
|
||||
@@ -126,12 +126,12 @@ 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 losses == 0.0 # No losses
|
||||
assert self_consumption == 100.0 # Only generation is consumed
|
||||
mock_battery.energie_abgeben.assert_called_once_with(400.0, hour)
|
||||
mock_battery.discharge_energy.assert_called_once_with(400.0, hour)
|
||||
|
||||
|
||||
def test_process_energy_insufficient_generation_battery_assists(inverter, mock_battery):
|
||||
# Battery assists with some discharge to cover the shortfall
|
||||
mock_battery.energie_abgeben.return_value = (
|
||||
mock_battery.discharge_energy.return_value = (
|
||||
50.0,
|
||||
5.0,
|
||||
) # Battery discharges 50 Wh with 5 Wh loss
|
||||
@@ -149,12 +149,12 @@ def test_process_energy_insufficient_generation_battery_assists(inverter, mock_b
|
||||
) # Grid supplies the remaining shortfall after battery discharge
|
||||
assert losses == 5.0 # Discharge losses
|
||||
assert self_consumption == 250.0 # Generation + battery discharge
|
||||
mock_battery.energie_abgeben.assert_called_once_with(200.0, hour)
|
||||
mock_battery.discharge_energy.assert_called_once_with(200.0, hour)
|
||||
|
||||
|
||||
def test_process_energy_zero_generation(inverter, mock_battery):
|
||||
# Zero generation, full reliance on battery and grid
|
||||
mock_battery.energie_abgeben.return_value = (
|
||||
mock_battery.discharge_energy.return_value = (
|
||||
100.0,
|
||||
5.0,
|
||||
) # Battery discharges 100 Wh with 5 Wh loss
|
||||
@@ -170,12 +170,12 @@ 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 losses == 5.0 # Discharge losses
|
||||
assert self_consumption == 100.0 # Only battery discharge is consumed
|
||||
mock_battery.energie_abgeben.assert_called_once_with(300.0, hour)
|
||||
mock_battery.discharge_energy.assert_called_once_with(300.0, hour)
|
||||
|
||||
|
||||
def test_process_energy_zero_consumption(inverter, mock_battery):
|
||||
# Generation exceeds consumption, but consumption is zero
|
||||
mock_battery.energie_laden.return_value = (100.0, 10.0)
|
||||
mock_battery.charge_energy.return_value = (100.0, 10.0)
|
||||
generation = 500.0
|
||||
consumption = 0.0
|
||||
hour = 12
|
||||
@@ -188,7 +188,7 @@ def test_process_energy_zero_consumption(inverter, mock_battery):
|
||||
assert grid_import == 0.0 # No grid draw as no consumption
|
||||
assert losses == 10.0 # Charging losses
|
||||
assert self_consumption == 0.0 # Zero consumption
|
||||
mock_battery.energie_laden.assert_called_once_with(500.0, hour)
|
||||
mock_battery.charge_energy.assert_called_once_with(500.0, hour)
|
||||
|
||||
|
||||
def test_process_energy_zero_generation_zero_consumption(inverter, mock_battery):
|
||||
@@ -207,7 +207,7 @@ def test_process_energy_zero_generation_zero_consumption(inverter, mock_battery)
|
||||
|
||||
|
||||
def test_process_energy_partial_battery_discharge(inverter, mock_battery):
|
||||
mock_battery.energie_abgeben.return_value = (50.0, 5.0)
|
||||
mock_battery.discharge_energy.return_value = (50.0, 5.0)
|
||||
generation = 200.0
|
||||
consumption = 400.0
|
||||
hour = 12
|
||||
@@ -226,7 +226,7 @@ def test_process_energy_partial_battery_discharge(inverter, mock_battery):
|
||||
|
||||
def test_process_energy_consumption_exceeds_max_no_battery(inverter, mock_battery):
|
||||
# Battery is empty, and consumption is much higher than the inverter's max power
|
||||
mock_battery.energie_abgeben.return_value = (0.0, 0.0)
|
||||
mock_battery.discharge_energy.return_value = (0.0, 0.0)
|
||||
generation = 100.0
|
||||
consumption = 1000.0 # Exceeds the inverter's max power
|
||||
hour = 12
|
||||
@@ -239,12 +239,12 @@ 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 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
|
||||
mock_battery.energie_abgeben.assert_called_once_with(400.0, hour)
|
||||
mock_battery.discharge_energy.assert_called_once_with(400.0, hour)
|
||||
|
||||
|
||||
def test_process_energy_zero_generation_full_battery_high_consumption(inverter, mock_battery):
|
||||
# Full battery, no generation, and high consumption
|
||||
mock_battery.energie_abgeben.return_value = (500.0, 10.0)
|
||||
mock_battery.discharge_energy.return_value = (500.0, 10.0)
|
||||
generation = 0.0
|
||||
consumption = 600.0
|
||||
hour = 12
|
||||
@@ -259,4 +259,4 @@ def test_process_energy_zero_generation_full_battery_high_consumption(inverter,
|
||||
) # Grid covers remaining shortfall after battery discharge
|
||||
assert losses == 10.0 # Battery discharge losses
|
||||
assert self_consumption == 500.0 # Battery fully discharges to meet consumption
|
||||
mock_battery.energie_abgeben.assert_called_once_with(500.0, hour)
|
||||
mock_battery.discharge_energy.assert_called_once_with(500.0, hour)
|
||||
|
24
tests/testdata/optimize_input_1.json
vendored
24
tests/testdata/optimize_input_1.json
vendored
@@ -26,21 +26,21 @@
|
||||
]
|
||||
},
|
||||
"pv_akku": {
|
||||
"kapazitaet_wh": 26400,
|
||||
"max_ladeleistung_w": 5000,
|
||||
"start_soc_prozent": 80,
|
||||
"min_soc_prozent": 15
|
||||
"capacity_wh": 26400,
|
||||
"max_charge_power_w": 5000,
|
||||
"initial_soc_percentage": 80,
|
||||
"min_soc_percentage": 15
|
||||
},
|
||||
"inverter": {
|
||||
"max_power_wh": 10000
|
||||
"wechselrichter": {
|
||||
"max_leistung_wh": 10000
|
||||
},
|
||||
"eauto": {
|
||||
"kapazitaet_wh": 60000,
|
||||
"lade_effizienz": 0.95,
|
||||
"entlade_effizienz": 1.0,
|
||||
"max_ladeleistung_w": 11040,
|
||||
"start_soc_prozent": 54,
|
||||
"min_soc_prozent": 0
|
||||
"capacity_wh": 60000,
|
||||
"charging_efficiency": 0.95,
|
||||
"discharging_efficiency": 1.0,
|
||||
"max_charge_power_w": 11040,
|
||||
"initial_soc_percentage": 54,
|
||||
"min_soc_percentage": 0
|
||||
},
|
||||
"temperature_forecast": [
|
||||
18.3, 17.8, 16.9, 16.2, 15.6, 15.1, 14.6, 14.2, 14.3, 14.8, 15.7, 16.7, 17.4,
|
||||
|
16
tests/testdata/optimize_input_2.json
vendored
16
tests/testdata/optimize_input_2.json
vendored
@@ -26,16 +26,16 @@
|
||||
]
|
||||
},
|
||||
"pv_akku": {
|
||||
"kapazitaet_wh": 26400,
|
||||
"start_soc_prozent": 80,
|
||||
"min_soc_prozent": 15
|
||||
"capacity_wh": 26400,
|
||||
"initial_soc_percentage": 80,
|
||||
"min_soc_percentage": 15
|
||||
},
|
||||
"eauto": {
|
||||
"kapazitaet_wh": 60000,
|
||||
"lade_effizienz": 0.95,
|
||||
"max_ladeleistung_w": 11040,
|
||||
"start_soc_prozent": 5,
|
||||
"min_soc_prozent": 80
|
||||
"capacity_wh": 60000,
|
||||
"charging_efficiency": 0.95,
|
||||
"max_charge_power_w": 11040,
|
||||
"initial_soc_percentage": 5,
|
||||
"min_soc_percentage": 80
|
||||
},
|
||||
"dishwasher" :{
|
||||
"consumption_wh": 5000,
|
||||
|
12
tests/testdata/optimize_result_1.json
vendored
12
tests/testdata/optimize_result_1.json
vendored
@@ -617,13 +617,13 @@
|
||||
1,
|
||||
1
|
||||
],
|
||||
"entlade_effizienz": 1.0,
|
||||
"discharging_efficiency": 1.0,
|
||||
"hours": 48,
|
||||
"kapazitaet_wh": 60000,
|
||||
"lade_effizienz": 0.95,
|
||||
"max_ladeleistung_w": 11040,
|
||||
"capacity_wh": 60000,
|
||||
"charging_efficiency": 0.95,
|
||||
"max_charge_power_w": 11040,
|
||||
"soc_wh": 32400.000000000004,
|
||||
"start_soc_prozent": 54
|
||||
"initial_soc_percentage": 54
|
||||
},
|
||||
"start_solution": [
|
||||
18.0,
|
||||
@@ -676,4 +676,4 @@
|
||||
10.0
|
||||
],
|
||||
"washingstart": null
|
||||
}
|
||||
}
|
||||
|
12
tests/testdata/optimize_result_2.json
vendored
12
tests/testdata/optimize_result_2.json
vendored
@@ -666,13 +666,13 @@
|
||||
1,
|
||||
1
|
||||
],
|
||||
"entlade_effizienz": 1.0,
|
||||
"discharging_efficiency": 1.0,
|
||||
"hours": 48,
|
||||
"kapazitaet_wh": 60000,
|
||||
"lade_effizienz": 0.95,
|
||||
"max_ladeleistung_w": 11040,
|
||||
"capacity_wh": 60000,
|
||||
"charging_efficiency": 0.95,
|
||||
"max_charge_power_w": 11040,
|
||||
"soc_wh": 60000.0,
|
||||
"start_soc_prozent": 5
|
||||
"initial_soc_percentage": 5
|
||||
},
|
||||
"start_solution": [
|
||||
0.0,
|
||||
@@ -774,4 +774,4 @@
|
||||
14.0
|
||||
],
|
||||
"washingstart": 14
|
||||
}
|
||||
}
|
||||
|
12
tests/testdata/optimize_result_2_full.json
vendored
12
tests/testdata/optimize_result_2_full.json
vendored
@@ -666,13 +666,13 @@
|
||||
1,
|
||||
1
|
||||
],
|
||||
"entlade_effizienz": 1.0,
|
||||
"discharging_efficiency": 1.0,
|
||||
"hours": 48,
|
||||
"kapazitaet_wh": 60000,
|
||||
"lade_effizienz": 0.95,
|
||||
"max_ladeleistung_w": 11040,
|
||||
"capacity_wh": 60000,
|
||||
"charging_efficiency": 0.95,
|
||||
"max_charge_power_w": 11040,
|
||||
"soc_wh": 60000.0,
|
||||
"start_soc_prozent": 5
|
||||
"initial_soc_percentage": 5
|
||||
},
|
||||
"start_solution": [
|
||||
12.0,
|
||||
@@ -774,4 +774,4 @@
|
||||
14.0
|
||||
],
|
||||
"washingstart": 14
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user