Files
nanobot-runtime/projects/iot/memory.md
2026-09-11 14:27:08 +02:00

20 KiB
Raw Blame History

  • 2026-09-09: Založen projekt iot — zaměření na hardware, IoT a bastlení obecně (ESP32, Raspberry Pi, senzory). Motivace: teplotní senzor v pokoji „chlívek" (okno s holubími hřebí), zájem o ESP32 a RPi na testování. Serverové/Proxmox věci zůstávají v projektu proxmox.
  • 2026-09-09: Vytyčeny čtyři témata projektu: 1) znovu zapojit měření teploty/vlhkosti v pokoji „chlívek"; 2) samostatný Proxmox LXC kontejner na MQTT broker; 3) provozovat Home Assistant ve VM na Proxmoxu; 4) otevřená otázka — jak dotáhnout čidla k HA, když jsou fyzicky jinde, hlavně Zigbee a Matter.
  • 2026-09-09: Rozhodnutí k Zigbee architektuře: USB dongle v serveru/RPi odmítnut jako nepraktický — čidla jsou na místech bez počítače, RPi tam mít nechce, brána musí být jednoduchá, spolehlivá a okamžitě funkční (žádný boot, žádný maintenance). Směr: Ethernet Zigbee coordinator (SLZB-06 / UZG-01 typ), umístěný strategicky pro rádiový dosah, připojený přes LAN; Zigbee2MQTT + MQTT broker v LXC na Proxmoxu se k němu dostanou po TCP.
  • 2026-09-09: Rozšíření rozhodnutí o Zigbee bráně: kladné volby — brána nesmí vyžadovat počítač (RPi ani nic jiného na místě čidel), musí být jednoduchá, okamžitě po power-loss funkční, bez boot procesu a maintenance. Navíc: WiFi nutně, Ethernet kabel vyřazen jako nepoužitelný v daných místech. Postavení vlastního routeru/bridge z RPi nechce. Max. zásah = přehrání firmware.

