Commit Graph

467 Commits

Author SHA1 Message Date
Dusan Vojacek
48f5a6b00b Discord EV: dva výběry (odjezd × cíl) místo řady tlačítek
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>
2026-06-12 19:14:56 +02:00
Dusan Vojacek
60eda46dd7 V098: týdenní požadavky EV (ev_weekly_requirement) + fn_ev_session_defaults
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>
2026-06-12 19:14:40 +02:00
Dusan Vojacek
f0e81def5d open question: TUV delta jednotky °C/min vs užití v solveru (~60× podhodnocené chladnutí)
All checks were successful
CI and deploy / migration-check (push) Successful in 15s
CI and deploy / deploy (push) Has been skipped
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 19:09:33 +02:00
Dusan Vojacek
815a233049 feat(telemetry): idle-skip zápisů — neukládat 1min řádky idle zařízení
Some checks failed
CI and deploy / migration-check (push) Successful in 28s
CI and deploy / deploy (push) Failing after 17m56s
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>
2026-06-12 19:06:41 +02:00
Dusan Vojacek
f71bc944b4 fix(db): čtecí cesty telemetrie robustní vůči řídkým řádkům (idle-skip)
- fn_fill_audit_interval: EV a TČ agregace sum(power_w)/15 místo avg přes
  přítomné řádky — avg by při řídké telemetrii nadhodnotil aktivitu části
  slotu; chybějící minuta = 0 W (idle). TČ drží NULL bez power_w (MIM-B19N).
- fn_update_tuv_usage_stats: delta TUV normalizovaná na °C/min délkou mezery
  mezi řádky (gap_min), mezery > 30 min vyloučeny; pro hustá 1min data
  numericky identické s původním LAG.
- vw_pool_pump_day_energy: komentář — on_minutes drží invariant „zapnuté
  čerpadlo se ukládá každou minutu".

Pro hustá 1min data beze změny výsledků; připravuje idle-skip zápisů
v telemetry_collector (navazující commit).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 19:06:23 +02:00
Dusan Vojacek
e41840cb7d V097: wallboxy TeltoCharge na reálný RS485 převodník 172.16.1.16 (unit 1/2, 9600 8N1)
All checks were successful
CI and deploy / migration-check (push) Successful in 19s
CI and deploy / deploy (push) Successful in 1m4s
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>
2026-06-12 18:31:49 +02:00
Dusan Vojacek
8289e32a03 docs: heat-pump.md odkaz na MIM-B19N registry (dopatch k d63a85a)
Some checks failed
CI and deploy / deploy (push) Has been cancelled
CI and deploy / migration-check (push) Has been cancelled
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 18:24:36 +02:00
Dusan Vojacek
d63a85a2ea TČ Samsung přes MIM-B19N: endpoint 172.16.1.17, plný poll, registry doc
Some checks failed
CI and deploy / migration-check (push) Failing after 7m29s
CI and deploy / deploy (push) Has been skipped
- V096: endpoint home-01 TČ z placeholderu 192.168.1.103 na reálný Waveshare
  RS485 TO POE ETH (B) 172.16.1.17:502; telemetry_heat_pump.room_temp_c.
- R__048: fn_telemetry_heat_pump_sample rozšířena (water_inlet, room_temp,
  defrost, alarm_code) — drop/comment bez parametrů dle konvence.
- poll_heat_pump: místo TODO stubu (zapisoval dummy 45/55 °C!) skutečné čtení
  MIM bloku 50-75 + defrost reg 2; gate na comm_status ready (jinak skip);
  operating_mode off/heat/cool/auto/dhw/error; power_w NULL (MIM příkon nemá).
- docs/04-modules/modbus-registers-mim-b19n.md (mapa, 9600 8E1, DIP adresa,
  troubleshooting E6xx) + heat-pump.md odkaz.

