Decision Log
Chronologický záznam klíčových rozhodnutí a závěrů pro lepší kontext v budoucích konverzacích.
Patří sem trvalá rozhodnutí, důležité trade-offy, omezení a lessons learned z incidentů nebo změn. Nepatří sem backlog, wishlist ani plánované změny, které ještě nejsou rozhodnuté nebo realizované.
2026-07-23 — Scrypted přesunut na pmx2; chronické replikační timeouty byly CPU hlad, ne ZFS
Kontext
GH #87 hlásil opakované selhání replikace VM 105 (zfs snapshot ... got timeout) a pbs-truenas: 500 read timeout. Issue směřovalo vyšetřování na ZFS, PBS a TrueNAS.
Zjištění
- Všechny obviněné komponenty byly zdravé:
rpoolONLINE (20 % plný, 0 chyb, žádné zamrzlé__replicate__snapshoty), TrueNAS pooly ONLINE, PBS datastore dostupný. Klíčový ukazatel: IO pressure = 0, zatímco CPU pressure ~60 % a load ~11 na 12 jádrech. - Příčina: Scrypted (LXC 106) dělal AI detekci objektů na CPU. CT 106 spotřeboval ~50× víc CPU než zbytek uzlu. Timeouty padaly vždy v :30, kdy se replikační job sečetl s trvalou zátěží a
zfs snapshotnestihl svůj tvrdý interní timeout. VM 105 byla oběť, ne zdroj. Chronické: 2–11× denně po 7 dní. - OpenVINO na AMD iGPU neakceleruje — slepá ulička.
@scrypted/openvinoje Intel framework (Intel CPU/iGPU/NPU). Oba uzly jsou AMD, takže inference běží čistě na CPU bez ohledu na to, že je iGPU passnutá. Passthrough/dev/dri/renderD128má smysl jen pro hardwarové dekódování videa (VAAPI), ne pro detekci. Nezkoušet to znovu rozchodit — nejde to.
Rozhodnutí
- CT 106 migrován pmx1 → pmx2. NFS bind mount
/mnt/pve/nvr-truenasoznačenshared=1(věcně správné — stejný export na obou uzlech, odblokuje migraci), offline ZFS send ~7,5 G / 1:16. Opraven chybný passthroughcard0→card1(oba hosty majícard1/226:1). - Vědomá revize rozmístění z 2026-07-06, kde byl Scrypted záměrně na pmx1 a pmx2 vyhrazen pro pfSense + HA. Nové okolnosti: (a) chronické CPU zahlcení pmx1, (b) Scrypted drží zvonek, což ho řadí mezi kritické služby, ne mezi „ostatní". Původní rozhodnutí tuhle roli nezohledňovalo.
cpuunits: 50na CT 106 jako pojistka co-rezidence s korunními klenoty — pod tlakem ustoupí pfSense/HA, ale když je volno, nic ho neomezuje (detekce zůstává plnorychlá). Hard cap by zbytečně zhoršil detekci.- Coral TPU zvažován a zamítnut. Spotřebu neospravedlní (3/4 roku běží dům z FTV, baterka kryje slabší dny), hluk není vnímán, další kamery se neplánují, a pmx2 má obrovskou rezervu. Přehodnotit jen při: přidání kamer navzdory plánu, nebo když se změřený inference time ukáže jako příliš vysoký (≳300 ms/snímek). Pokud se pro Coral někdy rozhodne, volit USB, ne M.2 — M.2 varianta tahá
gasketDKMS modul, který se rozbíjí při upgradech Proxmox kernelu; USB jede přeslibedgetpuv userspace bez kernel modulu.
Výsledek
pmx1 load 11,4 → 0,15, CPU pressure 60 % → 0,00 %. Replikace 105-0 prošla čistě (FailCount 0, 1,85 s). Žádné timeouty od migrace. GH #87 uzavřeno.
Reziduální riziko
Při údržbě pmx2 se Scrypted logicky vrátí na pmx1 a problém se ten den vrátí s ním. Řešit vypnutím Scryptedu po dobu údržby, ne hardwarem.
Vedlejší nález: NVR si retenci řídí sám
archive/nvr prořezán 3,09 T → 2,83 T bez zásahu → alert „Refquota exceeded 89,8 %" byl důsledek záměrně těsné kvóty, ne hrozby zaplnění. Dotažena fáze 2: refquota 3,15 T → 2,90 T. Do budoucna nečíst vysoké procento na archive/nvr jako incident.
2026-07-23 — pmx1 běží horko; teploty se nikde neměří (podezření u smrti starého pmx2)
Zjištění
Při diagnostice #87 se ukázalo, že teploty uzlů se nesbírají ani nealertují — lm-sensors není nainstalovaný, ačkoli k10temp data poskytuje. Ruční odečet odhalil rozdíl, který nešel ignorovat:
| pmx2 (ASUS PN54-S1) | pmx1 (no-name) | |
|---|---|---|
| load | 0,95 | 0,69 |
| Tctl | 59 °C | 81 °C |
| DMI | ASUSTeK / ELM_PN54_S1 |
nevyplněné placeholdery |
pmx1 je při nižší zátěži o 22 °C teplejší než pmx2. Vzorkování po 3 s ukázalo setrvalý růst 62 → 80 °C při pouhém load 0,42 → 0,70 — teplotní křivka extrémně citlivá na minimální zátěž. Před odlehčením nesl pmx1 Scrypted (4 jádra inference 24/7) týdny → reálně seděl u TjMax nonstop.
Hypotéza (nedokázaná — a to je pointa)
Starý pmx2 byl no-name mini PC se stejným CPU Ryzen 5 7430U, umřel 2026-07-05 náhlou smrtí desky bez shutdown sekvence (zdroj vyloučen výměnou adaptéru) — a hostoval tehdy právě Scrypted. Kombinace levné šasi + trvalá inference 24/7 + doložitelně marginální chlazení je konzistentní s tepelným/VRM úmrtím. Dokázat to nejde, protože teplotu nikdo neměřil — a přesně to je důvod, proč monitoring zavést.
Rozhodnutí
- Zavést teplotní monitoring pmx1 + pmx2 (
lm-sensors→ Grafana, alert na trvale >85 °C). Zapsáno dotodos.md. - Fyzická údržba pmx1 (prach, teplovodivá pasta) je doporučená, ale až po zavedení monitoringu — jinak nebude s čím porovnat, jestli zásah pomohl. Postup: nejdřív neinvazivně profouknout a ověřit, že ventilátor točí; teprve pak otevírat, a jen s pastou po ruce. Časovat na klidnou chvíli (dům běží — klenoty jsou na pmx2 — ale pmx1 je DR cíl a nese PBS).
- Ponaučení pro budoucí rozmisťování: trvalá CPU zátěž (AI inference, transcoding) nepatří na levné no-name šasi bez měření teplot. Pokud pmx1 i po vyčištění zůstane výrazně tepleji než pmx2 při srovnatelné zátěži, jde o konstrukční limit chlazení → zvážit, jestli má takový stroj držet DR roli celého domu.
2026-07-24 — QDevice arbiter na TrueNAS živý; ha-manager odemčen
Rozhodnutí a provedení
Dokončen QDevice (3. quorum hlas) pro 2-node cluster — rozdělaný Incus CT qnetd na TrueNAS dotažen do provozu:
- Statická IP
192.168.20.23natvrdo v kontejneru (systemd-networkd) jako autoritativní zdroj, + DHCP rezervace na pfSense pro úplnost přehledu. Konvence: kritická infra (pmx nody, quorum device, switche) = statická IP v zařízení; pfSense rezervace jen jako dokumentace/pojistka. Nody i qnetd tak nezávisí na DHCP při bootu. corosync-qnetd+ sshd na qnetd, root klíče pmx1/pmx2 →pvecm qdevice setup 192.168.20.23 -f.- Výsledek: expected votes 2 → 3, Flags: Quorate Qdevice.
Dopad
- Kterýkoli PVE node teď může spadnout bez ztráty kvóra (přeživší 1 + qdevice 1 = 2 ze 3). Tím padá blocker rebootu pmx1 (dist-upgrade) i prerekvizita ha-manageru.
- Caveat: arbiter běží na TrueNASu. Když spadne TrueNAS sám, nody drží 2/2 = OK. Ztráta kvóra hrozí jen při dvojitém výpadku (TrueNAS + jeden node současně) — přijatelná hrana.
- Proč to nezavádí kruhovou závislost na pfSense: corosync i qdevice komunikují po L2 na VLAN 20 (přímo mezi nody + arbiter), nerouteují se přes pfSense; nody i qnetd mají statické IP. Výpadek pfSense (VM 100) proto neshodí kvórum — to je zároveň důvod, proč je qnetd staticky.
Follow-up: ha-manager (odemčeno)
Zapnout ha-manager pro pfSense (100) + HA (102) + debian-services (107) je teď proveditelné. Chce: ověřit funkční watchdog/fencing na obou nodech, ověřit replikaci 107, přijmout RPO = poslední replika (à 90 min, pro tyto workloady OK) a ~2–3 min automatický failover. Řeší přesně failure mode z 2026-07-05 (náhlá smrt nodu → dnes ruční DR). Samostatná řízená akce vč. failover testu.
2026-07-24 — PBS zůstává VM v clusteru (re-potvrzeno živými daty); TrueNAS jako kandidát na kompletní HW výměnu
Re-potvrzení rozhodnutí z 2026-07-06
Otázka „přesunout/replikovat PBS na TrueNAS" znovu zvážena — rozhodnutí „PBS zůstává VM v clusteru" platí, živá data ho posilují:
- Data PBS už na TrueNASu jsou — datastore
tank/pbs-data(275 G) leží na TrueNAS datasetu; VM 105 je jen výpočetní skořápka, co ho mountuje. Na datové úrovni tedy není co „přesouvat", a kruhová závislost je už rozbitá: cluster umře → zálohy na TrueNASu přežijí → PBS se rozjede kdekoli a datastore připojí (viz DR postup). - TrueNAS nemá RAM nazbyt (hůř než v červenci): 7,6 GB total, 588 MB free, ARC uškrcený na 1,1 GB. 4GB PBS VM by ARC rozdrtila a degradovala všechny storage služby (NVR, NFS, Immich media, i PBS datastore). Přesně ta ARC starvation z 2026-07-06.
- QDevice + ha-manager to otáčí: PBS jako cluster VM je teď bezpečnější (auto-failover), ne rizikovější.
TrueNAS HW
Uživatel zamítl RAM upgrade TrueNASu (NUC8i3BEH, 8 GB/2C-4T) ve prospěch úvahy o kompletní nové TrueNAS krabici. Zapsáno jako otevřená úvaha (todos) — memory-tight stav (588 MB free, ARC 1,1 GB) je i tak signál, že current box je na hraně. Breakpoint pro PBS-na-TrueNAS se otevře až s výrazně větší RAM; do té doby PBS zůstává v clusteru.
2026-07-24 — HW roadmapa: konsolidovaný reshuffle (cíl H1 2027, hradlem je cena RAM)
Nahrazuje dřívější dílčí úvahy (náhrada pmx1, nový TrueNAS) jedním plánem. Cíl uživatele: udělat to celé do ~půl roku, aby byl fleet čistý. Trigger fáze 2 = návrat cen RAM.
Kontext: RAM/NAND krize (mid-2026)
DDR5 +110 %, chipy ~4× dráž, vrchol teď, návrat cen až Q4 2027+. Konkrétně (Mironet, 2026-07-24): Crucial 32GB (1×32GB) DDR5-5600 SODIMM = 8 863 Kč a vyprodáno — jeden modul = cena celého mini PC. Ověřeno, že žádná krabice ve fleetu nemá DDR5 k přesunu: pmx1 = 2×16GB DDR4-3200, TrueNAS = 8GB DDR4, pmx2 má DDR5 ale v provozu. → jakýkoli nový node s DDR5 je teď fakticky nekoupitelný/předražený.
Fáze 1 — teď (RAM krize): nic s DDR5
- Thermal pmx2 (Scrypted, 72–82 °C, alert 88, Tjmax ~95 — monitorováno, ne havárie) řešit buď USB Coral (~2000 Kč, nula RAM), nebo jen jet na Grafana monitoringu. USB Coral pro Scrypted není dev-preferovaný (TF-Lite plugin, „lesser performance"), ale na 6 kamer stačí; je to jediná cesta, co neplatí vrchol cen RAM.
- Žádné node nákupy.
Fáze 2 — cíl H1 2027 (až RAM zlevní): reshuffle
- M1 Plus (Minisforum, Mironet ~8 837 Kč barebone, 3letá záruka): i5-12600H 12C/16T, Iris Xe (silný OpenVINO target → Scrypted detekce na iGPU = Scrypted-ideál, Coral tím odpadá), 2× DDR5 SODIMM až 96 GB (nepájená), 2× 2.5GbE, 1× M.2, USB4/WiFi6E → nový pmx1. Kup barebone; DDR5 (Crucial 32GB, ~8 863 Kč — začít 1×32, druhý slot na později) až v 2027. Tradeoff: i5-12600H je 45W třída (teplejší než N100), ale detekce na iGPU drží CPU load nízko + je to řádně chlazený kus + monitoring teplot už běží.
- Starý pmx1 (Ryzen 5 7430U, 32 GB DDR4) → nový TrueNAS. Jeho 32 GB (vs. dnešních 8) opraví ARC starvation; jako NAS (nízký CPU) poběží chladně → thermal strach mizí. DDR4 sedí.
- Disky:
archive(4TB WD Purple) je na USB → triviálně přepojit na nový TrueNAS.tank(1TB Intel 660p NVMe) → do M1 Plus jako rpool; POZOR: tím zaniká pooltank→ předem naplánovat migraci PBS datastore (tank/pbs-data, 275 G) + app-data (nginx/grafana/ loki NFS) + VM storage. To je jádro celé operace, ne swap disku. - Retire NUC8i3BEH (8GB, nejslabší článek).
- Nekupuje se disk ani nový TrueNAS box — reuse existujícího HW obchází i nafouknuté ceny NAND.
Zamítnuté varianty (kontext)
Nvidia (jen kvůli LLM, ten jde na samostatný Mac Mini); Lunar Lake / MSI Cubi NUC AI (RAM v pouzdře, 32 GB strop); N100/N-series jako pmx1 (1× SODIMM nebo slabý CPU — není peer pmx2); RAM upgrade současného TrueNASu (řeší se reshuffle-em zdarma); PBS na TrueNAS (viz samostatný záznam výše).
2026-07-24 — Směr náhrady pmx1: Intel Arc iGPU (ne Nvidia, ne Lunar Lake); LLM na samostatný Mac Mini
Poznámka 2026-07-24: konkretizováno a nahrazeno záznamem „HW roadmapa: konsolidovaný reshuffle" výše (M1 Plus = ten Intel iGPU box; Coral jen fáze 1). Tento záznam ponechán pro kontext úvahy.
Kontext
Diagnostika #87 odhalila, že pmx1 běží horko (81 °C, no-name kus, sesterský kus umřel) a že detekce dře na CPU (OpenVINO na AMD neakceleruje). Otevřela se otázka náhrady pmx1 za stroj s GPU akcelerací.
Rozhodnutí (směr, ne konkrétní kus)
- Intel s Arc iGPU je zvolený směr. Pro tenhle workload mix (Scrypted detekce + Immich ML + Jellyfin transcode) vyhrává nad Nvidia: nativní OpenVINO (Scrypted detekce s nulovou migrací — přesně to, co je na AMD slepá ulička), QuickSync pro Jellyfin, OpenVINO i pro Immich ML, in-kernel i915/xe driver bez DKMS (stejný argument, proč jsme zavrhli M.2 Coral), passthrough přes renderD128 jako dnešní iGPU.
- Nvidia zamítnuta. Jediná osa, kde vyhrávala, byl lokální LLM (CUDA). Ten padá na samostatný Mac Mini (Apple Silicon je na LLM efektivnější a odděluje compute od kritické infra) → z úvah o pmx nodu LLM mizí, a s ním důvod pro Nvidia (DKMS driver, větší/hlučnější skříň, migrace Scryptedu na ONNX/CUDA).
- Lunar Lake (MSI Cubi NUC AI, Core Ultra 7 258V) zamítnut — RAM v pouzdře CPU, 32 GB strop navždy (už zamítnuto 2026-07-06 pro klenoty; pro workhorse+DR roli je to bez LLM sice mírnější, ale nulová trvalá rezerva a žádný upgrade = zbytečné riziko). Preferovat model s SODIMM (Meteor/Arrow Lake mini PC s Arc iGPU) → cesta na 64 GB. NPU Lunar Lake není potřeba — na OpenVINO detekci stačí Arc iGPU.
Priorita a hranice
- Není urgentní. #87 je vyřešený přesunem Scryptedu na pmx2; detekce tam běží na CPU s rezervou. Pořadí kroků: repasta/vyčištění pmx1 ≫ (případný Coral USB jen na detekci) ≫ nový box.
- Coral vs box = falešná volba — řeší různé problémy. Coral (USB, ~1500 Kč) sundá jen detekci z CPU, neřeší teplo pmx1 ani transcode/Immich. Box řeší vše, ale je to projekt + výdaj. Kupovat teď ani jedno — detekce netlačí, pmx1 nejdřív repasta.
- Konkrétní kandidáti + živé ceny → samostatná
storm-researchsession (zapsáno v todos).
2026-07-23 — Klima: idle ventilátor se nechává běžet; „fan OFF při thermo-off" neprůchodné
Kontext
Otázka: když Daikin po dosažení setpointu odpojí kompresor (thermo-off), vnitřní jednotka dál točí ventilátorem (míchá vzduch + měří return-air teplotu). Přání bylo ventilátor v tu chvíli úplně zastavit — primárně kvůli hluku.
Zjištění
- Fan-off při thermo-off je na Daikinu field setting jednotky, ne runtime registr. Náš Modbus gateway (EKMBDXA/EKMBDXB) exponuje jen runtime (on/off, mode, setpoint, rychlost/směr ventilátoru) — field settings v mapě nejsou (ověřeno proti manuálu 4P357732-1).
- Field setting nejde pohodlně změnit. Všech 10 jednotek je vestavěných (FXSQ podhledové, FXNQ parapetní) a žádná Madoka není nainstalovaná — jediná ovládací plocha je HA přes Modbus. Změna field settingu by znamenala buď otevírat zabudované jednotky k PCB, nebo instalatérem dočasně nabusovat ovladač na F1/F2 každé jednotky. Není to zásah „na zavolání".
- Fan-off by navíc oslepil return-air čidlo jednotky (stojatý vzduch pod stropem) → vynutil by si externí čidlo pro řízení. Wall-thermostat řízení jde jen softwarovým bang-bangem v HA.
Rozhodnutí
- Klima control se nechává as-is — jednotky v thermo-off drží ventilátor běžet (záměr výrobce; na modulačním VRV je to šetrnější než softwarové power-cycling, které maří inverter modulaci a přidává cyklovací opotřebení + overshoot přes anti-short-cycle timery outdooru).
- Softwarový bang-bang (generic_thermostat + power switch + nástěnný termostat) se nestaví. Zvažováno, zamítnuto: energeticky se nevyhraje (úspora = jen ventilátor, řádově desítky W/jednotka), na VRV kontraproduktivní. Kdyby se přání vrátilo, prototypovat na jedné jednotce (ložnice), ne plošně.
- Jediná dostupná páka na hluk = rychlost ventilátoru přes Modbus, a ta je už vytažená naplno — fan speed 1 všude a natrvalo. „Nechat as-is" tedy není rezignace, ale stav bez dalšího dostupného kroku.
Follow-up (jen kdyby)
Kdyby u jednotek někdy byla Madoka na sběrnici (servis, rozšíření), fan-off field setting se stává proveditelným zadarmo — dá ticho bez cyklování. Do té doby neřešit.
2026-07-22 — DALI tlačítka: kanonická je vrstva spárovaných vypínačů v komponentě; ButtonManager končí
Zjištění
Dokumentace tlačítek žila ve dvou rozporných světech: provozní stránky popisovaly AppDaemon (FoxtronSceneController + ButtonManager) jako současnost, pět design dokumentů popisovalo nikdy nerealizovanou ButtonManager/Room vizi — a skutečný stav (custom komponenta ha-foxtron-dali skládá gesta, páruje fyzické vypínače jako HA zařízení s device triggery a eventem foxtron_dali_button_action) nebyl zdokumentovaný vůbec. Audit komponenty navíc odhalil, že foxtron_dali_button_action se kvůli bugu v parsování mapování instancí reálně nikdy nestřílel (opraveno 2026-07-22 v repu komponenty) — proto si nikdo nevšiml, že device triggery nefungují.
Rozhodnutí
- Kanonická identita vypínače = spárované zařízení v HA registru (komponenta, identifier
dali4sw_<bus>_<addr>_<up>_<low>), eventsfoxtron_dali_button_action(device_id/flap/press_type) pro HA automatizace, legacyfoxtron_dali_button_eventzůstává pro AppDaemon. - AppDaemon
button_manager(+buttons.yaml,check_buttons.py) se odstraní — jediný konzument (zvonek, dvojklik nahoře → otevření branky) se přepne na nativní event; do té doby běží obojí. ButtonManager/Room design dokumenty přesunuty dodocs/chytry_dum/archiv/s bannerem. FoxtronSceneControllerzůstává — živá logika světel, v souladu s rozhodnutím 2026-06-17 (AppDaemon zachovat). Migrace scénové logiky do HA automatizací není na stole.- Provizorní spárovaná zařízení přejmenována (
Vypínač <Místnost> <upřesnění>) a přiřazena do areas; nalezen duplikát WC (spárován 2× ve starém i novém formátu) a jeden neidentifikovaný vypínač (bus 21_23, addr 1) — viz todos.
2026-07-22 — Floorplan: pojmenované SVG polygony jako geometrický zdroj pravdy, pozice v dashboardu jako zdroj pravdy rozmístění
Rozhodnutí
- Půdorysy = čisté SVG (
www/floorplan/1np.svg,2np.svg), každý polygon místnosti neseid(unikátní prostor) adata-area(HA area). Generujescripts/floorplan_build.pyz Inkscape overlay zdrojáků (~10 MB, drženy mimo repo — skript je bere jako argument). Rozdíly polygon vs. area vědomě:bazen_wc/bazen_technologie→ areabazen(hrubý area model dle 2026-06),schodiste(2NP) → areahala. - Pozice prvků v
dashboards/pudorys.yaml(picture-elements,top/left%) = zdroj pravdy fyzického rozmístění světel, rolet a vypínačů. Slouží dashboardu i budoucí blízkostní analýze (vypínač→roleta: primárně stejná area/polygon, blízkost jen jako disambiguace uvnitř místnosti). Vypínače v dashboardu jsou pasivní ikony stitle= jméno spárovaného zařízení (nejsou to entity).
2026-07-20 — Celodomovní blokování reklam: Unbound forwarding přes DoT na AdGuard DNS (+ DNS4EU fallback)
Zjištění
Unbound na pfSense běžel jako čistý rekurzivní resolver — DNS4EU servery (86.54.11.211/.11, filtrovaná varianta) zapsané v General Setup se pro klientské dotazy vůbec nepoužívaly (žádná forward-zone). Dům tedy do této změny neměl žádné DNS blokování reklam, přestože konfigurace vypadala, že ano. Docs (firewall.md) navíc spekulovaly „pravděpodobně Cloudflare" — nikdy neověřeno proti živému stavu.
Rozhodnutí
Unbound přepnut do forwarding módu s DNS-over-TLS (ověření certifikátu přes TLS hostname):
- AdGuard DNS Default
94.140.14.14+94.140.15.15(dns.adguard-dns.com) — primární, blokuje reklamy a trackery. Vědomě zvolena Default varianta (ne Family) — platí pro celý dům. - DNS4EU Protective + Ad Blocking
86.54.11.13(noads.joindns4.eu) — třetí upstream jako nezávislý evropský fallback se stejnou politikou. - DNSSEC ponechán zapnutý (oba provideři podporují). Host overrides
*.marada.nameforwarding neovlivňuje.
Trade-offy
- Fallback není strict primary/backup — Unbound RTT-balancuje mezi všemi třemi upstreamy, část dotazů jde na DNS4EU i za normálu. Akceptováno: oba blokují reklamy, výpadek jednoho providera dům nepoloží.
forward-first(auto-návrat k rekurzi) pfSense GUI nepodporuje — custom-options hack zamítnut (KISS). - False positive filtru = rozbitá stránka; řešení: Host Override, nebo vypnout Enable Forwarding Mode (návrat k nefiltrované rekurzi). Bez self-hosted AdGuard Home není per-doména whitelist — vědomě přijato, žádná nová služba.
- Zařízení s hardcoded DNS (typicky IoT) filtr obcházejí — follow-up v todos.
Provedení
Config zapsán přes SSH + PHP (config_set_path → write_config → services_unbound_configure); automatický backup v config history (Diagnostics → Backup & Restore) = rollback cesta. Ověřeno: forward-zone s @853#hostname, aktivní TLS spojení na :853, doubleclick.net → 0.0.0.0, normální domény i lokální overrides OK. Při tom opravena chyba doc_gen_pfsense.py (boolean <forwarding> je prázdný tag — čte se přítomnost, ne hodnota).
2026-07-06 — Nový pmx2 v provozu: join, migrace klenotů, replikace 90 min
Rozhodnutí
Nový uzel (ASUS PN54-S1) nainstalován a připojen do clusteru jako pmx2 (192.168.20.3, PVE 9.2.4, ZFS rpool, ashift 12, ARC limit ~2,8 GB). Rozmístění: korunní klenoty pfSense (100) + HA (102) běží na pmx2 (novější/spolehlivější HW), pmx1 nese unifi/PBS/scrypted/immich (+win11 trvale off). Do budoucího ha-manageru půjdou jen pfSense + HA + debian-services (debian přidán ještě týž večer — nginx na něm nese externí přístup ha.marada.name); scrypted/unifi/immich vědomě mimo HA i mimo replikaci (PBS restore stačí — rozhodnutí uživatele). Malá HA množina = failover se vejde do RAM přeživšího uzlu (trojice na pmx1 je těsná ~29/30 G; nouzový ventil = stopnout Immich) a minimální fencing blast radius. Replikace: 100/102 pmx2→pmx1, 105 (PBS) pmx1→pmx2, vše à 90 min (ne 15 — RPO zisk je u tohoto workloadu kosmetický: HA po startu stejně re-polluje stav, pfSense config se skoro nemění; opotřebení disků s frekvencí nesouvisí, replikují se jen delty). Inkrementální sync potvrzen: 26 s.
Zjištění (limity infrastruktury)
- USW-48-PoE je 1GbE — dual 2.5GbE porty na PN54 jsou bez 2.5G switche/přímého kabelu k ničemu.
- SSH cipher strop ~60 MB/s (single-core) → replikace/migrace reálně ~30 MB/s. Mitigace k zvážení:
migration: type=insecurev datacenter.cfg, přímý kabel, nebo nechat být (delty jsou malé). Viz todos. - Verze: no-subscription repo dal 9.2.4, pmx1 má 9.1.9 — join v rámci major 9 OK; pmx1 se dožene bezvýpadkově (klenoty teď běží na pmx2, reboot pmx1 ničemu nevadí).
- Kvórum: expected 2 → smrt uzlu = ztráta kvóra, dokud není QDevice. QDevice je proto prerekvizita ha-manageru, ne nice-to-have.
Lekce z migrace (agentův fail)
qm migrate zdědil bwlimit 10 MB/s ze stale replikačního jobu → vypadal zaseklý; agent ho chybně prohlásil za mrtvý a smazal rozpracovaný disk na cíli → migrace odsouzena, nutný čistý restart. Postup příště: u „zaseklé" migrace nejdřív ps (zfs send/recv, cstream throttle) a změřit progress (zfs get referenced 2× po sobě), teprve pak zasahovat. Dlouhé migrace pouštět nohup ... & na uzlu, ne přes drženou SSH session. Druhý pokus: „46 GB" byla iluze (thick rezervace + snapshoty; reálná data 8,6 G), downtime 32 ms (HA) / neznatelný (pfSense).
Operační dopad
- vzdump job 21:00 automaticky následuje guesty po migraci — ověřeno: denní řada záloh nepřerušená vč. dne incidentu.
- Storage zůstává thick (thin zamítnut: overcommit=freeze-pool riziko výměnou za úsporu, kterou při 18% zaplnění nepotřebujeme).
- Mosquitto běží jako HA add-on (192.168.20.7:1883), ne na debian-services — opravena stale informace v memory.
- Immich: z mrtvého pmx2 přežily jen fotky (7438 ks / 2,6 G, TrueNAS
archive/stash/immich-import); DB/metadata pryč — akceptováno. Nový CT 104 na pmx1 = experiment: fresh Docker deploy (v3.0.1), vědomě bez replikace a mimo backup job.
2026-07-06 — PBS zůstává VM v clusteru (TrueNAS hosting zamítnut)
Rozhodnutí
PBS (105) zůstává jako VM v Proxmox clusteru se ZFS replikací na druhý uzel. Přesun na TrueNAS (řešil by kruhovou závislost zálohovacího serveru na zálohovaném clusteru) zamítnut.
Důvod
TrueNAS box (NUC8i3BEH) má jen 8 GB RAM a 2 jádra — 4GB PBS VM by vyhladověla ZFS ARC. Kruhová závislost je dostatečně mitigována replikou PBS na druhý uzel (incident 2026-07-05 potvrdil: PBS obnoven z repliky během minut) + datastore na TrueNAS přežívá smrt clusteru tak jako tak. Na TrueNASu zůstává rozdělaný qnetd kontejner pro QDevice (viz todos).
2026-07-06 — Náhrada pmx2: ASUS ExpertCenter PN54-S1 (S70016AL)
Rozhodnutí
Mrtvý pmx2 (no-name mini PC, Ryzen 5 7430U) nahradí ASUS ExpertCenter PN54-S1-S70016AL — Ryzen 7 260 (Zen4), 32 GB DDR5 SODIMM, 1TB NVMe, dual 2.5GbE, ~24 000 Kč.
Důvod
Vybíráno z ~10 kandidátů. Rozhodly parametry podstatné pro virtualizační uzel, ne špičkový CPU výkon: 2× SODIMM (cesta na 64 GB — po výpadku musí jeden uzel občas unést všechno), dual 2.5GbE, 2× M.2 (možnost ZFS mirror), AMD (homogenita s pmx1 pro cpu: host migrace) a business QC/servis po zkušenosti s umřelým no-name kusem. Zamítnuto: Beelink SER9/SEi13 (pájená RAM / starý mid-range Intel, předražené), Lenovo IdeaCentre 01Q8X10 (Snapdragon = ARM, Proxmox x86-only), Acemagic F1A (QC, malware skandál 2024), MSI Cubi NUC AI+ i ASUS NUC 14 Pro AI (Lunar Lake = 32 GB RAM on-package bez upgradu), PN54 s Ryzen AI 7 350 (+9k za NPU/Zen5, které headless uzel nevyužije).
Operační dopad
Po doručení: PVE 9 + ZFS, join do (nyní jednouzlového) clusteru, obnova replikací, návrat VM. Migrovatelným VM nastavit cpu: x86-64-v3 — cpu: host migrace Zen3→Zen4 projde jen jedním směrem. Kroky v todos.md.
2026-07-06 — Výpadek pmx2 (HW smrt) — obnova HA/PBS z ZFS replik na pmx1
Příčina
pmx2 (mini PC) 5. 7. ve 23:32 náhle zhasl — v syslogu žádná shutdown sekvence, jen konec běžné replikační SSH session (23:30) a pak ticho. Test výměnou napájecího adaptéru z pmx1 zdroj vyloučil → mrtvý hardware (deska/„něco uvnitř").
Důsledky
Down: HA (102), PBS (105), Immich (104), Scrypted (106), Jellyfin (110). Cluster ztratil kvórum (2 reálné uzly → 1 hlas ze 2), pmxcfs na pmx1 read-only. Druhá vlna 6. 7. ráno: test zdroje = reboot pmx1 → pvecm expected 1 reboot nepřežije → bez kvóra nenastartovala žádná VM včetně pfSense → celý dům bez sítě, nutný zásah z fyzické konzole.
Oprava
pvecm expected 1→mvconfigů 102/105 z/etc/pve/nodes/pmx2/qemu-server/na pmx1 → start z ZFS replik. Poslední replika 23:30:05, crash 23:32 → RPO ~1 minuta (šťastné načasování 90min intervalu).- Replikační joby 100-0/102-0/105-0 disabled (cíl mrtvý, spamovaly by chyby).
pvecm delnode pmx2→ jednouzlový cluster, expected=1 trvale, reboot přežije. Configy LXC 104/106/110 zálohovány na pmx1:/root/pmx2-configs-backup-20260706.
Lessons / follow-up
- DR runbook měl díru: předpokládal jen
qm startz repliky, ale bez kvóra je pmxcfs read-only a config VM „patří" mrtvému uzlu. Doplněno dodisaster_recovery.md(kvórum + mv configu). pvecm expected 1není perzistentní — po každém rebootu znovu, dokud je cluster degradovaný. Trvale řeší až delnode (teď) / QDevice (budoucnost).- Dvouuzlový cluster ztrácí kvórum při výpadku kteréhokoli uzlu → po stavbě nového uzlu přidat QDevice (
corosync-qnetd) na TrueNAS (todos). - ZFS replikace se plně osvědčila (RPO ~1 min, RTO ~10 min) — po obnově clusteru vrátit a přidat i pro UniFi VM 109 (todo existuje).
- Immich/Scrypted/Jellyfin repliku neměly → obnova z PBS (datastore na TrueNAS přežil, PBS běží).
2026-06-24 — Klima dashboard: master tlačítka okna + presety stínění + rename 2 žaluzií
Rozhodnutí
Na Klima dashboard přidána master tlačítka Otevřít vše / Zavřít vše pro 10 oken (inline cover.open_cover/close_cover, seznam entit přes YAML anchor &okna_vse) a dva presety stínění jako skripty script.stineni_dopoledni / script.stineni_odpoledni s tlačítky nad „Stínění 1NP". Presety posílají nejdřív pozici, pak tilt:
- Dopolední: kuchyně + Relax sedací + Relax dřevník → pozice 0; jídelna → pozice 10 (90 % zavřeno); všechny 4 → tilt 70.
- Odpolední: Vrba + Hala schody + Koupelna → pozice 0 + tilt 70.
Zároveň přejmenovány dvě cover entity (registry, friendly name beze změny): cover.relax_zaluzie_drevnik → cover.hala_zaluzie_vrba (friendly „Vrba", area hala) a cover.relax_zaluzie_portal → cover.relax_zaluzie_drevnik (friendly „Relax dřevník", area relax).
Důvod
Okna neměla v entities kartě šipku „zavřít" → master tlačítka problém obejdou (servisní volání funguje bez ohledu na UI). Stará entity_id byla zavádějící: entita s _drevnik byla fyzicky Vrba u terasy a _portal byl Relax dřevník — nesedělo to na umístění. Přejmenováno teď, dokud byla jediná reference (klima.yaml); blast radius minimální, historie v recorderu se při rename zachovává (HA 2022.4+).
Gotcha — HA 2026.6.x skrývá „zavřít" u device_class: window
Cover entity-row v entities kartě nezobrazí tlačítko zavřít (šipka dolů) pro device_class: window, i když entita CLOSE plně podporuje (supported_features 15). U shutter/blind se zobrazí — proto stínění šipku dolů má a okna ne. Ověřeno controlled experimentem (window vs shutter, oba sf=15, liší se jen device_class) i živě na 2026.6.x. V dev větvi HA frontendu už tahle logika není → regrese konkrétní verze. Workaround pro per-okno šipku by byl override device_class na shutter; zvoleno místo toho master tlačítka (KISS, sémanticky čisté).
Operační dopad
- Somfy IO (overkiz) zabíjí probíhající pohyb následným příkazem — potvrzeno 2026-06-24: při odpoledním presetu koupelna sjížděla ze 100, tilt příkaz ji zrušil → nesjela. Fix: mezi
set_cover_positionaset_cover_tilt_positionjewait_template, který čeká na dosažení cílovécurrent_position(skupina = 0, jídelna = okno 8–13, protože Somfy nehlásí přesných 10),timeout: 120+continue_on_timeout: truejako pojistka. Čeká se na pozici, ne na stavclosing— odolné vůči latenci overkiz (žaluzie drží výchozí pozici dokud nedojede, wait nepředběhne). - Pozice se posílá jen žaluziím, co ještě nejsou na cíli (2026-06-24):
closena už zavřenou Somfy IO žaluzii ji stejně rozjede a sklopí tilt na 0 (zbytečný pohyb + flicker). Skript proto přesvariables: zavritspočítá podmnožinu (expand | rejectattr current_position == 0) aset_cover_positionpošle jen jí; jídelna analogickyifna okno 8–13; tilt 70 se pak pošle všem. Druhý stisk presetu na už zastíněné žaluzie → žádný pohyb pozice, jen (případně) tilt. - Skripty
mode: restart→ opakovaný stisk čistě přepíše běžící preset. - Staré body v InfluxDB zůstaly pod starým entity_id (u žaluzií irelevantní, žádný Grafana panel je nepoužívá).
2026-06-24 — Workflow paralelních session: worktrees + ruční merge sdílených logů
Rozhodnutí
Paralelní agent session jedou každá ve vlastním git worktree (izolace), ne sdíleně nad jedním master checkoutem. decision_log.md a todos.md zůstávají jako jednotlivé soubory (žádný per-entry split). Konflikt z paralelních zápisů se neřeší automaticky (žádný merge=union driver) — agent ho integruje ručně se správným newest-first pořadím. Toto chování je nově zakotvené v commit-confirmation.md (sekce „Append-only sdílené logy" + krok 5b), aby ho dělala každá session spolehlivě, ne náhodou.
Důvod
Paralelní session sdílející jeden master checkout je nebezpečné: git commit v jedné sebere i rozdělanou práci druhé (společný index) + race na sdílených souborech. Worktree to izoluje. Per-entry split (docs/decisions/*.md + generátor) konflikt řeší u zdroje, ale přesouvá ho na generovaný soubor a přidává infrastrukturu — zamítnuto kvůli KISS a přání zachovat jeden soubor. merge=union je čistě KISS, ale slepuje text hloupě (rozhází date pořadí, neumí dedup) — zamítnuto ve prospěch vědomého agent-merge, který dá korektní výsledek. Cena: vyžaduje agenta v procesu commitu, což sólo provoz stejně má.
Operační dopad
- Nikdy nemíchat režimy — když jedu worktrees, master checkout se ručně needituje (je to jen push target). Mixování bylo příčinou divergence
zahradni_domek.md(744 vs 691 řádků ve dvou kopiích). - Před pushem commitu dotýkajícího se
decision_log.md/todos.md:git fetch origin master, integrovat pokud se rozešel, ručně ověřit pořadí. Vizcommit-confirmation.md. - Worktree se po session uklízí (
git worktree remove+git branch -D); čisté worktree = 0 commitů navíc, bezpečné smazat. 2026-06-24 uklizeno 6 nahromaděných. EnterWorktree/ExitWorktreenefungují na worktree vytvořený harnessem při startu session — z něj se ven dostat nedá, je potřeba session spustit přímo v main repu (app-level volba, nesettings.json).
2026-06-22 — FTV export módy (Mode 1/3 přes Victron grid setpoint) + výdělek z dodávky
Rozhodnutí
Ruční přepínač dodávky do sítě řízený přes Victron ESS grid setpoint (HACS victron_mqtt, zapisovatelné number entity na Cerbo GX). input_boolean.ftv_max_export: OFF = Mode 1 (samospotřeba, setpoint 0), ON = Mode 3 (setpoint −12500 → export 12,5 kW, vybíjí baterku do floor input_number.ftv_export_min_soc, default 20 %; přetok >12,5 kW → baterka). Páky: …ac_power_set_point (0/−12500), …ess_max_feed_in_power (12000 strop), …ess_min_soc_limit (floor). Plus počítadlo výdělku z dodávky (sensor.vykup_vydelek_dnes, Kč) přes Riemann integraci export×výkupní cena.
Klíčové zjištění — Mode 2 je nativně nedosažitelný
Záměr „export PV první, NIKDY nevybíjet, jen přetok >12,5 do baterky" v nativním ESS nejde: ESS vždy upřednostní nabití baterky před exportem; jediná páka co vynutí export-first je záporný grid setpoint, který ale vybíjí baterku (= Mode 3). Discharge-blok přes min SoC=100 je anti-pattern — spustí low-battery ochranu = grid-charge (nákup fixu) na 100 %. Workflow ověření (Victron ESS dokumentace + adversariální review) to zachytilo před zápisem do YAML. Zůstaly 2 čisté módy přes input_boolean.
Bezpečnostní obálka (perzistentní setpoint na Cerbu = pád HA nesmí nechat Mode 3 přes noc)
ftv_export_apply:number.set_value, kanonické pořadí (do Mode 3 floor→setpoint; návrat setpoint→0 první), read-back setpointu + notifikace při neshodě, Mode 3 vylučujeftv_tc_boost.ftv_export_guard(à 10 min): vypne při výkupu (OTE−0,30) ≤ práh (default 0 = nikdy se ztrátou).ftv_export_reset: 23:00 +homeassistant.start→ Mode 1, swait_templatena dostupnost victron entit.- Clamp hodnot (range entit je ±1 000 000, žádná knihovní pojistka).
Flip-test (živě, 2026-06-22, PV 15 kW / SoC 90 %)
Mode 3 ON → setpoint −12500, grid −12257 W (export ~12,3 kW, pod limitem 12,5), baterka z +6,6 kW nabíjení → ~0, ftv_tc_boost OFF (mutual exclusion). Revert → setpoint 0, grid ~0, baterka +13 kW. Celý řetězec ověřen.
Cenové prahy (kdy ON)
Výkup = OTE − 0,30 (marže EnerSpot, ne distribuce — ta se na exportu neplatí). Práh „neprodávej se ztrátou" = OTE 0,30. Mode 3 vybíjí baterku (~1,2 Kč/kWh opotřebení) → reálně dává smysl až od OTE ≳ 1,5. Ranní prodej s jistým odpoledním dobitím z mařeného přebytku: break-even ~OTE 1,5; bez té jistoty se ranní prodej obchoduje proti večernímu nákupu (práh skočí na OTE ≥ 4,28). Detail rizeni_energie.
Operační dopad
Nasazeno (input_boolean.yaml, input_number.yaml, automations.yaml, template.yaml, sensor.yaml, configuration.yaml, dashboards/ftv.yaml), commity 14f495e + 230c478, restart (sensor.yaml + utility_meter). Dashboard: přepínač/rezerva/práh/setpoint + spot graf dnes+zítra + výdělek dnes. Rodina: navod_pro_rodinu/energie — do Victron GUI nesahat, přepínat na dashboardu.
2026-06-22 — AK je v létě dead-end sink (kompresor nehřeje + VZT neodebírá)
Zjištění
Akumulačka AK je v létě slepá ulička pro přebytek, ze dvou důvodů současně:
- Kompresor ji nenatopí — topná služba je gated globálním stop-temp (léto venku >20 °C →
binary_sensor.ecoforest_heating_mode_active = off). Známo od 2026-06-21. - VZT z ní v létě neodebírá — jediný letní možný konzument tepla z AK je VZT ohřívač bazénové haly (okruh DG1, dostává vodu ≈ teplota AK, otevírá ventil sám na svůj požadavek). V létě hala teplo nepotřebuje → ventil neotevře. Ověřeno daty (2026-06-22): po natopení patronou na 40,6 °C AK monotónně chládne ~1,2 °C/14,5 h = ~38 W standing loss (čistá ztráta nádrže, žádný odběr; reálný odběr 2 kW by srazil ~4 °C/h).
Důsledek
Patrona do AK v létě = zmařená elektřina (COP 1, teplo se nespotřebuje, vyteče do strojovny). AK boost (kompresor i patrona) má smysl jen v topné sezóně. Doc rizeni_energie tvrdila „z AK celoročně topí VZT ~2 kW v noci" — opraveno na topnou sezónu.
2026-06-21 — Bazén: FTV boost ohřevu (Aseko floor <28 / boost 28-32 / cap 32)
Rozhodnutí
Bazén = velký letní surplus sink (39 m³ ≈ 45 kWh/°C). Řízení ohřevu konsolidováno do jediné automatizace „Bazén - řízení topení" (automations.yaml, nahradila prostý Mirror Aseko→switch.topeni_bazen):
- < 28 °C: topí Aseko (komfort floor,
binary_sensor.topeni_aseko). - 28–32 °C: topí navíc při
input_boolean.ftv_bazen_boost(přepínač na dashboardu) — jímání FTV přebytku. - > 32 °C: cap (hystereze 31,5/32).
Topí kompresor TČ (COP), bazén z AK neodebírá (samostatná větev z kondenzátoru — projekt Veskom). Druhá automatizace „Bazén - filtrace při FTV boostu" vynutí
switch.filtrace_bazenpo dobu boostu.
Klíčová designová zjištění
- Sonda bez filtrace měří vzduch, ne vodu → boost topí až po ≥15 min běhu filtrace (settle vázán na filtraci, ne na dobu boostu). Filtrace Aseko běží 8:00–20:00; FTV přebytek (plná baterka) nastává až dopoledne/v poledne → než boost najede, filtrace už hodiny běží, teplota spolehlivá. Settle je tedy v praxi vždy splněný, je to jen pojistka.
- Dual-writer s Aseko vyřešen tím, že nová automatizace je jediný zapisovatel
switch.topeni_bazen(kombinuje Aseko request i boost). Aseko cíl teploty doporučeno srovnat na 28 °C. - Aseko zápis: HA nikdy nepíše do dávkování/chemie Aseka; řídí jen relé ohřevu a (při boostu) filtrace.
- COP pořadí (léto): kompresor → bazén + DHW (COP 3–4) → patrony (COP 1). Bazén před patronou ne kvůli odběru z AK, ale kvůli COP.
Operační dopad
Nasazeno (automations.yaml + input_boolean.yaml + dashboards/ftv.yaml), deploy reload. Dokumentace: bazen.md → „Ohřev bazénu a FTV boost". Entity_id přepsané automatizace zůstalo automation.mirror_binary_sensor_topeni_aseko_to_switch_topeni (HA drží registrované id při změně aliasu), friendly name „Bazén - řízení topení".
2026-06-21 — TČ surplus: AK/buffer kanál je v létě inertní (topná služba stopnutá stop-temp)
Zjištění (živě ověřeno během boostu)
Při boostu (DHW 60 / AK 48) DHW naskočilo a nahřálo se na 62 °C, ale AK se nehřeje (35,5 °C, 12,5 °C pod bus setpointem 48), TČ stojí (příkon 0 W). Příčina: venku 30 °C, binary_sensor.ecoforest_heating_mode_active = off — „Stop temperature for heating" je 5 °C, takže celý topný režim je globálně vypnutý. AK (topný buffer) je součást topné služby → bez aktivního topení se nehřeje a bus setpoint (2722) to neobejde (nastaví cíl, ale topná služba je stopnutá). DHW i bazén jsou samostatné služby (StopT je neovlivní) → fungují celoročně.
Důsledek / rozhodnutí
- AK boost kanál = jen zimní. V létě nelze rozjet bez zvednutí globální stop-temp (společná pro dům i halu → roztopila by dům). Zápisy 2713/2722 v
ftv_tc_boostzůstávají (neškodný no-op v létě, funkční v zimě). - Letní kompresorový surplus sink = DHW (400 l, plný za ~15 min) + bazén (39 m³, samostatná služba) → bazén je ta velká letní cesta. Patrony EP1/EP2 (COP 1) overflow.
2026-06-21 — FVE surplus přes kompresor: Path B ověřen a nasazen (manuální boost v1)
Zjištění (živý flip-test přes HA modbus.write_register)
Setpoint-by-BUS funguje — narozdíl od inertní e-Manager surplus funkce (2775/2777). Zápis 2705=1 (DHW demand by bus) + 2720=600 a 2713=1 + 2722=480:
sensor.ecoforest_dhw_setpoint48 → 60,_heating_buffer_setpoint30 → 48 (override se aplikoval),_dhw_power0 → 15,7 kW tepla, příkon 2,3 → 4,4 kW → COP ~3,5 = kompresor (ne patrona COP 1),- vypnutí přepínače → setpointy zpět 48/30, výkon 0. DHW teplota za 80 s beze změny (51,4 °C) → bez přehřátí.
Rozhodnutí
Cesta = Path B (HA řídí TČ setpointy přes BUS), surplus registry 2775/2777 opuštěny natrvalo. Nasazena minimální v1 (commit 129dc70): input_boolean.ftv_tc_boost (ON → DHW 60 / AK 48, OFF → 48 / 30) + automatizace ftv_boost_setpointu_tc_dhw_ak (+ re-assert na startu HA) + noční bezpečnostní reset ftv_nocni_reset_setpointu_tc_22_00 (22:00 → vypne boost, DHW 45 / AK 30). Zápis jen přes HA modbus.write_register (hub ecoforest, slave 17). modbus/ecoforest.yaml se nemění → deploy bez restartu.
Klíčový princip (od uživatele)
Setpointy zvedat dřív než nastane curtailment — jakmile je baterie plná, je pozdě (přetok max 12,5 kW, při záporné ceně nula). Proto teď manuální přepínač (zvednout ráno za slunce); automatika později vázaná na předpověď výroby, ne na curtailment signál.
Další (vše „později")
Prediktivní automatické zvedání (Forecast.Solar), patrony EP1/EP2 jako overflow (COP 1), bazén (Aseko koexistence), watchdog/age-check. Operační: před trvalým boostem na 60 sníží uživatel termostatický směšovač TV ze 75 na 55 °C (scald cap).
2026-06-21 — FVE surplus přes kompresor TČ: Fáze 0 — zapisovatelné, ale blokované na e-Manageru
Zjištění (živý write-test 2775/2777 + offsety, plně zarollbackováno)
- Registry surplus jsou zapisovatelné a drží:
2775(surplus enabled by BUS),2777(setpoint kW ×10), offsety2725/2727. „Bus control" v menu je zapnutý. - Kompresor ale nenaskočí — ani s offsety dávajícími headroom (TV cíl 60 vs 52,5; AK cíl 48 vs 36,4) a
2777=4 kW. 150 s idle, compref 0 %, 0 kW. - Příčina (control manuál 3.2.7 e-MANAGER): surplus-by-BUS je součást e-Manager funkce „Surplus control", která (a) musí být zapnutá v installer menu a (b) řídí podle měřené network balance přes CEM elektroměr. Ani jedno není — projekt CEM C20 + e-Manager vynechal a patrony jdou přes HA relé (viz tepelne_cerpadlo.md). Registry jsou tedy zapisovatelné, ale inertní.
Rozhodnutí / cesty dál
- v1 = patrony EP1/EP2 přes HA relé (
switch.ftv_do_boileru3 kW,switch.ftv_do_akumulacky5 kW) — fungují dnes, COP 1, bez TČ commissioningu. Curtailment lze jímat hned, nezávisle na kompresoru. - Kompresor (efektivní nadstavba, COP 3–4) má 3 cesty:
- A-CEM (Veskom zapne e-Manager + doinstaluje CEM): zamítnuto jako default — autonomní honění bilance sítě by se pralo s Victron ESS (oba řídí grid balance).
- A-BUS (Veskom zapne e-Manager, krmený z HA přes 2777): elegantní, TČ samo moduluje + distribuuje; čeká na Veskom + potvrzení, že BUS-only jede bez CEM.
- B — HA řídí setpointy přímo (2705 demand + 2720/2722 setpoint po BUS, bez e-Manageru): funguje hned, sedí na AppDaemon architekturu; HA nese bezpečnost (watchdog musí stáhnout setpoint, jinak TČ dotápí ze sítě — downside ale ohraničený: nádrže cappnou, 60 °C cutoff + směšovač). Preferovaná cesta k otestování.
- Offsety rozhodnuty (pro A-BUS i případně B): TV +12 → 60 °C (HTR, směšovač chrání kohoutky, legionella), AK +18 → 48 °C (standardní kondenzátor — nad ~50 padá COP, AK krmí nízkoteplotní okruhy), bazén odložen (největší sink ~45 kWh/°C, ale gated DI4 + Aseko dual-writer; filtrace běží ~12 h/den + lze spustit přes relé → reálné ve Fázi 2).
Lekce (durable) — single Modbus master
Rollback test-skriptu selhal kvůli kolizi druhého mastera (ModbusIOException — pymodbus souběžně s HA pollingem). Potvrzeno empiricky, ne jen z doku: všechny zápisy do TČ musí jít přes HA modbus.write_register (jediný legitimní master), nikdy přes pymodbus. Read-only probe (scripts/ecoforest_surplus_probe.py) je OK pro diagnostiku (retry), ale zápisy ne. (Kompresor během testu neběžel → bez škody; registry ručně srovnány na 0.)
Operační dopad
Bez runtime dopadu — TČ na nativní regulaci, všechny surplus registry 0. Aktualizován rizeni_energie.md + todos.md. Kompresorová Fáze 2 čeká na rozhodnutí cesty (B test přes HA / dotaz Veskomu na A-BUS).
2026-06-21 — FVE baterka: detekce „plného nabití" přes SOC (vebus float/storage v ESS nefunguje)
Zjištění
sensor.baterka_posledni_plne_nabiti (template.yaml) detekoval plné nabití přes vebus_inverter_state == float/storage. V tomhle AC-coupled + DC-MPPT ESS Multiplus do float/storage NIKDY nepřejde — baterii dobíjejí MPPT + Fronius, top-of-charge řídí DVCC/ESS, Multiplus zůstává v absorption/sustain. Ověřeno: za 48 h jen bulk/absorption/sustain/inverting, žádný float. Značka tak zamrzla na 27. 5. → senzor hlásil falešných „25 dní od plného nabití", ačkoli SOC reálně držel 99,7–99,8 % hodiny každý slunný den (např. 20. 6.). Odhaleno uživatelem (VRM ukazoval baterku včera plnou hodiny).
Rozhodnutí
Detekce přepnuta na SOC ≥ 99 % držené 15 min (numeric_state trigger + HA-start fallback s condition). SOC je v tomhle systému spolehlivý signál „plně nabito"; práh laditelný.
Dopad
Oprava NENÍ kosmetika: plánovaný balancing interlock řízení přebytků (Fáze 1b — dní_od_plného > 14 → potlačit jímání) by s rozbitým senzorem napořád blokoval jímání přebytku FTV. Po nasazení se dní_od_plného srovná, jakmile SOC dnes překročí 99 % na 15 min (HA-start fallback NEsepne na pouhý reload templatu — až na příští plný start / dosažení prahu).
Gotcha (durable): v AC-coupled Victron ESS se nedá spoléhat na vebus_inverter_state float/storage jako na „baterka plná" — používat SOC nebo systémový battery state. Stejná past hrozí u jakékoli logiky vázané na charge-fázi Multiplusu.
2026-06-21 — Závlaha: forecast-only brána nahrazena Open-Meteo vodní bilancí
Rozhodnutí
Dešťová brána binary_sensor.zavlaha_predpoved_deste (forecast met.no, dopředu, denní granularita) nahrazena vodní bilancí krmenou z Open-Meteo (free API, bez klíče):
- 2 bilance v mm (
input_number.zavlaha_bilance_{plocha,sklenik}): denně ve 4:00bilance += déšť_včera − ET0_včera×kc, clamp ⟨−50,+20⟩. Záměrně včerejší naměřené hodnoty (ne dnešní forecast — odpolední déšť by minul); forecast je jen veto v ranní bráně (skip když dnes/zítra ≥ 5 mm). Plocha počítá déšť, skleník (krytý) jen výpar. Záporná = zalévej, kladná = skip; po zálivce reset na 0. Vydatný déšť → strop +20 → přirozený vícedenní skip. Zdroj:sensor.zavlaha_{et0_dnes,et0_vcera,srazky_dnes,_vcera,_zitra}(REST, rest.yaml). - Open-ground jen ráno —
zavlaha_vecer(21:00) vypnuta (zakomentována). Trávník/kapky/stromy večer = houby. Jediný večerní běh zůstal skleník (kapka, bezpečné), navázaný na ET0 místo holé teploty. - Stromy oddělené od záhonů (
input_number.zavlaha_doba_stromy) — hlubší/řidší dávka. - Dávky zmrazeny na osvědčené ~10 min jako runtime tuning, ne návrhové číslo.
Důvod
Incident 20.6.2026: ~2 h po večerní bouřce se ve 21:00 spustila závlaha do kaluží. Z historie: brána byla OFF přesně v okně 20:00–01:00 — denní agregát met.no konvektivní bouřku nezachytil a po přechodu „už neprší" se otevřela. Forecast-only brána je principiálně slepá ke spadlému dešti. Open-Meteo dává naměřené srážky (past_days) + korektní ET0 (FAO-56) zdarma → bilance řeší přesně tu třídu selhání.
Zamítnuté alternativy (7 iterací ideace):
- Smart Irrigation (HACS) — instalovaný, ale rozbitý (bucket −362 mm,
reset_bucketse nevolá, orphaned automatizaceunavailable) a config-divadlo (throughput/soil/drainage). V gate režimu nepřináší nic navíc; ruční bilance je transparentní a bez závislosti. - Deep-infrequent — půda nedovolí: ~40 cm zeminy/navážky nad nepropustným jílem → mělčí kořenová zóna, perchování, sklon k podmáčení (empiricky 10 min v chladnu podmáčelo stínná místa). Primární riziko = přelití. Navíc celá výsadba teprve zakořeňuje. „Hluboko a zřídka" je budoucí knob (zvednout práh), ne letošek.
- Rotace okruhů / 3+ kýble — malé osvědčené dávky dělají rána krátká, špička zmizí i bez rotace; frekvenci řeší ET, víc kýblů zbytečné.
Operační dopad
Nové entity: 4 REST sensory (rest.yaml), 3 helpery (input_number.yaml), automatizace zavlaha_vyhodnoceni_bilance (04:00). Upraveny zavlaha_rano (brána = bilance < −5 a forecast < 5 mm), zavlaha_zahony_{rano,vecer} (reset bilance, večer dle ET0), okruh 7 → doba_stromy. binary_sensor.zavlaha_predpoved_deste ponechán jako informativní. Dokumentace: zavlaha.md. Ruční úklid (mimo repo, .storage): smazat dormant automation.sensor_smart_irrigation_travnik_2. Bez restartu — stačí reload. Ladění prahů/dávek probíhá za provozu (první 1–2 týdny).
2026-06-20 — Řízení přebytků FTV: revize návrhu po multiagentním review
Rozhodnutí
Návrhová rozvaha rizeni_energie.md zpřesněna po adversariálním review. Změny oproti původní rozvaze (2026-06-17):
- v1 = nativní HA YAML, ne AppDaemon. Kompresor (priorita #1) NEMÁ v HA zapisovatelnou entitu (Ecoforest read-only), takže buildovatelná v1 = patrony (EP2 5 kW → EP1 3 kW) + léto klima soak (~60–70 % hodnoty). Na dvě relé + script netřeba watchdogovaný AppDaemon mozek; ten je až Fáze 2 pro spojitou kompresorovou modulaci.
- Fáze 0 verification gate. Před kódem ručně ověřit zapisovatelnost Modbus 2775/2777. Surplus registry jsou čitelné (ověřeno read-only
scripts/ecoforest_surplus_probe.py, hodnoty 0), zapisovatelnost neověřena (vyžaduje „Bus control" v menu TČ + write test dle procedury v hlavičce skriptu). - Signál curtailmentu dvoustupňový. MPPT
voltage_current_limitedsám je falešně pozitivní (fíruje při CC/CV dobíjení plné baterie) → přidána PV-rise potvrzovací smyčka. - Práh diverze = OTE 0,50 (HW realita firmy), ne 0,30; v pásmu 0,30–0,50 firma neexportuje → jímat doma (rozhodnutí uživatele).
- Balancing interlock: dokud
dní_od_plného > 14ASOC < 100, surplus diverze potlačena (nech baterii dojít na 100 % pro BMS balancing). Live 23,5 dne = po termínu. - ESS firmy nedotýkat — řídit jen loady (žádný zápis do
ac_power_set_pointanidess_mode).
Důvod
Review (3 čočky: KISS / safety / grounding) ukázalo, že původní 9-stupňový AppDaemon návrh byl předimenzovaný vůči tomu, co jde dnes postavit, a obsahoval chyby: vymyšlené entity (ecoforest_aux_*), rozbité čtení spot ceny (atribut now() → None), falešně pozitivní signál, chybný práh 0,30 místo firemních 0,50, chybějící balancing interlock a fail-safe nezávislý na mozku. KISS: v1 řeší curtailment dvěma relé + scriptem v nativním YAML; AppDaemon až tam, kde má spojité řízení smysl (kompresor).
Operační dopad
Aktualizován rizeni_energie.md (signál, architektura v1/Fáze 2, fázovaný rollout). Nový read-only skript scripts/ecoforest_surplus_probe.py + ruční write-test procedura (Fáze 0). Bez runtime dopadu — žádné řízení zatím neběží. Side-finding z probe (2026-06-20): TČ hlásí alarm level 4 (long-time) a stojí idle s DHW 43,5 °C pod setpointem 48 °C — ke kontrole (aktivní alarm kód v registru 2069).
2026-06-20 — FVE: doložená geometrie polí, mapování stringů a empirický curtailment
Zjištění (z projektové dokumentace + živé měření 2026-06-19)
Do repa zařazena kompletní projektová dokumentace FVE (docs/manualy/fve_marada: technická zpráva, jednopólové schéma, výchozí revize). Z ní + z měření v HA plyne:
- Geometrie polí (dosud chybějící vstup pro Forecast.Solar): 58 panelů AIKO NEOSTAR 2S A450 (450 Wp) na dvou střechách:
- Dům: 32 ks, azimut 121° (JV), sklon ~35°.
- Carport: 26 ks, sklon ~2° (téměř plochý), dělení ≈ 1/3–2/5 na jih, zbytek na sever — při 2° je rozdíl J/S skoro kosmetický.
- Mapování stringů na střechy a měniče (dovozeno z počtů panelů 32 + 26 a typu zapojení; schéma to explicitně neuvádí): dům = stringy 17s1p + 15s1p (688/607 V) → Fronius Symo; carport = 5s2p + 2× 3s2p + 2s2p (202/120/120/81 V) → 3× Victron MPPT. Sedí na počty i na to, že dlouhé sériové stringy patří na jednu koplanární rovinu (Fronius), nízkonapěťové paralelní na členitý plochý carport (MPPT).
- Proč baterie padá na 100 % k polednu: JV orientace hlavního pole (35°) posouvá špičku výroby do dopoledne. S 64 kWh baterií a letním nízkým odběrem se úložiště naplní kolem poledne → curtailment brzy odpoledne, ne v pravé poledne. Empiricky 2026-06-19: poledne plný výkon (~14 kW), krátké propady výroby na ~0,5 kW ve ~13:47 a ~14:42 (nejlevnější čtvrthodiny spotu, baterie 100 %).
Rozhodnutí
- Cenový práh dodávky firmy (OTE < 0,5 → nedodávat) se nechává být. Skutečný break-even výkupu je OTE 0,30 (výkup = OTE − 0,30); firma dala 0,5 jako konzervativní buffer. Rozdíl je finančně marginální (řád desítek Kč/rok — pásmo 0,30–0,50 má výkupní marži 0–0,20 Kč/kWh na pár čtvrthodin denně). Hodnota není v ladění prahu, ale v jímání mařeného přebytku do tepla (viz rizeni_energie.md).
- Curtailment Victronu je interní (frekvenční posun na Fronius + škrcení MPPT) — HA do něj nezasahuje. Řízení přebytků proto cílí na přidávání domácích spotřebičů (TČ kompresor → patrony → wallbox → chlazení), ne na boj s ESS firmy.
Operační dopad
Dokumentace: aktualizován ftv.md (orientace polí, mapování stringů, vstupy pro Forecast.Solar, firmou nastavený práh 0,5), rizeni_energie.md (odblokován krok Forecast.Solar, empirické chování), todos.md. Bez runtime dopadu. Odblokovává Forecast.Solar (geometrie známá) → krok k prediktivní ranní arbitráži.
2026-06-19 — HA default route přes IoT NIC: trvalá oprava odebráním gateway z enp0s19
Symptom
Otevření branky přes HA (PUT http://192.168.60.10/ISAPI/AccessControl/RemoteControl/door/1) padalo na timeout. sensor.doorbell_call_status byl unavailable od 11:23. Zvonek přitom z Macu (VLAN 20) odpovídal okamžitě (401 za ~5 ms, ISAPI zdravé) a na síti byl živý (ARP, DNS pokusy).
Root cause (živě ověřeno)
HA host má dvě NIC, obě měly nastavenou gateway (enp0s18→20.1, enp0s19→40.1). HAOS si proto sám volí primární a v 11:23 ji přehodil na enp0s19 (VLAN 40 / IoT). Tím šel default route přes IoT VLAN → pfSense pravidlo „Block IoT to Internal Networks" (interface IOT/opt2, log: false → tichý drop) zařízlo HA→VLAN 60. Same-subnet provoz (Fronius 40.25 na VLAN 40, Scrypted 20.21 na VLAN 20) jel dál → maskovalo to příčinu a svádělo na zařízení. Recidiva incidentu 2026-05-06 (HA OS upgrade přehodí primary NIC).
Mylné mezizávěry během debugu (zaznamenané jako varování): „zaseklé ISAPI zvonku", „session leak z 1s pollu", reboot zvonku. Žádný neplatil — zvonek byl celou dobu zdravý.
Rozhodnutí
Default route se zafixuje na VLAN 20 odebráním gateway z enp0s19 (IoT NIC gateway nepotřebuje, jen same-subnet L2). Když má gateway jen enp0s18, výběr default route je deterministický a HAOS ho nemůže přehodit.
ssh root@192.168.20.7 'ha network update enp0s19 --ipv4-method static --ipv4-address 192.168.40.7/24 --ipv4-gateway "" --ipv4-nameserver ""'
Důvod / klíčové zjištění
- UI gateway smazat neumí (validace IoT NIC to nedovolí) — proto dřívější pokusy uživatele „nepřežily". CLI
ha network update --ipv4-gateway ""tu validaci obejde a drží. - Ověřeno: po
ha network reloadzůstala gateway smazaná,primarynaenp0s18, HA→zvonek401, entity naskočily naidle. Reload re-aplikuje z perzistované konfigurace = silný proxy perzistence. - Lepší než plánované route-metric pinning (todo z 2026-05-06): bez gateway nemůže být
enp0s19default route vůbec, nezávisle na primary flagu i metrice. - 1s poll zvonku s incidentem nesouvisel — neměnit kvůli tomuhle.
Operační dopad
HA→VLAN 30/50/60 obnoveno (branka, kamery přímo, MEDIA). Změna je na HA hostiteli, ne v repu (mimo ha-deploy). Aktualizováno homeassistant.md (Dual-NIC), memory ha-dual-nic. Follow-up: ověřit perzistenci po nejbližším plném rebootu / HA OS upgrade (viz todos.md) — pokud se gateway vrátí, fallback je úzké pfSense pravidlo 192.168.40.7 → 192.168.60.10.
2026-06-20 — AI Log Monitor: triáž bez šumu, re-surface prahem, vlastní logging
Kontext
Otevřené GitHub issues od ai-monitor bota se hromadily (21 otevřených, většina historická nebo benigní). Živá kontrola sítě ukázala, že část byla stale (#52 — AP dávno online), neexistující/přejmenované zařízení (#73 — „U7-Pro-Outdoor" = AP8 carport, benigní wevent Resource busy šum), nebo boot-only událost re-flagovaná denně (#43 — systemd-networkd-wait-online). Monitor navíc neměl jak issues zavírat a re-komentoval totéž každých 12 h.
Rozhodnutí
Ladění scripts/log_monitor.py:
- Auto-close zamítnut — issues zavírá člověk ručně. Monitor je sám nezavírá (riziko zavření reálného problému během slepého běhu, kdy mlčí Loki/zdroj).
- Re-surface jen při seriózním opakování: otevřené issue se znovu nekomentuje každý běh; re-comment + Telegram jen P0 vždy, P1 až při
occurrence_count ≥ SERIOUS_RECURRENCE_THRESHOLD(default 50 / 12 h). Přidánoccurrence_countdo Gemini JSON. - Tvrdší triáž v promptu: přechodné jednorázovky (Tailscale „context canceled"), boot-only selhání na hostu s dlouhým uptime a známý benigní šum → P2 (nezakládá issue).
- Vlastní strukturované logování (
logging): INFO→stdout, WARNING/ERROR→stderr→journald→Loki. Chyby samotného monitoru (Loki/Gemini/GitHub/Telegram) jsou dohledatelné i v logu, ne jen v Telegramu; při nevalidním JSONu z Gemini se loguje prvních 800 znaků odpovědi.
Důvod
- Žádné count-gating zakládání nových issues: reálná kritická chyba (degradovaný ZFS pool, SMART fail, OOM, ztráta kvóra) se v okně objeví třeba jednou — gating podle počtu by ji potlačil. Suprese šumu je sémantická práce Gemini (priorita), ne mechanický práh. Práh se používá jen pro re-surface už založeného problému.
- Self-monitoring gap: Gemini Flash občas vrátí nevalidní JSON (
responseMimeType: application/jsonto nezaručuje). Předtím to šlo jen do Telegramu; teď i do logu se vzorkem odpovědi → debugovatelné.
Operační dopad
- Žádný HA runtime dopad. Skript běží na
debian-services(192.168.20.20) přes systemd timer 08:00/20:00; deploy ručníscpdo/opt/scripts/(service/timer beze změny). - Práh 50 je prvotní odhad — doladit podle reálného provozu.
- Dokumentace: log_monitor.md.
- Související tooling gotcha (mimo tento soubor, v paměti agenta): pfSense MCP hlásí balíček Tailscale jako stopped/disabled i když běží — ověřovat v GUI, ne přes MCP service status.
2026-06-18 — Zahradní domek: fasáda modřínové plotovky 100/121/146, bez nátěru, rohy a větrání
Rozhodnutí
Vnější svislý rastr se mění z řezaného KVH 120×19 (60/80/100/120 mm) na kupované modřínové plotovky tří frézovaných šířek 100 / 121 / 146 mm (~21 mm), mezera ~13 mm. Modřín bez nátěru — jednorázový bezbarvý Bochemit před montáží, pak přirozené šednutí a žádná údržba. Finální sekvence prken, rozměry runs a detaily v zahradni_domek.md.
Důvod
- Tři hotové šířky místo řezání: odpadá podélné řezání na stolní pile i 15% rezerva na odřezky; konzistentní frézované hrany. Spread 100 : 121 : 146 drží výrazný nepravidelný rytmus.
- Bez nátěru = záměr i KISS: přirozené šednutí modřínu je esteticky preferované; modřín (trvanlivost tř. 3–4) se uživí sám. Bezbarvý Bochemit (NE pigmentovaný Estetik, který by bránil šednutí) jako jediná, jednorázová ochrana — po montáži jsou záda v otevřeném rastru nepřístupná. Tím padá Rubio DuroGrit i údržba à 3–5 let.
Klíčové konstrukční závěry
- Rozměry obkladu (run) ≠ holé OSB. Latě stojí 40 mm nad OSB → každá stěna přesahuje. Hierarchie překryvu v rozích přední > boční > zadní: přední run = OSB +122 mm, boční +101 mm, zadní +80 mm. Finální runs 3112 / 3075 / 2081 mm.
- Větrání — korekce dřívějšího omylu: vodorovné latě přerušují svislý tah za rastrem, takže žádný „komín sání dole / výdech nahoře". Otevřený rastr (~10 %) dýchá celou plochou napřímo. Reálné role: folie (pojistná rovina) + sražená hrana latí 15° + segmentované latě (mezírka pro odvod vody). Velká větrací štěrbina pod podhledem proto není potřeba.
- Roh střecha–stěna — rohová lať drží folii: v koutě se dává rohová lať (KVH 60×40, sražená hrana), přišroubovaná skrz přeložený spoj folií (střešní shingle přes stěnovou) do věnce → mechanicky sevře lap po celé délce. Plotovky běží v plné výšce až ~5–10 mm pod podhled (jen dilatace), žádná 15–20mm štěrbina. (Reviduje dřívější závěr „folii drží jen věnec + podhledové plotovky, ne stěnová lať" — komín neexistuje, takže zavřít horní hranu latí je v pořádku; podmínka: shingle zůstává, střešní folie lapuje PŘES stěnovou, roh. lať je vně folie.)
- Vruty: jeden v ose na lať — i u 146mm. Dva vruty s vodorovným rozestupem (vedle sebe i diagonálně) → prkno praskne přes šířku. Diagonála problém neřeší. Miskovatění 21mm plotovky se bere jako součást přírodního vzhledu.
- Dělení 146 napůl zamítnuto: práce navíc, zabíjí akcent rytmu, syrový pilový řez nesedí k frézovaným hranám.
Operační dopad
Žádný runtime dopad (mimo HA). Aktualizován zahradni_domek.md: materiál, skladba, sekvence kladení, rohy, rozmístění latí, vruty, ochrana dřeva, materiálový odhad, postup i fáze realizace.
2026-06-17 — Řízení přebytků FTV: architektura AppDaemon + návrhová rozvaha
Rozhodnutí
Řízení přebytků FTV (jímání přes TČ surplus + spotová arbitráž dodávky) se postaví jako AppDaemon appka podle vzoru existující appdaemon/apps/daikin_modbus.py — ne jako HA automatizace ani samostatná služba. Charakterizační měření jako scripts/ Python skript. Celá návrhová rozvaha (kaskáda, principy, defenzivní arbitráž, balancing, nepravidelné spotřebiče) je v rizeni_energie.md. Zatím neimplementováno — řízení neběží.
Důvod
- AppDaemon už je zavedený a používaný (
daikin_modbus.pyřídí Daikin přes Modbus,foxtron_scene_controllertlačítka). Není to nová moving part — tím padl hlavní KISS argument proti. Naopakdaikin_modbus.pyje hotový vzor přesně pro tenhle úkol: zápis přesmodbus.write_register, periodic guard = watchdog, debounce, HA služby. (Tím se fakticky uzavírá i todo „AppDaemon zachovat/eliminovat" → zachovat.) - HA automatizace odmítnuty pro mozek: predikční matematika (forecast × absorpce × spot × SOC) a watchdog v Jinja jsou křehké a nečitelné. Python je uživatelova silná stránka.
- Human-operability zajištěna i s Pythonem: kill-switch
input_boolean, stav publikovaný do HA senzorů, watchdog vrací TČ vlastní regulaci. Dům funguje i bez appky.
Klíčové designové závěry (detail v rizeni_energie.md)
- Self-consumption ≫ dodávka (fix 3,98–4,92 vs výkup OTE−0,30) → kaskáda kompresor → baterka → patrony → wallbox/chlazení → dodávka → curtailment.
- Proaktivní TČ (pustit do tepla brzy, ne čekat na plnou baterku — kompresor 6 kW je úzké hrdlo vs 26 kWp).
- Přetok 12,5 kW = vzácný zdroj → alokovat do drahých hodin; baterka = časový posun z levného poledne.
- Defenzivní ranní arbitráž vázaná na pesimistický dvoudenní forecast + tvrdý SOC floor.
- Full charge ≥ 1×/14 dní (BMS balancing) má přednost před arbitráží, načasovat na slunný den.
Operační dopad
Žádný okamžitý — designové rozhodnutí pro budoucí implementaci. Postup po krocích (zapisovatelnost → charakterizace → appka) v todos.md a session plánu.
2026-06-16 — Atrea rekuperace: Modbus mapa, opravené chyby a model řízení
Zjištění (živě ověřeno sondou na 192.168.40.33)
Atrea aMotion má celou čtecí mapu jako input registry (FC04) — teploty, průtoky, stavy, dokonce i „config/type" registry 1201–1206. Holding registry (FC03) existují jen pro zapisovatelný „request" blok kolem 1001–10xx (work_regime 1001, temp_request 1002, fan_power_req 1004, …). Čtení holdingu mimo tento blok vrací exception 2 (Illegal Data Address).
Rozhodnutí
- Root cause „chronicky nemocné atrea": 5 senzorů (1201, 1202, 1203, 1205, 1206) bylo chybně
input_type: holding→ exception 2 každých 5 min, zaplavovalo error log a dělalo zreload_allminu (doorbell incident 2026-06-14). Opraveno přepnutím nainput_type: input. Tím je root cause pryč; opatrnost vůčireload_allv ha-deploy skillu ale zůstává jako obecná zásada. - Model řízení = jen výkon ventilátorů zapisovat, zbytek číst. Aktivní zápis pouze do
fan_power_req(holding 1004) přesinput_number.atrea_vykon_ventilatoru+ automatizaciatrea_zapis_vykonu_ventilatoru(mode: restart kvůli limitu 30 relací / 30 s). Režim (work_regime) a bypass zůstávají read-only. - Bypass se neřídí ručně. Bypass v auto módu je samostatná termostatická automatika nad teplotami (otevře, když
Ti > Tpa zároveňTe < Ti). Ruční zápis by bojoval s protimrazovou/komfortní logikou jednotky. Free-cooling bypass je ale podmíněný netopnou sezónou — v topné sezóně jednotka prioritizuje udržení tepla a bypass pro chlazení nepovolí (jen ochranné pohyby). - Sezóna se řídí přes
H1010, práh na Modbusu není. Jednotka byla v topné sezóně i v červnu (I1010=2), protožeH1010=0(auto dle průměrné T-ODA) a servisní práh ~16 °C je na dobře izolovaný dům s velkými solárními zisky moc konzervativní. NastavenoH1010=1(auto dle průměrné T-ODA + tepelný zisk) → jednotka překlopí do netopné sezóny dřív, když detekuje vnitřní zisky. Práh teploty je servisní parametr v aTool, na Modbusu nedostupný (jde měnit jen režim přepínání). HA ovládání:input_select.atrea_rezim_sezony+ automatizaceatrea_zapis_rezimu_sezony; čtení:sensor.rekuperace_sezona(I1010),sensor.atrea_season_setting(H1010). - Noční chlazení (work_regime 5) je vrstva nad bypass automatikou — když jsou splněné podmínky, navýší průtok ventilátorů pro rychlejší noční výplach tepla. Není to proxy na bypass. Proto se trvale nezapíná (přes den nic navíc nepřinese, jen vyšší spotřebu/hluk); spíná se cíleně z HA jen pro agresivní noční předchlazení.
- Autoritativní register mapa je nově v repu:
docs/manualy/atrea_duplex/(oficiální Atreamodbus_comm aMotionv04). Jednotka používá aMotion 4místné adresování (H10xx/I10xx), ne RD5 5místné.
Důvod
KISS a bezpečnost: výkon ventilátorů je jediná osa, kterou má smysl aktivně řídit (jednotka jede v power módu, fan_control_type=0). Průtokové registry reálně vrací 0 (pravděpodobně bez osazeného průtokového/tlakového čidla) — řídit přes flow_*_req by bylo k ničemu. Bypass i noční chlazení si jednotka obstará sama lépe, než by to dělala domácí automatizace.
2026-06-16 — Spotové ceny (OTE) + HDO tarif (NT/VT) jako vstup pro budoucí řízení dodávky FTV
Rozhodnutí
Nainstalovány dvě HACS integrace: rnovacek/homeassistant_cz_energy_spot_prices (spotová cena OTE, 15min, Kč/kWh) a Cmajda/ha_cez_distribuce (HDO NT/VT podle EAN odběru). Zatím jen sběr dat — žádné řízení dodávky/spotřeby. Detaily entit a obsluha: ceny_a_tarify.md.
Důvod
- Výkup za spot, odběr za fix — od 13. 6. 2026 připojena FTV výrobna. Výkup u EnerSpot = OTE spot − 300 Kč/MWh (0,30 Kč/kWh), odběr fix (E.ON Variant). Spotová cena je relevantní jen pro rozhodnutí „dodávat / nedodávat přebytek".
rnovacekzvolen místoha_epex_spot/Ge Spot— nativní OTE pro ČR, přepočet ČNB, 15min granularita sedící s EnerSpot zúčtováním; KISS, bez API klíčů.- Korekce prahu — práh není 0, ale 0,30 Kč/kWh. Původní záměr „nedodávat při záporném spotu" je moc nízký: v pásmu 0–0,30 Kč/kWh je OTE kladný, ale výkup po odečtu marže záporný → dodávka prodělečná. Práh pro dodávku = OTE ≥ 0,30 Kč/kWh.
- HDO (D57d) přidáno, ale nesouvisí přímo se spot výkupem — řídí odběr (kdy TČ topí za NT), užitečné až pro self-consumption (přebytek do TČ/bojleru, když se dodávka nevyplatí).
Operační dopad
- Obě integrace žijí jako HACS custom_components + config entry v
.storage, tj. mimo git (gitignored). Po reinstalaci HA nutná ruční reinstalace přes HACS + config flow — viz „Co dělat, když to nefunguje" v ceny_a_tarify.md. - Samotné řízení dodávky (template senzor výkupní ceny, binary „vyplatí se dodávat", napojení na střídač/curtailment) je otevřená položka — viz todos.md.
2026-06-15 — Syslog ingest přesunut z HA na standalone Alloy na debian-services (logging review ⑧)
Rozhodnutí
Syslog collector už neběží v HA Alloy addonu. Nový standalone Alloy (grafana/alloy:v1.16.3, docker) na debian-services přijímá veškerý syslog (UDP 5514 / TCP 5601) a píše do lokálního Loki. HA Alloy addon osekán na jen journal pipeline. Relay (nativní rsyslog na debian-services) zůstává a jen přesměrován na lokální Alloy.
Důvod
- Odstranění SPOF: dřív Alloy syslog listener běžel na HA → restart/výpadek HA (časté, kvůli config deployům) zahodil syslog ze VŠECH zařízení právě v okamžiku incidentu (UDP se nebufferuje). Teď syslog ingest sedí u Loki na debian-services — výpadek HA logování zbytku domu neovlivní.
- Konec round-tripu: zdroje dřív tekly debian (relay) → HA (Alloy) → debian (Loki). Teď vše lokální na debian-services.
- Journal zůstává na HA záměrně: systemd journal HA Core/addonů se čte lokálně, nelze sbírat vzdáleně. Dva collectory podle lokality = správně, ne duplikace. Sjednocení na jeden (forward journalu jako syslog) zamítnuto — ztratilo by strukturovaná pole (
unit/container_name) a rozbilo HA dashboardy.
Provedení / verifikace
Bezpečné pořadí bez výpadku ingestu: ① nový Alloy additivně (test RFC5424 → hostname OK) → ② přepnout relay forward 192.168.20.7:5514 → 127.0.0.1:5514 → ③ repoint pmx/PBS 99-loki.conf na 192.168.20.20:5514 → ④ oseknout HA addon (deploy přes ha-deploy, restart addonu). Po každém kroku ověřeno v Loki přes servername label (debian-services vs HomeAssistant). Výsledek: 100 % job=syslog má servername=debian-services, journal teče dál, oba freshness alerty normal.
Operační dopad
- Nový kontejner
alloyvdocs/files/docker/debian-services/docker-compose.yml; configdocs/files/docker/debian-services/alloy/config.alloy. Deploy přesscp+docker compose up -d alloy. - Relay config nově verzován:
docs/files/config_backups/debian-services-relay/. - Nový přímý RFC5424 zdroj →
docs/files/config_backups/99-loki.conf(cílí na192.168.20.20:5514). - Bracket
[hostname]hack i relay zatím zůstávají — standardní Alloy build by mohl__syslog_message_hostnamepopulovat nativně (retire bracketu + relay), ale neověřeno; ponecháno jako budoucí optimalizace.
2026-06-15 — Zrušen automatický GitOps deploy → ruční deploy přes skill ha-deploy
Rozhodnutí
Odstraněn celý HA-side auto-sync: automatizace System - Git Auto-Sync (5min cron), HA GitOps - Apply Synced Changes, HA GitOps - Failure Alert; skripty auto_sync.sh, safe_update.sh, preview_update.sh; status/lock soubory a sensory ha_safe_update_*. Nasazení teď řídí skill ha-deploy (.claude/skills/ha-deploy/): po git push na master udělá pull na HA (shell_command.ha_git_deploy = git reset --hard origin/master), config check (s rollbackem při chybě) a cílený reload nebo restart podle změněných souborů.
Důvod
- Autonomie řešila neexistující problém. Každá změna stejně prochází pracovní session (commit/push dělá asistent na pokyn) — HA si nikdy nemusí změnu „najít sám". Auto-sync byl overengineering pro tenhle workflow.
- Byl aktivním zdrojem incidentů. Za dva dny dvakrát: lock/status race (deploy se neaplikoval, viz entry 2026-06-14) a
reload_allzaseknutý na nemocnémmodbus atrea(2 h výpadek rest+template domény, viz entry 2026-06-14). Méně pohyblivých částí = ména ploch na selhání. - Cílený reload místo
reload_all. Skill volá jenautomation.reload/template.reload/rest.reload… podle toho, co se změnilo —reload_all(který kaskáduje přes modbus a zasekl se) se už nepoužije.
Operační dopad
- Po push se deploy nestane sám — musí ho spustit skill
ha-deploy(asistent) nebo člověk ručně přes Vývojářské nástroje → Akce →shell_command.ha_git_deploy+ reload/restart v UI. Postup bez AI je zdokumentován vhomeassistant.md. - Ztracená drift-protection (auto
reset --hardpři lokální editaci) je nahrazena disciplínou „edituj jen v gitu" + pasivnímbinary_sensor.ha_gitops_stale(bez alertu). - Zachována pasivní viditelnost:
sensor.ha_config_commitvs.sensor.ha_github_commit,binary_sensor.ha_gitops_stale.
2026-06-14 — Zvonek unavailable: GitOps reload_all zaseknutý na modbus atrea (ne digest, ne breaking change)
Příčina
Po ranním HA update-restartu na core-2026.6.3 se v 06:49 UTC spustila automatizace „HA GitOps - Apply Synced Changes" a zavolala reload_all. Ten reload se zasekl na trvale nezdravém modbus atrea (registry 1201–1206 vrací pymodbus isError) a nedoreinicializoval rest ani template doménu. Setup domén při startu byl přitom úspěšný a rychlý (rest 0.20 s, template 0.02 s) — entity fungovaly ~10 min (anyone_home naběhl on v 06:40), než je ten reload_all shodil. Jde o druhý projev GitOps apply problému (viz entry „GitOps apply: race mezi lock a status sensorem" níže).
Důsledky
Všechny rest + template + modbus entity zůstaly unavailable ~2 h: binary_sensor.doorbell_ring, sensor.doorbell_call_status, binary_sensor.anyone_home, FTV/Victron/Ecoforest template sensory atd. Prakticky: nešlo zvonění (automatizace zvonek_zvoneni_a_notifikace nikdy nedostala trigger), zmizely odvozené FTV/klima senzory.
Oprava
Ruční template.reload (oživil template doménu bez výpadku) → čistý homeassistant.restart (obešel zaseknutý reload_all, všechny domény naběhly zdravě) → shell_command.reset_update_status (status visel na restart). Čistý restart degradaci nezpůsobuje — problém je výhradně reload_all, ne start.
Falešné stopy (zdokumentováno, ať se nehledá znovu)
- httpx digest (#85888): vyvráceno —
httpx 0.28.1(verze v core-2026.6.3)DigestAuthproti doorbell ISAPIcallStatusověřeně vrací HTTP 200/idle. Digest funguje. - Breaking change „legacy template syntax" (2026.6): netýká se — config nemá
platform: templatenikde (jenmodbussensors:, jiná integrace).template.yamlje modernítemplate:syntax.
Rozhodnutí — doorbell zůstává na nativním REST
Ring detekce zůstává na rest sensoru (rest.yaml, digest přes httpx). Dočasně nasazený command_line+curl --digest workaround (commit 81e1fa6) byl vrácen (ab5e691), protože digest funguje a REST je KISS jednodušší — bez shell skriptu a parsování hesla ze secrets.yaml. Entity registry pak vyžadovalo ruční úklid (smazat orphaned *_cmdline záznamy, přejmenovat REST *_2 → původní entity_id).
Lessons / follow-up
reload_allje jen tak robustní jako nejnemocnější YAML integrace. Nemocnýmodbus atreaudělá zreload_allminu. Viz todos: guard/oprava atrea + zvážit nepoužívat automatickýreload_allpo startu.- Diagnostická past: silná korelace „rozbilo se to po updatu" svedla na unáhlenou úzkou hypotézu (digest). Skutečný rozsah (celá
rest+templatedoména, ne jen doorbell) ukázal jiný root cause. Loki HA core logy ze startu ({service_name="homeassistant"}) byly klíčové —Setup of domain …časy +Apply Synced Changesv 06:49.
2026-06-14 — Hostname labely pro infra syslog (pmx/PBS template, pfSense přes relay)
Rozhodnutí
Všechny syslog zdroje teď do Loki dorazí s hostname labelem. pmx1/pmx2/PBS: jejich 99-loki.conf template prependuje [%HOSTNAME%] do MSG (forward zůstává přímý na HA:5514). pfSense: přesměrován z přímého HA:5514 na rsyslog relay 192.168.20.20:514.
Důvod
Alloy loki.source.syslog v community buildu (v0.0.8) nepopuluje __syslog_message_hostname; jediný funkční způsob extrakce hostname je regex nad [hostname] prefixem v těle zprávy (loki.process stage). Stockový RFC5424Format template prefix nepřidává → pmx1/pmx2/PBS/pfSense dřív dorazily bez hostname (nešlo je rozlišit). Oprava per-zdroj:
- pmx/PBS mají vlastní rsyslog → stačilo do jejich self-defined
RFC5424Formattemplate doplnit[%HOSTNAME%](chirurgická změna, přímá cesta zachována, ověřeno proti funkčnímu relay template). - pfSense GUI neumí vlastní syslog template → nelze přidat bracket na zdroji, proto přesměrován na relay, který bracket přidává centrálně. Trade-off: pfSense logy závisí na relay (debian-services), ale ten hostuje i Loki — žádný nový SPOF.
Operační dopad
- LogQL filtrování
{job="syslog", hostname="pmx1"}atd. funguje pro celou infrastrukturu; dashboardy „Syslog Overview" / „Infrastructure Health" (agregace per hostname) jsou tím smysluplné. - pfSense hostname =
pfSense.marada.lan(FQDN, ostatní mají krátké jméno — kosmetická nekonzistence, viz todos ⑦). - Nový přímý RFC5424 zdroj nasazuj přes verzovaný
docs/files/config_backups/99-loki.conf(obsahuje bracket template), jinak dorazí bez hostname.
2026-06-14 — Grafana log-freshness alerting + patch bump (odložení majoru na 13.x)
Rozhodnutí
Nasazen provisionovaný Grafana alerting (Telegram contact point + policy + dvě „log source silent" pravidla pro journal a syslog), nový dashboard „Log Pipeline Health". Grafana bumpnuta jen v rámci minor větve 12.3.3 → 12.3.7, ne na major 13.0.2.
Důvod
- Freshness alerting je přímá pojistka proti incidentu z 2026-06-12 (mrtvý journal 3 měsíce bez povšimnutí).
noDataState: Alertingchytí i úplné zmizení jobu, ne jen pokles na nulu — přesně ten případ. - Patch místo majoru: 13.0.0 je stará ~2 měsíce; major verze Grafany nesou regrese typicky právě v provisioningu/alertingu, který jsme zrovna nasadili — stackovat major na čerstvou věc = zbytečné míchání proměnných při případném debugu. 12.3 je aktivně patchovaná (12.3.7 z 9. 6.), takže žádná urgence. Na 13.x až vyjde 13.1.x (odchycené
.0regrese) nebo až se 12.3 blíží EOL. - chatid jako literál, ne env: Grafana při env-expanzi provisioning hodnot zahodí string-quoting u čistě numerické hodnoty →
chatidz env selže na unmarshal. Chat id navíc není secret (bez bot tokenu je k ničemu), takže literál v repu je čistší než křehký workaround. Secret (bot token) zůstává v env.
Operační dopad
- Výpadek log pipeline (journal i syslog) teď přijde na Telegram do ~15 min. Stejný bot/chat jako
log_monitor.py. - Alerting je provisionovaný = v UI read-only; změny jen přes repo + redeploy Grafany.
- Provisioning failure je pro Grafanu fatální (nenastartuje) — YAML chyby v
provisioning/alerting/shodí celou Grafanu, ověřuj logy po deployi.
2026-06-14 — GitOps apply: race mezi lock a status sensorem (restart se neaplikoval)
Příčina
Automatizace „HA GitOps - Apply Synced Changes" měla tvrdou podmínku binary_sensor.ha_safe_update_running == off. safe_update.sh ale zapíše status (reload/restart) až úplně na konci a hned exitne — lock adresář mizí přes trap v řádu milisekund po zápisu statusu. HA čte obě hodnoty dvěma nezávislými command_line sensory s pollem 5 s; status sensor zaznamenal změnu na restart dřív, než lock sensor stihl přečíst, že lock už je pryč. Trigger se spustil, podmínka viděla zastaralé on → akce se zahodila, restart se nikdy neprovedl a status visel na restart.
Důsledky
Deploy TČ Energy (2026-06-12) se zasekl — commit stažen, ale HA nerestartovalo, takže nové entity nebyly. Obejito ručně (shell_command.reset_update_status + homeassistant.restart). Postihlo by to každý restart-class deploy.
Oprava
Tvrdá podmínka nahrazena wait_template na binary_sensor.ha_safe_update_running == 'off' (timeout 30 s, continue_on_timeout: true) na začátku akce. Lock je v okamžiku triggeru fakticky vždy už uvolněný (status se nastaví až po dokončení), takže wait jen dopolluje zaostávající sensor a po timeoutu bezpečně pokračuje. automations.yaml je reload-class, fix se nasadil bez výpadku.
Lessons / follow-up
- Pozor na podmínky čtoucí dva nezávisle pollované sensory, které mají být konzistentní — mezi nimi je vždy okno až do délky poll intervalu. Buď jeden zdroj pravdy, nebo
wait_templatemísto bodové podmínky.
2026-06-14 — mDNS hostname-conflict storm na HA (Avahi reflector × dual-NIC)
Příčina
HA OS má dvě NIC na stejném hostu: enp0s18 (LAN, 192.168.20.7) a enp0s19 (IoT VLAN, 192.168.40.7). systemd-resolved publikoval homeassistant.local na LAN. pfSense Avahi reflector (allow-interfaces=vtnet1,vtnet2,vtnet3,vtnet4) tenhle announcement reflektoval z LAN (vtnet1) do IoT VLAN (vtnet3), kde ho HA druhý NIC enp0s19 zachytil jako „cizí" host claimující vlastní jméno → konflikt → přejmenování homeassistantN → N+1 → znovu announce → reflektuje se → nekonečná eskalace.
Důsledky
~10 přejmenování/s, ~37 700 řádků/h balastu do systemd journalu a Loki (job="journal"), čítač published jména dosáhl 30 000+. Systémový hostname zůstal celou dobu homeassistant (jde jen o dočasný mDNS-published suffix). Loki retention a čitelnost journalu citelně zaneseny. Konfliktní adresa byla vždy 192.168.20.7 — tj. LAN announcement vracející se přes IoT linku.
Oprava
Odebrání IoT (vtnet3 / OPT2) z Avahi reflectoru: pfSense GUI → Services → Avahi → Settings → odškrtnout IoT interface → Save. avahi-daemon.conf je auto-generovaný balíčkem („Do not edit this file" — přímá editace přes SSH se při příštím save přepíše), proto jen GUI. Verifikace: count_over_time konfliktů spadl z ~37 700/h na 0 do několika sekund po restartu avahi. Rollback: zaškrtnout IoT zpět.
Lessons / follow-up
- Proč tahle cesta a ne HA-side
ha network update enp0s19 --mdns off: odebrání z reflectoru zachová HA nativní mDNS announce+resolve na IoT VLAN (ESPHome/zeroconf discovery nových zařízení dál funguje), zatímco--mdns offby ho uřízl. Navíc opravuje latentní bug — IoT zařízení teď resolvujíhomeassistant.localna správnou192.168.40.7(dříve reflector cpal do IoT VLAN.20.7, což je cross-VLAN firewallem blokovaná adresa). - Vědomý trade-off: IoT mDNS je teď plně izolovaný od ostatních VLAN. Cross-VLAN discovery IoT zařízení napřímo po
.local(mimo HA, mimo CUPS/AirPrint proxy na debian-services) přestane fungovat — IP funguje dál. Pokryto: Aqara FP2 ap. → HA na IoT nativně; tiskárna → AirPrint announce z debian-services (LAN). Reflector zůstal pro LAN↔GUEST↔MEDIA (AirPlay nedotčen, vizdocs/technologie_domu/media.md). - Obecné pravidlo: mDNS reflector + multi-homed host = riziko conflict loopu. Při přidávání dalšího dual-homed stroje do reflektovaných VLAN tohle ověřit.
2026-06-12 — Journal pipeline do Loki byl 3 měsíce mrtvý (Alloy override config)
Příčina
Vlastní override config Alloy addonu (alloy/config.alloy) měl v loki.source.journal dvě chyby proti configu, který si addon generuje sám:
- Chyběl
path = "/var/log/journal"— bez něj Alloy hledá journal podle machine-id svého kontejneru a tiše čte nula řádků. Host journal je do kontejneru mountnutý právě na/var/log/journal(addon optionjournald: true). forward_tosměřoval přesloki.relabel.journalkomponentu — relabel pravidla se ale aplikují už u zdroje (relabel_rules); druhý průchod běží až po zániku__journal_*metadat,regex "(.*)"matchne prázdný řetězec a labelyunit/app/hostnamesmaže.
Důsledky
Od 2026-03-17 12:07 do 2026-06-12 nebyly v Loki žádné logy HA Core, addonů ani Z2M (job="journal" neexistoval). Nikdo si toho nevšiml — žádný alert na výpadek log source neexistuje a log_monitor.py prázdný výsledek journal query interpretuje jako „čisto". Diagnostický klíč: Alloy web UI hlásil komponentu „healthy", ale metrika loki_source_journal_target_lines_total = 0 (healthy ≠ čte data).
Oprava
Dva commity do alloy/config.alloy (8993271, c9fdca5): doplněn path, forward_to přepojen rovnou na loki.write.endpoint.receiver. Po restartu addonu journal teče s plnými labely. Rollback: revert commitů + restart addonu.
Lessons / follow-up
- „Healthy" stav Alloy komponenty znamená jen „běží" — při debugu vždy číst metriky (
:12345/metrics). - Při override configu addonu vždy diffovat proti generovanému configu addonu (
rootfs/etc/cont-init.d/alloy_setup.shv repu addonu). - Korekce dřívějšího závěru: pfSense filterlog do Loki teče (~1,7M řádků/den, 97 % celkového objemu), jen bez
hostname/applabelů, takže je nedohledatelný. Gotcha „filterlog neteče" v.agent/memory/MEMORY.mdbyla mylná — opravena. - Celkový review loggingu 2026-06-12 odhalil další otevřené body (retence Loki vypnutá, žádné freshness alerty, stale dashboardy, RFC5424 zdroje bez hostname) — viz
todos.mdsekce Monitoring Stack.
2026-06-12 — TČ v Energy dashboardu: Riemann integrace + proporční breakdown po službách
Rozhodnutí
Spotřeba TČ pro HA Energy se počítá Riemann integrací okamžitého příkonu (reg 2193, polling 30 s), ne z energetických counterů TČ. Breakdown DHW / bazén / topení vzniká proporčním rozdělením 2193 podle okamžitých tepelných výkonů služeb (reg 2187/2188/2189); zbytek (standby, čerpadla) jde do bucketu „Other", takže buckety sedí přesně na celek. Implementace: modbus/ecoforest.yaml + template.yaml (ecoforest_electric_power_*) + nový sensor.yaml (ecoforest_electric_energy_*).
Důvod
TČ nemá lifetime kWh registr ani per-service elektroměr — jen denní/měsíční/roční countery, které se resetují. Reset + jediný vadný read přes Modbus bránu (192.168.40.34, historicky náchylná k timeoutům) by total_increasing statistiku napočítal dvakrát; Riemann integrace je vůči výpadkům čtení robustní (jen po dobu výpadku neroste). Denní counter 2206 se čte pouze jako diagnostika/cross-check. Proporční split je korektní aproximace, protože kompresor obsluhuje služby sekvenčně.
Vědomá omezení
- Bazénovou VZT (DG1) ani podlahu baz. haly (SG3) nelze oddělit od topení domu — z pohledu TČ je to jedna služba „heating", okruhy berou z akumulačky bez měření. Jemnější rozpad = kalorimetry na okruzích (zamítnuto, overengineering bez rozhodovacího use-case).
- Hodnoty jsou interní odhad TČ (z inverteru), ne fakturační měření.
- Spotřebu klimatizací (Daikin) přes Modbus číst nelze — EKMBDXA/DIII protokol energetická data vůbec nepřenáší (ověřeno proti celému manuálu). Případné řešení = podružné měření na přívodu venkovní jednotky (např. Shelly Pro EM).
Operační dopad
4 nové buckety v Energy dashboardu (Individual devices); provozní popis pro rodinu: docs/technologie_domu/vzduchotechnika/tepelne_cerpadlo.md §„Spotřeba TČ v HA Energy dashboardu", technický detail: docs/manualy/ecoforest_ecogeo/modbus.md.
2026-06-12 — HACS závislosti dashboardů + Aseko integrace (evidence)
Rozhodnutí
Evidujeme externí HACS závislosti, na kterých stojí konfigurace, aby budoucí „odkud se to tu vzalo / můžu to smazat" mělo odpověď:
- expander-card (
Alia5/lovelace-expander-card) — rozbalovací sekce na Klima dashboardu (dashboards/klima.yaml). Bez ní se karty zobrazí jako „Custom element doesn't exist". - AlexxIT/WebRTC Camera — two-way audio doorbellu v dashboardu (viz doorbell sekce v MEMORY.md).
- scrypted-advanced-notifier / @scrypted/mqtt — doorbell → MQTT → HA most.
- Aseko bazén — integrace přes HACS
aseko_local(lokální, ne cloud) → senzory chemie/zdraví bazénu.
Důvod
Tyto integrace nejsou v repu (HACS custom_components/ je gitignorovaný), takže z konfigurace samotné není poznat, že na nich něco závisí. Bez evidence hrozí, že se po čisté reinstalaci HA „ztratí" a dashboardy/funkce se rozbijí bez zjevné příčiny.
Operační dopad
Po reinstalaci HA / migraci nutno tyto HACS balíčky doinstalovat, jinak: Klima dashboard rozbitý (expander-card), doorbell bez two-way audia (WebRTC), bazénová chemie bez dat (aseko_local). Operační detaily expander-card: docs/chytry_dum/home_assistant/dashboardy.md.
2026-06-12 — WiFi: AP8 carport, NP2 kanály pinned, doc_gen_unifi na API-key auth
AP8 carport přidán (192.168.20.18)
Venkovní U7 Pro Outdoor (UAPA6B0) adoptován, pfSense rezervace .18 (hostname ap8-carport), uplink USW-48-PoE port 8 (1 Gbps, PoE 25.5 W). AP2 (U6-LR, .12) je záměrně odpojen — čeká na přemístění; v controlleru zůstává adoptovaný.
Radio fix: Min RSSI off + NP2 kanály fixní
Rozhodnutí: AP1 měl na 2.4 GHz zapnutý per-radio Min RSSI (-75) → vypnuto. AP6+AP7 běžely na auto kanálech a RRM je posadil do co-channel kolize na obou pásmech (2.4 ch11 + 5G ch48) → kanály zafixovány: AP6 = 11/48, AP7 = 6/44. NP2 je tím čisté: 2.4 GHz 1/6/11 (AP1/AP7/AP6), 5 GHz 36/44/48.
Důvod: Min RSSI kick je dokumentovaný anti-pattern pro Apple klienty (wifi.md). Auto-RRM se ukázal jako nespolehlivý u sousedních AP — fixní kanály jsou deterministické.
Jak: Přímo přes classic API (PUT /rest/device/<id> s radio_table), MCP server zápis rádií neumí. Ověřeno live po reprovisioningu.
doc_gen_unifi.py: API-key auth + síťový watchdog
Rozhodnutí: Skript přepsán z user/password loginu (účet už neexistuje → 403) na API klíč UNIFI_MCP_API_KEY z .env (header X-API-KEY) — tentýž credential, který používá UniFi MCP server. Zamítnuta varianta „skript volá MCP": vrstva navíc nad stejným HTTP API, MCP toolset má díry (žádné get/setting, stat/rogueap, zápis rádií) a závislost na third-party balíčku.
Rozšíření: watchdog celé sítě — offline zařízení, firmware drift, roaming assistant na WLAN, auto-kanály, airtime, uplink speed, port flapping/errors/STP, PoE budget, weak clients, kanálové konflikty obou pásem. Issues sekce je v generovaném dokumentu první.
Pozn. k Network 10.x API: rest/device (GET) a stat/event s API klíčem nefungují (404); konfigurace zařízení vč. port_overrides je ale celá ve stat/device.
Nálezy z prvního běhu watchdogu (k řešení)
- Roaming Assistant zapnutý na WLAN úrovni u SSID
wifi,wifi guest,media(5 GHz, -75 dBm) — vypnout (viz todos). sw-dilnaport 7: 4650× link down (flapping) + chyby; port 5: 165k TX errors při 10M linku — prověřit kabeláž v dílně.
Druhé kolo (téhož dne)
- AP5 a AP8 kanály zafixovány na aktuální hodnoty (AP5 = 6/36, AP8 = 6/40) — žádná RF změna, jen vypnutí auto-RRM. Všech 7 online AP má teď fixní kanály.
- „Remote syslog vypnutý" byl false positive watchdogu — settings klíč je
rsyslogd, nersyslog(bug zděděný ze staré verze skriptu). Syslog je zapnutý (192.168.20.20:514) a v Loki ověřeno, že logují všechna AP i oba switche. Skript opraven. - Cross-check UniFi vs. pfSense rezervace přidán do watchdogu (
check_pfsense_reservations, pfSense v2 API, auto-skip bezPFSENSE_API_KEY), ne docheck_consistency.py— ten je záměrně offline CI gate. První běh: všechna adoptovaná zařízení rezervace mají.
Roaming Assistant vypnut na všech SSID (třetí kolo)
Rozhodnutí: WLAN-level Roaming Assistant (min-RSSI kick, -75 dBm na 5 GHz) vypnut na wifi, wifi guest, media přes rest/wlanconf.
Důvod: V hustém pokrytí 7 AP s 802.11v/r a laděnými výkony je benefit nulový (Apple klienti roamují sami), zatímco kick škodí na venkovní hraně dosahu (zahrada/auto u AP8 — žádné lepší AP neexistuje, klient se dostane do kick-reconnect smyčky) a u stacionárních zařízení na media (AirPlay dropouty).
Korekce historie: Dřívější zdůvodnění ve wifi.md („No Internet / DNS drop po roamingu") mylně přisuzovalo Min RSSI symptom, jehož skutečnou příčinou byly out-of-sync MAC tabulky mezi dvěma switchi (FDB problém, vyřešen 2026-02 konsolidací AP na jeden USW-48-PoE). wifi.md opraveno — zdůvodnění odděleno od incident-specific poznatků; kanálová tabulka aktualizována na pinned plán.
2026-06-10 — GitOps pipeline: cílený reload místo plošného restartu + alerting
Rozhodnutí
Auto-sync pipeline (GitHub → HA) nově aplikuje změny podle typu: no_action (docs, skripty, dashboardy, AppDaemon, Z2M/Alloy configy) · reload (automatizace, scripts, scény, template, input_*, rest, blueprints → homeassistant.reload_all, bez výpadku) · restart (configuration.yaml, modbus/, climate.yaml a vše neznámé → plný restart, povolen kdykoliv). Selhání pipeline nově alertuje na mobil.
Důvod
Původní automatizace „Restart After Success" restartovala celý dům po každém konfiguračním commitu, proto byla v březnu 2026 vypnutá — od té doby se změny aplikovaly jen ručně, což tiše porušovalo předpoklad „dům se aktualizuje sám". Navíc měla design umožňující restart-smyčku (trigger to: success bez resetu status souboru) a auto_sync.sh uměl při rozbitém git fetch navždy tiše hlásit „up to date". Reload pokrývá ~80 % běžných commitů bez výpadku, takže auto-aplikace už není obtěžující a lze ji mít zapnutou. Smyčka je vyloučena designem: automatizace status resetuje na idle dřív, než akci provede.
Operační dopad
- Commit do dashboardů/docs = žádná akce; běžné YAML = reload bez výpadku; core soubory = restart HA (~1–2 min).
- Nové entity:
binary_sensor.ha_gitops_stale(nasazený commit ≠ GitHub), automatizaceHA GitOps - Apply Synced ChangesaHA GitOps - Failure Alert(mobil: vadný commit hned, fetch fail >20 min, stale >30 min). - Změny
zigbee2mqtt/configuration.yamlvyžadují ruční restart Z2M addonu (HA restart je neaplikuje). - Plný popis a troubleshooting:
docs/infrastruktura/servery/homeassistant.md, sekce GitOps.
2026-06-10 — Canon GX7040: oprava DNS + síťové hardening
Root cause „nemůže se připojit k internetu"
Tiskárna hlásila chybu připojení k internetu, přitom lokální tisk (CUPS přes IPP) fungoval — proto byl výpadek neviditelný. Příčina: DNS bylo ručně nastavené na 0.0.0.0 (manual setup). Cloud služby Canonu (a SMTP) nerozresolvovaly. Oprava: DNS přepnuto na Auto setup (přebírá z DHCP → pfSense 192.168.40.1). Proxy = Do not use, IP/gateway v pořádku (DHCP rezervace 192.168.40.8).
Lesson: lokální IPP tisk maskuje výpadek WAN/DNS na tiskárně. Monitoring přes HA IPP integraci (stav + inkousty) odhalí unavailable dřív, než to zjistí uživatel u tiskárny.
Síťové hardening — vypnuté nepoužívané discovery/print protokoly
CUPS na debian-services tiskne výhradně přes ipp://192.168.40.8/ipp/print (ověřeno CUPS web UI). Proto vypnuto:
- WSD (Windows discovery) — nikdo netiskne přímo z Windows do IoT VLAN.
- LPD/LPR (515), RAW (9100), LLMNR — CUPS je nepoužívá.
Ponecháno zapnuté: IPP (631), Bonjour/AirPrint, SNMPv1 (community public, read-only — pro monitoring). Ověřeno z LAN po změně: 631 succeeded, 9100 + 515 refused, tisk funguje. Rollback = checkboxy zpět v Remote UI → System info → LAN → Advanced setup. IP/IPsec filtering ponecháno vypnuté — segmentaci řeší pfSense (IoT izolovaná od LAN).
Scan-to-email: přímé SMTP místo Canon cloudu
Canon cloud scan-to-email má limit 4 strany → nepoužitelné. Řešení: přímý SMTP (Printer settings → Set mail server), který limit nemá (strop = velikost přílohy mailserveru). Příjemci pro víc lidí přes Scan(Email direct from device) adresář. IJ Cloud Printing Center záměrně neregistrováno (cloud závislost + zdroj přesně té chyby s internetem). Chyba 3414 = nenastavený mail server, zmizí po vyplnění SMTP.
Doc fix
firewall.md uvádělo IP tiskárny 192.168.40.9 — reálně 192.168.40.8 (souhlasí inventory + DHCP rezervace). Opraveno.
2026-06-02 — Zahradní domek: detail střešního přesahu, rozteč latí, mřížky
Stav stavby: skelet + OSB opláštění stěn i záklop střechy hotové, přesah OSB ~150 mm všemi směry (víc než původně plánovaných 60 mm). Dveře na východ, spád na západ.
Rozhodnutí
1. Wraparound přesahu místo open-eave s čelním prknem dokola. Střešní folie se zahne kolem hrany OSB na spodní stranu přesahu a shingle-lapem překryje stěnovou folii (souvislá obálka). Podhled tvoří plotovky 120×19 (stejný variabilní rastr jako stěny) šroubované přímo přes folii do OSB, bez provětrávací latě — na podhled neprší ani nesvítí, mezery 10–15 mm mezi plotovkami k odvětrání stačí; větraná mezera je detail pro plochy exponované dešti/UV.
2. Hrany přesahu — dvě dýchají, dvě se zavírají. Mezera kontralať+lať pod plechem (~80 mm) je průtočný kanál podél spádu: zadní hrana (okap, západ) = sání → větrací okapní pás (hřebínek proti ptákům), přední hrana (hřeben, východ) = výdech → čelní prkno se štěrbinou ~20 mm pod odsazenou/perforovanou ukončovací lištou. Boky (podél spádu) se uzavírají: krajní kontralať na hraně OSB + čelní prkno KVH 120×19 (skladba čela ~117 mm ≈ výška prkna 120 — sedí). Uzavřít všechny čtyři hrany = mrtvá kapsa, kondenzát zpod plechu nemá kam schnout.
3. Ventilační štěrbina stěnového rastru: 15–20 mm mezi horní hranou stěnových plotovek a podhledem. Výstup 40mm větrané mezery za stěnovým rastrem (vzduch → prostor pod podhledem → ven spárami podhledu). Kritické nezalepit/nedotáhnout prkna na doraz.
4. Rozteč vodorovných latí stěn ~550 mm (původně ~400 mm). KVH prkno 19 mm s 1 vrutem na lať potřebuje podporu max. ~600 mm; pod 500 mm je zbytečně hustě. 4 latě na zadní/boční stěnu, 5 na přední. Spodní lať 50–80 mm nad hranou OSB (fixuje folii), horní těsně pod věncem.
5. Ventilační mřížky podél spádu: výdech východ (přední) nahoře, sání západ (zadní) dole. Revize původního jih/sero návrhu (solární zisk na jih je reálný, ale druhořadý). Osa Z→V vyhrává ze dvou důvodů, které se sčítají: (a) šikmý strop pultovky žene teplý vzduch do nejvyššího (východního) koutu → výdech patří tam; (b) převažující západní/jihozápadní vítr v ČR → západní stěna návětrná (přetlak na sání), východní závětrná (podtlak na výdech), vítr posiluje komínový tah. Háček: západní sání je na návětrné straně (hnaný déšť) → žaluziová mřížka + nad zónou odstřiku. Pokud lokální vítr (plot, terén) míří jinam, řídit se realitou pozemku.
Zamítnuté alternativy
- Smrková prkna 19×100 místo KVH 60×40 na latě/kontralatě střechy — kontralať 19 mm = poloviční větraná mezera (minimum 40 mm); samořez plechu 4,8×35 by 19mm latí téměř prošel; tenký smrk praská při šroubování přes EPDM podložky. Úspora ~1 500 Kč nestojí za kompromis.
- Provětrávací lať pod podhledem přesahu — overkill (viz bod 1), navíc by zvýšila čelo o 40 mm a komplikovala krytí.
2026-06-01 — Meteo / srážkoměr: plán Ecowitt WS90 Powered by Shelly (Zigbee), odloženo
Rozhodnutí
Pro venkovní meteo (srážky + vítr + UV + solar) cílit na Ecowitt WS90 Powered by Shelly spárovaný přímo do stávajícího Zigbee koordinátoru přes Z2M nebo ZHA — bez Ecowitt RF gateway, bez Shelly hubu. Nákup odložený, dokud nedozraje HA integrace.
Důvod
- WS90 je 7-in-1 senzor: piezo srážkoměr (bez pohyblivých dílů), ultrazvukový anemometr, UV, solar radiation, teplota/vlhkost. Pokrývá víc než samostatný WH40, navíc bez mechaniky k zanášení.
- Shelly varianta používá standardní Zigbee 3.0 místo Ecowitt sub-GHz RF, takže odpadá samostatná gateway. Bluetooth slouží jen pro initial pairing.
- Alternativa klasická WS90 + GW2000 je dnes vyzrálá, ale přidává krabičku navíc a uzamyká do Ecowitt ekosystému. Pokud později budou potřeba další Ecowitt senzory (WH51 záhony, WH57 blesky, WH55 leak), gateway přidám tehdy — ne preventivně.
- Pro vyhřívání anemometru v zimě (proti sněhu/námraze) plánovat 12 V / 1 A power adapter + extension cord k WS90; solar topení neuživí.
- Umístění: zahradní domek (rozhodnuto 2026-06-17). Skrz stěnu jde jen 12 V DC napájecí kabel pro vyhřívání anemometru — síťový adaptér 230 V zůstává uvnitř, ven jde nízké napětí. Žádný datový kabel skrz zeď — data jdou bezdrátově přes Zigbee do koordinátoru. Průchodku dimenzovat na rezervu (vodotěsnost + tah, řeší se venkovní prostředí, ne síťové napětí).
Co blokuje nákup
- Z2M issue #31070: WS90 se spáruje, ale hodnoty se neaktualizují po počátečním reportu (chybný attribut reporting binding).
- ZHA quirks issue #4558: chybí decoding pro vítr (rychlost/směr/gust), UV index a srážky — tj. právě ty senzory, kvůli kterým WS90 kupuju.
- Bez fixu by senzor v HA reportoval jen teplotu/vlhkost = drahý teploměr.
Trigger pro nákup
- Z2M issue #31070 closed/merged a komunitní zpráva potvrzuje, že hodnoty se aktualizují, NEBO
- ZHA quirks #4558 merged a wind/UV/rain atributy mapované.
Stav 2026-06-18 — trigger SPLNĚN, nákup odblokován
- Z2M (náš stack, SLZB-MR3): WS90 device page má dnes plnou podporu — dekóduje vítr (speed/dir/gust), UV, srážky, teplota/vlhkost, osvit, baterii + odvozené (rosný bod, wind chill, rain rate…). Tím padá obava z „drahého teploměru".
- #31070 closed jako completed (2026-05-11): „hodnoty se neaktualizují" nebyl z2m software bug, ale firmware WS90. Řešení potvrzené v komentářích: před párováním (nebo po něm s re-pair) aktualizovat firmware přes Bluetooth/Shelly app, pak reporting stabilní. Pozor: stížnosti na stabilitu u fw 1.1.6 → po nákupu nahrát nejnovější fw a ověřit aktualizaci hodnot.
- #4558 closed jako completed (2026-04-04): ZHA quirk merged přes PR #4708, dodáno v HA 2026.4.0 (funguje bez custom quirku). Relevantní jen jako pojistka, kdyby se přešlo z Z2M na ZHA.
- Reziduální riziko = firmware reporting stabilita, ne decoding. Mitigace levná (BT firmware update). Nákup proto reálně možný hned.
Operační dopad
Žádný okamžitý — designové rozhodnutí pro budoucnost. Položka v todos.md sleduje stav obou issues. Pokud do ~12 měsíců nedozraje, přehodnotit (fallback: klasická WS90 + GW2000).
Vyloučené alternativy
- Hydreon RG-15 (optický): jen srážky, accuracy horší než tipping-bucket, komunitní podpora slabá.
- Davis Vantage Pro2: 15k+ Kč, profi liga, overkill pro homelab.
- Netatmo srážkoměr: cloud-dependent, proti self-hosted filozofii.
- Klasická Ecowitt WS90 + GW2000: funkční dnes, ale druhá gateway navíc; lépe počkat na čistší Zigbee path, dokud reálně nepotřebuju i jiné Ecowitt senzory.
2026-06-01 — Zahradní domek: fasádní folie Swisstherm Plus + detail spodní hrany
Rozhodnutí
Pod variabilní svislý rastr (mezery 10–15 mm mezi prkny) i pod střešní trapézový plech použít Swisstherm Plus 120 g s integrovanou páskou (milpe.cz, ~63 Kč/m², role 1,5 × 50 m). Spodní hranu folie NElepit k OSB butylem — řešit mechanicky tlakem spojní vodorovné latě + shingle lap přes čelo OSB + soklová perforovaná lišta.
Důvod — folie
- Otevřený rastr s mezerami 10–15 mm a ~13 % otevřené plochy vyžaduje fasádní folii certifikovanou pro otevřený rainscreen. Běžné střešní/fasádní DHV (Jutadach 135, Delta-Vent S) mají certifikaci typicky do 5 mm spár → tvůj případ překračuje limit. Swisstherm Plus je certifikovaný do 20 mm spár a 30 % otevřené plochy — komfortně pokrývá.
- UV stabilita za otevřeným rastrem trvale. Černá PE 0,2 mm by zkřehla za 2–4 roky kvůli UV skrze mezery.
- Integrovaná páska na hranách role řeší horizontální překryvy → odpadá samostatná role akrylové pásky na ně.
- Difúzní otevřenost zajistí odvod stavební vlhkosti z OSB ven přes větranou mezeru 40 mm. Funguje i po budoucím dodatečném zateplení.
- Cenová pozice: ~63 Kč/m² vs. Tyvek UV Facade ~280 Kč/m². Pro nezateplenou stodolu je Swisstherm Plus právě správná úroveň — Tyvek je premium overspend.
Důvod — detail spodní hrany (bez butylu)
Konflikt dvou požadavků: (1) voda zvenku za folii ne, (2) případný kondenzát/zafouklá vlhkost ven ano. Plné lepení butylem k čelu OSB splní (1) ale poruší (2). Mechanická fixace tlakem spodní vodorovné latě řeší obojí: folie pod laťí přitištěná po celé délce → těsné, pod laťí volně končí shingle lapem → kondenzát vykápne ven nad EPDM. Soklová perforovaná lišta uzavírá detail pohledově a brání hmyzu/myším.
Nákup
- 1× Swisstherm Plus 1,5 × 50 m s integrovanou páskou — ~4 700 Kč (milpe.cz)
- 1× Jutadach SP SUPER 50 × 25 m (univerzální fasádní akrylová) — ~360 Kč — vertikální spoje folie, ventilační mřížky, rezerva do dílny
- Butyl páska — NE, nepotřeba
- Soklová perforovaná lišta RAL 7016 — ~600–1 000 Kč — klempířský prvek (ne lepicí páska)
Celkem foliový systém: ~5 060 Kč.
Iterace v rámci rozhodnutí
Cesta k finálnímu výběru prošla několika kroky, které se vyplatí mít zaznamenané pro budoucí podobné detaily:
- Černá PE 0,2 mm (původně) → zamítnuto kvůli UV za otevřeným rastrem.
- DHV Jutadach 135 / Delta-Vent S → zamítnuto, certifikace nepokrývá spáry > 5 mm.
- Tyvek UV Facade → správný produkt pro dům, overspend pro stodolu (2× cena Swisstherm).
- Swisstherm Plus 120 g → finální volba (správná úroveň, certifikace pokrývá, integrovaná páska).
- Butyl na spodní hraně → původně doporučeno, korigováno: mechanická fixace pod laťí je správný detail (odráží původní záměr v
docs/projekty/zahradni_domek.mdpřed touto iterací).
2026-05-28 — Tepelné čerpadlo Ecoforest ecoGEO: dokumentace + read-only Modbus
Kontext
Zdokumentován realizační projekt vytápění (Veskom 24-2-0019) a navázáno Modbus mapování TČ Ecoforest ecoGEO B1 T5-22 HTR EH (zemní, 4 vrty). TČ má dva komunikační kanály: EasyNet (správa instalatéra) a paralelní BM2 RS485 Modbus port přes Waveshare bránu 192.168.40.34:502 do HA.
Stávající modbus/ecoforest.yaml byl spekulativní a nefunkční: senzory četly 0, switch.ecoforest_heat_pump byl ve skutečnosti coil 53 "control by BUS" (ne on/off), demand selecty zapisovaly reálné požadavky.
Rozhodnutí
- Fáze 1 = striktně read-only. Přepsán konfig na ověřenou register mapu (komunitní
bp-ouhaha/EcoForest-modbus-registers+ Ecoforest Modbus 2021), INPUT registry (FC04),int16+ scale 0.1, core set + alarm/demand/season discrete inputs. Žádné write entity. Řízení (setpointy pro FTV přebytky, dynamická křivka) je odložená Fáze 2 (vyžaduje "control by BUS", obchází část interlocků → až po testu v servisním okně). - Zimní program natrvalo. Control manuál potvrdil: Summer blokuje celý režim HEATING (i bazénovou halu); Winter povoluje HEATING+DHW+POOL. Sezónnost domu řešit přes Stop temperature for heating (globální práh pro všechny topné skupiny) + pokojové termostaty, ne přepínáním na léto.
- FTV patrony EP1/EP2 jsou řízené přímo z HA (Waveshare relé
modbus-rele-topeni), ne přes Ecoforest E-manager jak předpokládal projekt. Strategie přebytků: nejdřív kompresor (COP 3–5) přes setpointy, patrony až overflow.
Nález — špatná verze register mapy (vyřešeno → HP24)
Diagnostika (poller zastavený, čistý probe): brána OK (Modbus TCP→RTU, 19200 8N2), odpovídá slave 17, ale staré adresy (1–200/5000+, input FC04) vracely 0. Příčina: tahle jednotka používá mapu „HP24" (verze 24) — vše v HOLDING registrech (FC03), rozsah 2000+ (zdroj: TapHome template ecoforest-hp24). Stará komunitní mapa pro tuhle firmware generaci neplatí. Konfig přepsán na HP24 (venkovní 2080, DHW 2130, akumulačka 2132, program 2044, výkony 2186/2188/2193, patrony coily 2046/2047, …).
Blokace — fyzický RS485 (vyřešeno) → menu selektor BUS_HP24
Při ověřování instalatér zkoušel přehodit A/B a „vrátit". Slave 17 pak přestal odpovídat úplně; uživatel rozdělal TČ a našel jeden Modbus drát vypadlý ze svorkovnice — po vrácení slave 17 zase odpovídá. Kabel je tedy OK.
Zbývající blokace: HP24 registry (2000+) vrací „Illegal Data Address". Empiricky regulátor servíruje jen rozsah ~0–440 (samé 0), nic na 2000+. Po vyřešení od instalatéra (oficiální Ecoforest dokument „Modbus variables list HP24 V01.00 EN", str. 1) vyšlo najevo, že firmware v24 (WWD24 = ecoGEO B&C) podporuje DVĚ variabilní mapy (HP23 starší, HP24 nová) a jedna se vybírá v Installer Menu → Remote Control → „Selección BUS" mezi BUS_HP23 / BUS_HP24. Aktuálně je TČ na HP23 (nebo na žádné), proto HP24 adresy neexistují. Akce na instalatérovi: přepnout selektor na BUS_HP24. Pak HA konfig (přepsaný podle oficiálu) okamžitě začne číst.
Korekce — TapHome měl místy špatně
Oficiální Ecoforest dokument vyvrátil dvě věci, které měla TapHome HP24 šablona špatně:
- Tlaky mají gain 0,1 (/10), ne 0,01 (/100).
- Aux topidla 2046–2050 jsou holding registry s 0/1 (typ A), NE coily (TapHome měl prefix
C:). Pět aux registrů, ne dva: 2046 integrated, 2047 external generic, 2048 DHW aux (EP1), 2049 BUFFER aux (EP2), 2050 chiller. Adresy 2048/2049 přesně odpovídají patronám EP1 a EP2, které v tomto domě HA řídí přes Waveshare relé — TČ teď bude umět vidět, kdy jsou patrony aktivní.
Strategie — Fáze 2 přes registr 2775+2777
Oficiální mapa odhaluje elegantnější cestu pro FTV: 2775 Surplus control enabled by BUS + 2777 Surplus regulation setpoint (kW). HA řekne TČ „máme N kW přebytku" a TČ si samo nastaví výkon kompresoru — nemusí HA psát do jednotlivých setpointů. To je preferovaná cesta pro Fázi 2.
RESOLUTION (2026-05-28 večer) — BMS port byl v MB Slave místo MB Extended
Po dlouhém debugu se ukázalo, že selektor BUS_HP24 byl správně (instalatér), ale BMS port (kam fyzicky vede gateway) byl nastaven na MB Slave, ne na MB Extended. V základním režimu port odpovídá, ale neservíruje rozšířenou variabilní mapu (HP24 registry 2000+ vrací Illegal Data Address). Symptom přesně sedí: 0–~440 valid ale samé 0, 2000+ illegal. Uživatel přepnul Installer Menu → Externí řízení → Řízení BUS → BMS konfigurace → Protocol z MB Slave na MB Extended + power-cycle TČ jističi 60 s → data tečou živě (venkovní 17,8 °C, DHW 43,2 °C, tlaky 1,4/1,3 bar — sedí na EasyNet).
Lessons learned:
- Selektor
BUS_HP24(verze mapy) aMB Extended(režim portu) jsou dvě nezávislá nastavení — obě musí být současně. Instalatér měl první, ne druhé. - Český překlad firmwaru duplikuje název „řízení požadavku" pro dvě různé položky (Services control + BUS control) — orientovat se podle obsahu, ne podle názvu.
- Reg 2185 (power units) u téhle jednotky = 10 = W; výkony bereme bez scale, unit W.
- Pool temperature 2134 = 0 (TČ nemá zapojené čidlo bazénu, řízeno externě přes DI4); v configu zakomentováno.
- Pool setpoint 2151 ≠ cílová teplota bazénu — je to delivery T výstupní vody z TČ do výměníku (~40 °C). Cíl bazénu je externí termostat.
Po power-cyclu se objevil „Inverter Alarm 50" na displeji TČ; Modbus reg 2065 vrací alarm_level = 0 → alarm se nejspíš sám resetoval během bootu (běžné u invertorové elektroniky po power-cyclu).
Důvod
Bezpečnost a reverzibilita: read-only nemůže nijak zasáhnout do živého řízení domu. Mapování je deterministicky ověřitelné, jakmile instalatér zpřístupní data.
2026-05-25 — Klimatizace: cooling-only architektura a master cool guard
Kontext
Audit implementace odhalil tři bugy v appdaemon/apps/daikin_modbus.py a climate.yaml:
- Fan speed se čte/zapisuje do bitů 1..3 (reserved) místo 14..12 (per Daikin EKMBDXA manuál) → fan v UI nereflektuje realitu a změna nemá efekt.
- Fan control flag (bity 7..4 holding 42001) se nenastavuje na 6 — gateway ignoruje fan příkazy.
force_control_nibble: 6v apps.yaml bylo zakomentované. - Mode write na slave jednotky (1-00..1-08) vrací "illegal data" — DIII master/slave systém vyžaduje mode write jen na master (1-09 Janča, jižní pokoj). Slaves mají holding 42002 = 6 (Dependent) a kopírují master's mode automaticky.
Dodatečné nálezy:
- Madoky fyzicky neexistují. Dodací list R-24000204 uvádí 10× BRC1H52W, ale realizace je bez nich. Jediný kontrolér je Modbus + servisní technik.
- Uživatel deklaroval, že systém bude vždy chladit, nikdy topit.
Rozhodnutí — cooling-only architektura
Zjednodušení místo komplikovaného master/slave routingu:
- Mode register se po inicializaci NIKDY nezapisuje z runtime cesty. HA píše jen on/off + setpoint + fan per jednotka.
- Master 1-09 (Janča) je zamčený v cool přes:
- Startup guard (30 s po naběhnutí AppDaemonu): ověří master mode = 2; pokud ne, zapíše.
- Periodický guard každých 10 minut: stejná kontrola + zápis + persistent notification (
klima_master_guard). - Slaves automaticky chladí, protože přebírají master's mode přes DIII-Net hardware.
- HA
climateentity nabízí jenmodes: ["off", "cool"].set_hvac_mode("cool")se interně přeloží napower=on(žádný mode write).set_hvac_mode("off")napower=off. - Pokud někdo (servisní zásah) přepne master jinam, guard to do 10 min přepíše zpět + uživatel dostane persistent notification.
Rozhodnutí — UX optimalizace
- Optimistický refresh: po každém Modbus zápise AppDaemon volá
homeassistant.update_entityna 4 sensory cílové jednotky s odstupem 1.5 s a 8 s. UI reaguje do 1-2 s místo dosavadních 30 s polling intervalu. - Debounce: identické zápisy do 2 s se zahodí. Chrání před 7000 commands/year per unit limitem + před uživatelským spamem.
- Dashboard
Klima: přidán souhrnný panel "Stav klim" (kolik běží, master mode + setpoint), per pokoj velký thermostat card s viditelným mode + setpoint, vedle něj termostat na zdi.
Důvod
Nejjednodušší možné řešení splňující všechny požadavky:
- Master/slave routing v AppDaemon = řádově složitější kód, který by jen obcházel hardware design.
- Cooling-only předpoklad eliminuje 90 % mode logiky.
- Guard se chová jako self-healing safety net pro neočekávaný vstup zvenku.
- Madoky neexistují = ve skutečnosti není kdo by mode změnil, takže guard je jen safety net (low frequency, ne hot path).
Implementace
appdaemon/apps/daikin_modbus.py: kompletní refactor — fix bug #1 (bity 14..12), bug #2 (vždy fan_control_flag=6), startup+periodic guard, optimistic refresh, debounce.appdaemon/apps/apps.yaml: přidánomaster: "1-09",guard_interval_s: 600,debounce_s: 2.0.climate.yaml: 10 single + 1 group entity přepsány namodes: ["off","cool"], fan read fix (bity 14..12), set_hvac_mode jen on/off.dashboards/klima.yaml: souhrnný panel + thermostat cards per pokoj.
2026-05-25 — Klimatizace: provozní strategie a skupinové ovládání
Kontext
10 Daikin split jednotek (1-00..1-09, plus aggregát obýváku climate.daikin_room_a_1_01_1_03). V létě obrovský FTV přebytek. Rekuperace Atrea DUPLEX 560 má v létě výměník jen 0,7 kW — dům neuchladí, není její role. Trvale puštěné "noční předchlazení" přes bypass je kontraproduktivní (přes den táhne horký vzduch dovnitř).
Rozhodnutí — provozní režim klim
- Nepouštět klimy v režimu AUTO trvale. V přechodném období AUTO flip-flopuje topení/chlazení, energetická pohroma + nepředvídatelný komfort.
- Léto + PV přebytek: Daikiny v COOL módu, ne AUTO. Setpoint 23–25 °C pro běžný provoz, 22 °C pro PV soak.
- Drž klimy zapnuté přes celý solární peak (~10–18 h) — inverter moduluje na nízkém výkonu, dům akumuluje chlad do tepelné hmoty (beton, omítky, nábytek), uvolňuje se do večera. To je „zadarmo chlad z FTV".
- Po západu slunce vypnout (nebo zvedat setpoint vysoko) a větrat okny — venku chladněji než uvnitř, klima v noci by jela ze sítě/baterie zatímco výsledek je k mání zadarmo přes komínový tah.
- Neobývané zóny vypnout — 10 jednotek na low-load má nezanedbatelný sumární standby.
Rozhodnutí — climate group: scripty, ne HACS
Pro skupinové ovládání 10 jednotek odmítnuty cesty: a) HACS climate_group (dependency, single point of failure, průměrná current_temperature matoucí), b) nativní HA group: helper (neumí předat setpoint/HVAC mode). Zvolena cesta scriptů v scripts.yaml — KISS, žádná dependence, v repu, předvídatelné. Skupinové scripty (klima_off, klima_cool_24, klima_cool_25, klima_pv_soak) cílí 9 jednotek bez ložnice. Ložnice (climate.daikin_1_00) má vlastní presety (18/20/22), aby šla agresivně chladit nezávisle.
Rozhodnutí — HS portál a velkoplošná okna přízemí jako blocker klimy
Otevřený HS portál (a obecně velkoplošné posuvné dveře / okna v přízemí) přes horký den s běžící klimou = řádově 3–10 kW tepelného zisku za hodinu z venkovního vzduchu. Klima v té zóně se tím anuluje. Pravidlo: buď otevřeno NEBO klima, ne obojí. V noci s venkovní < vnitřní teplotou naopak chtěné (komínový tah).
V HA je k dispozici jeden souhrnný signál binary_sensor.dilna_sensor_3 (Modbus relé v dílně, série NC kontaktů) = "Okruh okna přízemí". Logika NC: ON = vše zavřeno, OFF = aspoň jedno otevřeno. Nerozlišuje konkrétní okno; pro orchestrátor stačí, pravidlo zní stejně bez ohledu na zdroj otevření.
Důsledek pro návrh
- Vytvořen dashboard
dashboards/klima.yaml(Klima panel) — teploty + skupinové ovládání + stav otvírání. - Orchestrátor okna ↔ klima jako další iterace (viz
todos.md), využije scripty +dilna_sensor_3+weather.forecast_home+ PV přebytek.
2026-05-14 — Dílna: standardní překližky a materiál pracovní desky
Náhrada 12 mm CP/C 237479 → MULTI BB/CP 113089
Demos drží 237479 (PV SUR BŘÍZA CP/C 1250×2500×12) v katalogu jako "Na objednávku, cenu nutno ověřit" — de-facto signál EOL bez oficiálního ohlášení. Náhrada 113089 PV SUR BŘÍZA MULTI BB/CP 1250×2500×12 (skladem, 1 858,90 Kč bez DPH, BFU 100, 9 vrstev).
Volba MULTI BB/CP místo levnější MULTI CP/CP (210702, na objednávku, 1 802 Kč): rozdíl 56 Kč/ks (3 %) je v rámci šumu, BB face dává znatelně lepší pohledovou stranu (drobné oválné záplaty místo větších záplat a suků z CP), CP back na nepohledové straně stačí. Skladová dostupnost vs. čekání na objednávku rozhodla.
Analogicky migrováno 18 mm: 18 mm CP/C → 113093 MULTI BB/CP 1250×2500×18 (skladem, 2 582,59 Kč bez DPH).
Materiál pracovní desky dílenského stolu: MPX bříza 40 mm (210713) místo buku spárovky
Stůl 2500 × 800 × 40 mm. Volba 210713 PV SUR BŘÍZA CP/C 1250×2500×40 (5 299 Kč bez DPH, skladem) proti 76251 SPAR BUK A/B 4000×800×40 NAPOJ (5 836 Kč bez DPH, 2-10 dní z centrálního skladu).
Důvody pro MPX:
- Dimenzionální stabilita. Buk spárovka má sezónní pohyb 3-5 mm na 800 mm šířky → vyžaduje uchycení přes drážky a táhla, jinak praská nebo se kroutí. MPX se nehne.
- Žádné finger-joints jako slabé body. Linkovaný buk je napojovaná spárovka (lamely nastavované cinkovým spojem). Pod úderem kladiva, dláta nebo padajícího kusu oceli praskne ve fingerjointu dřív než ve dřevě. MPX je homogenní.
- Žádná údržba olejem/voskem. Buk vyžaduje 1-2× ročně, MPX 0× (případně lokální přebroušení po 5 letech, nebo polyuretan).
- Rozměrový fit. Z 1250×2500 vyřízneš pás 800×2500 na desku + zbude užitečný odřezek 450×2500. Z buku 4000×800 zbude 1500 mm jako odpad.
- 40 mm v jednom kuse u obou — výhoda buku (jeden masivní kus) odpadá. MPX 40 mm nemusíš lepit doubled.
- Cena/m² nižší o 7 % + skladem.
Volil bych BUK jen pokud stůl ≥ 3 m (MPX bys musel napojovat), případně dominantně ruční nářadí + důraz na repairabilitu hoblíkem a klasický look. Pro tuhle dílnu (kombinace ruční + elektro, nevytápěná část roku, KISS údržba) MPX vyhrává.
2026-05-11 — pmx1 stejný upgrade + debian-services NFS mount race fix
Co se stalo
- pmx1 upgradován stejně jako pmx2 (kernel 6.17.13-7-pve pin, ZFS 2.4.1, pve-manager 9.1.9). Reboot ~4 min, vše naběhlo čistě.
- Po rebootu pmx1 šly debian-services Docker služby do stavu "Up, ale prázdné" — nginx, grafana, n8n, cups, influxdb v restart loopu. Důvod: NFS mount
/mnt/dataz TrueNAS192.168.20.4:/mnt/tank/app-datapři boot LXC 107 selhal smount.nfs: Network is unreachable, ačkolivnetwork-online.targetbyl aktivní o sekundu dříve. Bind mounty v Docker kontejnerech se navázaly na prázdné adresáře, takže nginx neměl conf.d, grafana/n8n/influxdb neměly data dir. - Důsledek:
ha.marada.name,wifi.marada.name,data.marada.namebyly z internetu nedostupné ~10 min, než se na to přišlo. Direct IP přístup (192.168.20.7:8123apod.) fungoval celou dobu — bypass nginxu.
Příčina
/etc/fstab měl NFS line s prostými defaults:
192.168.20.4:/mnt/tank/app-data /mnt/data nfs defaults 0 0
_netdev systemd automaticky vygenerovanou mnt-data.mount unit neoznačil za network-dependent, mount se zařadil do local-fs.target a vykonal se ještě před tím, než síťová vrstva LXC fakticky resolvovala TrueNAS přes ARP. network-online.target v LXC kontejnerech reportuje "online" eagerně podle stavu interface, ne podle reálné reachability.
Důležitý poznatek: NFS mezi debian-services (.20) a TrueNAS (.4) NEPROCHÁZÍ přes pfSense — oba endpointy jsou na VLAN 20, stejný L2 subnet. Mount má fungovat i s pfSense down, problém byl čistě v LXC systemd timing, ne v síťové cestě.
Oprava
/etc/fstabna debian-services:192.168.20.4:/mnt/tank/app-data /mnt/data nfs _netdev,nofail,x-systemd.mount-timeout=60,noatime 0 0_netdev→ systemd zařadí doremote-fs.target+Wants=network-online.target+After=network-online.targetnofail→ boot pokračuje i kdyby NFS selhal (žádný emergency mode), ale Docker pak nenastartuje (záměr)x-systemd.mount-timeout=60→ 60s na první mount attemptdocker.servicedrop-in/etc/systemd/system/docker.service.d/10-wait-for-nfs.conf:[Unit] RequiresMountsFor=/mnt/data After=mnt-data.mount Requires=mnt-data.mountsystemctl daemon-reload. Dependency graph ověřen.- Reboot-test 2026-05-11 ~11:03: LXC 107 rebootnut z pmx1 (
pct reboot 107). Boot timeline ukázal správné pořadí:nfs-client.target→remote-fs-pre.target→remote-fs.target→mnt-data.mount→docker.service. Všech 7 kontejnerů startovalo až po úspěšném NFS mountu, žádné restart loopy.ha.marada.name/wifi.marada.name/data.marada.namepo ~60 s vrátily 200/302. Fix potvrzen funkční.
Operační dopad
- Příští reboot pmx1 / LXC 107 už by neměl shodit nginx + Docker stack na debian-services.
- Pokud TrueNAS NFS dlouhodobě nedostupný, Docker se sám nestartne (s
nofail) — boot LXC ale projde čistě, dá se diagnosticky pracovat. To je správné chování (lepší než dnešní "půl-startovaný stack s prázdnými mounty"). - Backup:
/etc/fstab.bak.20260511-085833na debian-services.
Lessons / follow-up
- Pro každý NFS/CIFS/jiný síťový mount v
/etc/fstabna libovolné VM/LXC v homelabu vždy_netdev,nofail+ explicit systemd dependency od služby, která mount potřebuje. Dnes není zmapováno, kde všude jinde tohle můžeme mít rozbité — viz follow-up. - Validace fixu vyžaduje reboot LXC 107, ne jen daemon-reload. Plánovat při příštím přirozeném okně (další pmx1 reboot / plánovaný upgrade).
network-online.targetv LXC nereflektuje plnou L3 reachability — eagerně reportuje "online" jakmile rozhraní existuje. Pro NFS na stejném subnetu je to obvykle dost, ale s race podmínkou se to dnes ukázalo. Jiné scénáře (RDS, cross-VLAN routing) by mohly selhat ještě výrazněji.
2026-05-10 — pmx2 kernel soft lockup ve ZFS, upgrade kernelu + ZFS, čistka cluster ghost
Příčina
Kernel 6.17.9-1-pve + ZFS 2.4.0-pve1 na AMD Ryzen 5 7430U trefily race v smp_call_function_many_cond (cross-CPU IPI při TLB flush) během ZFS writeback. systemd-journal zavolal fsync → ZFS zpl_fsync → folio_clear_dirty_for_io → flush_tlb_mm_range → IPI gate, na kterém se zaseklo CPU#5 (544 s) i CPU#3 (637 s). Klasický ZFS-on-Linux + nový kernel + AMD timing bug, ne chyba konfigurace.
Důsledky
-
-
- 2026 06:10:21 — poslední log na pmx2, kernel zombie (jádra v IPI deadlocku, ale ne plný panic)
-
- corosync ztratil totem (
Totem is unable to form a cluster),pvescheduleršel do "no quorum" - HAOS VM 102 zamrzla s celým hostem → HA, doorbell, automatizace, MQTT mimo provoz ~3.5 h
-
-
- 2026 09:48:12 — pmx2 sám rebootnul (pravděpodobně softdog watchdog po extrémně dlouhém timeoutu nebo
kernel.panicauto-reboot, jakmile se zhroutilo dost subsystémů, aby se kernel dostal k panic handleru). Uživatel nebyl doma, HW nikdo nereset, UPS-backed = power glitch vyloučen.
- 2026 09:48:12 — pmx2 sám rebootnul (pravděpodobně softdog watchdog po extrémně dlouhém timeoutu nebo
-
- Při bootu HAOS přehodil primary NIC zpět na
enp0s19(známý gotcha z2026-05-06)
Pmx1 stejný HW + stejný buggy mix, jen "vyhrál loterii" — uptime 69 dní bez incidentu. Ne fix, jen statistika.
Oprava
apt dist-upgradena pmx2 — kernel6.17.13-7-pve, ZFS2.4.1-pve1(kernel modul i userspace),pve-manager 9.1.9- Pin kernelu před rebootem:
proxmox-default-kernel 2.1.0táhne závislost naproxmox-kernel-7.0(nový major branch). Pinnul jsem 6.17.13-7-pve přesproxmox-boot-tool kernel pin 6.17.13-7-pve && proxmox-boot-tool refresh, aby v produkci zatím nebootoval 7.x. - Reboot ~100 s, zpool healthy, všechny VM/LXC nahoru, HAOS NIC tentokrát rovnou na
enp0s18(race se neprojevil — neopravoval jsem, není to fix) - Cluster cleanup:
pveghost member (z éry před migrací na ZFS, kdy sepvepřejmenoval napmx1se stejnou IP192.168.20.2— duplicitní záznam v corosync.conf zůstal).pvecm delnode pvez pmx2,Config Version 5 → 6,Expected votes 3 → 2. Backupy vpmx2:/root/corosync.conf*.bak.20260510-112246.
Operační dopad
- Cluster je teď čistý 2-node (
expected_votes=2,quorum=2). Ztráta jednoho zdravého nodu = read-only stav (VMy běží, ale žádné start/stop/migrate/backup). Stejné riziko jako předtím (s ghostem fakticky 2/3 = taky no quorum při ztrátě jednoho), jen teď čistě reportované. - pmx1 zatím nepatchnut — stejný buggy mix, stojí v řadě po 24–48h pozorovacím okně pmx2.
- Pin politika: po každém upgradu před rebootem zkontrolovat
proxmox-boot-tool kernel lista explicitně pinovat zamýšlenou verzi, dokud neproběhne přechod na PVE 9.x (nebo cokoliv, co kernel 7.x dováží).
Lessons / follow-up
- Soft lockup v IPI/TLB během ZFS writeback je race condition, ne deterministický bug. Bez upgradu se trefí znovu — možná za týden, možná za půl roku. Druhý node se stejným HW = stejný risk → upgrade musí dorazit i na pmx1.
- Watchdog se nakonec uplatnil, ale s 3.5h zpožděním. Stojí za zvážení agresivnější
kernel.hung_task_panic=1+kernel.panic=10, aby se zombie stav konvertoval na rychlý reset. Otevřená otázka, ne automaticky → viztodos.md. - 2-node cluster bez qdevice = žádná quorum redundance. Kvůli homelab roli zatím akceptovatelné, ale stojí za zvážení (debian-services LXC nebo TrueNAS jako 3. arbiter hlas) → viz
todos.md. - HAOS dual NIC primary fix se po tomto rebootu nepotřeboval, ale to není dostatečný důvod fix nepsat — byla to race, příště se zase přehodí. Položka v
todos.mdz2026-05-06zůstává otevřená.
2026-05-08 — Zigbee coordinator: CC2674P10 → EFR32MG24, clean reset
Rozhodnutí
- Přejít z TI CC2674P10 (Z-Stack adapter) na Silicon Labs EFR32MG24 (EmberZNet adapter) jako primární Zigbee coordinator. Oba čipy fyzicky na SLZB-MR3 (smart switching role v UI, žádný HW swap).
- CC2674P10 přepnut do role "Thread RCP" / Matter-over-Thread (zatím nevyužito, k dispozici pro budoucí Matter zařízení).
- Síť kompletně přebudována od nuly — všech 39 zařízení re-paired. Cross-stack migrace zstack→ember
coordinator_backup.jsonnení v Z2M podporovaná (zigbee-herdsmanember adapter explicitně rejectuje, vizEmberAdapter.getStoredBackup).
Důvody
- CC2674P10 měl recurring silent stalls: 4× SLZB-MR3 reboot v rozmezí 5.–6. 5. 2026, mezitím Z2M MQTT bridge reportoval
connected, ale Zigbee rádio nepřijímalo zprávy. Auto-restart automatikazigbee_auto_restart_z2m_when_bridge_offlinenezabírala (čekala na bridge offline, který nenastal). Detail viz Z2M issue #28197 a HA Community thread o frequent adapter resets. - Side benefit clean resetu: vygenerován nový náhodný
network_key. Předchozí síť běžela na default well-known klíči Z2M01030507090b0d0f00020406080a0c0d(z dokumentace examples), kdokoliv s Zigbee snifferem v dosahu mohl dešifrovat veškerý provoz. Tento dlouhotrvající security issue byl tímto vyřešen. - Friendly_names a HA entity IDs zachovány — Z2M matchuje
device_idpodle IEEE vconfiguration.yaml, takže po re-pairu se entita objeví se stejným ID.
Trade-off
- ~37 zařízení × ručně přepárovat. Akceptovatelné, protože téměř vše je mains-powered (7× nástěnný termostat = routery, ~30× mmWave presence senzory = mains, 1× battery sensor zahrada). Žádné lezení na strop k battery zařízením.
- Ghost devices v configu (47 entries bez friendly_name, dlouhodobí offline duchové) při této příležitosti smazány z
zigbee2mqtt/configuration.yaml. Z2M při startu publishl prázdné MQTT retained payloads → HA discovery entity zmizely.
Lessons learned z migrace (2 hodiny zoufalství než přišel průlom)
1. Z2M addon ukládá serial port/baudrate mimo configuration.yaml
Addon má vlastní options storage (HA UI → Add-ons → Zigbee2MQTT → Configuration tab). Při startu přepíše serial sekci v configuration.yaml z těchto options, ne naopak. Hodiny jsme měnili port/baudrate/adapter v repu, addon to při každém startu rolloval zpátky. Smoking gun byl řádek z debug logu Z2M:
"serialPort":{"path":"tcp://192.168.40.2:7638",...}
6638. Fix: nastavit serial v addon UI, ne v YAML.
2. SLZB-MR3 TCP porty jsou per-fyzický-chip, ne per-role
- EFR32MG24 → port 6638 (vždy, bez ohledu na roli)
- CC2674P10 → port 7638 (vždy)
- Když se v UI prohodí role (MG24 = "Zigbee Coordinator", CC2674P10 = "Thread RCP"), porty se nehýbou. Z2M Config generator v SLZB UI ukazuje správnou kombinaci pro daný chip.
- Boot log
[EFR32MG24] Started server on port: 6638to potvrdí. Při debug se na něj koukat.
3. Z2M ember adapter rejectuje zstack coordinator_backup.json
Konkrétní check v zigbee-herdsman/src/adapter/ember/adapter/emberAdapter.ts:
if (!data.stack_specific?.ezsp || !data.metadata.internal.ezspVersion) {
throw new Error("[BACKUP] Current backup file is not for EmberZNet stack.");
}
stack_specific.zstack + metadata.internal.znpVersion → fail. Cross-stack migrace bez re-páru není možná v aktuální verzi Z2M (community workaround "stejný network_key v configu" je nespolehlivý a nezachová se s addon UI options).
4. Ghost devices v configu jako symptom zaseknutí mesh
Po roky se nahromadilo 47 entries bez friendly_name ('0xHEXIEEE': friendly_name: '0xHEXIEEE') — zařízení, která se kdysi pokusila joinit, ale nikdy se neusadila / nebyla pojmenovaná / odpojila se navždy. Při migraci ideální moment vyčistit. Pravidlo: pokud friendly_name == IEEE, je to ghost.
5. Diagnostika: ASH RSTACK probe je definitivní test chipu
Když Z2M dostává Received frame with CRC error ve smyčce, problém může být v Z2M, v SLZB proxy, nebo v chipu. Nezávislý test:
printf '\x1A\xC0\x38\xBC\x7E' | nc -w 3 192.168.40.2 6638 | xxd
1A C1 02 0B 0A 52 7E (Cancel + RSTACK + ASHv2 + reset cause SOFTWARE + CRC + flag). Pokud probe vrátí čistý RSTACK ale Z2M reportuje CRC error, problém je v Z2M nebo addon konfiguraci.
Aktuální provozní stav (po migraci)
- MG24 firmware:
20260416 DEV(SDK 9.0.1.0). Stable20250212jsme vyzkoušeli oba — chovaly se stejně (problém byl v addon options portu, ne firmware). Doporučení do budoucna: až SMLIGHT vydá nový stable, vrátit se na něj. - Z2M config:
port: tcp://192.168.40.2:6638, adapter: ember, baudrate: 115200, rtscts: false, transmit_power: 5, channel: 25. - Forensic kopie v
/config/zigbee2mqtt/:coordinator_backup.json.zstack-old,database.db.zstack-old,state.json.zstack-old,database.db.backup.zstack-old.
Pravidla pro budoucí Z2M / coordinator migrace
- Addon options jsou autoritativní pro serial config, YAML je sekundární — vždy ověř UI před debugem proxy/firmware.
- Cross-stack migrace přes backup file = re-páření (alespoň v Z2M 2.10.x + zigbee-herdsman 10.0.7).
- Default Z2M network_key je security risk — po každém clean network setupu ověř, že Z2M vygeneroval random key (ne
01030507...). Při legacy síti naplánuj rotaci. - Z2M syslog → Loki je rozbitý (separate TODO) — během migrace přidat
filedolog_output, ať máš lokální debug log na disku.
2026-05-06 — Zahradní domek: EPDM pod prahem + spodní detail OSB
Rozhodnutí
- Mezi spodní práh (KVH 120×60 impregnovaný) a dlažbu vložit EPDM pásek 60 mm × 3–5 mm.
- Spodní hrana OSB 15–20 mm nad dlažbou (≈10 mm nad horní hranou EPDM), nikoliv 5 mm jak původně zvažováno.
- PE folie shingle lap přes čelo OSB a hranu prahu, končí volně nad dlaždicí (≥30 mm pod hranou OSB), nelepit těsně po celé délce k prahu.
- Čelo OSB napustit napouštědlem před montáží.
Důvody
- Kapilární přerušení: dřevo prahu nesmí přímo lízat dlažbu — i impregnace má omezenou životnost. EPDM nesaje a ruší vzlínání.
- Odstřik vody dopadající na dlažbu sahá až ~20–30 cm vzhůru. 5 mm spára by hranu OSB udržela trvale vlhkou; čelo OSB saje jak houba.
- Folie shingle lap = voda po folii teče ven (přes hranu prahu pryč), ne pod OSB. Bodové prolepy páskou (ne souvislé) nechávají kondenzátu cestu ven.
Trade-off
- O 15–20 mm vyšší spodní hrana OSB znamená, že stavba je o tolik víc exponovaná zezdola — proto je nutný sokl/lišta co nejdřív po zaplášťování (ideálně před první zimou), ne až jako finiš.
Lessons / pravidla pro budoucí venkovní stavby na dlažbě
- KVH na dlažbě vždy přes EPDM/lepenku, i když je impregnovaný.
- OSB čelo nikdy v zóně odstřiku bez krytí folií + následně lištou.
- Spodní hrana foliového pláště drenážuje, netěsní — voda musí mít kudy ven.
2026-05-06 — Doorbell incident: HA OS upgrade přehodil primary NIC
Příčina
HA OS upgrade 17.1 → 17.2 (slot A → B) v noci na 2026-05-05 po rebootu přehodil v NetworkManageru primary: true z LAN NIC enp0s18 (192.168.20.7) na IoT NIC enp0s19 (192.168.40.7). HA tím začala posílat veškerý non-local traffic ze zdroje 192.168.40.7.
Důsledky (časová osa)
- 2026-05-05 04:54 UTC
sensor.doorbell_call_status→unavailable. REST poll na192.168.60.10z IoT NIC narazil na pfSense pravidloBlock IoT to Internal Networks(vtnet3 rule "OPT2 → Private_Networks") → drop bez logu (filterlog do Loki neteče). Tím padla i ring detection arest_command.doorbell_open_gate(timeout 5 s). - HomeKit ring přes Scrypted (192.168.20.21) fungoval, protože šel přes jiný zdroj — proto symptom "zvonek zvoní na hodinkách, ale HA nedělá nic".
- Po opravě primary zpět na enp0s18 zůstalo druhotné: HA dál posílala Cast zařízením streamovací URL
http://192.168.40.7:8123/...z paměti — Cast (VLAN 50) na.40.7nedosáhne (VLAN 50 → VLAN 40 pravidlo neexistuje), TTS "Někdo zvoní u dveří" nehrálo.
Oprava
- Primary NIC zpět na LAN: v HA UI (Settings → System → Network) workaround "změnit IP a zpět" donutil Supervisor přepsat NM connection a primary skončil na
enp0s18. Přímo vymazat gateway u IoT NIC v UI nešlo (validace). - Restart HA Core (
ha core restart) smazal cache zdrojové IP pro Cast → URL pro Cast pak generována správně z192.168.20.7.
Lessons learned a prevence
- Po každém HA OS upgrade: zkontrolovat
ha network infožeprimary: truezůstalo naenp0s18(LAN). Pokud se přehodilo, uplatnit fix postup výše. - Preventivní pinning: nastavit explicitní route metric, aby budoucí upgrade nepřepočítal pořadí — viz follow-up v
todos.md. - pfSense filterlog do Loki neteče — diagnostiku síťových dropů lze dělat jen lokálně přes SSH (
pfctl -ss,clog /var/log/filter.log). Follow-up: zapojit pfSense syslog do Loki, viztodos.md. - Bug v pfSense pravidle
Block MEDIA to Internal Networks(vtnet4): source je192.168.50.1(gateway IP) místo<OPT3__NETWORK>— pravidlo je no-op. VLAN 50 → ostatní privátní VLANy tak NENÍ blokovaná. Pokud má opravdu blokovat, opravit source. Follow-up vtodos.md.
2026-05-06 — Tuya mmWave: form factor wins over reliability
Rozhodnutí
Zůstat u Tuya 24G mmWave senzorů (~30 ks v domě) navzdory endemickému bugu occupancy DP stuck off. Hardwarová migrace na Aqara FP2 / FP1E / podobné odmítnuta.
Důvod
- Form factor je primární kritérium. Tuya MTG235-ZB-RL (flush-mount, kruhové pouzdro do sádrokartonu) i hranatá nástěnná varianta zmizí v architektuře. Aqara FP2 byl označen jako "hodně nesystémová" — viditelné plastové pouzdro je vizuálně rušivé.
- Aqara FP2 zůstává jen tam, kde jeho velikost nevadí — 3 ks v obýváku/Relax, kde je velký otevřený prostor a smysl dává zonal detection (gauč × jídelní stůl × průchozí zóna).
Hardware varianty v provozu
- Flush-mount (zapuštěná do stropu, sádrokarton): Tuya MTG235-ZB-RL "24G Human presence sensor with relay" (TZE200/TZE204). Použito např. WC, Spíž. Kratší horizontální dosah (kužel dolů).
- Surface-mount (přisazená na zeď, hranaté pouzdro): Tuya "2.4G/5.8G MmWave radar". Použito např. Technická. Delší dosah, scanuje celou místnost.
- Obě Tuya varianty mají stejný occupancy-DP-stuck-off bug, ale jiné Z2M mappingy.
- Aqara FP2 (WiFi, ne Zigbee) — jen v obýváku/Relax pro zonal detection.
Coping mechanism
Default: software workaround, ne hardwarová výměna.
- Robust template pattern:
binary_sensor.presence_<area>_robustORuje native occupancy starget_distance > 0(případněilluminancefallback) - AppDaemon listener tweaks
- Z2M device reconfigure když firmware DP stuck
ESPHome LD2410/LD2412 ve vlastním malém pouzdře jsou přijatelná alternativa, pokud jde o flush-mount realizovat. Jinak hardware swap je last resort — framing "až když budeš rekonstruovat tuhle místnost", ne "měl bys vyměnit".
2026-04-27 — AI stack: zjednodušení na n8n + MCP
Dify.ai, AnythingLLM, OpenClaw zrušeny
Rozhodnutí: Stack pro "Rodinného Asistenta" zúžen na n8n (orchestrace + AI nodes) + MCP servery (kontextová vrstva) + Gemini Flash (LLM). Dify.ai (LXC 108) decommissionovaný. AnythingLLM a OpenClaw vypadly z plánu úplně.
Důvod: Dify duplikoval funkcionalitu, kterou pokrývá kombinace n8n AI nodes + MCP servery. RAG nad volnými dokumenty (knowledge base) byl jediný feature, který MCP nepokrývá — ale 99 % domácích AI dotazů jsou strukturovaná data (HA stav, logy, repo dokumentace), kde je MCP přesnější než vektorový search. Kompromis: ad-hoc tool pro PDF lookup pokud opravdu vznikne use case (faktury, manuály), místo celého RAG frameworku.
Dopady: docs/chytry_dum/ai_stack.md přepsán; TODOs Dify.ai a AI Knowledge Base v todos.md zrušeny; LXC 108 dify plánovaná dekomise (PBS zálohy slabé — poslední 2026-02-18 — ale nejsou závislosti, riziko nízké).
2026-04-27 — UniFi: migrace na UniFi OS Server + MCP přístup
UniFi OS Server jako primární controller
Rozhodnutí: Nasazen samostatný UniFi OS Server (Network App 10.3.55) na 192.168.20.5:11443 jako VM 109 na pmx1 (2 vCPU, 4 GB RAM, 30 GB ZFS, cloud-init, onboot=1, MAC bc:24:11:78:4e:7d). Všech 9 zařízení (7 AP + USW-48-PoE + USW-Lite-8-PoE) je adoptováno na nový controller a ONLINE.
Důvod: UniFi OS Server poskytuje oficiální API (Integration v1) s API key auth, což je výrazně bezpečnější než legacy session login na původním LXC 101. Zároveň je to maintained aktivně Ubiquiti, zatímco klasická Network Application v Java na LXC se postupně utlumuje.
Stav legacy LXC 101 (192.168.20.6:8443): Destroyed (2026-04-27) včetně unreferenced disků. PBS zálohy zachovány (15 denních, retence dle backup jobu).
Single point of failure pmx1: UniFi OS Server VM 109 nemá ZFS replikaci na pmx2 — výpadek pmx1 znamená ztrátu UniFi managementu (data plane na AP/switch zůstává s last-known configem). Mitigace: PBS restore (~10 min), případně budoucí ZFS replikace 109 → pmx2.
MCP přístup přes enuno/unifi-mcp-server
Rozhodnutí: Použít enuno/unifi-mcp-server v0.2.4 (Apache 2.0) přes uvx, autentizace přes oficiální UniFi API key (UNIFI_MCP_API_KEY v .env). Konfigurace v .mcp.json jako unifi.
Důvod: Oficiální API key (scopable, revocable) místo storage admin user/pass v env. 74 MCP tools, confirmation u mutujících operací (sedí s AGENTS.md "Safety before speed"). Alternativa sirkirby/unifi-network-mcp má víc tools (161), ale primárně user/pass auth — odmítnuto.
Ověřeno: Curl proti /proxy/network/integration/v1/sites|devices|clients vrací HTTP 200, klíč má read přístup k požadovaným endpointům.
Skripty (backup_unifi.py, doc_gen_unifi.py, sync_pfsense_unifi.py) zatím nepřevedeny
Rozhodnutí: Skripty zůstávají napojené na legacy .20.6 přes user/pass — refactor na nový API key + endpoint /proxy/network/integration/v1/ je samostatný úkol (viz todos.md).
Důvod: Skripty zálohují/synchronizují prázdný legacy controller, což je tichá ztráta zálohy. Riziko: pokud je backup_unifi.py v cron/scheduleru, pravidelně produkuje useless artefakt. Nutno migrovat dřív, než dojde k decommissi LXC 101.
Nginx wifi.marada.name ještě cílí na legacy
Pozn.: docs/files/docker/debian-services/nginx/conf.d/wifi.conf proxiuje https://192.168.20.6:8443. Updates vyžaduje koordinovaná změna nginx config + redeploy — viz follow-up.
2026-03-11 — Konsolidace logování
rsyslog relay zachován
Rozhodnutí: Zachovat rsyslog relay na debian-services pro RFC3164 zařízení (TrueNAS, UniFi APs, Aruba switche).
Důvod: Alloy addon na HAOS neumožňuje snadno vystavit další porty. Přechod na přímé RFC3164 by vyžadoval fork addonu nebo komplexní override config. Stávající relay funguje spolehlivě.
Poznámka: Alloy loki.source.syslog teoreticky podporuje syslog_format="rfc3164", ale praktická implementace na HAOS addonu je příliš invazivní.
Smazání loki_search.py a check_homelab.py
Rozhodnutí: Smazat oba skripty. Nahrazeny Grafana MCP tools (query_loki_logs, list_loki_label_names, query_loki_stats, query_loki_patterns) a GitHub MCP.
Důvod: MCP nástroje poskytují stejnou funkcionalitu přímo v AI agentu bez nutnosti údržby Python skriptů. Pro CLI ad-hoc dotazy stačí Grafana UI.
Grafana dashboardy v repu s auto-provisioningem
Rozhodnutí: Dashboard JSON soubory verzovány v docs/files/docker/debian-services/grafana/dashboards/, Grafana je automaticky načítá přes file-based provisioning.
Důvod: Dashboardy musí být součástí repa, aby šly reprodukovat a reviewovat. Auto-provisioning zajišťuje synchronizaci.
Grafana MCP: oprava .env načítání
Rozhodnutí: Grafana MCP server v .mcp.json spouštěn přes sh -c ". .env && exec uvx mcp-grafana" místo přímého uvx mcp-grafana.
Důvod: ${GRAFANA_TOKEN} env var nebyla dostupná v prostředí MCP procesu, protože .env se nenačítala. Shell wrapper to řeší.
2026-03-11 — Monitoring Stack Revize
CheckMK → Uptime Kuma
Rozhodnutí: Nahradit CheckMK za Uptime Kuma. Důvod: CheckMK je enterprise IT nástroj; naše potřeba je "upozorni když něco spadne." Uptime Kuma pokrývá HTTP/TCP/ICMP health checks a push notifikace bez operační complexity. CheckMK Fáze 3+4 nebyly nikdy dokončeny — signal overengineeringu.
InfluxDB 1.8 → 2.x
Rozhodnutí: Zahodit InfluxDB 1.8 (stará data jsou zašuměná), nasadit InfluxDB 2.x čistě. Důvod: InfluxDB 1.8 je EOL, jen InfluxQL, žádná auth, žádné retention policies v UI. HA nativně podporuje v2.
Grafana verzování a provisioning
Rozhodnutí: Pinout Grafana verzi (přejít z latest), dashboardy uchovávat jako JSON v repozitáři přes Grafana provisioning.
Důvod: latest tag způsobuje neočekávané breaking changes při každém docker compose pull. Dashboardy v repozitáři jsou verziovatelné a opakovatelně nasaditelné.
Automation vrstva
Rozhodnutí: Vybrat jednu automation vrstvu (n8n nebo Python skripty), ne obojí bez jasného rozdělení rolí. Stav: Nerozhodnuto — vyžaduje přehled co n8n a Python skripty aktuálně dělají.
rsyslog relay
Rozhodnutí: Ověřit zda Alloy zvládne RFC3164 přímo (parametr syslog_format). Pokud ano, relay na debian-services eliminovat.
Stav: Neověřeno — akce v todos.
Celková filozofie stacku
Závěr: Stack trpí "AI-assisted sprawl" — každá konverzace přidala nástroj bez celkového kontextu. Jádro (Proxmox/ZFS/pfSense/TrueNAS/PBS/Tailscale/HAOS/Zigbee2MQTT) je solid. Okolní vrstvy (monitoring, metrics, automation) potřebují konsolidaci.
2026-03-10 — Velux KLF200 Recovery Incident
Symptom
Velux integrace v Home Assistant přestala fungovat. Custom komponenta opakovaně hlásila chyby při čtení dat zařízení a následně už se na 192.168.40.10:51200 nedařilo připojit.
Pozorování z logů
custom_components.veluxopakovaně hlásilaError fetch limitation data for cover #...- následně se v logu objevovalo
Unable to connect to KLF200: [Errno 111] Connect call failed ('192.168.40.10', 51200) - watchdog automatizace
velux_klf200_auto_recoveryse spouštěla, ale končila na template condition ještě předswitch.turn_off
Rozhodnutí
Watchdog zůstává postavený na TCP healthchecku + power cyklu KLF200 přes smart plug + reload integrace, ale rate-limit logika byla opravena tak, aby se automatizace sama neblokovala.
Skutečná závada recovery
Podmínka v velux_klf200_auto_recovery kontrolovala state_attr(..., 'current') == 0, zatímco automatizace běží v mode: single. Tím si běžící instance sama zablokovala pokračování a recovery se nikdy nedostala k power cyklu ani reloadu integrace.
Nejpravděpodobnější příčina primárního incidentu
Nejlepší současná hypotéza je, že po sérii restartů Home Assistantu zůstaly v KLF200 staré session / TCP spojení, gateway narazila na svůj interní limit a nová spojení pak odmítala. To odpovídá pozorovanému connection refused na portu 51200.
Důsledek pro provoz
- problém nebyl jen v samotném KLF200, ale i v rozbité self-healing vrstvě
- od commitu
6faca8aby recovery měla znovu skutečně dojít až k power cyklu a reloadu integrace - při další podobné sérii restartů je stále vhodné omezit zbytečné reconnect stormy a sledovat, zda KLF200 znovu nezačne odmítat nová spojení
2026-03-10 — Home Assistant Areas a Labels
Rozhodnutí
Area v Home Assistantu mají reprezentovat větší, stabilní a lidsky srozumitelné prostory. Jemnější lokální logika řízení, zejména pro presence a světla v rámci členitých místností, se nemá modelovat dalším drobením Area, ale pomocí skupin, helperů a automatizačních zón.
Důvod
Příliš jemné Area zhoršují přehlednost, komplikují přiřazení zařízení ovlivňujících větší celek a vedou k modelu, který je spíš odrazem dosahu čidel než skutečné struktury domu. Stabilnější Area lépe odpovídají lidskému ovládání, dashboardům a budoucímu floorplanu.
Labels
Labels mají sloužit pro průřezové role a vlastnosti napříč místnostmi, ne jako druhá hierarchie polohy. Prakticky: Area odpovídá na otázku „kde to je“, zatímco Label odpovídá na otázku „co to je / jakou to má roli“.
Důsledek pro návrh
- koupelny a WC mají být obvykle samostatné
Area, pokud jsou to samostatné a běžně rozlišované místnosti - otevřené nebo členité prostory mají mít spíše větší
Area, případně rozdělení jen tam, kde to dává smysl i lidsky a provozně - budoucí jemné chování presence a lokálního osvětlení má vzniknout nad stabilními
Area, ne přestavbou area modelu
2026-03-08 — TrueNAS, AppArmor, WiFi
TrueNAS: Chybějící IPv4 Gateway
Problém: TrueNAS neměl nastavený IPv4 default gateway (ipv4gateway prázdný v middleware konfiguraci). Žádný internetový provoz nefungoval.
Fix: midclt call network.configuration.update '{"ipv4gateway": "192.168.20.1"}' + gai.conf IPv4 preference + Init script pro persistenci.
AppArmor: swtpm & dhclient DENIED
Problém: AppArmor na PVE blokoval swtpm (chybějící capability sys_admin) a dhclient (unix socket protocol match limitace).
Fix:
- swtpm: Přidáno
capability sys_admindo/etc/apparmor.d/local/usr.bin.swtpm - dhclient: Přepnut do complain mode (
flags=(attach_disconnected,complain)) — známá AppArmor limitace s unix dgramprotocol=0Ověření (2026-03-09): Na PVE je/{,usr/}sbin/dhclientskutečně v complain mode (aa-status+/etc/apparmor.d/usr.sbin.dhclient). PřetrvávajícíDENIEDzáznamy prodhclientjsou audit hlášky v complain mode a mají být považovány za monitoring noise, ne za aktivní blokující incident.
WiFi DNS Timeouty: Monitoring Noise
Rozhodnutí: DNS timeout, IP timeout a ACL reject hlášené UniFi AP (STA-TRACKER) jsou monitoring noise, ne reálné DNS selhání. Důvod: pfSense Unbound běží, DNS firewall pravidla pro všechny VLAN existují, resoluce funguje. AP pouze reportuje krátké prodlevy při roamingu/probuzení.
2026-02-18 — Apple DHCP Reconnection Failure (VYŘEŠENO)
Symptom
Po odpojení a reconnectu (návrat k opuštěnému AP, nebo restart Mac/iPhone na stejném AP) DHCP selhalo na 5–8 minut. pfSense posílalo DHCPOFFER/ACK korektně, ale packet na konečném AP do wireless sítě nedorazil (100% loss).
Co nepomohlo (Slepé uličky)
- Vypnutí Hardware Checksum Offload na pfSense (neprokázáno jako příčina).
- Smazání stale DHCP leases (opravilo to pouze logování duplicate UID, nikoliv packet loss).
- UniFi Fixy: Vypnutí Fast Roaming, UAPSD, Downgrade U6-LR na starší ovladač 6.6.73 — AP za bug nemohlo, ping selhával i přímo z něj.
- Proxmox Firewall: Změny fwbr na linux bridge (shoda okolností, že restart sítě dočasně pročistil switch tabulku).
SKUTEČNÁ PŘÍČINA: Inter-Switch Roaming + MAC Aging Time
Zásadní informace byla, že problém začal až po přidání Switche 2, kdy se APčka rozdělila mezi dva fyzické switche spojené LACP Trunkem. Když iPhone (Apple obecně) udělal roam mezi AP na různých switchích, MAC tabulky se zbláznily:
- iPhone odejde z AP na Switchi 1 k AP na Switchi 2.
- Vráti se zpět k AP na Switchi 1. AP vytvoří linku.
- Switch 2 si ale stále pamatuje, že iPhone před minutu odešel od něj směrem k TRK1 (Trunk na Switch 1), a má na tuto MAC adresu tvrdý Aging Time (5 minut).
- Když pfSense (či cokoliv zvenčí) pošle paket na iPhone (např. DHCPOFFER) a ten prochází přes Switch 2, Switch 2 vidí: "iPhone je na TRK 1" a pošle paket špatným směrem (pryč od reálného AP1).
- Paket oběžnou dráhou umře, dokud nevyprší 5ti minutový Aging Time na Switchi 2, tabulka se smaže a MAC learning se udělá nanovo.
Správné řešení
V SOHO (Home/SMB) sítích bez pokročilých "Stacking" protokolů pro okamžitý meziswitchový FDB sync je roaming nutné držet v rámci jednoho fyzického L2 switche. Akce: Fyzicky přepojit všechny Access Pointy tak, aby vedly výhradně do jednoho switche. Tím se lokální přepínání MAC adresy (z portu např. 14 na port 15) odehraje okamžitě a bez ohledu na restové/přechodové stavy na trunku.
2026-02-17 — Rebalancing VM/CT a Alloy Direct
LXC Migration: debian-services (107) → pmx1
Rozhodnutí: Přesunout LXC 107 z pmx2 na pmx1. Důvod: pmx2 měl 6 CT/VM (~24 GB), pmx1 jen 3 (~5 GB). Po migraci lepší resilience — výpadek jednoho nodu nezabije vše.
Alloy: Nginx → Direct Loki
Rozhodnutí: Alloy posílá logy přímo na 192.168.20.20:3100 místo přes Nginx (loki.marada.name).
Důvod: Výpadek Nginx by jinak znamenal ztrátu logů. Loki má port binding na 3100, Nginx zůstává pro manuální API přístup.
2026-02-16 — Proxmox ZFS Migration
Cluster: pve/pve2 → pmx1/pmx2
Rozhodnutí: Přejmenovat nody z pve/pve2 na pmx1/pmx2 při reinstalaci.
Důvod: Konzistentní pojmenování, oba nody jsou identické (NiPoGi E3B, Ryzen 5 7430U, 30 GB RAM).
Storage: LVM-thin → ZFS
Rozhodnutí: Při reinstalaci přejít z LVM-thin na ZFS root. Důvod: ZFS replication pro DR, snapshoty, lepší integrace s PBS.
DR: PBS Cold Standby → ZFS Replication
Rozhodnutí: Nahradit starou strategii (noční restore ze záloh na pve2) nativní ZFS replikací každých 15 min. Důvod: RPO 15 min místo 24h, RTO ~5 min místo ~45 min. Bez nutnosti skriptů a cronů.
Distribuce VM/CT: Split across nodes
Rozhodnutí: Nekoncentrovat vše na jeden nod. pfSense na pmx1, HA+PBS na pmx2. Důvod: Pokud spadne jeden nod, druhý stále běží s částí služeb. Kritické VM (pfSense, HA, PBS) mají repliky na druhém nodu.
Dokumentace: Monorepo
Rozhodnutí: Zůstáváme u monorepa — docs/ v ha-config repozitáři.
Důvod: Vazba mezi dokumentací a konfigurací je příliš těsná. AI agent vidí kód i docs naráz → lepší kontext. Jednoduchost.
Gitea: Odstraněna
Rozhodnutí: Gitea už neběží v debian-services stacku. Důvod: Přesun na GitHub.
2026-02-15 — Centrální Logování (Loki)
Architektura: Syslog → HA Alloy → Loki
Rozhodnutí: Všechny zdroje posílají syslog (RFC5424) na HA Alloy addon (UDP 5514). Alloy přeposílá do Loki na debian-services přes Nginx reverse proxy. Důvod: HA Alloy je single collector — čte journal (HA core + addony) i syslog (infra zařízení). Loki běží v Dockeru na debian-services vedle Grafany.
Relay pro legacy zařízení
Rozhodnutí: Zařízení podporující pouze BSD syslog (RFC3164) — UniFi APs, Aruba switche, TrueNAS — posílají na rsyslog na debian-services (UDP 514), který relayuje do HA. Důvod: Alloy addon nepodporuje RFC3164 přímo. rsyslog na debianu slouží jako translator.