mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2025-04-17 07:55:15 +00:00
* Migrate from Flask to FastAPI * FastAPI migration: - Use pydantic model classes as input parameters to the data/calculation classes. - Interface field names changed to constructor parameter names (for simplicity only during transition, should be updated in a followup PR). - Add basic interface requirements (e.g. some values > 0, etc.). * Update tests for new data format. * Python requirement down to 3.9 (TypeGuard no longer needed) * Makefile: Add helpful targets (e.g. development server with reload) * Move API doc from README to pydantic model classes (swagger) * Link to swagger.io with own openapi.yml. * Commit openapi.json and check with pytest for changes so the documentation is always up-to-date. * Streamline docker * FastAPI: Run startup action on dev server * Fix config for /strompreis, endpoint still broken however. * test_openapi: Compare against docs/.../openapi.json * Move fastapi to server/ submodule * See #187 for new repository structure.
144 lines
5.1 KiB
Python
144 lines
5.1 KiB
Python
import unittest
|
|
|
|
from akkudoktoreos.class_akku 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()
|