# Teltonika TeltoCharge — Modbus registry (EMS)

Zdroj: oficiální „TeltoCharge Modbus RTU Communication protocol" rev 0.5
(2024-07-23). Připojení: sdílená RS485 sběrnice → Waveshare RS485 TO POE ETH (B) **172.16.1.16:502** (V097; 9600 8N1, Modbus TCP↔RTU; WB1 = unit 1, WB2 = unit 2, plánovaný Chint = unit 3) → Modbus TCP (endpoint
`site_endpoint`, FC 3 čtení, FC 6/16 zápis). Wallbox musí být v aplikaci
nastaven jako *secondary (server)*.

## Čtení (telemetry_collector, blok 0–40 jedním FC 3)

| Reg | Význam | Formát |
|-----|--------|--------|
| 0–2 | Napětí L1–L3 | int16, V |
| 3–5 | Proud L1–L3 | int16, ×10 A |
| 6 | **EVSE status (DLM)** | 0=C nabíjí · 1–3=B1–B3 připojeno · 4=D1 stop od EV · 5–6=D2–D3 zákaz · 7=A bez EV · 8=F chyba · 9=E |
| 27 | Charge point state | 0–9 (informativní) |
| 33 | IEC61851 stav | 0–8 |
| 34/35 | Warning / Error bity | bitfield |
| 38 | Okamžitý výkon | uint16, W |
| 39 | Energie session | uint16, kWh×100 |
| 40 | Trvání session | uint16, s |
| 41–44 | Celková energie (FW ≥1.13) | uint64, kWh×100 |

Mapování stavů v EMS (`TELTO_STATUS_MAP` v `telemetry_collector.py`):
7→`available`, 0→`charging`, 1–3→`preparing`, 4→`suspended_ev`,
5–6→`suspended_evse`, 8→`faulted`, 9→`unknown`. Detekce příjezdu/odjezdu
(`fn_ev_session_transition`) stojí na přechodu `available` ↔ ≠`available`.

**Při selhání čtení se vzorek NEzapisuje** — fabrikovaný `available` by falešně
ukončil session a EV výkon 0 by špinil bazál (pravidlo 15).

## Zápis (control exporter — `write_ev_setpoints`, `write_ev_arrival_hold`)

| Reg | R/W | Význam | Hodnoty | EMS zapisuje |
|-----|-----|--------|---------|--------------|
| 15 | R/W | **Amps to use** (limit proudu) | 0 = stop, 6–32 A | hodnota z plánu (`ev{1,2}_current_a`); příjezd EV → hold 0 A. **Zapisuje se KAŽDÝ tick** (re-asert, ne write-on-change — viz níže) |
| 16 | R/W | Start/Stop session | 0 nic · 1 stop · 2 start | ne (tvrdé zastavení řešíme reg 15 = 0) |
| 19 | R/W | Communication timeout (watchdog) | 0–600 s (0 = vypnuto), default 30 | per charger `asset_ev_charger.watchdog_comm_timeout_s` (default **300**) |
| 20 | R/W | Failsafe current | 0, 6–32 A, default 6 | per charger `asset_ev_charger.watchdog_failsafe_a` (default **8**) |

Všechny čtyři registry jsou dle oficiálního protokolu (wiki *External control
RS485* / protokol rev 0.5) **R/W** — verify job je čte zpět standardní FC 3
větví (žádný write-only registr v této sadě).

**„Zákaz nabíjení" = reg 15 = 0.** Protokol rev 0.5 v této sadě **nemá**
samostatný boolean „charging enable/disable" registr — řízení je proudovým
limitem (reg 15: 0 = stop) plus volitelně reg 16 (1 = stop session). EMS
používá **reg 15 = 0** jako řízené zastavení (arrival-hold i běžný plán);
reg 16 se nezapisuje. Failsafe (reg 20) je hodnota PŘI výpadku komunikace,
ne při běžném provozu — běžně auto stojí na 0 A, dokud plán neřekne jinak.