Živý stav: TCP :502 OK, Modbus bez odpovědi (čeká na protokol převodníku /
paritu EVEN / polaritu A-B — checklist v docu).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 18:24:10 +02:00
Dusan Vojacek
1406796a62 Perf ROOT CAUSE: rolling faktor se počítal per řádek — hoist do proměnné (canonical PV fn 4.5s→~0.45s)
All checks were successful
CI and deploy / deploy (push) Successful in 46s
CI and deploy / migration-check (push) Successful in 23s
Skutečná příčina 600k buffers: CTE factor/factor_raw (single-ref) PG inlinuje
do projekce with_factor → fn_pv_forecast_correction_factor (48 ms / 1.9k
buffers) se vyhodnocovala ~300× per výstupní slot. Plan cache s tím neměl nic
společného (dřívější count(*) měření projekci zahodilo, proto vycházelo
0.42 s). Faktor se teď počítá jednou do v_rolling_factor a vkládá jako
literál (13. argument format).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 17:48:08 +02:00
Dusan Vojacek
8554cd1bc1 Perf: canonical PV fn přes plpgsql execute format — vynucený plán dle skutečných hodnot
All checks were successful
CI and deploy / migration-check (push) Successful in 21s
CI and deploy / deploy (push) Successful in 51s
set plan_cache_mode=force_custom_plan na SQL funkci v PG 18 nezabral (stále
generický plán, 4.5-9 s / 600k buffers). plpgsql EXECUTE s literály = vždy
čerstvý plán: tělo s konstantami změřeno 0.42 s / 34k buffers. Signatura,
chování i výstup beze změny.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 15:54:44 +02:00
Dusan Vojacek
62a5c64f77 HOTFIX web: /status/full 500 (str→tzinfo), /plan/compare 500 (chybějící comparison), canonical PV fn 4.5s→0.4s (force_custom_plan)
All checks were successful
CI and deploy / migration-check (push) Successful in 19s
CI and deploy / deploy (push) Successful in 1m17s
1) full_status._iso_utc dostával z JSONB bundle stringy → AttributeError → 500
   celého /status/full; nyní parsuje přes _parse_ts.
2) /plan/compare: NameError — 'comparison = _bundle_from_current(compare_raw)'
   se nikdy nesestavilo (smazaný řádek), endpoint vždy 500.
3) fn_forecast_pv_slots_range_canonical_ab: PG 18 cachuje plány SQL funkcí →
   generický plán 4.5 s / 607k buffers; set plan_cache_mode=force_custom_plan
   → 0.4 s / 34k (změřeno explain analyze na živé DB). Táhne /plan/current,
   /plan/compare i rolling plánovač.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 15:48:10 +02:00
Dusan Vojacek
dd3bd55c0e Fix reg 340: záporný buy+sell má přednost před úsvitovou výjimkou
All checks were successful
CI and deploy / migration-check (push) Successful in 13s
CI and deploy / deploy (push) Successful in 53s
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>
2026-06-12 15:19:10 +02:00
Dusan Vojacek
b66bb712e4 HOTFIX dashboard: pv-slots-corrected čte delta profil z cache (R__079 → fn_pv_forecast_delta_profile_cached)
All checks were successful
CI and deploy / migration-check (push) Successful in 14s
CI and deploy / deploy (push) Has been skipped
Endpoint GET /sites/{id}/forecast/pv-slots-corrected (dashboard) volal těžkou
fn_pv_forecast_delta_profile inline (~44 s/site na prod) — uživatel: 45 s
response, telemetry endpoint vyhladověl. Kanonická plánovací řada (R__088) už
cache používala, R__079 ne. Cache je pro všechny 4 lokality naplněná, čtenář
po HOTFIX 2/2 nikdy nepočítá.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 15:14:07 +02:00
Dusan Vojacek
c7f595c587 HOTFIX BA81: export plan guard neodstavuje pole B při kladné vykupní ceně
Some checks failed
CI and deploy / deploy (push) Has been cancelled
CI and deploy / migration-check (push) Has been cancelled
_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>
2026-06-12 15:07:17 +02:00
Dusan Vojacek
a208cc627d Konvence: comment on function / drop function VŽDY bez parametrů; názvy fn unikátní (žádné overloady)
All checks were successful
CI and deploy / migration-check (push) Successful in 41s
CI and deploy / deploy (push) Successful in 1m4s
Od uživatele po 42883 incidentu (R__018 comment na staré signatuře shodil
2 deploye): odkaz přes signaturu se rozbije při každé změně parametrů.
R__018 převeden na bez-parametrovou formu, pravidlo v CLAUDE.md Konvencích.
Zbylých 51 parametrizovaných comment on / 6 dropů v repu funguje (míří na
aktuální signatury) — normalizovat při dotyku.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 14:57:05 +02:00
Dusan Vojacek
9213d3544b HOTFIX 3: comment signatura (int, boolean) — deploy R__018 padal 42883; force refresh po PATCH kalibrace
All checks were successful
CI and deploy / migration-check (push) Successful in 18s
CI and deploy / deploy (push) Successful in 1m0s
Throttle commit změnil signaturu fn_refresh_site_pv_delta_profile_cache na
(int, boolean default false), ale comment on function dál mířil na (int) →
repeatable migrace selhala (function does not exist), oba deploye (7da7205
i 18bf93a) spadly — na produkci NENÍ nic z delta hotfixů. PATCH kalibrace
nově volá refresh s p_force=true (throttle nesmí zadržet přepočet po změně
parametrů).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 14:54:42 +02:00
Dusan Vojacek
18bf93a801 HOTFIX 2/2: delta profil — čtenář NIKDY nepočítá, jen čte cache
Some checks failed
CI and deploy / migration-check (push) Successful in 18s
CI and deploy / deploy (push) Failing after 28s
Postřeh uživatele odhalil druhou půlku problému: _cached getter měl
max_age 30 min s INLINE fallbackem na plný 44s přepočet — dosud to maskoval
15min refresh; po throttlu refresh jednou za 6 h by KAŽDÉ čtení po
vystárnutí cache (plan/current, canonical sloty plánovače) spouštělo 44 s.
Čtenář teď vrací cache bez ohledu na stáří; počítá výhradně refresh
(throttle 6 h + denní catch-up). Inline jen first-run/analytická okna.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 14:46:51 +02:00
Dusan Vojacek
7da7205c07 Hotfix merge: DB výkon (delta cache throttle) + presence watcher + Tesla zákopy
All checks were successful
CI and deploy / migration-check (push) Successful in 26s
CI and deploy / deploy (push) Has been skipped
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 14:25:32 +02:00
Dusan Vojacek
11767dfdbd HOTFIX výkon: delta-profile cache 44 s/site se přepočítávala každých 15 min
Some checks failed
CI and deploy / deploy (push) Has been cancelled
CI and deploy / migration-check (push) Has been cancelled
fn_fill_forecast_accuracy (tick :02/:17/:32/:47, 4 lokality) na konci volá
fn_refresh_site_pv_delta_profile_cache → fn_pv_forecast_delta_profile =
agregace 120 dní nad 4.1M řádky forecast_accuracy = ~44 s/site na prod
→ ~3 minuty plné DB zátěže KAŽDOU čtvrthodinu → timeouty /sites a
/health/detailed (30 s), celodenní 'pomalý server'.

