uprava zapisovani casu do deye (nevyvolava self_sustain), notifikace na discord pri zmene rezimu
This commit is contained in:
@@ -22,11 +22,15 @@ Indexy: podle `(site_id, status, created_at)` a částečný index pro `pending`
|
||||
|
||||
## Verifikace a bezpečnost
|
||||
|
||||
1. Po `mismatch` se odešle **Discord** alert (`notification_service.send_discord` / `notify_modbus_mismatch`), pokud je nastaven `DISCORD_WEBHOOK_URL`.
|
||||
1. Po `mismatch` se odešle **Discord** alert (`notify_modbus_mismatch`), pokud je nastaven `DISCORD_WEBHOOK_URL`.
|
||||
2. **Retry** zápisu max. **3×** (počítáno přes `attempt_count` po zápisech).
|
||||
3. Po třech neúspěšných cyklech: přepnutí lokality na **SELF_SUSTAIN** přes `ems.fn_set_mode` (`activated_by` = `system:mismatch`, poznámka = důvod) a **kritický** Discord alert (`notify_self_sustain_activated`).
|
||||
3. Po třech neúspěšných cyklech ověření:
|
||||
- **Obyčejné registry** (mimo souvislý blok Deye **62–64**): přepnutí lokality na **SELF_SUSTAIN** přes `run_fn_set_mode_with_discord` → `ems.fn_set_mode` (`activated_by` = `system:mismatch`, poznámka = důvod). Při skutečné změně `mode_code` jde na Discord **kritická** zpráva (stejný formát jako u ostatních přepnutí režimu).
|
||||
- **Výjimka — systémový čas 62–64:** přepnutí režimu **se neprovádí**. Po 3 neúspěšných ověřeních jde **kritický** Discord (`notify_modbus_clock_verify_exhausted`); střídač a EMS režim zůstávají v aktuálním stavu (čas na sběrnici může vyžadovat ruční kontrolu / firmware).
|
||||
|
||||
Implementace: `services/control_exporter.py` — `verify_modbus_commands`, `_switch_to_self_sustain`.
|
||||
**Discord při jakékoli změně režimu** (nejen Modbus): `notification_service.run_fn_set_mode_with_discord` volá `ems.fn_set_mode` a při změně `mode_code` oproti stavu před voláním pošle zprávu (`notify_operating_mode_changed`). Úroveň: `user:api` → info, obecné `system:*` → warning, `system:mismatch` → critical. Použití: HTTP `POST /api/v1/sites/{site_id}/mode`, `_switch_to_self_sustain` v `control_exporter`. Vypršení `valid_until`: `ems.fn_expire_modes()` vrací řádky `(site_id, site_code, old_mode, new_mode)` pro každé provedené přepnutí; scheduler v `main.py` (a lazy expire v `_fetch_operating_mode`) z nich pošle Discord.
|
||||
|
||||
Implementace: `services/control_exporter.py` — `verify_modbus_commands`, `_verify_deye_clock_command_run`, `_switch_to_self_sustain`; `services/notification_service.py` — `run_fn_set_mode_with_discord`, `notify_operating_mode_changed`.
|
||||
|
||||
## Střídač (Deye)
|
||||
|
||||
@@ -56,6 +60,6 @@ Tabulka pro budoucí logování **cut-off** přepínačů (mikroinvertory / GEN
|
||||
|
||||
## Související soubory
|
||||
|
||||
- Migrace: `db/migration/V023__modbus_command_journal.sql`, `V025__deye_physical_mode.sql`, `V030__deye_clock_sync_at.sql`
|
||||
- Migrace: `db/migration/V023__modbus_command_journal.sql`, `V025__deye_physical_mode.sql`, `V030__deye_clock_sync_at.sql`; repeatables `db/routines/R__fn_set_mode.sql` (`fn_expire_modes` vrací detail přepnutí pro notifikace)
|
||||
- Backend: `backend/services/control_exporter.py`, `backend/services/modbus_client.py`, `backend/services/notification_service.py`, `backend/app/main.py`
|
||||
- Registry Deye: `docs/04-modules/modbus-registers.md`
|
||||
|
||||
@@ -100,11 +100,11 @@ Registry **62–64** nastavují invertoru čas v **Europe/Prague**.
|
||||
- reg **63:** `den << 8 | hodina`
|
||||
- reg **64:** `minuta << 8 | sekunda` — při zápisu z EMS jsou **sekundy vždy 0** (stabilnější hodnota; na zařízení pak sekundy dál běží).
|
||||
|
||||
**Řidší zápis:** před každým exportem setpointů EMS **přečte** 62–64 (FC 0x03). Do journalu **62–64 nezařadí**, pokud je dekódovaný čas invertoru vůči aktuální **Europe/Prague** v odchylce **≤ 60 s** *a zároveň* od posledního **úspěšného zápisu** 62–64 neuplynulo **24 h** (`asset_inverter.deye_last_system_time_sync_at`, mění se jen při zápisu). Je-li sloupec NULL (např. první provoz), zápis času se **nevynechá**. Při selhání čtení se čas **zapíše** (bezpečný fallback). Sloupec `deye_last_system_time_sync_minute` doplňuje začátek pražské minuty u **úspěšného zápisu** 62–64.
|
||||
**Řidší zápis:** před každým exportem setpointů EMS **přečte** 62–64 (FC 0x03). Do journalu **62–64 nezařadí**, pokud je dekódovaný čas invertoru vůči aktuální **Europe/Prague** v odchylce **≤ 60 s** *a zároveň* od posledního **úspěšného ověření** trojice 62–64 v journalu (stav `verified` po toleranční kontrole níže) neuplynulo **24 h**. Tomu odpovídají sloupce `asset_inverter.deye_last_system_time_sync_at` a `deye_last_system_time_sync_minute`: doplňují se **až po úspěšné toleranční verifikaci** v `_verify_deye_clock_command_run`, nikoli po samotném FC 0x10 zápisu (aby řídicí logika ne„myslela“, že je čas na invertoru sjednocený, dokud to verify nepotvrdí). Je-li `deye_last_system_time_sync_at` **NULL** (první provoz / nikdy neověřený sync), zápis času se **nevynechá**. Při **selhání čtení** 62–64 před rozhodnutím se čas **zařadí do journalu** (bezpečný fallback). Při scénáři „žádný řádek journalu, všechny hodnoty jako poslední `verified`“ se **čas v DB neaktualizuje** (žádný fiktivní sync).
|
||||
|
||||
Zápis prochází journal jako každý jiný registr; na sběrnici jde souvislý blok **FC 0x10**.
|
||||
|
||||
**Verifikace (journal):** u souvislého bloku **62–64** není porovnání bajt po bajtu — invertor mezi zápisem a čtením posune sekundy. EMS považuje zápis za úspěšný, pokud se dekódované časy (z `value_to_write` trojice vs. přečtené hodnoty) liší nejvýše o **120 s** (`control_exporter._verify_deye_clock_command_run`).
|
||||
**Verifikace (journal):** u souvislého bloku **62–64** není porovnání bajt po bajtu — invertor mezi zápisem a čtením posune sekundy. EMS považuje zápis za úspěšný, pokud se dekódované časy (z `value_to_write` trojice vs. přečtené hodnoty) liší nejvýše o **120 s** (`control_exporter._verify_deye_clock_command_run`). Po **třech neúspěšných ověřeních** bloku 62–64 EMS **nepřepíná** provozní režim na SELF_SUSTAIN (na rozdíl od ostatních registrů); pošle **kritický Discord** (`notify_modbus_clock_verify_exhausted`) a příkazy zůstanou ve stavu vhodném pro diagnostiku — viz `modbus-command-journal.md`.
|
||||
|
||||
**Před vytvořením journalu:** pokud je navrhovaná hodnota **shodná s posledním `verified`** záznamem daného registru v `modbus_command`, EMS **řádek nevytvoří** a na Modbus neposílá (žádný „X → X“ zápis jen kvůli periodickému exportu). Výjimky řeší stávající logika (řidší 62–64 výše, denní TOU 3–6 + meta sloupce na `asset_inverter`).
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ Tyto politiky jsou parametrizace AUTO/SELF_SUSTAIN, ne samostatné fyzické stav
|
||||
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/sites/{site_id}/mode
|
||||
POST /api/v1/sites/{site_id}/mode
|
||||
{
|
||||
"mode": "SELF_SUSTAIN",
|
||||
"valid_until": null,
|
||||
@@ -46,9 +46,9 @@ POST /api/sites/{site_id}/mode
|
||||
}
|
||||
```
|
||||
|
||||
Backend: `ems.fn_set_mode` + HTTP na Loxone `/dev/sps/io/EMS_Mode/{loxone_mode_value}`. Dočasné přepisy s `valid_until` ruší `fn_expire_modes()`.
|
||||
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`.
|
||||
**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)
|
||||
|
||||
@@ -62,4 +62,4 @@ Backend: `ems.fn_set_mode` + HTTP na Loxone `/dev/sps/io/EMS_Mode/{loxone_mode_v
|
||||
|
||||
### Otevřené body
|
||||
|
||||
- [ ] Doplnit alerty při `ems_heartbeat_status = 'stale'`
|
||||
- [ ] 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`)
|
||||
|
||||
Reference in New Issue
Block a user