fix(control): reg 108 v PV_SURPLUS sleduje charge intent (BA81 nenabíjelo levné ráno)

deye_battery_charge_discharge_amps: v PASSIVE+PV_SURPLUS reg 108 = max když plán
chce nabíjet (bat_w>0) místo tvrdé 0; baterka nabere co zvládne, přebytek nad
nabíjecí rychlost do sítě. + kalibrace: SoC u maxima → dojet na 100% (BMS). Sell
beze změny. Vědomě přepsán test starého chování. 365 passed. Všechny Deye lokality.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dusan Vojacek
2026-06-16 16:32:01 +02:00
parent 17147ca412
commit daf7ed4d4b
7 changed files with 83 additions and 8 deletions

View File

@@ -1,4 +1,9 @@
"""PASSIVE + PV_SURPLUS: 108=0 (nepoužívat baterii), 109=max; 142 zůstává zero-export (1/2)."""
"""PASSIVE + PV_SURPLUS: reg 108 sleduje charge intent (fix 2026-06-16).
bat_w>0 (plán chce nabíjet z přebytku) → 108=max (baterka nabere co zvládne, zbytek ven);
SoC u maxima + přebytek → 108=max (BMS kalibrace na 100 %); jen "prodej PV a drž baterku"
daleko od maxima (bat_w<=0) → 108=0. 109=max, 142 zůstává zero-export (1/2).
"""
from __future__ import annotations
@@ -23,8 +28,11 @@ class PassivePvSurplusChargeAmpsTests(unittest.TestCase):
self.assertEqual(ch, 0)
self.assertEqual(dis, 90)
def test_pv_surplus_even_if_lp_shows_positive_battery_w(self) -> None:
"""Plán může mít kladný battery_w; exportní záměr je PV_SURPLUS → 108=0."""
def test_pv_surplus_with_positive_battery_w_charges_at_max(self) -> None:
"""Fix 2026-06-16: plán chce nabíjet z přebytku (bat_w>0) → 108=max (ne 0).
Baterka nabere kolik zvládne, přebytek nad nabíjecí rychlost jde do sítě (BA81).
"""
ch, dis = deye_battery_charge_discharge_amps(
lock_battery=False,
deye_mode="PASSIVE",
@@ -36,6 +44,41 @@ class PassivePvSurplusChargeAmpsTests(unittest.TestCase):
export_mode="PV_SURPLUS",
export_ban=False,
)
self.assertEqual(ch, 100)
self.assertEqual(dis, 100)
def test_pv_surplus_near_full_tops_off_for_calibration(self) -> None:
"""SoC u maxima (97 >= 100-3) + přebytek → 108=max i při bat_w<=0 (BMS kalibrace)."""
ch, dis = deye_battery_charge_discharge_amps(
lock_battery=False,
deye_mode="PASSIVE",
self_sustain_local_use=False,
bat_w=0,
grid_w=-2000,
max_charge_a=100,
max_discharge_a=100,
export_mode="PV_SURPLUS",
export_ban=False,
current_soc_pct=97.0,
max_soc_pct=100,
)
self.assertEqual(ch, 100)
def test_pv_surplus_sell_hold_far_from_full_zeros_charge(self) -> None:
"""Prodej PV a drž baterku daleko od maxima (bat_w<=0, SoC nízko) → 108=0."""
ch, dis = deye_battery_charge_discharge_amps(
lock_battery=False,
deye_mode="PASSIVE",
self_sustain_local_use=False,
bat_w=0,
grid_w=-2000,
max_charge_a=100,
max_discharge_a=100,
export_mode="PV_SURPLUS",
export_ban=False,
current_soc_pct=60.0,
max_soc_pct=100,
)
self.assertEqual(ch, 0)
self.assertEqual(dis, 100)