Add export plan guard to block Deye export against plan.
Force PASSIVE/no-export when sell is negative or export_mode is NONE, and alert NEG_SELL_EXPORT in plan_actual_slot_guard when export still occurs. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -58,6 +58,21 @@ Ověření: logy backendu kolem pokusu **nebo** `select id,status,created_at fro
|
||||
|
||||
---
|
||||
|
||||
## Exekuční pojistky exportu (AUTO)
|
||||
|
||||
Po `_build_setpoints`, před zápisem Modbus (`orchestrator.export_setpoints`):
|
||||
|
||||
| Guard | Podmínka | Efekt |
|
||||
|-------|----------|--------|
|
||||
| **`_apply_export_plan_guard`** | `effective_sell_price < 0` **nebo** (`export_mode = NONE` a `grid_setpoint_w ≥ 0`) | PASSIVE, `export_ban`, `grid_export_limit = 0`, vybíjení baterie do sítě vynulováno (`battery_w = max(0, …)`), `deye_physical_mode = PASSIVE` |
|
||||
| **`_apply_price_failsafe_guard`** | `is_predicted_price = true` | PASSIVE, všechny výkonové setpointy 0, žádný export |
|
||||
|
||||
Implementace: `backend/services/control/setpoints.py`. Ověření: `pytest backend/tests/test_control_export_plan_guard.py`.
|
||||
|
||||
**Poznámka:** PV B (nekontrolovatelné pole) může při záporné vykupní stále fyzicky exportovat — pojistka řídí Deye (baterie + řízené FVE A), ne mikroinvertory na GEN bez cut-off.
|
||||
|
||||
---
|
||||
|
||||
## Logika exportu
|
||||
|
||||
```python
|
||||
|
||||
@@ -60,7 +60,7 @@ pro **reg 178** (spolu s peak shaving bity 4–5).
|
||||
| Job | Frekvence | Popis |
|
||||
|-----|-----------|--------|
|
||||
| `verify_modbus` | každé **2 min** | Pro každou aktivní site vybere `written` příkazy s `written_at` v posledních **20 min** a zavolá `verify_modbus_commands`. |
|
||||
| `plan_actual_slot_guard` | **:05, :20, :35, :50** (po `audit_filler`) | `ems.fn_plan_actual_slot_guard_all_active` (+ `plan_actual_slot_guard.py` jen Discord): poslední 2 uzavřené 15min sloty — fatální odchylka **plán vs. audit síť** → **Discord** (`critical`), dedup přes `ems.plan_fatal_deviation_sent`. |
|
||||
| `plan_actual_slot_guard` | **:05, :20, :35, :50** (po `audit_filler`) | `ems.fn_plan_actual_slot_guard_all_active` (+ `plan_actual_slot_guard.py` jen Discord): poslední 2 uzavřené 15min sloty — fatální odchylka **plán vs. audit síť** → **Discord** (`critical`), dedup přes `ems.plan_fatal_deviation_sent`. Kódy: `GRID_SIGN_MISMATCH`, `GRID_EXPORT_SPIKE`, **`NEG_SELL_EXPORT`** (`sell < 0` a skutečný vývoz < −4 kW), `GRID_LARGE_DEVIATION`, … Exekuční pojistka proti opakovanému vývozu: [`control.md`](control.md) — `_apply_export_plan_guard`. |
|
||||
|
||||
Plná tabulka jobů je v [`lifespan.py`](../../backend/app/lifespan.py).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user