Fix: (1) cache refresh throttle 6 h přes delta_profile_cached_at (+p_force;
profil má 14d poločas — 4×/den bohatě stačí); (2) 15min tick lookback
48→3 h (insert část); (3) denní 48h catch-up job 05:50.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 14:25:27 +02:00
Dusan Vojacek
e490e8cd26 Presence watcher: cost-aware pacing (Fleet API je placené)
All checks were successful
CI and deploy / migration-check (push) Successful in 48s
CI and deploy / deploy (push) Has been skipped
- 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>
2026-06-12 14:19:41 +02:00
Dusan Vojacek
2122fa2035 Tesla presence watcher: geofence, ev_presence_obs, 'píchni auto' pobídka
All checks were successful
CI and deploy / migration-check (push) Successful in 47s
CI and deploy / deploy (push) Has been skipped
- V095 ems.ev_presence_obs (state/at_home/distance/charging/shift per ~5 min)
- tesla_client: get_vehicle_api_state (jen /vehicles — nebudí), haversine_m
- collector poll_tesla_presence: online → poloha → geofence 150 m vs GPS site;
  přechod pryč→doma + Disconnected → Discord pobídka s aktuálním přebytkem
  (cooldown 2 h); vše logováno pro budoucí dostupnostní statistiku
- 6 testů (haversine, přechody); docs: zákopy reauth procesu (6 bodů)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 14:14:48 +02:00
Dusan Vojacek
ea4ca0e3de reauth.sh: prázdný seznam vozidel = chybí partner registrace (ne spánek)
All checks were successful
CI and deploy / migration-check (push) Successful in 57s
CI and deploy / deploy (push) Has been skipped
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 14:12:45 +02:00
Dusan Vojacek
ca4340ffdd CI retrigger po flyway repair (failed V093 odstraněna z historie)
All checks were successful
CI and deploy / migration-check (push) Successful in 42s
CI and deploy / deploy (push) Successful in 1m26s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 13:49:52 +02:00
Dusan Vojacek
5ae6b609cc FIX V093: asset_vehicle nemá sloupec notes — migrace failovala a blokovala
All checks were successful
CI and deploy / migration-check (push) Successful in 17s
CI and deploy / deploy (push) Has been skipped
všechny deploye od ~13:40 (R__082 OTE fix, V094, bot fallback ve frontě).
V093 nebyla aplikována (transakční rollback) — úprava failed migrace je
legitimní (immutability platí pro APLIKOVANÉ); na serveru nutný jednorázový
'flyway repair' (smaže failed záznam z historie).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 13:48:12 +02:00
Dusan Vojacek
3d51176819 Hotfix merge: Discord notifikace (bot fallback)
All checks were successful
CI and deploy / migration-check (push) Successful in 17s
CI and deploy / deploy (push) Has been skipped
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 13:44:32 +02:00
Dusan Vojacek
b651191fdb FIX: Discord notifikace se od začátku tiše zahazovaly — bot REST fallback
Some checks failed
CI and deploy / deploy (push) Has been cancelled
CI and deploy / migration-check (push) Has started running
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>
2026-06-12 13:44:30 +02:00
Dusan Vojacek
ee3581da02 Hotfix merge: OTE import (format %.3f) + Tesla reauth/redirect opravy + bazén příprava + měkký EV cíl
All checks were successful
CI and deploy / migration-check (push) Successful in 18s
CI and deploy / deploy (push) Has been skipped
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 13:39:29 +02:00
Dusan Vojacek
de849e7e8b HOTFIX: fn_ote_day_signals_prague — Postgres format() neumí %.3f
Some checks failed
CI and deploy / migration-check (push) Has been cancelled
CI and deploy / deploy (push) Has been cancelled
OTE import dnes spadl (InvalidParameterValueError: unrecognized format()
type specifier '.') — denní cenové signály poprvé trefily větev s %.3f/%.2f;
PG format() zná jen %s/%I/%L. Náhrada %s + round(x, N) ve všech 7 výskytech.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 13:39:27 +02:00
Dusan Vojacek
ce1ca8eecb Tesla: graceful 400 na token refresh + one-shot reauth skript
Some checks failed
CI and deploy / migration-check (push) Failing after 16m36s
CI and deploy / deploy (push) Has been skipped
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>
2026-06-12 13:14:04 +02:00
Dusan Vojacek
5a10da57e9 Tesla OAuth: redirect URI je /t-auth (oprava všude + Caddy rewrite)
All checks were successful
CI and deploy / migration-check (push) Successful in 26s
CI and deploy / deploy (push) Has been skipped
V dev portálu je registrováno https://ems.vojacek.eu/t-auth — docs i setup
skript diktovaly /tesla/callback (mismatch = invalid_auth_code / chybné
návody). Caddy blok nově servíruje callback stránku na /t-auth (rewrite).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 12:45:57 +02:00
Dusan Vojacek
315bd0ca46 v2 test: levný sell (<opp hodnota) posílá přebytek do auta, ne do sítě
All checks were successful
CI and deploy / migration-check (push) Successful in 5m31s
CI and deploy / deploy (push) Has been skipped
Postřeh uživatele — pásma nízkého výkupu před zápornými okny: mechanismus
měkkého cíle to už řeší (opp 1 Kč/kWh > sell 0.3 → auto vyhraje), test
to dokládá: plná domácí baterka + 9 kW PV → ~17 kWh do auta, minimální export.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 12:22:56 +02:00
Dusan Vojacek
85dff7f13e v2: měkký EV cíl — oportunistické nabíjení nad target (+ strop energie)
All checks were successful
CI and deploy / migration-check (push) Successful in 44s
CI and deploy / deploy (push) Has been skipped
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>
2026-06-12 12:17:59 +02:00
Dusan Vojacek
2325bbcbd6 Tesla LFP: kapacita 62.5 kWh (bylo 75 = LR) + default cíl 100 %
All checks were successful
CI and deploy / migration-check (push) Successful in 29s
CI and deploy / deploy (push) Has been skipped
Model Y 2025 Standard RWD s LFP: menší pack, ale pravidelné 100 % je žádoucí
(balancování). Kapacita vstupuje do energy_needed a EV usage statistik.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 12:10:45 +02:00
Dusan Vojacek
15d47e8a80 Bazén: sezóna (schedulable), filtrace dle teploty vody, Loxone čidla
All checks were successful
CI and deploy / migration-check (push) Successful in 42s
CI and deploy / deploy (push) Has been skipped
- V092: ems.loxone_sensor + telemetry_loxone_sensor (hypertable) — generické
  čtení Loxone hodnot (poslouží i ohřevu/akumulačce); pool sloupce teplotní
  funkce (ref/base/per_c/min/max) + water_temp_sensor_id
