Files
ems/docs/04-modules/pool-pump.md
Dusan Vojacek f70111f44b feat(pool): řízení bazénu Phase 1 — nejlevnější okno + dump-load (bez solveru)
fn_pool_schedule_slot: nejlevnější souvislé okno denního runtime budgetu
(fn_pool_daily_runtime_min) z vw_site_effective_price + dump-load při sell<=0.
fn_pool_control_tick: každých 15 min spočte stav a zařadí POOL_PUMP_ON (jen když
existuje signal_route → bezpečné před aktivací). lifespan job pool_control.
Shelly přes signal_service, žádné Modbus. Bazál odečet (R__003) se tím stává
správným (řízená+plánovaná zátěž). Aktivace provozně: daily_runtime_min=480,
schedulable, signal_route.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 22:00:49 +02:00

60 lines
3.0 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.
# Bazénové čerpadlo (Shelly) — řízení
Řízená zátěž: filtrační čerpadlo bazénu přes Shelly Plug S Gen3 (relé). EMS ho
spíná podle cen, čte telemetrii a započítává do plánu.
## Datový model (V087, V092)
- `ems.asset_pool_pump``rated_power_w`, `min_run_min`, `daily_runtime_min`
(statický cíl filtrace/den), `schedulable`, `shelly_switch_id`, `endpoint_id`,
teplotní parametry: `runtime_base_min`, `runtime_min_per_c`, `runtime_ref_temp_c`,
`runtime_min_min`, `runtime_max_min`, `water_temp_sensor_id`.
- `ems.telemetry_pool_pump` — 1min: `is_on`, `power_w`, `energy_wh_total` (hypertable).
## Denní runtime budget — `fn_pool_daily_runtime_min(pump_id)`
`clamp(runtime_base_min + runtime_min_per_c × (teplota runtime_ref_temp_c),
runtime_min_min, runtime_max_min)` z poslední teploty vody (`telemetry_loxone_sensor`,
< 24 h). **Bez čidla** → fallback `daily_runtime_min` (např. 480 = 8 h). Teplotní
režim se zapne pouhým napojením `water_temp_sensor_id` — žádný kód navíc.
## Rozvrh do slotů (Phase 1, bez solveru) — `fn_pool_schedule_slot(pump_id, slot)`
Vrací ON/OFF pro 15min slot:
- **Nejlevnější souvislé okno** délky = runtime budget (z `vw_site_effective_price`,
kalendářní den slotu v Europe/Prague, řazeno dle efektivní nákupní ceny). PV/záporné
dny → okno padne automaticky přes poledne.
- **+ dump-load overlay:** `sell <= 0` (záporná/nulová výkupní cena) → ON i mimo okno
(zkonzumuj přebytek místo exportu se ztrátou).
- `false` když pump není `schedulable` nebo nejsou ceny pro den.
## Control smyčka — `fn_pool_control_tick()` + APScheduler
Job `pool_control` (každých 15 min, hranice slotu, `lifespan.py`) volá
`fn_pool_control_tick()` → pro každý aktivní řiditelný bazén spočte
`fn_pool_schedule_slot` a **idempotentně** zařadí signál `POOL_PUMP_ON`
(`fn_signal_enqueue_bool`) — **jen když existuje `signal_route`** (jinak bezpečně
nic). Doručení na Shelly (`Switch.Set`) + readback verify (`Switch.GetStatus`) řeší
`signal_service` (každých 15 s). Žádné Modbus.
## Bazál
`fn_update_baseline_stats` (R__003) bazén **odečítá** z bazálu — to je správné
**jen** když ho zároveň řídíme (řízená + plánovaná zátěž). Bez řízení by to
plánovač oslepilo. S tímto řízením je odečet korektní.
## Aktivace (provozní, per site)
1. `asset_pool_pump.daily_runtime_min` = cílové minuty (480 = 8 h), `schedulable = true`.
2. Seed `signal_route` (`POOL_PUMP_ON``http_rest` na Shelly endpoint, `map_bool`
true/false → on/off; `verify_config_json` přes `Switch.GetStatus`).
3. Ověřit `fn_pool_schedule_slot` vrací rozumné sloty + telemetrii Shelly, pak teprve
ostře (control tick enqueueuje až s existující route).
## Roadmap
- **Phase 2:** `pool_on[t]` do solveru (`solver_v2`) — co-optimalizace proti
baterii/exportu (golden gate). Dump-load pak z živého SoC/PV, ne jen z ceny.
- Teplotní čidlo: napojit `water_temp_sensor_id` → runtime se prodlouží/zkrátí dle
teploty vody automaticky.