Commit Graph

29 Commits

Author SHA1 Message Date
Dusan Vojacek
fc6d9833a7 feat(ev): geofence arrival trigger (default-off)
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>
2026-06-14 22:55:17 +02:00
Dusan Vojacek
03b7396676 Tesla charge_limit_soc = strop, ne cíl session
All checks were successful
CI and deploy / migration-check (push) Successful in 24s
CI and deploy / deploy (push) Successful in 1m14s
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>
2026-06-13 01:00:13 +02:00
Dusan Vojacek
b08782525e fix(modbus): zadne vecne pending v journalu + flock timeout + EV poll backoff
Zivy incident home-01 (TeltoCharge .16): zapis 15/19-20 koncil failed
s prazdnym error_msg, nebo zustal trvale pending a zablokoval exportni ticky.

- _gateway_exclusive: neblokujici flock s deadline (EMS_MODBUS_FLOCK_TIMEOUT_S,
  default 20 s) -> GatewayLockTimeout misto starvation bez limitu
- execute_modbus_commands: invariant written/failed + neprazdny error_msg
  (str(e) or repr(e)); safety net pres BaseException (CancelledError, chyba DB);
  journal update mimo retry cyklus zarizeni; force_disconnect bez zamku brany
- telemetry poll_ev_chargers: po 3 selhanich backoff 5 min per (host,port,unit)
  - mrtvy unit_id drzi branu 4x8=32 s z kazde minuty
- testy backend/tests/test_modbus_execute_failsafe.py; docs
  modbus-command-journal.md (sekce Robustnost zapisu + konfigurace)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 00:17:04 +02:00
Dusan Vojacek
26013e229b fix: defrost MIM — 0xFF znamená OFF (dopatch k e2688bb)
All checks were successful
CI and deploy / migration-check (push) Successful in 14s
CI and deploy / deploy (push) Successful in 47s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 21:41:01 +02:00
Dusan Vojacek
4ff5f7c3eb HOTFIX: poll_inverter SELECT bez deye_zero_export_mode — KeyError zastavil inverter telemetrii všech lokalit
All checks were successful
CI and deploy / migration-check (push) Successful in 34s
CI and deploy / deploy (push) Successful in 1m10s
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>
2026-06-12 21:01:31 +02:00
Dusan Vojacek
d8f6de77d5 home-01: ulice z externího CT (reg 619) + celková spotřeba domu; Deye zero-export to CT
All checks were successful
CI and deploy / migration-check (push) Successful in 19s
CI and deploy / deploy (push) Successful in 1m5s
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>
2026-06-12 20:24:56 +02:00
Dusan Vojacek
5530253662 EV arrival hold: po detekci píchnutí okamžitě 0 A — nabíjení spouští až plán
All checks were successful
CI and deploy / migration-check (push) Successful in 28s
CI and deploy / deploy (push) Successful in 1m15s
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>
2026-06-12 19:52:10 +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
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
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
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
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
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
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
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
Dusan Vojacek
0ed6f18e1a EV řízení: zápis Amps-to-use přes journal + watchdog + okamžitý replan po příjezdu
Some checks failed
CI and deploy / migration-check (push) Successful in 39s
CI and deploy / deploy (push) Failing after 9m55s
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>
2026-06-11 22:51:38 +02:00
Dusan Vojacek
733224d18d Collector: poll_pool_pumps — 1min telemetrie Shelly bazénu
- 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>
2026-06-11 22:37:57 +02:00
Dusan Vojacek
5239463699 EV telemetrie: skutečné čtení Teltonika TeltoCharge (konec stub-u)
Some checks failed
CI and deploy / migration-check (push) Failing after 23s
CI and deploy / deploy (push) Has been skipped
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>
2026-06-11 22:10:46 +02:00
Dusan Vojacek
dede8d604d fix cutoff a grid peak shaving register
Some checks failed
CI and deploy / migration-check (push) Failing after 13s
CI and deploy / deploy (push) Has been skipped
2026-04-29 13:36:38 +02:00
Dusan Vojacek
342483b885 invert logic cutoff register
Some checks failed
CI and deploy / migration-check (push) Failing after 14s
CI and deploy / deploy (push) Has been skipped
2026-04-29 13:24:28 +02:00
Dusan Vojacek
c928e2234d Implement telemetry enhancements: add reading of Deye registers 145 and 179 in telemetry collector to derive is_export_limited and pv_derating_flags. Update fn_telemetry_inverter_sample to store these flags, and adjust related documentation and API endpoints accordingly.
Some checks failed
CI and deploy / migration-check (push) Failing after 19s
CI and deploy / deploy (push) Has been skipped
2026-04-22 23:02:14 +02:00
Dusan Vojacek
93f883f5e0 sql first refactor
Some checks failed
CI and deploy / migration-check (push) Successful in 5s
CI and deploy / deploy (push) Failing after 20s
2026-04-19 20:02:20 +02:00
Dusan Vojacek
806274cf59 uprava adutiu - nacitani dalsich registru, uprava ekonomiky
Some checks failed
deploy / deploy (push) Failing after 1m15s
test / smoke-test (push) Successful in 2s
2026-04-10 21:53:32 +02:00
Dusan Vojacek
920d9ff40c fix pv vyroby (unsinged)
All checks were successful
deploy / deploy (push) Successful in 35s
test / smoke-test (push) Successful in 7s
2026-04-10 20:30:03 +02:00
Dusan Vojacek
182d5a37e1 third version before modbus cleanup 2026-04-03 16:03:06 +02:00
Dusan Vojacek
9f4126946d second version 2026-04-03 14:23:16 +02:00
Dusan Vojacek
897b95f728 x 2026-03-20 14:30:03 +01:00