- R__098 fn_pool_daily_runtime_min: clamp(base+per_c×(t−ref)) z poslední
  teploty <24 h, fallback daily_runtime_min; JSON detail pro UI/solver
- collector poll_loxone_sensors: /jdev/sps/io/<name>/state, LL.value parse,
  no-op bez čidel
- sezóna = schedulable přepínač (dokumentováno vč. SQL); hranice filtrace ×
  ohřev TČ (oddělené logiky, sdílí jen čidlo)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 11:47:03 +02:00
Dusan Vojacek
f3eb16892f Milník: Discord bot fáze B (EV tlačítka)
All checks were successful
CI and deploy / migration-check (push) Successful in 21s
CI and deploy / deploy (push) Has been skipped
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 11:41:35 +02:00
Dusan Vojacek
0e7f7b69ae Discord bot fáze B: tlačítka na EV zprávě → patch session + okamžitý replan
All checks were successful
CI and deploy / migration-check (push) Successful in 21s
CI and deploy / deploy (push) Has been skipped
services/discord_bot.py: gateway klient jako lifespan task (spojení ven,
žádný veřejný endpoint; bez DISCORD_BOT_TOKEN tiše spí). Tlačítka
[za 2h][za 4h][ráno][do plna][nenabíjet] s custom_id ev:<site>:<charger>:<akce>
(přežijí restart); whitelist DISCORD_ALLOWED_USER_IDS; akce = fn_ev_session_
apply_patch → run_rolling_replan → export_setpoints → edit zprávy novým plánem.

