Merge branch 'worktree-agent-a53f3277d55fecfcb' into dev
This commit is contained in:
@@ -376,12 +376,33 @@ stav baterie auta → cíl (+kWh), deadline, plánovaná nabíjecí okna s ø ce
|
||||
|
||||
Tvrdý cíl (deadline) = „bez tohohle neodjedu"; měkký cíl = „klidně doplň
|
||||
do 100 %, když je energie skoro zadarmo". Implementace: dekompozice
|
||||
Σ(EV energie) == needed − unmet + opp; `opp ∈ [0, headroom]`
|
||||
(headroom = (100 − target) % kapacity, jen když `asset_vehicle.
|
||||
opportunistic_value_czk_kwh > 0`; default 1 Kč/kWh, 0 = vypnuto).
|
||||
Σ(EV energie) == needed − unmet + opp; `opp ∈ [0, headroom]`.
|
||||
**Headroom = (100 − max(target, soc_at_connect)) % kapacity** (fix paradoxu
|
||||
„nižší target → větší headroom": auto fyzicky bere jen energii nad svým
|
||||
aktuálním SoC). **Hodnota kWh:** `coalesce(ev_session.opportunistic_value_czk_kwh,
|
||||
asset_vehicle.opportunistic_value_czk_kwh)` — V099 přidal per-session override
|
||||
(NULL = zdědit z vozidla, 0 = vypnout pro session ⇒ headroom_wh = 0; patch
|
||||
klíčem `opportunistic_value_czk_kwh` ve `fn_ev_session_apply_patch`, validace ≥ 0).
|
||||
Default vozidla 1 Kč/kWh, 0 = vypnuto.
|
||||
Hodnota = ušetřené BUDOUCÍ nabíjení (auto neumí zpět — žádný noční prodej),
|
||||
proto nízká → uplatní se při záporných cenách / plné domácí baterce
|
||||
(lepší než curtail), běžné ceny ji nezaplatí. Víkendový vzor „pátek
|
||||
nemusím do plna, víkend doplní zadarmo" z toho plyne sám. Dekompozice
|
||||
zároveň stropuje celkovou energii do auta (dřív při buy<0 chyběl strop).
|
||||
Session zůstává v plánu i po dosažení targetu, dokud má headroom.
|
||||
zároveň stropuje celkovou energii do auta (dřív při buy<0 chyběl strop) —
|
||||
a **bez session je EV == 0** (stop-session nevypíná jen tvrdý cíl, ale i
|
||||
oportunismus). Session zůstává v plánu i po dosažení targetu, dokud má headroom;
|
||||
**oportunistická vrstva není omezená deadline** (auto bývá doma dál, odjezd
|
||||
řeší rolling replan — rozhodnutí 2026-06-12).
|
||||
|
||||
### Min. výkon wallboxu a účtování via-bat (2026-06-12, dev)
|
||||
|
||||
- **`asset_ev_charger.min_power_w`** (1380 W = 6 A IEC 61851) jde přes
|
||||
`fn_planning_site_context` do solver_v2: binárka `ev_on[e][t]`,
|
||||
`setpoint ∈ {0} ∪ [min_power_w, max]` — žádné nevykonatelné 400–900 W.
|
||||
- **Tvrdý cíl** sčítá jen sloty **před** deadline (slot začínající v deadline
|
||||
už nepatří „do deadline" — oprava off-by-one).
|
||||
- **`ev_direct ≤ gi + PV`** (fyzikální split; via_bat kryje vybíjení baterie).
|
||||
- **Reporting:** kWh do EV z baterie (via_bat) neplatí slotový buy; solver_v2
|
||||
je oceňuje oportunitní cenou v `planning_interval.battery_arbitrage_czk`
|
||||
(min sell exportního slotu téhož pražského dne, jinak terminal value) a
|
||||
`fn_plan_current_bundle.intervals` nese `ev1/ev2_via_bat_w` pro UI.
|
||||
|
||||
@@ -819,4 +819,30 @@ Plánovač má dvě implementace, přepínané env proměnnými (`backend/app/co
|
||||
front-load v sell<0 (`planner_pv_risk_frontload_czk_kwh`, V090), denní SoC
|
||||
rampa (`safety_soc_target_wh` × `planner_safety_soc_risk_factor`, V091).
|
||||
Detail: hlavička `solver_v2.py` + changelog 2026-06-12.
|
||||
- **EV ve v2 — účtování, headroom, min. výkon (2026-06-12):**
|
||||
- **Deadline boundary:** tvrdý cíl sčítá energii jen ve slotech `t < t_deadline`
|
||||
(první slot s `interval_start >= deadline` už energii dodává po odjezdu —
|
||||
dřívější off-by-one `range(t_dl + 1)` opraven).
|
||||
- **Měkký cíl (oportunismus):** dekompozice `Σ(EV energie) == needed − unmet + opp`;
|
||||
`opp ∈ [0, headroom_wh]`. **Headroom** = `(100 − max(target_soc_pct,
|
||||
soc_at_connect_pct)) % kapacity` (R__039) — „nenabíjet" (nízký target) už
|
||||
paradoxně NEzvětšuje oportunistickou vrstvu; auto fyzicky bere jen nad svým
|
||||
SoC. Hodnota kWh = `coalesce(ev_session.opportunistic_value_czk_kwh,
|
||||
asset_vehicle.opportunistic_value_czk_kwh)` (V099: session override; NULL =
|
||||
zdědit, 0 = vypnout pro session → `headroom_wh = 0`); patch klíčem
|
||||
`opportunistic_value_czk_kwh` v `fn_ev_session_apply_patch` (validace ≥ 0).
|
||||
**Oportunistická vrstva NENÍ omezená deadline** (rozhodnutí 2026-06-12:
|
||||
auto bývá doma dál, odjezd řeší rolling replan). **Bez session je EV == 0**
|
||||
i při `buy < 0` (stop-session; dřív neomezené „pumpování").
|
||||
- **Min. výkon wallboxu:** `asset_ev_charger.min_power_w` (6 A ≈ 1380 W) jde
|
||||
přes `fn_planning_site_context` (vehicles JSON) do binárky `ev_on[e][t]` —
|
||||
setpoint ∈ {0} ∪ [min, max]; konec nevykonatelných 400–900 W setpointů.
|
||||
- **Fyzikální split:** `Σ_e ev_direct[e][t] ≤ gi[t] + pv_a_net + pv_b_eff`
|
||||
(direct jen ze sítě + PV; via_bat kryje `bd`). Ekonomiku nemění, ale split
|
||||
direct/via_bat už není arbitrární.
|
||||
- **Reporting via_bat:** kWh do EV z baterie neplatí slotový buy — solver_v2
|
||||
plní `battery_arbitrage_czk` oportunitní cenou (min `sell` exportního slotu
|
||||
téhož pražského dne, jinak terminal value; clamp ≥ 0) × via_bat energie
|
||||
(dřív konstantní 0). `fn_plan_current_bundle` nese `ev1/ev2_via_bat_w`
|
||||
v `intervals`, aby UI necenilo EV kWh z baterie slotovým buy.
|
||||
- Regresní brána a měření: `scripts/harness/README.md` (golden replay, economics report, penalty audit, `solver_v2_eval.py`); plán refaktoru: `docs/refactor-clean-planner.md`.
|
||||
|
||||
@@ -5,6 +5,45 @@ Formát: **datum (ISO)** · stručný důvod · soubory · chování / ověřen
|
||||
|
||||
---
|
||||
|
||||
## 2026-06-12 — EV účtování v2: headroom, deadline boundary, min. výkon WB, via-bat reporting
|
||||
|
||||
**Problém (hloubková diagnóza EV):** (a) „nenabíjet" (nízký target) oportunismus
|
||||
nevypnul a paradoxně ZVĚTŠIL headroom (= 100 − target); session bez mandátu
|
||||
(nebo žádná session) při `buy < 0` pumpovala energii bez stropu; (b) off-by-one
|
||||
v deadline sumě (`range(t_dl + 1)` — slot začínající v deadline se počítal „do
|
||||
deadline"); (c) reporting lhal: `battery_arbitrage_czk` konstantně 0, via_bat se
|
||||
nepropagoval do bundle, UI cenilo EV kWh z baterie slotovým buy; (d) split
|
||||
ev_direct/via_bat byl arbitrární (direct nesvázán s gi + PV); (e) min. výkon
|
||||
wallboxu (`asset_ev_charger.min_power_w`, 1380 W = 6 A) ignorován → setpointy
|
||||
400–900 W nevykonatelné.
|
||||
|
||||
**Mechanismus:** headroom z `max(target_soc_pct, soc_at_connect_pct)` a
|
||||
opportunistic_value = `coalesce(session, vehicle)` v `fn_planning_site_context`
|
||||
(V099: `ev_session.opportunistic_value_czk_kwh`, NULL = zdědit, 0 = vypnout;
|
||||
patch přes `fn_ev_session_apply_patch`, validace ≥ 0); solver_v2: deadline suma
|
||||
`range(t_dl)`, bez session EV == 0, dekompozice `total == needed − unmet + opp`
|
||||
i pro needed = 0; binárka `ev_on` → setpoint ∈ {0} ∪ [min_power_w, max]
|
||||
(min_power_w nově ve vehicles JSON kontextu); `Σ ev_direct ≤ gi + pv_a_net +
|
||||
pv_b_eff`; `battery_arbitrage_czk` = via_bat kWh × oportunitní cena (min sell
|
||||
exportního slotu téhož pražského dne, jinak terminal value, clamp ≥ 0);
|
||||
`fn_plan_current_bundle.intervals` + `ev1/ev2_via_bat_w`. **Oportunismus PO
|
||||
deadline zůstává POVOLENÝ** (rozhodnutí: auto často doma, odjezd řeší rolling
|
||||
replan). Fixtures: `extract_fixtures.py --keep-ev` (default dál EV nuluje).
|
||||
|
||||
**Soubory:** `V099__ev_session_opportunistic.sql`, `R__039_fn_planning_site_context.sql`,
|
||||
`R__015_fn_ev_session_patch.sql`, `R__033_fn_plan_current_bundle.sql`,
|
||||
`services/planning/solver_v2.py`, `services/planning/db_io.py`,
|
||||
`scripts/harness/extract_fixtures.py` + README, `docs/04-modules/ev-charging.md`,
|
||||
`docs/04-modules/planning.md`.
|
||||
|
||||
**Ověření:** `tests/test_solver_v2.py` +7 (deadline boundary, stop-session,
|
||||
no-session při buy<0, direct ≤ gi+pv, setpoint ∈ {0}∪[1380, max], opp po
|
||||
deadline > 0, battery_arbitrage_czk > 0 u via_bat); golden gate beze změny
|
||||
snapshotů (v1 nedotčen, fixtures bez EV); `solver_v2_eval.py` před/po identický
|
||||
(CELKEM −1283.5 Kč, Δ −221.9 vs v1); plná sada 310 passed / 4 xfailed.
|
||||
|
||||
---
|
||||
|
||||
## 2026-06-12 — idle-skip telemetrie: TUV delta normalizovaná na °C/min
|
||||
|
||||
**Problém:** telemetry_collector nově přeskakuje 1min zápisy idle zařízení
|
||||
|
||||
Reference in New Issue
Block a user