From a9a6a88a88fe1390e15c22d9437e5f900ff92809 Mon Sep 17 00:00:00 2001 From: Dusan Vojacek Date: Sun, 14 Jun 2026 22:23:38 +0200 Subject: [PATCH] =?UTF-8?q?fix(planner):=20EV=20tolerance=20'dost=20dobr?= =?UTF-8?q?=C3=A9'=20=E2=80=94=20konec=20hon=C4=9Bn=C3=AD=20posledn=C3=ADc?= =?UTF-8?q?h=20%=20do=20100=20%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit needed_wh=0 když live_soc >= least(target,99) - charge_done_tolerance_pct (V107, default 3 p.b.). Effective target zastropovaný na 99 (clamp) → bez věčného mini-dobíjení a cyklování nabíječky. Ověřeno živě: session #6 needed_wh 1329→0. Co-Authored-By: Claude Opus 4.8 (1M context) --- db/migration/V107__ev_charge_done_tolerance.sql | 10 ++++++++++ db/routines/R__038_fn_ev_session_planning_json.sql | 11 ++++++++++- docs/04-modules/ev-charging.md | 6 ++++++ docs/planning-changelog.md | 7 +++++++ 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 db/migration/V107__ev_charge_done_tolerance.sql diff --git a/db/migration/V107__ev_charge_done_tolerance.sql b/db/migration/V107__ev_charge_done_tolerance.sql new file mode 100644 index 0000000..a4905d7 --- /dev/null +++ b/db/migration/V107__ev_charge_done_tolerance.sql @@ -0,0 +1,10 @@ +-- EV: tolerance „dost dobré" pro deadline charging — nehonit posledních pár % do +-- targetu (taper region u plného auta). Řeší věčné mini-dobíjení odhalené live-SoC +-- fixem (live_soc clamp 99 vs target 100 → needed nikdy neklesne na 0 → cyklování +-- nabíječky, Tesla notifikace). needed_wh = 0 když live_soc >= least(target,99) − tolerance. + +alter table ems.asset_vehicle + add column if not exists charge_done_tolerance_pct numeric(4, 2) not null default 3.0; + +comment on column ems.asset_vehicle.charge_done_tolerance_pct is + 'Tolerance „dost dobré" pro deadline charging (procentní body). needed_wh=0 když live_soc >= least(target,99) − tato tolerance — nehonit poslední taper k 100 % (zbytečné start/stop nabíječky a Tesla notifikace). 0 = tvrdě na target. Default 3 p.b.'; diff --git a/db/routines/R__038_fn_ev_session_planning_json.sql b/db/routines/R__038_fn_ev_session_planning_json.sql index 1abfbbb..b432e81 100644 --- a/db/routines/R__038_fn_ev_session_planning_json.sql +++ b/db/routines/R__038_fn_ev_session_planning_json.sql @@ -75,6 +75,7 @@ as $fn$ v.battery_capacity_kwh, v.default_target_soc_pct, v.opportunistic_value_czk_kwh as v_opp, + coalesce(v.charge_done_tolerance_pct, 3.0) as charge_done_tolerance_pct, ems.fn_ev_session_delivered_wh(es.charger_id, es.session_start) as live_delivered_wh from ems.ev_session es join ems.asset_ev_charger ch on ch.id = es.charger_id @@ -103,12 +104,20 @@ as $fn$ when coalesce(c.target_soc_pct, c.default_target_soc_pct) is null then null else c.target_deadline end, + -- effective target zastropovaný na 99 (clamp live_soc) → bez věčného + -- mini-dobíjení u plného auta. „Dost dobré" tolerance: needed=0 když je + -- live_soc ve vzdálenosti tolerance od targetu (nehonit poslední taper → + -- žádné zbytečné start/stop nabíječky). 0 = tvrdě na target. 'energy_needed_wh', case when c.target_deadline is null then 0::numeric when coalesce(c.target_soc_pct, c.default_target_soc_pct) is null then 0::numeric + when c.live_soc_pct >= + least(coalesce(c.target_soc_pct, c.default_target_soc_pct)::numeric, 99) + - c.charge_done_tolerance_pct + then 0::numeric else greatest( 0, - (coalesce(c.target_soc_pct, c.default_target_soc_pct)::numeric + (least(coalesce(c.target_soc_pct, c.default_target_soc_pct)::numeric, 99) - c.live_soc_pct) / 100.0 * (c.battery_capacity_kwh * 1000) ) diff --git a/docs/04-modules/ev-charging.md b/docs/04-modules/ev-charging.md index 6b67c47..999861c 100644 --- a/docs/04-modules/ev-charging.md +++ b/docs/04-modules/ev-charging.md @@ -250,6 +250,12 @@ counter 0.18). Bez toho byl `energy_delivered_wh` trvale 0 → needed_wh konstan plánovač slepý k pokroku → phantom 11 kW okna i u plného auta. Funguje pro Teslu i Zoe (power-based, bez API). Pozn.: reg 39 rozbitý ⇒ i EV audit/ekonomika z něj jede naslepo. +**Tolerance „dost dobré" (V107):** `energy_needed_wh = 0` když +`live_soc >= least(target, 99) − asset_vehicle.charge_done_tolerance_pct` (default +3 p.b.). Effective target je zastropovaný na 99 (= clamp live_soc), takže se nehoní +poslední taper k 100 % (jinak věčné mini-dobíjení → cyklování nabíječky / Tesla +notifikace). `charge_done_tolerance_pct = 0` → tvrdě na target. + --- ## Statistika příjezdů diff --git a/docs/planning-changelog.md b/docs/planning-changelog.md index 0fce650..18e5bb6 100644 --- a/docs/planning-changelog.md +++ b/docs/planning-changelog.md @@ -5,6 +5,13 @@ Formát: **datum (ISO)** · stručný důvod · soubory · chování / ověřen --- +## 2026-06-14 — EV: tolerance „dost dobré" — konec honění posledních % do 100 % + +- **Problém:** po live-SoC fixu zůstalo malé deadline dobití (~1.33 kWh v 05:00) honící posledních ~2 % k targetu 100 %. live_soc clampnuté na 99 % vs target 100 % → needed_wh nikdy neklesne na 0 → **věčné mini-dobíjení = start/stop nabíječky, Tesla notifikace, zbytečné Modbus zápisy** (cyklování). +- **Mechanismus (fix):** effective target zastropovaný na 99 (= clamp live_soc); `energy_needed_wh = 0` když `live_soc >= least(target,99) − tolerance`. Tolerance per-vozidlo: nový sloupec `asset_vehicle.charge_done_tolerance_pct` (default 3 p.b., V107). 0 = tvrdě na target. Ponecháno: anti-fragmentace + 3f `min_power_w` floor (scattered 1f trickle) jako další solver fix (plán bod #3). +- **Soubory:** `V107__ev_charge_done_tolerance.sql`, `R__038_fn_ev_session_planning_json.sql`, `docs/04-modules/ev-charging.md`. +- **Ověření (živá DB):** session #6 home-01 (live_soc 97.9, target 100): `energy_needed_wh` 1329 → **0** (97.9 ≥ 99−3 = 96). Golden gate: R__038 je upstream solveru (frozen JSON fixtures) → netýká se ho. + ## 2026-06-14 — phantom 11 kW okna: plánovač slepý k pokroku nabíjení EV (živé SoC) - **Problém:** Tesla připojená na 70 %, dotankovaná na ~98 %, ale plán emitoval **15 oken po 11 kW** (20:15–23:45) — phantom. `fn_ev_session_planning_json` vracela `energy_needed_wh = 18750 Wh` konstantně po celou session.