solver nastavuje stavy deye
Some checks failed
CI and deploy / migration-check (push) Failing after 14s
CI and deploy / deploy (push) Has been skipped

This commit is contained in:
Dusan Vojacek
2026-04-20 08:33:56 +02:00
parent 6447666cee
commit 43b594c8d5
10 changed files with 219 additions and 70 deletions

View File

@@ -11,6 +11,7 @@ from services.control.exporter_monolith import (
_deye_reg178_verify_with_double_read,
_deye_tou_params,
_deye_tou_power_verify_match,
_deye_zero_export_amps_for_passive,
deye_reg_triggers_self_sustain_after_verify_exhaust,
get_deye_mode,
)
@@ -62,7 +63,7 @@ class ModbusVerifyPolicyTests(unittest.TestCase):
class DeyeTouParamsTests(unittest.TestCase):
def test_sell_uses_reserve_soc(self) -> None:
"""SELL: plánovaný výdej baterie alesvěň tak velký jako plánovaný export (|bat| ≥ |grid|)."""
"""SELL: záporný grid_setpoint_w i battery_w → selling first; TOU SOC = reserve."""
sp = ControlSetpoints(
battery_w=-8000,
grid_export_limit=8000,
@@ -79,8 +80,23 @@ class DeyeTouParamsTests(unittest.TestCase):
self.assertFalse(g)
self.assertEqual(s, 20)
def test_pv_led_export_with_small_battery_is_passive(self) -> None:
"""Regrese site 25A 17:30: |bat| < |grid| → PASSIVE (FVE přetok, ne „vylít baterku“)."""
def test_explicit_deye_physical_mode_from_plan_overrides_detection(self) -> None:
sp = ControlSetpoints(
battery_w=-8000,
grid_export_limit=8000,
ev1_current_a=0,
ev2_current_a=0,
heat_pump_enable=False,
grid_setpoint_w=-8000,
ev1_power_w=0,
ev2_power_w=0,
target_soc_pct=50,
deye_physical_mode="PASSIVE",
)
self.assertEqual(get_deye_mode(sp), "PASSIVE")
def test_pv_led_export_with_small_battery_is_sell(self) -> None:
"""Obě záporné → SELL (bez porovnání |bat| vs |grid|)."""
sp = ControlSetpoints(
battery_w=-733,
grid_export_limit=1294,
@@ -92,10 +108,10 @@ class DeyeTouParamsTests(unittest.TestCase):
ev2_power_w=0,
target_soc_pct=50,
)
self.assertEqual(get_deye_mode(sp), "PASSIVE")
self.assertEqual(get_deye_mode(sp), "SELL")
def test_large_export_small_battery_is_passive(self) -> None:
"""Export v plánu větší než výdej z baterie → PASSIVE."""
def test_large_export_small_battery_is_sell(self) -> None:
"""I když |bat| < |grid| — stále SELL při obou záporných setpointech."""
sp = ControlSetpoints(
battery_w=-1500,
grid_export_limit=8000,
@@ -107,7 +123,7 @@ class DeyeTouParamsTests(unittest.TestCase):
ev2_power_w=0,
target_soc_pct=50,
)
self.assertEqual(get_deye_mode(sp), "PASSIVE")
self.assertEqual(get_deye_mode(sp), "SELL")
def test_passive_uses_min_soc(self) -> None:
sp = ControlSetpoints(
@@ -181,6 +197,36 @@ class DeyeTouParamsTests(unittest.TestCase):
self.assertTrue(g)
self.assertEqual(s, 95)
def test_charge_any_positive_pair_without_w_threshold(self) -> None:
sp = ControlSetpoints(
battery_w=50,
grid_export_limit=0,
ev1_current_a=0,
ev2_current_a=0,
heat_pump_enable=False,
grid_setpoint_w=80,
ev1_power_w=0,
ev2_power_w=0,
target_soc_pct=50,
)
self.assertEqual(get_deye_mode(sp), "CHARGE")
def test_zero_export_amps_fve_overflow(self) -> None:
c, d = _deye_zero_export_amps_for_passive(-1000, 0, 100, 90)
self.assertEqual(c, 0)
self.assertEqual(d, 90)
def test_zero_export_amps_import_hold_discharge(self) -> None:
c, d = _deye_zero_export_amps_for_passive(500, 0, 100, 90)
self.assertEqual(c, 100)
self.assertEqual(d, 0)
def test_zero_export_amps_full_when_discharge_with_export(self) -> None:
"""Export + plánované vybíjení → plné proudy (SELL řeší režim 142 zvlášť)."""
c, d = _deye_zero_export_amps_for_passive(-2000, -500, 100, 90)
self.assertEqual(c, 100)
self.assertEqual(d, 90)
def test_self_sustain_tou_stays_min_soc_even_if_sell_negative(self) -> None:
"""SELF_SUSTAIN: nízké TOU (min_soc), ne 100 % z negativní vykupní — LP se nepoužívá."""
sp = ControlSetpoints(