Ověřené kandidáty (network coordinator s WiFi):

  1. SMLIGHT SLZB-06p10 / SLZB-06M — Zigbee 3.0 coordinator, podporuje Ethernet, USB i WiFi v jednom; firmware bez OS, okamžitý start; Z2M připojení tcp://<ip>:6638; správa přes vlastní web UI (vč. remote flash). Nejrozšířenější v komunitě, Z2M oficiálně podporuje jako síťový adapter.
  2. SONOFF ZB Bridge Pro (ZBBridge-P) — WiFi Zigbee brána, vyžaduje Tasmota flash (EZSP firmware pro EFR32MG21), poté funguje jako network coordinator pro Z2M (tcp://ip:8888 přes tasmota ZBBridge režim). Levnější, ale hacknutá cesta — flash přes webový proces, komunitní návody existují (stephengrier.com, haade.fr).
  3. SONOFF ZBDongle-Max (Dongle-Max) — Zigbee/Thread PoE dongle (EFR32MG24 + ESP32), podporuje Ethernet, WiFi i USB; síťový mód pro Z2M. Novější kus, méně zavedený v Z2M než SLZB-06, ale funguje jako network adapter.

Zdroj: zigbee2mqtt.io (remote adapter how-to), smlight.tech manual, blakadder.com — vyhledáno, částečně ověřeno (Z2M remote adapter stránka potvrzuje síťový mód SONOFF ZBBridge přes Tasmota).

  • 2026-09-09: Correction k Zigbee meshu: user opravuje dřívější tvrzení, že se Zigbee síť "doroste" k náplňovým čidlům přes mesh. Teoreticky Zigbee je mesh, ale prakticky to u čidel na CR2032 (a malé) baterky nefunguje — čidlo se probudí jednou za čas, odvysílá naměřené hodnoty, a v tu chvíli většinou nikdo jiný nevysílí (routery spí/nemají co přenášet), takže relay cesta přes mesh zařízení reálně nevzniká. Ověřeno prakticky mnohokrát. Náplňové čidlo musí mít přímý rádiový dohled na coordinator, jinak má smolíka (ztracené zprávy, odpojené čidlo). Důsledek pro architekturu: umístění WiFi coordinatoru je ještě kritičtější — musí být fyzicky blízko / v dohledu všech čidel, případně více coordinatorů na více místech (každý s vlastní Z2M instancí).
  • 2026-09-09: Volba Zigbee brány: SONOFF ZB Bridge Pro (ZBBridge-P). Důvody: kompaktní provedení, rozumná cena (~29 USD), napájení USB (flexibilní umístění kdekoliv se zásuvkou/USB adaptérem, bez Ethernet kabelu). Přijatý tradeoff: vyžaduje Tasmota flash (EZSP firmware pro EFR32MG21) před použitím jako network coordinator pro Zigbee2MQTT (připojení tcp://ip:8888). Flash je v rámci akceptovaného zásahu (max. přehrání firmware). Odmítnuty: SLZB-06M (dražší, Ethernet-zaměřený tvar), ZBDongle-Max (dražší, PoE dongle tvar).
  • 2026-09-09: User potvrzuje: napájení i Tasmota flash si zvládne sám, žádná asistence od agenta při fyzické instalaci není potřeba. Další krok až po fyzickém pořízení ZB Bridge Pro — pak navázat software stack (MQTT LXC, Z2M, HA VM) na Proxmoxu.
  • 2026-09-09: Téma: Tuya WiFi čidla. User by je rád používal (levná, dostupná), ale problém: mají natvrdo vypálenou HTTPS adresu (cloud endpoint) — lokálně mluvit s nimi nejde přímo. Čidla jsou battery-powered, připojují se na WiFi jen v krátkých časových úsecích, když právě vysílají (probudí se, pošlou data na Tuya cloud, zase spí). Tím pádem: nelze je směrovat do vlastní sítě a čekat na trvalé spojení; lokální integrace by vyžadovala zachytit komunikaci v okamžiku vysílání (prakticky nespolehlivé) nebo přesměrovat DNS (ale čidlo mluví HTTPS na natvrdo daný endpoint — MITM/TLS pinning problém). Zatím otevřená otázka, jak s nimi pracovat, aniž by data šla do Tuya cloudu.
  • 2026-09-09: User vlastní hromadu Tuya čidel, z nich velká část WiFi (historicky vybraná pro nejsnazší zapojení). Tuya aplikace hodnotí jako nahovno, Tuya cloud má omezení počtu API volání (rate limity). Požadavek: vycítání čidel mít plně ve vlastní režii (žádná závislost na Tuya cloudu, žádná API volání). Diskutované cesty: (a) cloud API bridge — nevyhovující, právě kvůli limitům a cloudu; (b) reflash na Tasmota/OpenBK — u WiFi čidel záleží na chipu (Realtek/ESP/Beken), ne vše jde reflashovat, battery čidla navíc vysílají jen krátce; (c) zachytávat Tuya lokální protokol — u battery WiFi čidel nemožné (krátká spojení, HTTPS pinning). Otevřená otázka zůstává: jak dostat existující Tuya WiFi battery čidla do vlastní režie; reálně znamená inventuru — projít jednotlivá čidla, zjistit chipy a určit, která jdou reflashovat, a která jsou mrtvá pro lokální použití.
  • 2026-09-09: Vyřazeny cesty k Tuya WiFi čidlům: reflash nereálný — user má většinou novější Tuya čidla (chipy bez komunitní podpory, ne Beken/ESP generace); sniff/MITM zachytávání hodnoceno jako kravina, nedává to smysl jako režie. Zbývá jediné rozvětvení: (a) Tuya cloud API s rozumným pollingem — teplota/vlhkost se mění pomalu, takže limit volání nemusí být reálný problém, pokud se dotazuje např. jednou za 5-15 min a ne po každém čidle zvlášť; nebo (b) postupná náhrada Tuya WiFi battery čidel Zigbee variantami (brána ZB Bridge Pro už je zvolená). Fyzicky: čidla mluví HTTPS na natvrdo vypálený endpoint — data nelze dostat lokálně vůbec, jediná cesta ven je cloud API.
  • 2026-09-09: Plan rozšířen o Tuya cloud API včítání: polling s nízkou frekvencí, cílově 10-15 min (user preference max 10-15 min). Data se publikují na MQTT jako u ostatních čidel.

Ověřeno na developer.tuya.com (primární zdroj), že cloud REALNĚ ví, kdy hodnota naposledy přišla:

  • GET /v1.0/devices/{device_id} vrací kromě status[] (code/value) také "update_time" (timestamp poslední aktualizace stavu zařízení, sekundy) a "online" flag — stačí z jednoho endpointu.
  • GET /v2.0/cloud/thing/{device_id}/report-logs (nebo /v1.0/iot-03/.../report-logs) vrací per-DP logy s "event_time" pro každý kód — přesná historie kdy co došlo, vč. časů jednotlivých reportů.
  • Tzn. problém "app ukazuje hodnotu starou týden a neumí říct že neplatí" je řešitelný: náš tuya2mqtt script bude porovnávat update_time/event_time proti aktuálním časem a ke každé hodnotě připojí timestamp posledního reálného reportu (a/nebo flag "stale"), takže HA/možné notifikace můžou detekovat mrtvá čidla.
  • 2026-09-09: Upřesnění tuya2mqtt designu: nechat API vrátit update_time pro každé zařízení, držet lokálně poslední známý update_time; pokud se mezi pollly nezměnil, hodnoty se na MQTT nepublikují vůbec (žádný stale flag ve zprávě, žádné opakované posílání stejných dat). MQTT tak zůstane čistý — zpráva = nová data. Detekce mrtvého čidla se pak dělá na straně konzumenta (HA/možný watchdog): absence zprávy na topicu za dlouhý čas = stale/offline; příp. HA MQTT device triggers / last_change sensor. Je to jednodušší a idempotentní, žádné duplikáty v brokeru.
  • 2026-09-09: Ověřeno z Tuya primárních zdrojů (developer.tuya.com membership-service + support.tuya.com): IoT Core Trial Edition (free, jen pro osobní/debug použití) — basic resource pack = 26 000 API volání / měsíc (+ 68 000 messages). Po vyčerpání: přístup omezen, Trial neumí overage (nelze dokoupit), obnoví se začátkem dalšího měsíce. Další Trial limity: max 50 zařízení v projektu, max 10 controllable devices, 1 data center, žádný log backtracking. Trial je navíc oficiálně časově omezený (6 měsíců, pak žádost o prodloužení — dle support.tuya.com lze prodloužit opětovnou žádostí). Rate limit navíc per-endpoint (např. ~10 req/s na některé, 500/s celkové API maximum) — pro náš use case irelevantní.

Spotřeba našeho designu: 1 hromadné volání za poll (GET /v1.0/iot-03/devices/status vrací status pro všechny device_id najednou) — při pollu co 15 min = 96 volání/den = ~2 880/měsíc, tj. cca 11 % kvóty. I s per-device report-logs voláními (pokud bychom chtěli event_time per DP) se do 26k vejdeme, ale hromadný status endpoint to pravděpodobně vyřeší i s update_time. Konec vahy: 15-min poll bezpečně v limitu; 10-min poll taky (~4 320/měsíc).

  • 2026-09-09: Oprava/uhrazení hromadného status endpointu: GET /v1.0/iot-03/devices/status (Get the latest status of multiple devices) — ověřeno v API reference: vrací POUZE code/value per DP, ŽÁDNÝ timestamp (žádné update_time, žádný event_time). Navíc limit max 20 device_ids per volání. Userova zkušenost tedy potvrzena dokumentací — hromadný endpoint pro náš dedup-design (aktualizace dle update_time) NEVYHOVUJE, protože nevrací čas posledního reportu.

Zpětný dopad na design kvót: musí se volat per-device endpoint, který update_time vrací. Kandidáti: (a) GET /v1.0/devices/{device_id} (Device Management) — vrací status[] + update_time + online (ověřeno dříve v docs); 1 volání per zařízení. (b) GET /v2.0/cloud/thing/batch (Query Device Details in Bulk) — nutné ověřit, zda vrací update_time. (c) GET /v2.0/cloud/thing/{device_id}/report-logs — event_time per DP, ale těžší volání.

Matematika s per-device voláním (a) při N čidlech:

  • 10 čidel: poll 15 min = 96 pollů/den × 10 = 960 volání/den ≈ 29k/měsíc — TĚSNĚ PŘES 26k Trial limitem.
  • 10 čidel, poll 20 min: 72 × 10 × 30 = 21 600 — pod limitem.
  • Závěr: per-device read s update_time na Trial edici vyžaduje poll ≥ ~20 min při 10 čidlech, NEBO batch endpoint (b) pokud vrací update_time (ověřit), NEBO Message Service (push namísto pollingu — 68k messages/měsíc kvóta, nutno prověřit).

Dotaz usera "co znamená +68k zprav": 68 000 messages = kvóta Message Service — push zprávy od Tuya cloudu (device status changes doručené aktivně, ne polling). Zatím neověřeno, zda/v jakém formátu to zahrnuje device status reports; potenciálně řeší celý problém (push místo poll), ale vyžaduje ověření API a vlastní endpoint (MQTT bridge / webhook receiver).

  • 2026-09-09: Ověření Tuya Message Service jako skalabilní cesty (místo per-device pollingu): Tuya Message Service používá Apache Pulsar (ne MQTT/HTTP webhook) — po aktivaci subscription na cloud projektu cloud aktivně PUSHuje event data, když se stav zařízení změní (data reporting, offline events, registrace). Klient se připojuje Pulsar SDK/consumerem, cloud doručuje zprávy do fronty, čte se pull-style z Pulsar topicu. Zdroj: developer.tuya.com (Get Messages by Message Queue — device-msg-queue-practice, subscribe-mq, integrate-mq). Klíčové fakty: "If the device status in the project changes, such as registration, data reporting, and offline events, Message Service is used to actively push event data to you with Pulsar" — tedy přesně náš use case, device status reports pushnuté okamžitě po reportu čidla.

Význam pro design: tím pádem NULOVÝ polling nutný pro běžný provoz — čidlo reportuje → cloud pushne zprávu → náš consumer publikuje na MQTT. 68k messages/měsíc Trial kvóta je v pohodě (čidlo reportuje typicky 1-2×/hodinu, 20 čidel = ~1-2k zpráv/den = max ~60k/měsíc, na hraně ale reálně méně, protože ne každý report = nová zpráva pro každé DP). Per-device poll (GET /v1.0/devices/{id}) si necháváme jako bootstrap/fallback (první načtení stavu po restartu, ověření že jsme nezmeškali nic).

Dopad na kvóty: API volání klesnou na minimum (bootstrap + health-check), messages se posunou do 68k kvóty. Skaluje se lineárně s počtem čidel bez nutnosti měnit poll frekvenci.

Otevřené body k doladění: (a) Pulsar consumer běží v našem LXC (Python klient existuje — tuya-iot-pulsar-sdk), (b) formát zprávy obsahuje data + timestamp (nutno ověřit na reálných datech), (c) offline events umožňují detekovat mrtvá čidla pushem, ne pollingem.

  • 2026-09-09: User vytýká principiální problém pollingu: čidlo reportuje klidně každou minutu, ale uživatel to v HA vidí až za 20 minut (worst case = poll period). Tohle je přesně argument, proč polling je špatný model pro čidla, která reportují často. Pulsar push (Message Service) to řeší — zpráva dorazí okamžitě po reportu, tedy latence = sekundy, ne minuty. Tímto je designový směr definitivně: PULL (polling) jen jako fallback/bootstrap, primární tok = PUSH (Pulsar). 20-min poll fallback zůstává jako safety net pro případ výpadku consumeru, ale pro data je hlavní cesta push.
  • 2026-09-09: DEFINITIVNÍ ZÁVĚR k Tuya WiFi čidlům: architektonický slepý konec. Tuya cloud brutálně omezuje přístup k vlastním datům — kvóty (26k API volání/měsíc, 68k messages), Trial limit 50 zařízení, žádný overage dokup, data nutně přes cizí cloud. Žádná z probraných cest (per-device poll, hromadný poll, Pulsar push) tohle neobejde — limit je v samotném modelu "data musí projít Tuya cloud", ne v designu.

Rozhodnutí:

  • Target architektura = Zigbee (ZB Bridge Pro) + MQTT lokálně, plná vlastní režie, žádné kvóty.

  • Alternativa = WiFi senzory ve vlastní režii (ESP32 DIY) publikující přímo na MQTT.

  • Zpracování pravděpodobně v HA, ale ne nutně — MQTT je neutrální sběrnice, konzument může být cokoliv.

  • tuya2mqtt bridge degradován na legacy: běží pro existující Tuya WiFi čidla, dokud se nevymění. Neškáluje a jednou vymře.

  • Migrace postupná: Tuya čidlo umře / slabá baterie / špatné měření → náhrada Zigbee/ESP32 variantou. Žádná aktivní hromadná náhrada zdravých čidel.

  • DŮLEŽITÉ DO BUDOUCNA: nekupovat už žádná Tuya WiFi battery čidla. Lekce: před nákupem čidla ověřit, že data jdou dostat v plné vlastní režii (MQTT-first, žádný povinný cloud).

  • 2026-09-11: User má doma HackRF One a RTL-SDR (+ další SDR hardwar), SDR ho zajímá. Indexované zdroje: GNU Radio World (https://gnuradioworld.com — GNU Radio flowgraphy v prohlížeči přes WebAssembly, WebUSB podpora RTL-SDR/PlutoSDR/HackRF) a PySDR (https://pysdr.org — online učebnice SDR/DSP v Pythonu od Marca Lichtmana). Oba zdroje od téhož autora (777arc), vzájemně propojené — PySDR má ukázkové flowgraphy spustitelné přes GNU Radio World. Zapsáno do notes/notes.md sekce SDR/radio.

  • 2026-09-11: Research: jak se GNU Radio World připojuje k SDR hardware. Ověřeno přímo ve zdrojácích (repo 777arc/gnuradio-world, docs/hackrf.md + editor/src/hackrf.ts + runner/src/hackrf_worker.js):

  • Připojení je čistě přes WebUSB (navigator.usb) — žádný server, žádný native driver, žádný helper proces. Funguje jen v Chromiu (Chrome/Edge/Opera); Firefox a Safari WebUSB nemají.

  • Detekce: USB filtr vendorId 0x1d50, productId 0x6089 (HackRF One). Pro RTL-SDR a PlutoSDR analogické filtry.

  • Oprávnění: uživatel klikne „Add" u Device parametru nebo stiskne Run → browser requestDevice() prompt. WebUSB permise je per-origin a přežije zavření tabu; v .grc se ukládá jen USB serial number a runner si zařízení znovu nabhádne přes getDevices().

  • Runtime: editor drží WebUSB, ale USBDevice nikdy nepřechází mezi frames ani do Wasm. runner.html spustí hackrf_worker.js (JS worker), který claimne interface, posílá vendor control requesty (mode/sample rate/bw/freq/gainy — stejné requesty jako libhackrf) a drží 4 paralelní bulk transfery v letu. Data jdou přes shared-memory ring + futex-like control blok do Wasm GNU Radio scheduleru (thread-per-block, SharedArrayBuffer). libhackrf/libusb se do Wasm záměrně nekompiluje.

  • HackRF je half-duplex; jedno fyzické zařízení může vlastnit jen jeden aktivní Source/Sink; víc jednotek OK při explicitních serialech.

  • Linux: browser user musí mít přístup k USB nodu (udev), žádný native program nesmí mít HackRF otevřený. Snap Chromium nemusí USB dosáhnout. Windows: nutná WinUSB binding přes Zadig.

  • Fallback bez HW: device „fake" / „fake:" vygeneruje testovací tón, žádný USB se neotevírá; kromě toho ukázkové IQ nahrávky streamované z Cloudflare R2 (recordings.gnuradioworld.com).

  • 2026-09-11: GRWire — síťový přístup k SDR pro GNU Radio World (klíčové zjištění, user to chce vyzkoušet):

  • GRWire = malý Rust daemon na stroji se SDR + blok „GRWire Source" v GNU Radio World (v repo 777arc/gnuradio-world, adresář grwire/, first cut 2026-09-10).

  • Dolů mluví SoapySDR (podpora všeho s Soapy driverem: RTL-SDR, HackRF, …), nahoru jeden WebSocket wss:// (protokol grwire.v1: control JSON text frames + IQ binární frames, header 32 B fixed).

  • Setup: na stroji se SDR „grwire serve" → self-signed cert, vytiskne https://host:8073/ (otevřít jednou v browseru, akceptovat cert — jinak https stránka nesmí otevřít wss:// na LAN kvůli mixed content) + wss:// URL s tokenem. Token se ukládá do localStorage, NE do .grc (sharenutý flowgraph nesmí rozdávat přístup k rádiu). Origin allowlist jako defence in depth.

  • Daemon umí mix NCO (offset ladí v pásme bez HW retune glitche) + decimaci halfband kaskádou; Decimation=0 = automatický plán. HackRF nejde pod 1 MS/s hardwarově — 250 kS/s jen přes decimaci; 20 MS/s ci8 = 320 Mbit/s, WiFi nezvládne, proto decimace na straně daemona.

  • Backpressure: flow ack každých 8 frames, max quarter-second za posledním ackem; drop counters per vrstva (dev_overruns/host_drops/net_drops/client_drops), drop-oldest + FLAG_DISCONTINUITY.

  • Gain stages poziční (Stage 1/2/3 → u HackRF LNA/AMP/VGA), dialog relabelne dle rádia; výchozí -1000 = „nedriven" (0 dB je reálný gain).

  • Jeden client najednou (druhý refused, --takeover). Alternativa SoapyRemote z browseru nefunguje (TCP+UDP, raw sockety v browseru nejsou a nebudou).

  • Status: first cut, commit msg přiznává „hackrf signal doesnt look right though, rtl looks good" — RTL přes GRWire OK, HackRF zatím podezřelý; lokální WebUSB HackRF je plně funkční.

  • User to URČITĚ chce vyzkoušet (SDR na jiném počítači, dotáhnout přes síť do browseru).

GNU Radio World self-hosting: ano, opensource (GPLv3+, copyright Marc Lichtman). Build celého stacku ze zdrojáků (README dev quickstart): Ubuntu 24.04+, emsdk 3.1.70, Qt 6.9.1 wasm_multithread, GNU Radio kompilované do WebAssembly bez Pythonu; ~10 GB disk, první build ~1 h. Provoz přes „node server.mjs 8090" — nutné kvůli COOP/COEP headerům (SharedArrayBuffer pro thread-per-block scheduler). Ukázkové IQ nahrávky streamují z Cloudflare R2 (recordings.gnuradioworld.com), CORS povoluje origin portu 8090 — na vlastním portu nahrávky nefungují (nebo vlastní kopie bucketu).

  • 2026-09-11: GNU Radio World repo adresa (user request, poznamenej): https://github.com/777arc/gnuradio-world — GPLv3+, autor Marc Lichtman (777arc). Docker: oficiální prebuilt image neexistuje — v repo není Dockerfile, na Docker Hub / ghcr nic relevantního (jen cizí staré GNU Radio kontejnery, ne GNU Radio World). Self-host = build ze zdrojáků (emsdk 3.1.70 + Qt 6.9.1 wasm_multithread, ~10 GB, ~1 h). Live verze na gnuradioworld.com je aktualní vždy — self-host hlavně kombinovaně s GRWire daemonem na stroji se SDR.