Hloubková diagnóza EV potvrdila: oportunitní ekonomika via-baterie je v LP
správně, ale okraje lhaly nebo byly nevykonatelné:
- V099 + R__039: ems.ev_session.opportunistic_value_czk_kwh (NULL = zdědit
z asset_vehicle, 0 = vypnout pro session); headroom_wh z max(target_soc,
soc_at_connect) — „nenabíjet" (nízký target) už paradoxně NEzvětšuje
oportunistickou vrstvu; vehicles JSON nese min_power_w wallboxu.
- R__015: patch klíč opportunistic_value_czk_kwh (validace >= 0).
- solver_v2: (a) deadline suma range(t_dl) — slot začínající v deadline už
nepatří „do deadline"; (b) Σ ev_direct <= gi + PV (fyzikální split);
(c) binárka ev_on → setpoint ∈ {0} ∪ [min_power_w, max] (konec 400–900 W
nevykonatelných setpointů); (d) bez session EV == 0 (stop-session i golden
fixtures — žádné pumpování při buy<0); dekompozice total == needed − unmet
+ opp i pro needed = 0; (e) battery_arbitrage_czk = via_bat kWh × oportunitní
cena (min sell exportního slotu téhož pražského dne, jinak terminal value)
místo konstantní 0. Oportunismus PO deadline zůstává POVOLENÝ (rozhodnutí:
auto často doma, odjezd řeší rolling replan).
- R__033: fn_plan_current_bundle.intervals + ev1/ev2_via_bat_w (UI nemá cenit
EV kWh z baterie slotovým buy).
Golden gate beze změny snapshotů (v1 nedotčen, fixtures bez EV sessions);
solver_v2_eval před/po identický (CELKEM −1283.5 Kč, Δ −221.9 vs v1);
tests/test_solver_v2.py +7 testů; plná sada 310 passed / 4 xfailed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Tabulka ems.ev_weekly_requirement (dow 0=pondělí..6, target_soc_pct,
deadline_hour Europe/Prague, enabled; unique per vozidlo+den) se seedem
tesla-my pondělí 07:00 → 90 %. Nová ems.fn_ev_session_defaults(vehicle,
arrival) → jsonb {target_soc_pct, deadline, source}: kaskáda týdenní
požadavek (výskyt do 48 h) → forecast z ev_usage_stats
(target_soc_forecast_enabled, chování V089 beze změny) → defaulty vozidla
(deadline = příští výskyt default_deadline_hour). fn_ev_session_transition
ji volá při založení session (SQL-first, Python beze změny); comment
funkce sjednocen na styl bez parametrů.
Docs: ev-charging.md sekce Týdenní požadavky + kaskáda, CLAUDE.md seznam fn.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Slabý server: dict (tabulka, asset_id) → (signature, last_stored_at);
_idle_skip ukládá vždy při změně signature, aktivitě, po startu procesu
a heartbeat po > 840 s (každý 15min bucket má ≥ 1 řádek).
- telemetry_ev_charger: aktivní = status != 'available' nebo power > 50 W;
signature (status, výkon na 100 W)
- telemetry_pool_pump: aktivní = is_on nebo power > 5 W (ON řádky 1/min
kvůli on_minutes); signature (is_on, výkon na 10 W)
- telemetry_loxone_sensor: jen změna hodnoty ≥ 0.1 / heartbeat
- telemetry_heat_pump: aktivní = mode != 'off' nebo defrost; signature
(mode, teploty na 0.2 °C)
- telemetry_inverter: beze změny — NIKDY se nepřeskakuje (audit Wh split,
baseline, SoC plánovače)
Detekce příjezdu/odjezdu EV: previous_status přesunut z posledního řádku DB
do in-memory _EV_LAST_STATUS (po startu seed z vw_latest_ev_charger —
přechod během výpadku se pozná, prázdná DB nevystřelí falešný příjezd);
fn_ev_session_transition se volá jen při změně statusu.
PoolCard: staleness práh 5 → 16 min (> heartbeat 840 s).
Docs: telemetry.md sekce „Idle-skip zápisů" (pravidla pro nové čtecí dotazy:
sumy/gapfill, ne avg přes řádky), planning-changelog (TUV °C/min).
Testy: tests/test_telemetry_idle_skip.py — _idle_skip jednotkově + EV
arrival/departure přežije skip i restart procesu (303 passed).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Nahrazuje placeholder IP 192.168.1.101/.102 ze seedu; sdílená sběrnice
s plánovaným Chint elektroměrem (unit 3). Teltonika strana čeká na povolení
Modbusu v aplikaci.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
_apply_export_plan_guard při export_mode=NONE (plán nabíjí baterii, neexportuje)
vynucoval _passive_no_export_guard s export_ban=True + deye_gen_cutoff_enabled=True
bez ohledu na cenu -> reg 178 bity 0-1=3 (MI cutoff) + reg 145=0 a mikroinvertory
(pole B) fyzicky stály i při sell +1.36 Kč (BA81 dnes: gen port ~0 W od 12:16Z,
SoC 64 %, stringy 4.2 kW do baterie). Tvrdý ban nově JEN při záporné vykupní;
při kladné guard dál drží PASSIVE/143=0/baterie nevybíjí do sítě, ale MI jedou
(absorbce do baterie, přetok se prodá). Plánový z_gen_cutoff se respektuje.
Pre-existing fail test_neg_buy_and_sell_with_pv_b_forces_pv_a_off padá i na main
(pv_a_allowed_w None != 0) — nesouvisí, řešit zvlášť.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Uživatel: 'potřebuju do X % (tvrdý), ale klidně dobij na 100 % když je to
skoro zadarmo; při záporných cenách radši do auta než nechat na střeše'.
- V094 asset_vehicle.opportunistic_value_czk_kwh (default 1.0; = hodnota
ušetřeného BUDOUCÍHO nabíjení — auto neumí zpět, žádný noční prodej)
- R__039 ev_sessions: + headroom_wh ((100−target) % kapacity) + opp value;
session se nenuluje po dosažení targetu, dokud má headroom
- solver_v2: dekompozice Σ(EV) == needed − unmet + opp, opp ∈ [0, headroom],
odměna opp×value; zároveň FIX latentního bugu — při buy<0 chyběl strop
celkové energie do auta (model mohl pumpovat bez limitu)
- 3 testy (neg ceny sají nad target po strop; běžné ceny ne; cap při opp=0);
eval fixtures beze změny (sessions null)
Víkend (pátek nízký tvrdý cíl + víkendová negativa → samo doplní do 100 %)
vyplývá z mechanismu, žádná speciální logika.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- R__097: vw_latest_pool_pump + vw_pool_pump_day_energy (denní kWh z delty
čítače, minuty běhu) + ems_anon granty
- PoolCard na Dashboardu: stav/W/dnešní kWh+hodiny/7denní mini sloupce
- _notify_ev_arrival_plan: po příjezdu EV Discord souhrn (SoC auta → cíl,
deadline, nabíjecí okna shlukovaná ze slotů aktivního plánu, ø cena)
- docs/discord-ev-interaction.md: fáze B (bot s tlačítky přes gateway —
žádný veřejný endpoint; čeká na DISCORD_BOT_TOKEN od uživatele)
- docs: pool-shelly + ev-charging aktualizovány (pravidlo docs 1:1)
První commit na dev větvi (nová kadence: deploy až s milníkovým merge).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
poll_ev_chargers četl placeholder ('available'/0 W) — EV spotřeba se nikdy
neodečítala z bazálu a session detekce nefungovala. Nyní: blok registrů 0-40
jedním FC 3 (oficiální protokol rev 0.5), parse_teltocharge_frame (status z
reg 6 → available/preparing/charging/..., výkon reg 38, energie session reg 39,
proud max L1-L3 reg 3-5). Při selhání čtení se vzorek NEzapisuje (fabrikovaný
available by falešně ukončoval session).
fn_telemetry_ev_charger_sample: + p_current_a (drop staré 7-arg signatury).
6 nových testů parseru; plná sada beze změny. Docs: modbus-registers-teltocharge.md.
Po deployi: home-01 ev-charger-1/2 začnou posílat reálná data; bazál se začne
čistit od EV (EMA 00:30); rebuild stats má smysl až po ~2 týdnech čisté historie.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- docs/refactor-clean-planner.md: plán Fází 0-4, stav, závazná pravidla
(golden gate), návod nasazení v2 (shadow → vyhodnocení → přepnutí)
- docs/planning-changelog.md: záznam 2026-06-11 (Fáze 0-3 kompletní)
- docs/04-modules/planning.md: sekce Verze enginu v1/v2 + env flagy
- docs/audits/*: stav implementace FE fixů
- .claude/skills/ems-delta-triage: postup triáže neekonomického chování
(realita vs plán vs shadow peer vs oracle, verdikt s Kč)
- CLAUDE.md: ukazatele na refaktor, solver_v2 a delta-triage v 'Kde hledat co'
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pre-neg forecast cushion and evening push before negative-sell days now use telemetry SoC instead of chaining LP targets across days, so the planner does not stop discharging early when BMS is higher than the model.
Co-authored-by: Cursor <cursoragent@cursor.com>
Force PASSIVE/no-export when sell is negative or export_mode is NONE,
and alert NEG_SELL_EXPORT in plan_actual_slot_guard when export still occurs.
Co-authored-by: Cursor <cursoragent@cursor.com>
Restore _evening_peak_export_indices filter so push slots are chosen from
profitable peak-band nights, then ranked by sell until the Wh budget is
exhausted—not all profitable night slots and not a fixed top-3. Docs and
tests match v39 SoC balance tag.
Co-authored-by: Cursor <cursoragent@cursor.com>
SoC continuity now deducts only bd (ge_bat was double-counted via energy
balance), which stopped the plan from draining ~2× faster than BMS during
evening BATTERY_SELL. Also ships dynamic evening push budget + rolling
hysteresis (v38), drops unused fn_soc_tracking_bundle, and adds tests/docs.
Co-authored-by: Cursor <cursoragent@cursor.com>