fix cutoff a grid peak shaving register
This commit is contained in:
@@ -111,18 +111,19 @@ def apply_overrides(plan, overrides) -> Setpoints:
|
||||
|
||||
**Princip:** držet mapování plán → Deye **jednoduché**; detail a zdůvodnění v [`operating-modes.md`](operating-modes.md) (sekce *Keep it simple*).
|
||||
|
||||
### BA81: GEN port cut-off (mikroinvertory na GEN) přes reg 179
|
||||
### BA81: GEN port cut-off (mikroinvertory na GEN) přes reg 178 (0-based)
|
||||
|
||||
U instalací typu **BA81** (AC coupling / mikroinvertory na GEN portu) může solver uložit do plánu flag
|
||||
`planning_interval.deye_gen_cutoff_enabled` (true/false). Pokud je na střídači zapnutý feature flag
|
||||
`asset_inverter.deye_gen_microinverter_cutoff_enabled = true`, exporter provede **masked read-modify-write**
|
||||
registru **179**:
|
||||
`asset_inverter.deye_gen_microinverter_cutoff_enabled = true`, exporter provede **read-modify-write**
|
||||
registru **178** (v některých manuálech/UI uváděno jako “register 179” – 1-based):
|
||||
|
||||
- `deye_gen_cutoff_enabled = true` → reg **179** bits **0–1** = **3** (`11b`, enable = cut-off **ON** / export blokován)
|
||||
- `deye_gen_cutoff_enabled = false` → reg **179** bits **0–1** = **2** (`10b`, disable = cut-off **OFF** / export povolen)
|
||||
- `deye_gen_cutoff_enabled = true` → reg **178** bits **0–1** = **3** (`11b`, enable = cut-off **ON** / export blokován)
|
||||
- `deye_gen_cutoff_enabled = false` → reg **178** bits **0–1** = **2** (`10b`, disable = cut-off **OFF** / export povolen)
|
||||
|
||||
Zápisy se ukládají do `ems.modbus_command` a ověřují v `verify_modbus_commands` (porovnává se pouze maska
|
||||
bits 0–1). Detail registrů: [`modbus-registers.md`](modbus-registers.md) (reg 179).
|
||||
bits 0–1). Detail registrů: [`modbus-registers.md`](modbus-registers.md) (reg 178).
|
||||
|
||||
### Fyzický režim (`get_deye_mode` v `exporter_monolith.py`)
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ def calculate_pv_power(
|
||||
- Endpoint `GET /api/v1/sites/{site_id}/forecast/pv?date=YYYY-MM-DD` vrací vždy poslední `ok` run per `(interval_start, pv_array_id)` (`DISTINCT ON`), takže UI nevidí duplikáty z historických běhů.
|
||||
- **Kalibrace delty:** `GET /api/v1/sites/{site_id}/forecast/pv-delta-profile?from=…&to=…` vrací JSON z `ems.fn_pv_forecast_delta_profile` (`deltas`, `deltas_by_array`, `delta_learn_min_ts` z `ems.site_pv_forecast_calibration`). Volitelné query parametry: `half_life_days`, `threshold_w`, `top_n_days`, `non_top_day_factor`, `day_weight_gamma` (NULL u numerických přepsání = hodnota z kalibrační tabulky / default funkce).
|
||||
- **Úprava kalibrace z API:** `PATCH /api/v1/sites/{site_id}/configuration/pv-forecast-calibration` s JSON tělem (částečný update); odpověď je aktuální řádek kalibrace. Souhrn konfigurace v `GET …/configuration` obsahuje klíč `pv_forecast_calibration`.
|
||||
- **Telemetrie pro učení delty:** `telemetry_collector` při Modbus poll přidá čtení reg. **145** a **179**; `fn_telemetry_inverter_sample` ukládá `is_export_limited` / `pv_derating_flags` (bity 1 = solar sell off, 2 = GEN/MI cut-off aktivní dle masky `(reg179 & 3) == 2`). `fn_fill_forecast_accuracy` sloty s těmito signály označí `telemetry_derating`.
|
||||
- **Telemetrie pro učení delty:** `telemetry_collector` při Modbus poll čte reg. **145** a **178**; `fn_telemetry_inverter_sample` ukládá `is_export_limited` / `pv_derating_flags` (bity 1 = solar sell off, 2 = GEN/MI cut-off aktivní dle masky `(reg178 & 3) == 3`). `fn_fill_forecast_accuracy` sloty s těmito signály označí `telemetry_derating`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -25,8 +25,9 @@ Indexy: podle `(site_id, status, created_at)` a částečný index pro `pending`
|
||||
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. **Reg 178** (grid peak shaving switch): journal ukládá **celé 16bit** `value_to_write` (32 nebo 48). Při ověření se za **shodu** považuje shoda **bitů 4–5** maskou **`0x0030`** s očekáváním; `value_verified` = přečtená surová hodnota. Při nesouladu masky se **jednou** znovu přečte reg. 178 (druhé FC3) kvůli glitchům na RS485 — pokud druhé čtení maskou sedí, stav je **`verified`**.
|
||||
4. **Reg 179** (control board special 1, BA81 GEN cut-off): exporter zapisuje hodnotu 2/3 (clean write).
|
||||
Při ověření se za shodu považuje jen maska **bits 0–1** (`0x0003`) vůči očekávání (**3 = cutoff ON**, **2 = cutoff OFF**).
|
||||
4. **Reg 178** (control board special 1, BA81 GEN cut-off): exporter nastavuje bits **0–1** (2/3) pomocí
|
||||
**read-modify-write**, protože reg 178 je bitové pole i pro další volby (např. peak shaving bits 4–5).
|
||||
Při ověření se za shodu považuje maska **bits 0–1 a 4–5** (`0x0033`) vůči očekávání.
|
||||
4. **TOU výkon W (154–159):** firmware často vrátí **max. výkon z reg. 108/109 × 51.2 V** místo přesně zapsaného W; verify to akceptuje jako **shodu** (skutečný výkon je stejně omezen proudy 108/109).
|
||||
5. **Pojistka 62–64**: pokud by se řádek registru **62, 63 nebo 64** omylem dostal do striktní větve po jednom registru, verify to zachytí a zpracuje **jako toleranční celek 62–64** (stejně jako primární clock větev) — bez přepnutí do SELF_SUSTAIN jen kvůli tomu.
|
||||
6. Po třech neúspěšných cyklech ověření:
|
||||
@@ -48,8 +49,9 @@ Implementace: `services/control_exporter.py` — `verify_modbus_commands`, `_ver
|
||||
|
||||
`write_inverter_setpoints` přidá do journalu podle potřeby **62–64** (čas — po čtení z invertoru jen při driftu / 24h intervalu; viz `modbus-registers.md`) a **time pointy 148–177** (bloky 3–6 typicky jednou denně; viz `modbus-registers.md`), dále **108**, **109**, **141**, **142**, **178**, **143**. Každý řádek daného exportního běhu má **`deye_physical_mode`** (**PASSIVE** / **SELL** / **CHARGE**). **Reg 191** EMS nezapisuje (SolarmanApp). Převod výkonu: `battery_watts_to_amps` v `modbus-registers.md`.
|
||||
|
||||
Pokud je zapnutý feature `asset_inverter.deye_gen_microinverter_cutoff_enabled = true`, exporter navíc zapisuje
|
||||
**reg 179** (masked RMW) podle `planning_interval.deye_gen_cutoff_enabled` (BA81 GEN port cut-off).
|
||||
Pokud je zapnutý feature `asset_inverter.deye_gen_microinverter_cutoff_enabled = true`, exporter nastavuje
|
||||
**MI export cutoff** přes **reg 178 bits0–1** (BA81 GEN port cut-off) — stále jako jeden záznam `modbus_command`
|
||||
pro **reg 178** (spolu s peak shaving bity 4–5).
|
||||
|
||||
**Dávky:** `execute_modbus_commands` slučuje souvislé adresy do jednoho **`write_registers`** (FC **0x10**). `verify_modbus_commands` čte zpět po souvislých blocích (`read_holding_registers`, FC 0x03). Detail režimů: `modbus-registers.md`.
|
||||
|
||||
@@ -72,7 +74,7 @@ Vrátí počty `checked` / `verified` / `mismatch` a seznam dotčených příkaz
|
||||
|
||||
Tabulka pro budoucí logování **cut-off** přepínačů (mikroinvertory / GEN při záporné prodejní ceně). Záznam při **změně** stavu: `asset_code`, `new_state`, `previous_state`, `reason`, `sell_price_czk`, `triggered_by`. Zatím jen schéma; logika napojení v `control_exporter` je v TODO.
|
||||
|
||||
Poznámka: **GEN port cut-off na BA81** se aktuálně provádí přímo přes Deye **reg 179** a loguje se v `ems.modbus_command`.
|
||||
Poznámka: **GEN port cut-off na BA81** se aktuálně provádí přímo přes Deye **reg 178 (bits0–1)** a loguje se v `ems.modbus_command`.
|
||||
`cutoff_switch_log` je oddělená tabulka pro budoucí obecnější “cut-off” akce (nezávisle na konkrétním Modbus registru).
|
||||
|
||||
## Konfigurace
|
||||
|
||||
@@ -20,8 +20,7 @@ EMS zapisuje řídící hodnoty přes journal (`modbus_command`) a **`write_regi
|
||||
| 142 | Limit control (System work mode) | 0/1/2 | — | **0** = selling first, **1** = zero export to load, **2** = zero export to CT. Hodnota v non-SELL režimech pochází z `asset_inverter.deye_zero_export_mode` (závisí na instalaci – viz tabulka níže). V režimu SELL vždy **0**. |
|
||||
| 145 | Solar sell | 0/1 | — | **0** = disabled (přebytek FVE na **straně měniče** se nesmí vést do sítě — curtailment vůči síti), **1** = enabled. Platí jen pro **FVE pod kontrolou Deye** (`controllable = true`); druhá pole (např. **pv-b** u home-01) EMS tímto registerem neřídí. EMS dnes **vždy zapisuje 1**; při 108 = 0 a 145 = 1 přebytky z řiditelného stringu typicky tečou do sítě (viz pass-through níže). |
|
||||
| 143 | Export limit W | závisí na typu (SUN-20K až ~13 500) | 1 W | Max export do sítě; hodnota z `site_grid_connection.max_export_power_w` |
|
||||
| 178 | Grid peak shaving switch | bitmask | — | EMS zapisuje **pevnou** hodnotu (bez read-modify-write kvůli kolizím s paralelním čtením z Loxone): **32** (`0b00100000`, bit4–5 = **10**) v režimu **SELL**; **48** (`0b00110000`, bit4–5 = **11**) v **PASSIVE** a **CHARGE**. |
|
||||
| 179 | Control board special 1 | bitmask | — | **BA81:** bits **0–1** ovládají „MI export to Grid cutoff“ (AC coupling / GEN): **2** (`10b`) = disable (cutoff ON), **3** (`11b`) = enable. EMS zapisuje **masked RMW** (zachová ostatní bity) jen pokud `asset_inverter.deye_gen_microinverter_cutoff_enabled = true`. |
|
||||
| 178 | Control board special 1 | bitmask | — | Bitové pole pro více funkcí. **EMS používá:** (a) bits **4–5** pro peak shaving switch: **32** (`0b00100000`, bit4–5 = **10**) v režimu **SELL**; **48** (`0b00110000`, bit4–5 = **11**) v **PASSIVE/CHARGE**. (b) **BA81:** bits **0–1** pro „MI export to Grid cutoff“ (AC coupling / GEN): **2** = disable (cutoff OFF), **3** = enable (cutoff ON). EMS zapisuje jako **read-modify-write** (zachová ostatní bity). V některých manuálech/UI je to označené jako „register 179“ (1-based). |
|
||||
| 190 | GEN peak shaving | 0–16000 | 1 W | Peak shaving na GEN portu |
|
||||
| 191 | Grid peak shaving power | 0–16000 | 1 W | **EMS NEZAPISUJE** – nastavit **manuálně v SolarmanApp**. Hodnota určuje výkon peak shavingu v **W**. |
|
||||
|
||||
@@ -37,9 +36,9 @@ EMS zapisuje řídící hodnoty přes journal (`modbus_command`) a **`write_regi
|
||||
- **SELL:** **32** – bit4–5 = **10**, grid peak shaving **disable** (export do sítě).
|
||||
- **PASSIVE** a **CHARGE:** **48** – bit4–5 = **11**, grid peak shaving **enable**.
|
||||
|
||||
EMS **nezapisuje** read-modify-write (paralelní čtení jinými klienty může způsobit nesoulad).
|
||||
EMS zapisuje **read-modify-write** a zachovává ostatní bity (reg 178 obsahuje více funkcí).
|
||||
|
||||
**Ověření v journalu (`modbus_command`):** u zápisu **178** se při verify porovnávají jen **bity 4–5** maskou **`0x0030`** s očekávanou hodnotou (32/48); `value_verified` zůstává plný readback. Při nesouladu masky následuje **druhé FC3 čtení** reg. 178 (mitigace RS485 glitchů). U **TOU výkonu W (154–159)** verify akceptuje i readback **`max_charge_a × 51.2`** nebo **`max_discharge_a × 51.2`**, pokud firmware hodnotu přepíše na interní maximum (skutečný výkon je stejně omezen reg. 108/109). Detail: `modbus-command-journal.md`.
|
||||
**Ověření v journalu (`modbus_command`):** u zápisu **178** se při verify porovnává maska **bits 0–1 a 4–5** (`0x0033`) s očekávanou hodnotou; `value_verified` zůstává plný readback. Při nesouladu masky následuje **druhé FC3 čtení** reg. 178 (mitigace RS485 glitchů). U **TOU výkonu W (154–159)** verify akceptuje i readback **`max_charge_a × 51.2`** nebo **`max_discharge_a × 51.2`**, pokud firmware hodnotu přepíše na interní maximum (skutečný výkon je stejně omezen reg. 108/109). Detail: `modbus-command-journal.md`.
|
||||
|
||||
**Idempotence (proti spamu zápisů):** pokud poslední `verified` hodnota už má správně nastavené bity 4–5 (maska `0x0030`), EMS zápis reg. 178 v dalším běhu přeskočí (i když `value_verified` obsahuje jiné bity).
|
||||
|
||||
@@ -61,20 +60,15 @@ Režim **CHARGE_CHEAP** nastaví oba setpointy na stejný kladný výkon (min. 1
|
||||
|
||||
**PASSIVE (ZERO):** reg. **108/109** podle `_deye_zero_export_amps_for_passive` — při exportu v plánu bez vybíjení je **108 = 0** (přetok FVE); při importu bez nabíjení je **109 = 0** (držet baterii). Jinak oba max (AUTO). Detail: `operating-modes.md`.
|
||||
|
||||
### BA81: GEN port cut-off (reg 179) z plánu
|
||||
### BA81: GEN port cut-off (reg 178 bits0–1) z plánu
|
||||
|
||||
Pro instalace s AC coupling na GEN portu (mikroinvertory) může solver uložit do `planning_interval` flag **`deye_gen_cutoff_enabled`**.\n
|
||||
- `true` → exporter nastaví reg **179** bits0–1 na **3** (`11b`, enable = cut-off ON / export blokován)
|
||||
- `true` → exporter nastaví reg **178** bits0–1 na **3** (`11b`, enable = cut-off ON / export blokován)
|
||||
- `false` → exporter nastaví bits0–1 na **2** (`10b`, disable = cut-off OFF / export povolen)
|
||||
|
||||
Zápis do reg. 179 se v praxi provádí jako **„clean write“** hodnoty **2** nebo **3** (bez read-modify-write),
|
||||
protože některé firmware/UI varianty nevyhodnocují jen bity 0–1 maskou, ale očekávají přímo hodnotu 2/3.
|
||||
Ověření v journalu (`verify_modbus_commands`) přesto porovnává jen bits0–1 maskou `0x0003` (odolnost vůči
|
||||
paralelním změnám jiných bitů / verzím FW).
|
||||
Zápis se provádí jako **read-modify-write** nad **reg 178** (zachová ostatní bity registru).
|
||||
|
||||
**Idempotence:** EMS zápis reg. 179 přeskočí jen tehdy, když poslední `verified` hodnota je už **clean 2/3**.
|
||||
Masková shoda s hodnotami typu `0xfffe` / `0xffff` se záměrně **nepovažuje** za “už zapsáno”, aby se zařízení
|
||||
dostalo do stabilního stavu, který odpovídá UI i chování firmware.
|
||||
**Idempotence:** pokud poslední `verified` hodnota už má správně nastavené relevantní bity (maska `0x0033`), EMS zápis reg. 178 v dalším běhu přeskočí.
|
||||
**Pozn.:** Flag se v solveru vůbec nevytváří ani neukládá tam, kde není povolen feature `asset_inverter.deye_gen_microinverter_cutoff_enabled` – takové lokality ho nemají ani v UI.
|
||||
|
||||
### Provozní režim EMS SELF_SUSTAIN
|
||||
|
||||
@@ -67,7 +67,7 @@ Nabíjení ze sítě s vysokým cílovým SoC v TOU řeší větev **CHARGE** (g
|
||||
|
||||
**Implementace (BLOCK_EXPORT):** při `effective_sell_price < 0` (slot z plánu) EMS drží fyzicky stále **PASSIVE**, ale zapne **zákaz exportu přebytků** pro řiditelnou FVE:
|
||||
- **reg 145 = 0** (solar sell disabled) mimo SELL
|
||||
- **BA81:** navíc přes **reg 179** (bits0–1) aktivuje „MI export to Grid cutoff“ pro mikroinvertory na GEN portu (jen pokud je `asset_inverter.deye_gen_microinverter_cutoff_enabled = true`).
|
||||
- **BA81:** navíc přes **reg 178** (bits0–1; v některých UI jako “register 179”) aktivuje „MI export to Grid cutoff“ pro mikroinvertory na GEN portu (jen pokud je `asset_inverter.deye_gen_microinverter_cutoff_enabled = true`).
|
||||
Týká se jen výroby, kterou Deye umí ovlivnit; **pv-b / ongrid GEN** u home-01 tímto neomezíš.
|
||||
|
||||
#### PV1/PV2 vs. GEN port (důležité pro BLOCK_EXPORT)
|
||||
|
||||
@@ -251,7 +251,7 @@ Při `sell_price < 0` tedy nastává problém:
|
||||
- pokud výroba na GEN portu převýší okamžitou spotřebu + možný charge do baterie, zbytek fyzicky teče do sítě (nechtěný export za zápornou cenu).
|
||||
|
||||
Řešení na hardware úrovni:
|
||||
- **Deye reg 179 bits0–1** („MI export to Grid cutoff“) umožní GEN port **tvrdě odpojit**.
|
||||
- **Deye reg 178 bits0–1** („MI export to Grid cutoff“, často uváděno jako “register 179” v 1-based značení) umožní GEN port **tvrdě odpojit**.
|
||||
|
||||
#### Správné rozhodovací pravidlo (záměr)
|
||||
|
||||
@@ -278,7 +278,7 @@ kde:
|
||||
- (případně) explicitní `no_export` politika, pokud je v kontextu dostupná
|
||||
Mimo tyto případy je `z_gen_cutoff[t]` vynucené na `0`.
|
||||
- Cut-off je v účelové funkci **penalizované** (za „zahozenou“ GEN výrobu), aby se zapínalo jen jako poslední možnost.
|
||||
- Výstup se ukládá do `planning_interval.deye_gen_cutoff_enabled` (nullable) a exporter pak jen provede reg 179.
|
||||
- Výstup se ukládá do `planning_interval.deye_gen_cutoff_enabled` (nullable) a exporter pak nastaví bity reg 178.
|
||||
|
||||
**Scope / bezpečnost:** proměnná i flag existují jen na lokalitách, kde je zapnutý `asset_inverter.deye_gen_microinverter_cutoff_enabled` (tj. kde je GEN port s mikroinvertory reálně zapojen). Jinde se nic neřeší ani nezobrazuje.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user