services/ev_notify.py: sdílený builder souhrnu (vyčleněno z collectoru),
send bot-first s webhook fallbackem. requirements: discord.py>=2.4.
7 testů helperů (parse, deadline akce vč. morning přes Prague TZ).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 11:41:05 +02:00
Dusan Vojacek
08a43aa236 Milník: bazén vizualizace + EV Discord notifikace (fáze A)
All checks were successful
CI and deploy / migration-check (push) Successful in 50s
CI and deploy / deploy (push) Has been skipped
PoolCard na Dashboardu (vw_latest_pool_pump, vw_pool_pump_day_energy, granty),
Discord souhrn po příjezdu EV, docs (discord-ev-interaction, pool-shelly,
ev-charging), gitignore worktrees.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 11:21:00 +02:00
Dusan Vojacek
a7403227c1 gitignore: .claude/worktrees (omylem přibalený embedded repo z git add -A)
All checks were successful
CI and deploy / migration-check (push) Successful in 20s
CI and deploy / deploy (push) Has been skipped
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 10:59:28 +02:00
Dusan Vojacek
29d854f23d Bazén vizualizace + EV Discord notifikace po příjezdu (fáze A)
Some checks failed
CI and deploy / deploy (push) Has been cancelled
CI and deploy / migration-check (push) Has been cancelled
- 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>
2026-06-12 10:59:09 +02:00
Dusan Vojacek
5d2c09401a Vývojová kadence: dev větev (CI bez deploye), merge do main 1×/den/milník
All checks were successful
CI and deploy / migration-check (push) Successful in 21s
CI and deploy / deploy (push) Has been skipped
Tři rychlé pushe dnes = 3 deploye ve frontě a vynechané rolling ticky.
Workflow: dev přidán do validačních větví (deploy zůstává jen main).
Pravidlo + deploy okno v CLAUDE.md Konvencích.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 10:55:15 +02:00
Dusan Vojacek
6671157e8e Pravidla: dokumentace 1:1 s implementací je povinná součást každé změny
All checks were successful
CI and deploy / deploy (push) Successful in 51s
CI and deploy / migration-check (push) Successful in 21s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 10:38:14 +02:00
Dusan Vojacek
ab17e86900 Dokumentace: noc 11.→12. 6. — v2 aktivní, robustnostní trojice, EV forecast, CI opravy
Some checks failed
CI and deploy / migration-check (push) Successful in 16s
CI and deploy / deploy (push) Has been cancelled
- planning-changelog.md: záznam 2026-06-12 (přepnutí na v2, noční polštář /
  PV front-load / denní rampa s tabulkou, EV usage forecast, zimní posouzení)