### Reg 15 (amps) — VŽDY re-asert; reg 19/20 — write-on-change (EEPROM)

Export tick běží ~8×/hod (control_export `:14,:29,:44,:59` + rolling replan
`*/15` s exportem).

- **reg 15 (amps to use) se zapisuje při KAŽDÉM ticku** (`write_ev_setpoints`
  i `write_ev_arrival_hold`). **Důvod (incident 2026-06-13):** TeltoCharge si
  po výpadku komunikace sám přepíše reg 15 na failsafe (reg 20) — bez journal
  řádku. Kdyby byl reg 15 write-on-change proti journalu (poslední
  „0 verified"), EMS by tichý drift **0 → 8 A** na zařízení **NIKDY
  nezahlédlo** (verify čte zpět jen `written` řádky) a nikdy ho neopravilo:
  auto po každém krátkém výpadku spojení tiše jelo 8 A místo plánovaných 0 A.
  Reg 15 je volatilní řídicí registr (ne EEPROM), opakovaný zápis je v pořádku;
  re-asert každý tick zároveň drží verify jobu čerstvý `written` reg-15 řádek
  → případný drift se zachytí a hned opraví.
- **reg 19/20 (watchdog config) zůstávají write-on-change** přes
  `_drop_registers_matching_last_verified` proti **`ems.fn_modbus_device_state_map`**
  (nejnovější řádek journalu per registr, stav `written` **nebo** `verified`):
  zapíší se jednou po nasazení / po výpadku zařízení (nejnovější řádek
  `failed`/`mismatch` ⇒ registr v mapě chybí ⇒ znovu se zapíše) a pak už ne,
  dokud se hodnota nezmění — šetří EEPROM. Čekání na verify skip neblokuje,
  `written` (TCP ack) stačí.

Implementace: `_telto_setpoint_registers` (per-charger failsafe/timeout),
`_split_amps_and_watchdog` (reg 15 vs 19/20) v `services/control/outputs.py`.

### Watchdog — sytí ho i čtení; failsafe konfigurovatelný

Protokol definuje timeout jako *„if no **valid communication** is present
after a configurable time interval…"* — timer resetuje **jakákoli** validní
Modbus komunikace s unit ID wallboxu, **včetně FC 3 čtení**. Telemetrie čte
blok 0–40 každých **60 s**, takže watchdog 300 s je trvale sycen čtením a
**periodické zápisy k udržení spojení nejsou potřeba**. Failsafe (reg 20
„max allowed current on comm timeout") nastane až po `watchdog_comm_timeout_s`
bez jakéhokoli pollingu = skutečný výpadek EMS.

**Failsafe je per charger** (`asset_ev_charger.watchdog_failsafe_a`, default
8 A; `watchdog_comm_timeout_s`, default 300 s; migrace V106):
- default **8 A** = po skutečném výpadku EMS se auto přes noc pomalu dobije
  místo stání na 0 A;
- snížit lze na **6 A** (IEC 61851 minimum) nebo **0** (po výpadku nenabíjet),
  dle dotačních / komfortních požadavků;
- **běžný provoz po zapojení řídí reg 15 z plánu** (0 A drží arrival-hold +
  sycení watchdogu čtením telemetrie), failsafe se uplatní jen při výpadku —
  rozpor „chci řízený default 0 A, ale po výpadku malý proud" je tím vyřešen.

## WB2 mimo EMS (V105, 2026-06-13)

ev-charger-2 deaktivován (endpoint disabled + schedulable=false) — dle
dotačních podmínek ho řídí elektroměr mimo EMS. Telemetrie ani zápisy na
unit 2 neběží (RS485 brána 172.16.1.16 slouží jen WB1 + budoucí Chint).
Reaktivace: dva UPDATE v komentáři V105__wb2_deactivate.sql.
