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>
ev_vehicle_obs.trigger += 'geofence_arrival' (V109); presence cesta zapíše příjezd
i bez píchnutí (za flagem EV_GEOFENCE_ARRIVAL_OBS_ENABLED, default OFF); fn_ev_build_trips
páruje. Constraint name ověřen živě. Worktree agent.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
11000 W / (3x230) = 15.94 A; int() useklo na 15 A (~10.35 kW), round da
spravnych 16 A (~11 kW). Strop 32 A drzi horni mez. 74 control testu zelenych.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
_apply_export_plan_guard / _build_setpoints: kdyz slot CHARGE / importuje na
nabiti baterie (grid_sp>0 & bat>0), guard vrati sp beze zmeny a export_ban se
nenastavi. Opravuje, ze se baterie nedobila v zapornych cenach (CHARGE+17kW
prekloplen na PASSIVE -> Deye nenabijel ze site). Diagnoza: agent a599eecc.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Zivy incident home-01: aktivni plan mel ev_sessions:0, ac session bezela
(target 70 %). Planovac neviděl ~6 kW zatez auta a spatne rozvrhl baterii
(zbytecny vecerni import).
Root cause (dve pasti):
- fn_planning_site_context vracela session jako null, kdyz needed_wh=0
(auto nad targetem) i kdyz target_deadline is null.
- _ev_session_from_json (Python) zahazovala session bez deadline.
Fix:
- R__038 fn_ev_session_planning_json: session se vyradi (null) JEN bez tvrdych
dat (kapacita vozidla / soc_at_connect). target_deadline smi byt NULL --
solver hard deadline constraint aplikuje jen pri needed>0; oportunisticka
vrstva bezi i bez deadline. Auto nad targetem zustava v planu jako znama
zatez i s headroomem k levnemu doplneni. R__039 vola helper (deduplikace
dvou inline poddotazu, SQL-first).
- _ev_session_from_json si NULL deadline ponecha (energy_needed_wh default 0).
- testy test_ev_session_parse.py; docs ev-charging + planning-changelog;
CLAUDE.md funkce.
Navrh agresivnejsiho oportunistickeho algoritmu (P50 levnych oken z
market_price_stats misto konstanty 1 Kc/kWh) -- NEnasazeno, k rozhodnuti,
sepsano v docs/04-modules/planning.md (EV oportunismus); riziko regrese
golden ekonomiky, nutny EV fixture + eval.
Overeni: pytest -q 362 passed; golden replay gate 7 passed; solver_v2_eval
beze zmeny (fixtures bez EV session).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Zivy incident home-01 (TeltoCharge .16): od ~22:45 UTC 12.6. nevznikl zadny
telto journal radek (ani failed), auto jelo failsafe 8 A misto planovanych 0 A.
Root cause: reg 15 (amps) byl write-on-change proti journalu
(fn_modbus_device_state_map). Jakmile mel reg 15 radek "0 verified" a plan
dal chtel 0, NIKDY nevznikl novy prikaz -- a TeltoCharge si po vypadku
komunikace sam prepsal reg 15 na failsafe (reg 20) BEZ journal radku. Verify
cte zpet jen 'written' radky, takze tichy drift 0 -> 8 A nikdo nevidel ani
neopravil.
- reg 15 (amps to use) se zapisuje VZDY (re-asert) -- volatilni ridici
registr, ne EEPROM; drzi verify jobu cerstvy written radek -> drift se
zachyti a hned opravi. _split_amps_and_watchdog odděluje 15 od 19/20.
- reg 19/20 (watchdog config, EEPROM) zustavaji write-on-change.
- per-charger failsafe/timeout: asset_ev_charger.watchdog_failsafe_a /
watchdog_comm_timeout_s (V106; default 8 A / 300 s). "Zakaz nabijeni" =
reg 15 = 0 (protokol rev 0.5 nema samostatny enable registr).
- testy test_ev_write_on_change.py; docs teltocharge + journal + data-model.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Patch po příjezdu přepisoval target_soc_pct limitem auta (LFP 100 %) a
zahazoval kaskádu fn_ev_session_defaults (default vozidla 30 %) — auto by
se v noci tlačilo do plna ze sítě proti vůli majitele (session #2 dnes).
Nově se target snižuje jen pokud je limit auta POD ním;
fn_tesla_arrival_context vrací i target_soc_pct session.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wallbox dostával zápisy 15/19/20 každý export tick (~8x/hod: control_export
:14,:29,:44,:59 + rolling replan */15 s exportem), protože drop-unchanged
stál na fn_modbus_last_verified_map — dokud verify čtení nedoběhlo/selhalo,
mapa byla prázdná a celá trojice se psala pořád dokola. write_ev_arrival_hold
navíc psal trojici nepodmíněně při každém píchnutí kabelu (docstring lhal).
- nová ems.fn_modbus_device_state_map (R__100): nejnovější řádek journalu
per registr, hodnota jen pro written/verified; failed/mismatch => registr
chybí => po výpadku se konfigurace obnoví jedním zápisem
- write_ev_setpoints + write_ev_arrival_hold filtrují přes tuto mapu:
reg 15 jen při změně plánu, watchdog 19/20 jednou po startu/po výpadku
- verify job EV chargery ověřuje už dnes (fn_modbus_written_command_ids bez
filtru asset_type); registry 15/19/20 jsou dle oficiálního protokolu R/W
- watchdog Telto sytí jakákoli validní komunikace vč. FC3 čtení telemetrie
(60 s << 300 s) — periodické zápisy k udržení spojení nejsou potřeba,
failsafe 8 A nastane jen při skutečném výpadku EMS
- testy: tests/test_ev_write_on_change.py (drop, setpoints, arrival hold)
- docs: modbus-registers-teltocharge.md (sekce Zápis už není "NEimplementováno",
R/W tabulka, watchdog sémantika), modbus-command-journal.md (sekce EV
wallbox), CLAUDE.md (fn_modbus_device_state_map)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
V100 rozšířil view i logiku, ale SELECT v collectoru zůstal bez nového
sloupce — row['deye_zero_export_mode'] padal každou minutu od deploye
287353b (~33 min výpadek inverter telemetrie; EV/pool jely dál v heartbeat
rytmu).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fakturační elektroměr ~8 kW vs Deye 13.5 kW: hlavní okruhy domu (vč. wallboxu,
EV 10.5 kW při load 164 W) visí MEZI střídačem a CT u elektroměru — reg 625
(svorky) ani 653 (UPS port) je nevidí. home-01 bylo chybně vedeno jako bez CT.
V100: deye_zero_export_mode=2 (reg 142 → zero export to CT, propíše exporter),
sloupce inverter_grid_port_w + ups_load_w, komentáře se změnou sémantiky.
Collector: grid_power_w z reg 619 (instalace s CT; fallback 625),
load_power_w = pv + baterie + grid = celkový dům. R__049 +2 parametry,
R__052 + deye_zero_export_mode. Audit/baseline od teď počítají se skutečnou
ulicí; historie (do 2026-06-12) nese svorky střídače — přepočet ekonomiky po
faktuře. Baseline rebuild doporučen po týdnu nových dat.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
TeltoCharge po připojení kabelu sám rozjede nabíjení svým defaultem; EMS ho
dosud dohnal až exportem setpointů (do 15 min). _on_ev_arrival nyní před
replanem zapíše přes journal telto_amps_to_use=0 (write_ev_arrival_hold),
replan+export vzápětí nastaví plánované ampéry. Watchdog (300 s → failsafe
8 A) zachován — výpadek EMS auto nenechá na 0 A.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>
Arrival zpráva má dva persistent Selecty (custom_id ev:<site>:<charger>:dep
a :tgt, obsluha on_interaction + regex → přežijí restart):
„Kdy odjíždíš?" za 2 h | za 4 h | dnes večer 18:00 | zítra ráno 7:00 |
zítra poledne 12:00 | pondělí ráno 7:00; „Kolik potřebuješ?" 30/50/70/100 %
| Nenabíjet. Každý výběr okamžitě PATCHne session přes
fn_ev_session_apply_patch jen ve své dimenzi (absolutní deadline
Europe/Prague, nejbližší budoucí výskyt; pevná volba smí přes 48 h),
druhý rozměr zůstává z fn_ev_session_defaults. Pak replan + export a edit
zprávy přepočteným plánem (build_ev_plan_summary) + potvrzením. Whitelist
DISCORD_ALLOWED_USER_IDS i bot-first/webhook fallback beze změny; legacy
tlačítka h2/h4/morning/full/stop starších zpráv dál obsloužená.
Testy: mapování výběr→patch, absolutní deadline z voleb (půlnoc, pondělí
z pátku >48 h, pondělí ráno v pondělí), parse, legacy akce — bez DB/sítě.
Docs: discord-ev-interaction.md (nové UI, no-click = pohotovostní režim
30 % + oportunismus).
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>
Větev 'slabý úsvit (forecast<1500 W) → reg 340 neposílat' zastínila větev
'buy<0 a sell<0 + pole B → pv_a_allowed=0' — při hluboce záporných cenách
za úsvitu by se pole A nezavřelo. Prohozeno pořadí; opravuje pre-existing
fail test_neg_buy_and_sell_with_pv_b_forces_pv_a_off (293 passed, 4 xfail).
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>
- list poll 5→10 min; vehicle_data JEN při přechodu asleep→online nebo
max 1×/15 min (data /usr/bin/zsh.002/req); wake nikdy (gate na online)
- otevřená ev_session = auto u wallboxu → ŽÁDNÉ API cally (při AC nabíjení
auto nespí — bez gatu by data tekla celou noc nabíjení)
Odhad: </měsíc (online okna mimo wallbox jsou krátká).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Všechny site webhook URL jsou NULL a env DISCORD_WEBHOOK_URL nebyl nastaven
→ send_discord vždy skončil na 'not configured, skipping' (uživatel: 'nikdy
mi nic nepřišlo'). Fix: fallback přes bota (REST POST do DISCORD_EV_CHANNEL_ID
— token už v .env, žádný webhook netřeba); webhook má přednost, kdyby ho
uživatel později nastavil per site. Bot navíc při startu pošle '✅ online'
(viditelný důkaz, 1× per deploy).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
400 invalid_grant = spálený token rotací NEBO ~10min výpadek po revokaci
souhlasu (Tesla) — místo tracebacku log s návodem a return None (EMS jede
dál na defaultech). deploy/tesla/reauth.sh: authorize URL → výměna → DB →
ověření v jednom kroku (žádná příležitost pro rotační past).
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>
KV1 pozorování uživatele: ráno baterie na 11 % (min 10), prodává se do sítě
— nenadálý odběr/mrak by se kupoval za fixních 6.35. v1 mělo denní rampu
(safety_soc_target_wh z R__063: reserve 30 % ráno → reserve+noc večer,
6-19 h, flag planner_daytime_charge_target_enabled) — v2 ji ignoroval.
Mechanismus (vzor nočního polštáře): deficit pod rampou platí za KAŽDÝ slot
nájem buy×faktor (V091 asset_battery.planner_safety_soc_risk_factor,
default 0.05; 0=vypnuto) → ráno se nejdřív doplní rezerva (4 h deficitu
1 kWh při buy 6.35 ≈ 5.1 Kč > sell ~2.5), extrémní sell špička smí deficit
racionálně podstoupit. R__039 + db_io + 2 testy (KV1 scénář, spike).
Eval fixtures beze změny (sloupec v context_json fixtures není → 0);
živá produkce dostane faktor přes fn_planning_site_context.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v1 to řešil rampou (plný výkon než se řeže pole A — zelený bonus B, riziko
večerního mraku). v2 byl k načasování v okně sell<0 indiferentní (PV zdarma
kdykoliv) a směl nabíjení odložit — odklad ale spoléhá na predikci.
Mechanismus: malá prémie za držení energie dřív (objective −= soc[t] ×
frontload v neg slotech). Rozbíjí indiferenci směrem k front-loadu, nikdy
nepřebije skutečné ceny. Velikost z DB: asset_battery.
planner_pv_risk_frontload_czk_kwh (V090, default 0.01; 0 = vypnuto),
přes fn_planning_site_context (R__039). Test: 4 sloty plným tempem od startu.
Eval fixtures beze změny (sloupec v nich není → 0).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Postřeh uživatele: v1 držel přes noc rezervu nad min_soc (chyba predikce
noční spotřeby = neplánovaný drahý nákup); v2 slot fieldy night_baseload_*
ignoroval a směl plánovat vybití až na min_soc.
Mechanismus ve filozofii v2 (riziko jako cena, ne okno/penalta):
soft floor soc[t] >= min_soc + night_baseload_buffer_wh[t] (z DB
planner_night_baseload_buffer_percent, počítá R__063, klesá k 0 do rána);
porušení placené buy cenou slotu → extrémní sell špička smí polštář
racionálně prodat, běžná noc ne (buy > sell).
Eval na fixtures: v2 stále lepší na všech (+221.9 Kč vs v1; −10 Kč proti
stavu bez polštáře = cena robustnosti). BONUS: těsnější LP zrychlil extrémní
fixtures z 10 s timeoutu na 0.3–2.6 s. +3 testy (drží/spike prodá/feasible).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- services/tesla_client.py: access token s cache + ROTACE refresh tokenu do
ems.tesla_token (env jen seed — Tesla refresh token je jednorázový),
vehicles → vehicle_data?endpoints=charge_state, 408 (spící auto) = tiché
přeskočení, výběr vozidla dle VIN / jediného na účtu (VIN se auto-naučí)
- hook _patch_session_from_tesla v _on_ev_arrival: PŘED replanem doplní
soc_at_connect_pct (+ target z charge_limit_soc) do otevřené session přes
fn_ev_session_apply_patch (rozšířena o soc_at_connect_pct) — energii si
odvodí fn_planning_site_context (SQL-first); selhání neblokuje replan
- V086: asset_vehicle.vin, api_type='tesla' pro tesla-my (Model Y, home-01),
singleton ems.tesla_token; R__095: fn_tesla_token_get/upsert,
fn_tesla_arrival_context, fn_vehicle_set_vin
- config: TESLA_CLIENT_ID/SECRET/REFRESH_TOKEN (prázdné = vypnuto)
- testy parserů; plná sada beze změny
Aktivace: env do /opt/ems-deploy/.env + recreate backendu (docs/tesla-fleet-api.md §Stav).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bod 1 — write_ev_setpoints reálně (konec TODO stubu):
- reg 15 (0=stop, 6–32 A) z plánu přes _current_limit_for_charger; plná
journal pipeline (create_modbus_commands → execute, verify job 2 min generic)
- watchdog reg 19=300 s + reg 20=8 A: výpadek EMS → wallbox po 5 min failsafe
8 A (auto se přes noc nabije); drop-unchanged → zapisuje se jen při změně
- fn_modbus_last_verified_map: + p_asset_type (drop 2-arg; dosud hardcoded
'inverter' — pro chargery vracela {})
- verify: SELF_SUSTAIN fallback explicitně jen pro asset_type='inverter' —
mismatch wallboxu nesmí degradovat režim celé site
- journal register_name: mimo inverter platí jméno od volajícího
Bod 2 — telemetry_collector: přechod available→connected spustí fire-and-forget
run_rolling_replan(triggered_by=ev_arrival:<code>) + export_setpoints přes BG
pool — reakce na příjezd ~60 s místo až 15 min.
Bod 3 (Tesla API SoC) čeká na developer credentials.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- nová funkce na konci souboru + jeden řádek v run_telemetry_loop
(minimální dotyk kvůli souběžným změnám na main)
- čte vw_asset_pool_pump_http_poll, zapisuje fn_telemetry_pool_pump_sample
- při výpadku čtení nic nezapisuje (žádná fabrikovaná nula)
Co-Authored-By: Claude Fable 5 <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>
services/planning/solver_v2.py: MILP s objective = reálné peníze (cash +
degradace − terminal SoC value z DB faktoru). Tvrdá pravidla: bilance, SoC
dynamika, breaker (tvrdý), curtail jen A, GEN cutoff binárka, neg-buy/neg-sell
export bloky, export z baterie ⇒ arb floor (p.19), zákaz současného imp+exp,
EV deadline (placený slack 50 Kč/kWh místo infeasibility), TUV look-ahead,
provozní režimy. SQL masky allow_* vědomě ignorovány (heuristika, ne fyzika).
solver_v2_eval.py: v2 vs v1 na golden fixtures (SoC-fér):
v2 lepší na VŠECH 5 řešitelných (+231.5 Kč ≈ +22 %), extreme_neg_buy den
v1=INFEASIBLE → v2 OK (−674.5 Kč). Časy 0.4–10 s (2× na time limitu — TODO).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SoC série, neg-sell fáze/okna, evening push, pre-neg logika — čistý přesun,
fasáda v planning_engine.py beze změny chování (golden 5/5, baseline faily
beze změny). Roztroušené konstanty MORNING_PRENEG_* doplněny do constants.py.
planning_engine.py: 6345 → 3925 řádků (zbývá: solver, orchestrace, compare).
heuristics.py nese warning: hlavní kandidáti na prune ve Fázi 2/3.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Čistý přesun 57 konstant (vč. SOLVER_RELAX_STEPS) z planning_engine.py;
engine je importuje zpět (fasáda, beze změny chování). Golden replay 5/5,
unit testy beze změny vůči baseline (4+1 předexistující faily).
Ekonomické penalty/váhy tím získaly jedno místo — kandidáti na DB ve Fázi 2.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>