Files
ems/docs/04-modules/consumption.md
2026-04-03 16:03:06 +02:00

165 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Modul: Consumption (Spotřeba)
## Členění spotřeby
Systém rozlišuje dva typy spotřeby:
### 1. Bazální (neflexibilní) spotřeba
- Spotřeba kterou nelze odložit ani řídit
- Příklady: osvětlení, elektronika, vaření, cirkulační čerpadla
- **Zdroj:** měřená telemetrie ze střídače (`load_power_w` - suma flexibilní spotřeby)
- **Použití v plánování:** jako pevný vstup (musí být pokryta)
### 2. Flexibilní spotřeba
- Spotřeba kterou lze časově přesunout nebo regulovat
- Příklady: nabíjení EV, ohřev TUV, tepelné čerpadlo (při přetopení zásobníku)
- **Zdroj:** telemetrie z konkrétních zařízení (EV nabíječky, stavové vstupy Loxone)
- **Použití v plánování:** jako optimalizovatelná proměnná
---
## Jak se měří celková spotřeba
Střídač Deye poskytuje přes Modbus registr `load_power_w` = celková okamžitá spotřeba objektu (vše za hlavním jističem na AC straně střídače).
```
load_power_w (Deye) = bazální_spotřeba + EV_nabíjení + TUV + ostatní flexibilní
```
### Výpočet bazální spotřeby
Bazální výkon je to, co zůstane po odečtení řízených zátěží od celkové spotřeby ze střídače:
```
bazální_w = load_power_w - ev_power_w - heat_pump_power_w
```
- **`load_power_w`** telemetrie střídače (`telemetry_inverter`), 1min.
- **`ev_power_w`** v agregaci statistik se bere průměr výkonu ze všech nabíječek site v časovém okně ±30 s kolem měření střídače (`telemetry_ev_charger`).
- **`heat_pump_power_w`** stejně z `telemetry_heat_pump` (TČ včetně kompresoru; slouží jako proxy za měřitelný příkon TČ).
**Ukládání profilu:** tabulka `consumption_baseline_stats` (unikátní `(site_id, day_of_week, hour_of_day)`). Plní ji **`ems.fn_update_baseline_stats(site_id, lookback_days)`** z minutové telemetrie za posledních *N* dní; agregace po DOW a hodině (Europe/Prague). Do řádku se zapisuje jen bucket s alespoň 4 vzorky (minuty). **EMA 70/30** při `ON CONFLICT`: nový batch má váhu 30 %, existující průměr 70 % (postupné zpřesňování). Denní job v backendu: **00:30** (`fn_update_baseline_stats(..., 30)`).
**Predikce do horizontu:** **`ems.fn_get_baseline_forecast(site_id, from, to)`** generuje 15min sloty (`generate_series`), pro každý slot najde řádek podle DOW+hodiny v Praze. **`forecast_w`** = uložený průměr; **`confidence_w`** = konzervativní odhad `avg + 0.5 * COALESCE(stddev, 100)`. Pokud pro slot neexistuje statistika, fallback **`forecast_w = 500` W** (málo nebo žádná historie; prakticky odpovídá situaci před ~4 týdny kvalitních dat v jednotlivých hodinách). Směrodatná odchylka je v DB k dispozici pro budoucí použití v solveru (fáze 2).
**Solver (`planning_engine._load_slots`):** pro každý 15min interval efektivní ceny bere **`avg_power_w` z `consumption_baseline_stats`** podle DOW+hodiny slotu, jinak **500 W** nečte `consumption_baseline_interval`. Stejná hodnota se ukládá do **`planning_interval.load_baseline_w`** při každém běhu plánovače (přehled v UI / PostgREST). Odchylka vs. skutečnost: tabulka **`baseline_load_forecast_accuracy`**, plněno po auditu.
> **Poznámka:** TUV jako samostatný odečet zůstává otevřený bod, pokud není měřen zvlášť; aktuálně je TČ zahrnut v `heat_pump_power_w`.
---
## Ukládání spotřeby
### Real-time telemetrie
Celková spotřeba je součástí `telemetry_inverter.load_power_w` (1min záznamy).
EV nabíječky mají vlastní tabulku `telemetry_ev_charger` s přesným výkonem.
### Agregovaná spotřeba pro plánování
- **`consumption_baseline_stats`** primární vstup solveru: hodinový profil (DOW + hodina) z telemetrie, EMA, viz výše.
- **`consumption_baseline_interval`** volitelné 15min řady (`actual` / `forecast`) pro jiné účely; solver z ní bazál nečte.
---
## Predikce bazální spotřeby
### Metoda: DOW + hodina + EMA
Operativní predikce je v **`fn_get_baseline_forecast`** a v přímém dotazu v `_load_slots` na **`consumption_baseline_stats`**. Doplňkově lze z historie stavět 15min profily v `consumption_baseline_interval`, pokud je k tomu samostatný job není nutné pro běh LP.
---
## Flexibilní zařízení detailní popis
### EV nabíječky (Teltonika TeltoCharge 22kW)
**Komunikace:** Teltonika poskytuje REST API a/nebo OCPP protokol.
| Parametr | Hodnota |
|---|---|
| Max výkon | 22 000 W (třífázové) |
| Min výkon (1 fáze) | 1 380 W |
| Počet na home-01 | 2 |
| Protokol | OCPP 1.6 nebo Teltonika REST API |
**Co systém řídí:**
- Povolení/zakázání nabíjení (smart charging on/off)
- Omezení výkonu (charge current limit v Amperech)
- Časový plán nabíjení (nastavit okno kdy smí nabíjet)
**Telemetrie (stahuje se každou minutu):**
- stav konektoru (available / charging / faulted)
- aktuální výkon [W]
- kumulativní energie [kWh]
- proud [A], napětí [V]
- session ID
**Plánování:**
- EV se nabíjí v době levné energie nebo přebytku FVE
- Respektuje požadavek uživatele: "nabitý na X % do Y hodin"
- Pokud není požadavek nastaven → nabíjí při přebytku nebo nejlevnějším spotu
> **Otevřený bod:** Teltonika API vs OCPP rozhodnout při první integraci. Doporučujeme OCPP pro standardizaci.
---
### TUV / Tepelné čerpadlo
**Komunikace:** přes Loxone (HTTP Virtual Input zapnout/vypnout)
**Co systém řídí:**
- Povolení ohřevu (Loxone přepne výstupní relé)
- Systém pošle setpoint do Loxone, Loxone provede
**Telemetrie:**
- Stav ON/OFF (čteme z Loxone HTTP výstupu nebo Virtual Output stavu)
- Teplota zásobníku (pokud je čidlo v Loxone doporučeno)
- Aktuální výkon: není přímo měřen, používáme `max_power_w` z `asset_flexible_device`
**Plánování:**
- TUV se ohřívá v době přebytku FVE nebo levného spotu
- Minimální a maximální teplota zásobníku je respektována (pokud máme čidlo)
- Nouzová priorita: pokud teplota pod minimum → ohřát bez ohledu na cenu
---
## Výpočet bazální spotřeby v auditu
```sql
-- Agregovaná skutečná bazální spotřeba za 15min interval
CREATE VIEW consumption_vw_actual_baseline AS
SELECT
t.site_id,
time_bucket('15 minutes', t.measured_at) AS interval_start,
AVG(
t.load_power_w
- COALESCE(ev1.power_w, 0)
- COALESCE(ev2.power_w, 0)
-- TUV: odečíst max_power pokud byl v daném intervalu aktivní
) AS baseline_power_w
FROM telemetry_inverter t
-- JOIN na EV telemetrii
GROUP BY t.site_id, time_bucket('15 minutes', t.measured_at);
```
---
## Konfigurace (env proměnné)
```env
CONSUMPTION_FORECAST_LOOKBACK_WEEKS=4
TELTONIKA_API_URL_1=http://192.168.x.x/api # charger 1
TELTONIKA_API_URL_2=http://192.168.x.x/api # charger 2
TELTONIKA_POLL_INTERVAL_SEC=60
TUV_DEFAULT_POWER_W=2000 # fallback pokud není měřeno
```
---
## Otevřené body
- [ ] Teltonika: OCPP vs REST API rozhodnout před implementací
- [ ] TUV teplota zásobníku: přidat čidlo do Loxone pro přesnější řízení
- [ ] Bazální spotřeba: zpřesnit odečítání TUV výkonu (ON/OFF × čas vs pevný výkon)
- [ ] Sezónní korekce predikce spotřeby (léto vs zima) fáze 2