Files
ems/docs/04-modules/telemetry.md
Dusan Vojacek 02f0ab66e4
Some checks failed
CI and deploy / migration-check (pull_request) Failing after 27s
CI and deploy / deploy (pull_request) Has been skipped
gpt5.5 - odladeni dokumentace dle kodu
2026-05-02 19:17:04 +02:00

8.4 KiB
Raw Permalink Blame History

Modul: Telemetry (Sběr dat ze zařízení)

Co modul dělá

  • Čte data ze střídače Deye přes Modbus TCP
  • EV nabíječky Teltonika a tepelné čerpadlo Samsung mají zatím placeholder vzorky; konkrétní registry jsou TODO
  • Ukládá surová měření do DB (1min granularita)
  • Detekuje výpadky komunikace a loguje chyby
  • Agreguje 1min data na 15min průměry pro spotřebu, audit a plánování

Komponenta: telemetry_collector (Python service)

Samostatná Python služba. Běží jako smyčka, nezávislá na FastAPI.

Polling intervaly

Zařízení Interval Důvod
Deye střídač 60 s 1min granularita telemetrie
Teltonika EV nabíječka 1 60 s zatím placeholder available, 0 W
Teltonika EV nabíječka 2 60 s zatím placeholder available, 0 W
Samsung tepelné čerpadlo 60 s zatím placeholder hodnoty

Chování při chybě

  • Chyba komunikace: záznam se nezapíše, chyba se loguje
  • Kód zatím nedrží počítadlo po sobě jdoucích chyb podle zařízení; chyby se logují při jednotlivých poll pokusech
  • Data se neinterpolují chybějící minuty zůstanou prázdné (audit to pozná)

Deye SUN-20K Modbus registry

Komunikace: Modbus TCP, Unit ID dle DIP přepínače na střídači (typicky 1).

Mapování v kódu: backend/services/telemetry_collector.py (holding registry, decimal adresa = offset pro read_holding_registers).

Dec (hex) Typ Popis Jednotka Poznámka
500 (0x01F4) uint16 Provozní stav střídače enum raw do run_state, ladění
514 (0x0202) uint16 Dnešní nabití baterie Wh batt_charge_today_wh
515 (0x0203) uint16 Dnešní vybití baterie Wh batt_discharge_today_wh
588 (0x024C) uint16 Battery SoC % battery_soc_percent
590 (0x024E) int16 Tok výkonu baterie W signed z Deye; v DB battery_power_w platí + nabíjení, vybíjení
625 (0x0271) int16 Výkon sítě W signed: + import, export
653 (0x028D) uint16 Celková spotřeba W load_power_w
667 (0x029B) int16 Výkon GEN portu (FVE pole B) W (signed) gen_port_power_w; záporné při zpětném toku / bez výroby — číst signed
672 (0x02A0) int16 Výkon PV1 W (signed) pv1_power_w; při špatném unsigned čtení se záporné hodnoty jeví jako desítky kW
673 (0x02A1) int16 Výkon PV2 W (signed) pv2_power_w

pv1_power_w / pv2_power_w / gen_port_power_w v DB = signed W z Modbus (mohou být záporné).

pv_power_w = max(0, PV1) + max(0, PV2) + max(0, GEN) — okamžitá kladná výroba FVE pro dashboard a souhrny; záporné kanály do součtu nepatří (typicky večer při exportu z baterie do sítě).

gen_port_power_w zůstává uložen samostatně pro audit zeleného bonusu a diagnostiku.

Ověření po změně sběru: za denního SVitu zkontrolovat, že pv_power_w a jednotlivé kanály odpovídají očekávanému max. výkonu instalace (logika: aggregate_pv_production_w v telemetry_collector.py, unit testy tests/test_telemetry_pv_signed.py).

Zápis setpointů (plánování → Deye):

Aktuální řízení Deye je popsané v control.md a modbus-registers.md. Nepoužívá starý write_register model, ale journal ems.modbus_command a FC 0x10 (write_registers) pro registry 108/109/141/142/143/145/178/340 + TOU bloky.

Historická orientační mapa níže neplatí jako implementační kontrakt:

Registr (hex) Typ Popis Hodnota
0x00F3 Write Single Battery charge power limit W
0x00F4 Write Single Battery discharge power limit W
0x00F6 Write Single Grid export power limit W
0x00F0 Write Single Work mode enum (viz tabulka)

Rychlá kontrola komunikace: scripts/test_modbus_deye.py.


Teltonika TeltoCharge Modbus registry

Komunikace: Modbus TCP přes Waveshare, Unit ID = 1 (ověřit).

Registry doplnit z Teltonika TeltoCharge Modbus dokumentace / Loxone šablony.