- planning.md: default PLANNING_ENGINE_VERSION=v2 + sekce robustnosti
- refactor-clean-planner.md: Fáze 3 = v2 AKTIVNÍ
- ev-charging.md: EV spotřební forecast (sběr/statistiky/aktivace)
- consumption.md: bazál odečítá bazén
- deployment-self-hosted.md: tři CI vady + self-install deploy.sh + stop před flyway

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 10:37:20 +02:00
Dusan Vojacek
e0410f9638 v2: denní SoC bezpečnostní rampa — ráno dotáhnout rezervu, pak prodávat
All checks were successful
CI and deploy / migration-check (push) Successful in 30s
CI and deploy / deploy (push) Successful in 1m32s
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>
2026-06-12 10:17:19 +02:00
Dusan Vojacek
2932d48080 v2: PV-risk front-load — nabít v neg okně co nejdřív (nejistota predikce)
All checks were successful
CI and deploy / migration-check (push) Successful in 29s
CI and deploy / deploy (push) Successful in 1m0s
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>
2026-06-12 09:55:22 +02:00
Dusan Vojacek
e464b114b9 v2: noční SoC polštář — placená rezerva na neočekávaný noční nákup
All checks were successful
CI and deploy / migration-check (push) Successful in 34s
CI and deploy / deploy (push) Successful in 1m0s
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>
2026-06-12 09:49:21 +02:00
Dusan Vojacek
4095f0f912 EV spotřební forecast: týdenní rytmus vozidla → target SoC a deadline session
All checks were successful
CI and deploy / migration-check (push) Successful in 19s
CI and deploy / deploy (push) Successful in 56s
Myšlenka uživatele: pondělní služebka ~150 km (~35 kWh) chce skoro plnou,
konec týdne stačí míň, víkend = levné sloty na přípravu pondělka.

- V089: ev_vehicle_obs (odometer+SoC při příjezdu/ODJEZDU — auto v obou
  okamžicích vzhůru, žádné buzení navíc), ev_trip (km z odometru, kWh z ΔSoC;
  nabíjení cestou → charged_away flag), ev_usage_stats per (vozidlo, DOW);
  asset_vehicle: target_soc_forecast_enabled (default false), min_target_soc_pct
- R__096: fn_ev_build_trips (párování), fn_update_ev_usage_stats (job 00:50),
  fn_ev_next_departure (příští typický odjezd, >=4 vzorky, >=3 km),
  fn_ev_required_soc (P80 spotřeby dne + 10 p.b., clamp [min_target, 100])
- R__016: session při příjezdu bere forecast target+deadline (za per-vozidlo
  flagem, fallback defaulty, ruční patch vždy vyhrává) → víkendová session
  s pondělním deadline = v2 solver přirozeně nabije v levných slotech
- tesla_client: + vehicle_state endpoint (odometer v MÍLÍCH → km), collector:
  departure hook, lifespan: job 00:50

Aktivace po nasbírání dat: update asset_vehicle set target_soc_forecast_enabled=true.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 09:06:10 +02:00
Dusan Vojacek
002566ae5f Bazál: odečítat bazénové čerpadlo (telemetry_pool_pump) z baseline učení
All checks were successful
CI and deploy / migration-check (push) Successful in 21s
CI and deploy / deploy (push) Successful in 56s
Pravidlo 15: měřená řízená zátěž nesmí špinit bazální křivku — dosud se
odečítalo jen EV a TČ. Ruční chod čerpadla (vysávání…) i plánovaná filtrace
se nyní přiřazují zařízení, ne bazálu.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 00:27:00 +02:00
Dusan Vojacek
466c15fa84 Bazén: V085→V087 (out-of-order po V086) + seed Shelly Plug S Gen3 home-01
All checks were successful
CI and deploy / migration-check (push) Successful in 16s
CI and deploy / deploy (push) Successful in 1m14s
V088: endpoint shelly_http 172.16.1.15 + asset pool-pump-1 (rated 600 W odhad
— upřesní telemetrie; 480 min/den letní filtrace; schedulable=false =
telemetry-only start, ovládání signálem POOL_PUMP_ON po ověření).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 00:14:15 +02:00
Dusan Vojacek
02c35f8add Merge: bazénové čerpadlo přes Shelly (telemetrie + signal ovládání)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 00:12:43 +02:00
Dusan Vojacek
60176fc7b2 Tesla Fleet API: čtení SoC po příjezdu k wallboxu
All checks were successful
CI and deploy / deploy (push) Successful in 58s
CI and deploy / migration-check (push) Successful in 16s
- 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>
2026-06-11 23:29:24 +02:00