72 lines
4.3 KiB
Markdown
72 lines
4.3 KiB
Markdown
# Provozní režimy EMS
|
||
|
||
## Keep it simple
|
||
|
||
- **Méně heuristik a pevných wattových práhů v řízení** — každá magická konstanta je místo, kde se rodí neshody s plánem a ekonomikou.
|
||
- **SELL na Deye** používej jen tam, kde produktově opravdu chceme režim „**vylít baterii do sítě**“ (selling first). Vše ostatní patří do **PASSIVE** a tok FVE ↔ baterie ↔ síť se řeší **reg. 108 / 109 / 142** podle plánu a instalace.
|
||
- Novou logiku vždy ověřit proti **reálnému řádku plánu** (audit / `planning_interval`) a typické chybě „plán říká kW, měnič jede na MW“.
|
||
|
||
## Přehled
|
||
|
||
| Mode | Solver constraints | Deye fyzický režim | Baterie |
|
||
|------|-------------------|-------------------|---------|
|
||
| AUTO | žádné | PASSIVE/SELL/CHARGE dle plánu | dle plánu |
|
||
| SELF_SUSTAIN | no_export, min_import | vždy PASSIVE | plné limity |
|
||
| CHARGE_CHEAP | no_export, no_discharge | CHARGE | nabíjení max |
|
||
| PRESERVE | no_charge, no_discharge | PASSIVE | lock (0/0) |
|
||
| MANUAL | solver neběží | EMS nezapisuje | — |
|
||
|
||
Implementace: omezení LP v `planning_engine.solve_dispatch()` podle `mode_code` z `ems.site_operating_mode`; zápis Deye v `control_exporter.write_inverter_setpoints()` (včetně `lock_battery` u PRESERVE).
|
||
|
||
## Fyzické režimy Deye (výstup control_exporteru)
|
||
|
||
Detekce v `get_deye_mode` (`battery_w` = `battery_setpoint_w` z plánu, záporné = vybíjení; `grid_setpoint_w` záporné = export do sítě):
|
||
|
||
- **CHARGE:** `battery_w` > 500 **a** `grid_setpoint_w` > 200 → nabíjení ze sítě; reg. **142** dle CHARGE větve v exporteru, **178** = 48.
|
||
- **SELL:** `grid_setpoint_w` < 0 **a** `battery_w` < 0 **a** `|battery_w| ≥ |grid_setpoint_w|` → záměr **vybíjet baterii do sítě** (selling first); reg. **142** = 0, **178** = 32, **108** = 0, **109** = max, reg. **143** omezen podle `|grid_setpoint_w|` (viz `control_exporter.py`).
|
||
- **PASSIVE:** vše ostatní — tok FVE a baterie řídí **reg. 108** (nabíjení) a **109** (vybíjení, škálované podle `|battery_w|`), **142** = `deye_zero_export_mode`, **145** = 1, **178** = 48.
|
||
|
||
**SELF_SUSTAIN:** `battery_w = None` ⇒ v `get_deye_mode` jako 0 ⇒ typicky **PASSIVE**; v `write_inverter_setpoints` při `self_sustain_local_use=True` → **108 i 109 = max**, reg. **142** = zero export dle DB, TOU SOC = **`min_soc_percent`**. **PRESERVE:** `lock_battery` → **108 = 0**, **109 = 0**.
|
||
|
||
## EMS politiky (nejsou fyzické stavy Deye)
|
||
|
||
- **PV_SELL_ONLY:** AUTO + constraint solveru `max_discharge_from_pv`
|
||
- **BLOCK_EXPORT:** AUTO + záporná sell_price → `ge[t]=0`
|
||
- **NEGATIVE_HARVEST:** AUTO + záporná buy_price → max charge/load
|
||
- **PROTECT:** SELF_SUSTAIN s konzervativními limity
|
||
|
||
Tyto politiky jsou parametrizace AUTO/SELF_SUSTAIN, ne samostatné fyzické stavy.
|
||
|
||
---
|
||
|
||
## Loxone a UI (shrnutí)
|
||
|
||
EMS a Loxone sdílí pojmenované provozní režimy; Loxone dostává číslo režimu přes Virtual Input a může fungovat autonomně (watchdog při výpadku EMS).
|
||
|
||
```
|
||
POST /api/v1/sites/{site_id}/mode
|
||
{
|
||
"mode": "SELF_SUSTAIN",
|
||
"valid_until": null,
|
||
"notes": "…"
|
||
}
|
||
```
|
||
|
||
Backend: `ems.fn_set_mode` přes `run_fn_set_mode_with_discord` (při skutečné změně `mode_code` → Discord, pokud je `DISCORD_WEBHOOK_URL`) + HTTP na Loxone `/dev/sps/io/EMS_Mode/{loxone_mode_value}`. Dočasné přepisy s `valid_until` ruší `ems.fn_expire_modes()`, která vrací řádky `(site_id, site_code, old_mode, new_mode)` pro každé přepnutí — scheduler je použije pro stejné Discord upozornění.
|
||
|
||
**Klíčový princip:** Loxone watchdog nečte DB – sleduje pulzy `EMS_Heartbeat`. Detail: `docs/loxone-integration.md`. Detail Modbus / Discord: `docs/04-modules/modbus-command-journal.md`.
|
||
|
||
### Tabulka režimů (Loxone / zátěže)
|
||
|
||
| Kód | Loxone int | EV | TČ | Poznámka |
|
||
|-----|------------|----|----|----------|
|
||
| `AUTO` | 1 | dle plánu | dle plánu | setpointy z plánu |
|
||
| `SELF_SUSTAIN` | 2 | stop | stop | fallback / výpadek EMS |
|
||
| `CHARGE_CHEAP` | 3 | stop | stop | max nabíjení ze sítě |
|
||
| `PRESERVE` | 4 | stop | stop | baterie uzamčena (Modbus 0/0) |
|
||
| `MANUAL` | 0 | stop | stop | servis, EMS neexportuje |
|
||
|
||
### Otevřené body
|
||
|
||
- [ ] Doplnit alerty při `ems_heartbeat_status = 'stale'` (Discord při změně provozního režimu z backendu je popsán v `modbus-command-journal.md`)
|