Registr Typ Popis Jednotka
TBD Read Stav konektoru (OCPP status enum) enum
TBD Read Aktuální výkon W
TBD Read Kumulativní energie session Wh
TBD Read Proud L1/L2/L3 0.1A
TBD Read Napětí 0.1V
TBD Read Session ID uint
TBD Read Error code uint
TBD Write Max proud (charge limit) A (632A)
TBD Write Povolení nabíjení (on/off) bool

Samsung tepelné čerpadlo Modbus registry

Komunikace: Modbus TCP přes Waveshare.

Registry doplnit ze Samsung NASA Modbus dokumentace / Loxone šablony.

Registr Typ Popis Jednotka
TBD Read Venkovní teplota 0.1°C
TBD Read Teplota vody vstup 0.1°C
TBD Read Teplota vody výstup 0.1°C
TBD Read Teplota zásobníku TUV 0.1°C
TBD Read Příkon W
TBD Read Provozní režim enum
TBD Read Alarm kód uint
TBD Read Odmrazování aktivní bool
TBD Write Povolení provozu bool
TBD Write Požadovaná teplota TUV °C

Kód telemetrie (Python)

Implementace: backend/services/telemetry_collector.pypoll_inverter() používá konstanty DEYE_REG_* a sdíleného Modbus klienta z services.modbus_client; hlavní smyčka je run_telemetry_loop / run_telemetry_loop_wrapper.


Agregace 1min → 15min

Prováděna PostgreSQL funkcí ems.fn_fill_audit_interval() a navazujícími funkcemi pro baseline/accuracy. Spouští ji Python APScheduler: audit filler v minutách :01,:16,:31,:46, forecast accuracy v :02,:17,:32,:47.

-- Příklad agregace telemetrie na 15min průměr
-- (součást fn_fill_audit_interval)
SELECT
    site_id,
    time_bucket('15 minutes', measured_at) AS interval_start,
    AVG(pv_power_w)::INT          AS avg_pv_power_w,
    AVG(battery_power_w)::INT     AS avg_battery_power_w,
    AVG(grid_power_w)::INT        AS avg_grid_power_w,
    AVG(load_power_w)::INT        AS avg_load_power_w,
    LAST(battery_soc_percent, measured_at) AS last_soc_pct
FROM ems.telemetry_inverter
WHERE measured_at >= $1 AND measured_at < $1 + INTERVAL '15 minutes'
  AND site_id = $2
GROUP BY site_id, time_bucket('15 minutes', measured_at);

Timescale continuous aggregates (střídač → dashboard)

Nad ems.telemetry_inverter běží dva continuous aggregate (TimescaleDB); oba se periodicky obnovují (řádově každých 15 minut). Definice CA je ve verzovaných migracích (V011, V039); view nad CA držíme v repeatable souborech (db/views/R__*.sql), aby šla měnit jedna aktuální definice bez nové V migrace.

Objekt Bucket View pro PostgREST / UI Poznámka
ems.telemetry_inverter_hourly 1 hodina ems.vw_telemetry_hourly_7d CA a view v V011; security_invoker v V031. Hodinové trendy.
ems.telemetry_inverter_15m 15 minut ems.vw_telemetry_15m_7d db/views/R__071_vw_telemetry_15m_7d.sql posledních 7 dní, zarovnání s 15min sloty přehledu.

Frontend přehled (frontend/src/hooks/useDashboardData.ts): skutečné výkony a SoC po slotech bere z /vw_telemetry_15m_7d (klíč slotu = začátek 15min intervalu v UTC, stejně jako floorSlotUtcMs v grafu). Horní karty a aktuální SoC v grafu jsou dál z vw_site_status (poslední 1min vzorek) a z WebSocketu /ws/telemetry, aby „teď“ odpovídalo boxu i po refreshi agregátu.

Plánovač počáteční SoC nečte z těchto view bere poslední řádek z ems.telemetry_inverter (planning_engine._load_site_context).


Konfigurace (env proměnné)

TELEMETRY_POLL_INTERVAL_SEC=60
MODBUS_CONNECT_TIMEOUT_SEC=5
MODBUS_READ_TIMEOUT_SEC=3

TELEMETRY_POLL_INTERVAL_SEC a chybové prahy zatím nejsou v kódu používány; smyčka běží každých 60 s přímo v run_telemetry_loop_wrapper.


Otevřené body

  • Základní mapování Deye (holding registry 500673) v telemetry_collector.py
  • Doplnit Modbus registry Teltonika z dokumentace / Loxone šablony
  • Doplnit Modbus registry Samsung z dokumentace / Loxone šablony
  • Ověřit Unit ID všech zařízení při instalaci
  • Optimalizovat čtení Deye jako jeden read_holding_registers blok místo jednotlivých registrů