# 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.

**Operace: přepočet bez EMA „ocasu“:** denní job volá `fn_update_baseline_stats`, které při updatu bucketu míchá **70 % starý + 30 % nový** průměr. Je-li profil zaseklý, smaž statistiky a znovu načti z telemetrie — kanonické API je **`ems.fn_rebuild_consumption_baseline_stats(p_site_id, p_lookback_days)` v `db/routines/R__085_fn_rebuild_consumption_baseline_stats.sql`**: při **`p_site_id IS NULL`** maže celou `consumption_baseline_stats` a přepíná všechny řádky z `ems.site`; při konkrétním `site_id` jen řádky dané lokality. **Příklad (psql / MCP):** `select * from ems.fn_rebuild_consumption_baseline_stats(2, 30);` jedna lokality; **`select * from ems.fn_rebuild_consumption_baseline_stats(null::int, 30);`** všechny lokality *(první argument je site_id — ne zaměnit s počtem dnů).* Špatná měření (EV/TČ) funkce sama neopraví.

> **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: zatím není reálně čten z TČ; placeholder telemetrie a plánování
  používají parametry z `asset_heat_pump`, hlavně `rated_heating_power_w`

**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

## Odečet měřených řízených zátěží (update 2026-06-12)

Bazál = `load_power_w` − EV (`telemetry_ev_charger`) − TČ (`telemetry_heat_pump`)
− **bazén (`telemetry_pool_pump`)** — doplněno v `fn_update_baseline_stats`
(R__003). Ruční chod čerpadla (vysávání) se tak přiřadí zařízení, ne bazálu;
30d EMA okno historický šum vyplaví samo.
