fix lock charge on 100% SOC
This commit is contained in:
@@ -346,7 +346,9 @@ begin
|
|||||||
if v_charge_buf <= 0 then
|
if v_charge_buf <= 0 then
|
||||||
update _ems_plan_slot_wk wk set allow_charge = true;
|
update _ems_plan_slot_wk wk set allow_charge = true;
|
||||||
elsif v_energy_to_fill <= 0 then
|
elsif v_energy_to_fill <= 0 then
|
||||||
update _ems_plan_slot_wk wk set allow_charge = false;
|
-- Pokud rolling replan startuje s baterií plnou, nechceme zablokovat budoucí nabíjení po vybití.
|
||||||
|
-- Povolit alespoň nabíjení v PV surplus slotech, aby solver mohl vytvořit headroom a pak ho znovu zaplnit z FVE.
|
||||||
|
update _ems_plan_slot_wk wk set allow_charge = (wk.pv_surplus_w > 0);
|
||||||
else
|
else
|
||||||
update _ems_plan_slot_wk wk set allow_charge = (wk.pv_surplus_w > 0);
|
update _ems_plan_slot_wk wk set allow_charge = (wk.pv_surplus_w > 0);
|
||||||
v_cum := 0;
|
v_cum := 0;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
- **SQL-first:** horizont a sloty z DB funkcí (`fn_planning_horizon_end`, `fn_load_planning_slots_full`, …); viz **`CLAUDE.md`** → sekce *SQL-first a read-model*.
|
- **SQL-first:** horizont a sloty z DB funkcí (`fn_planning_horizon_end`, `fn_load_planning_slots_full`, …); viz **`CLAUDE.md`** → sekce *SQL-first a read-model*.
|
||||||
- **Dynamický horizont (jen OTE):** konec plánu z **`ems.fn_planning_horizon_end(site_id, horizon_start)`** (výchozí strop **36 h**, minimum pro rolling **1 h** – obojí jako defaultní argumenty v SQL, úprava přes repeatable migraci). Pomocná `ems.fn_last_effective_ote` vrací konec posledního OTE intervalu. Rolling replan při `NULL` přeskočí; denní plán použije krátký (1 h) fallback v Pythonu. Sloty v solveru jsou bez predikovaných cen v rámci tohoto horizontu.
|
- **Dynamický horizont (jen OTE):** konec plánu z **`ems.fn_planning_horizon_end(site_id, horizon_start)`** (výchozí strop **36 h**, minimum pro rolling **1 h** – obojí jako defaultní argumenty v SQL, úprava přes repeatable migraci). Pomocná `ems.fn_last_effective_ote` vrací konec posledního OTE intervalu. Rolling replan při `NULL` přeskočí; denní plán použije krátký (1 h) fallback v Pythonu. Sloty v solveru jsou bez predikovaných cen v rámci tohoto horizontu.
|
||||||
- **Terminal SoC shadow price:** v objective je člen `−(avg_buy_prvních_24h × planner_terminal_soc_value_factor / 1000) × soc[T−1]` (Kč), kde faktor je **`ems.asset_battery.planner_terminal_soc_value_factor`** přes **`ems.fn_planning_site_context`** (default v DB **0.9**); viz sekci *Tuning pro malé baterie* níže. Účel: konec horizontu nemusí končit zbytečně vyprázdněnou baterií (receding horizon).
|
- **Terminal SoC shadow price:** v objective je člen `−(avg_buy_prvních_24h × planner_terminal_soc_value_factor / 1000) × soc[T−1]` (Kč), kde faktor je **`ems.asset_battery.planner_terminal_soc_value_factor`** přes **`ems.fn_planning_site_context`** (default v DB **0.9**); viz sekci *Tuning pro malé baterie* níže. Účel: konec horizontu nemusí končit zbytečně vyprázdněnou baterií (receding horizon).
|
||||||
|
- **Masky `allow_charge` / `allow_discharge_export` (anti-mikrocyklování):** generuje `ems.fn_load_planning_slots_full`. Důležité: pokud rolling replan startuje s baterií na 100 %, `allow_charge` se nesmí stát globálně `false` pro celý horizont – jinak solver nemá motivaci baterii před PV špičkou „uvolnit“ (headroom), protože ji pak nesmí z PV znovu nabít. Aktuálně se v tomto případě `allow_charge` ponechá povolené alespoň pro sloty s `pv_surplus_w > 0`.
|
||||||
- **Runtime guard v exportu setpointů (legacy):**
|
- **Runtime guard v exportu setpointů (legacy):**
|
||||||
- při `AUTO` + `is_predicted_price=true` se na exportní vrstvě vynutí PASSIVE/no-export chování (u nových plánů by `is_predicted_price` v horizontu nemělo nastat).
|
- při `AUTO` + `is_predicted_price=true` se na exportní vrstvě vynutí PASSIVE/no-export chování (u nových plánů by `is_predicted_price` v horizontu nemělo nastat).
|
||||||
- **Ekonomika baterie:**
|
- **Ekonomika baterie:**
|
||||||
@@ -33,6 +34,19 @@ Solver optimalizuje celý horizont (typicky do konce známých OTE dat, strop z
|
|||||||
- pohled dopředu (ráno ví že přes poledne bude záporná cena → prodává z baterie)
|
- pohled dopředu (ráno ví že přes poledne bude záporná cena → prodává z baterie)
|
||||||
- kompromisy mezi prodejem, nabíjením, TČ a EV v globálním optimu
|
- kompromisy mezi prodejem, nabíjením, TČ a EV v globálním optimu
|
||||||
|
|
||||||
|
### Verifikace (DB)
|
||||||
|
|
||||||
|
Pro kontrolu masek nabíjení:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
select *
|
||||||
|
from ems.fn_load_planning_slots_full(<site_id>, <from_utc>, <to_utc>, <current_soc_wh>)
|
||||||
|
where allow_charge is true
|
||||||
|
order by interval_start;
|
||||||
|
```
|
||||||
|
|
||||||
|
- Pokud `current_soc_wh` odpovídá plné baterii (`soc_max_wh`), měly by být `allow_charge=true` alespoň sloty s PV přebytkem (`pv_surplus_w > 0`).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Klíčové předpoklady a specifika home-01
|
## Klíčové předpoklady a specifika home-01
|
||||||
|
|||||||
Reference in New Issue
Block a user