next cahgnes
This commit is contained in:
@@ -48,7 +48,7 @@
|
||||
|
||||
## Read-model JSONB (`ems.fn_*`)
|
||||
|
||||
FastAPI endpointy pro dashboard a konfiguraci preferují **jedno volání** `select ems.fn_*(…)` vracející **jsonb** (pole řádků, agregace, merge locků), aby v Pythonu nezůstávaly ad-hoc `SELECT`/`JOIN`/`WITH`. Pomocník `app.db_json.fetch_json` vrací `dict`/`list`. Telemetrie a IO zůstávají v Pythonu; čisté agregace a sjednocení TZ patří do SQL. Opakované migrace: `db/routines/R__fn_*.sql`, `db/views/R__vw_*.sql`.
|
||||
FastAPI endpointy pro dashboard a konfiguraci preferují **jedno volání** `select ems.fn_*(…)` vracející **jsonb** (pole řádků, agregace, merge locků), aby v Pythonu nezůstávaly ad-hoc `SELECT`/`JOIN`/`WITH`. Pomocník `app.db_json.fetch_json` vrací `dict`/`list`. Telemetrie a IO zůstávají v Pythonu; čisté agregace a sjednocení TZ patří do SQL. Opakované migrace: `db/routines/R__NNN_fn_*.sql`, `db/views/R__NNN_vw_*.sql` (prefix `NNN` = pořadí závislostí pro Flyway).
|
||||
|
||||
## Komponenty
|
||||
|
||||
@@ -77,18 +77,18 @@ ems-platform/
|
||||
V002__timescale_hypertables.sql
|
||||
V003__seed_site_home01.sql
|
||||
routines/
|
||||
R__fn_effective_price.sql
|
||||
R__fn_cop_estimate.sql
|
||||
R__fn_baseline_consumption.sql
|
||||
R__fn_fill_audit_interval.sql
|
||||
R__003_fn_baseline_consumption.sql
|
||||
R__005_fn_cop_estimate.sql
|
||||
R__011_fn_effective_price.sql
|
||||
R__019_fn_fill_audit_interval.sql
|
||||
(historicky) R__fn_plan_day.sql – primární plánování je PuLP v Pythonu
|
||||
R__fn_create_planning_run.sql
|
||||
views/
|
||||
R__vw_site_effective_price.sql
|
||||
R__vw_latest_telemetry.sql
|
||||
R__vw_telemetry_15m_7d.sql
|
||||
R__061_vw_site_effective_price.sql
|
||||
R__058_vw_latest_telemetry.sql
|
||||
R__071_vw_telemetry_15m_7d.sql
|
||||
R__vw_actual_baseline.sql
|
||||
R__vw_audit_summary.sql
|
||||
R__053_vw_audit_summary.sql
|
||||
R__vw_heat_pump_cop_history.sql
|
||||
flyway.conf
|
||||
|
||||
|
||||
@@ -271,9 +271,9 @@ CREATE TABLE telemetry_inverter (
|
||||
Z `telemetry_inverter` počítá TimescaleDB materializované agregáty (viz `db/migration/V011__indexes_and_aggregates.sql`, `V039__telemetry_inverter_15m_aggregate.sql`):
|
||||
|
||||
- **`telemetry_inverter_hourly`** – hodinové průměry + `LAST(battery_soc_percent, measured_at)`; čtení přes view **`vw_telemetry_hourly_7d`**.
|
||||
- **`telemetry_inverter_15m`** – čtvrthodinové bucket odpovídající 15min slotům EMS; čtení přes **`vw_telemetry_15m_7d`** (definice v **`db/views/R__vw_telemetry_15m_7d.sql`**, repeatable).
|
||||
- **`telemetry_inverter_15m`** – čtvrthodinové bucket odpovídající 15min slotům EMS; čtení přes **`vw_telemetry_15m_7d`** (definice v **`db/views/R__071_vw_telemetry_15m_7d.sql`**, repeatable).
|
||||
|
||||
PostgREST role `ems_anon` má `SELECT` na tyto views (ne na samotné CA); u view nad CA je `security_invoker = false`, stejně jako u `vw_telemetry_hourly_7d` (viz `db/views/R__z_postgrest_ems_anon_grants.sql`).
|
||||
PostgREST role `ems_anon` má `SELECT` na tyto views (ne na samotné CA); u view nad CA je `security_invoker = false`, stejně jako u `vw_telemetry_hourly_7d` (viz `db/views/R__072_z_postgrest_ems_anon_grants.sql`).
|
||||
|
||||
### `telemetry_ev_charger`
|
||||
Stav EV nabíječek.
|
||||
|
||||
@@ -70,6 +70,6 @@ Tabulka pro budoucí logování **cut-off** přepínačů (mikroinvertory / GEN
|
||||
|
||||
## Související soubory
|
||||
|
||||
- Migrace: `db/migration/V023__modbus_command_journal.sql`, `V025__deye_physical_mode.sql`, `V030__deye_clock_sync_at.sql`, `V044__deye_register_max_current_a.sql`; repeatables `db/routines/R__fn_set_mode.sql` (`fn_expire_modes` vrací detail přepnutí pro notifikace)
|
||||
- Migrace: `db/migration/V023__modbus_command_journal.sql`, `V025__deye_physical_mode.sql`, `V030__deye_clock_sync_at.sql`, `V044__deye_register_max_current_a.sql`; repeatables `db/routines/R__044_fn_set_mode.sql` (`fn_expire_modes` vrací detail přepnutí pro notifikace)
|
||||
- Backend: `backend/services/control_exporter.py`, `backend/services/modbus_client.py`, `backend/services/notification_service.py`, `backend/app/main.py`
|
||||
- Registry Deye: `docs/04-modules/modbus-registers.md`
|
||||
|
||||
@@ -159,7 +159,7 @@ ev_expected_w[t] = arrival_prob * ev_charge_power_typical
|
||||
### Fáze 3a – Historické průměry cen (hotovo)
|
||||
|
||||
1. Tabulka `ems.market_price_stats` – migrace **V022__extended_planning.sql**
|
||||
2. `fn_update_market_price_stats()` – `db/routines/R__fn_extended_planning.sql`, APScheduler **14:45** (`main.py`)
|
||||
2. `fn_update_market_price_stats()` – `db/routines/R__018_fn_extended_planning.sql`, APScheduler **14:45** (`main.py`)
|
||||
3. Solver: slotová páteř `generate_series` + `COALESCE(effective_*, fn_get_predicted_price(...))` v `_load_slots`
|
||||
|
||||
### Fáze 3b – TUV statistika potřeby (hotovo)
|
||||
|
||||
@@ -149,7 +149,7 @@ Nad `ems.telemetry_inverter` běží dva **continuous aggregate** (TimescaleDB);
|
||||
| Objekt | Bucket | View pro PostgREST / UI | Poznámka |
|
||||
|--------|--------|-------------------------|----------|
|
||||
| `ems.telemetry_inverter_hourly` | 1 hodina | `ems.vw_telemetry_hourly_7d` | CA a view v **V011**; `security_invoker` v **V031**. Hodinové trendy. |
|
||||
| `ems.telemetry_inverter_15m` | 15 minut | `ems.vw_telemetry_15m_7d` | **`db/views/R__vw_telemetry_15m_7d.sql`** – posledních 7 dní, zarovnání s 15min sloty přehledu. |
|
||||
| `ems.telemetry_inverter_15m` | 15 minut | `ems.vw_telemetry_15m_7d` | **`db/views/R__071_vw_telemetry_15m_7d.sql`** – posledních 7 dní, zarovnání s 15min sloty přehledu. |
|
||||
|
||||
**Frontend přehled** (`frontend/src/hooks/useDashboardData.ts`): skutečné výkony a SoC po slotech bere z **`/vw_telemetry_15m_7d`** (klíč slotu = začátek 15min intervalu v UTC, stejně jako `floorSlotUtcMs` v grafu). Horní karty a **aktuální SoC** v grafu jsou dál z **`vw_site_status`** (poslední 1min vzorek) a z WebSocketu `/ws/telemetry`, aby „teď“ odpovídalo boxu i po refreshi agregátu.
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ Shrnutí otevřených bodů z `docs/06-open-questions.md`, checklistů v modulec
|
||||
| Popis |
|
||||
|-------|
|
||||
| **Zelený bonus:** přesunuto na `asset_pv_array` (`green_bonus_*`), výpočet `fn_green_bonus_revenue()`, audit_filler (`fn_fill_audit_interval`) počítá bonus z výroby pole; legacy sloupce odstraněny ze `site_market_config` (V018). |
|
||||
| **Rozšířený horizont plánování 96h** (fáze 3a+3b+3c): tabulky `market_price_stats`, `tuv_usage_stats`, funkce `fn_update_market_price_stats`, `fn_update_tuv_usage_stats`, `fn_get_predicted_price` (V022 + `R__fn_extended_planning.sql`), solver váhy 1,0 / 0,7 / 0,4, joby 14:45 / 00:45 v `main.py`. |
|
||||
| **Rozšířený horizont plánování 96h** (fáze 3a+3b+3c): tabulky `market_price_stats`, `tuv_usage_stats`, funkce `fn_update_market_price_stats`, `fn_update_tuv_usage_stats`, `fn_get_predicted_price` (V022 + `R__018_fn_extended_planning.sql`), solver váhy 1,0 / 0,7 / 0,4, joby 14:45 / 00:45 v `main.py`. |
|
||||
| **Import OTE – robustní provoz:** timeouty + retry/backoff v `price_importer.py`, detailní error kódy v API, fallback D+1 → dnešek, scheduler importů 13:30 / 14:00 / 00:05. |
|
||||
| **Fail-safe bez OTE dat:** při predikovaných cenách v kritickém okně je zákaz exportu; vybíjení baterie omezeno jen v predikovaných slotech; runtime guard v `control_exporter.py` brání SELL v nejistém stavu. |
|
||||
| **Forecast provoz:** refresh každé 2 hodiny (`:05`), konfigurovatelný Open-Meteo horizont (`OPEN_METEO_FORECAST_DAYS`, default 7, clamp 2..16), endpoint pro UI vrací latest-run bez duplicit slotů. |
|
||||
|
||||
@@ -43,6 +43,6 @@ Tento soubor slouží jako živý seznam věcí které je potřeba rozhodnout p
|
||||
|
||||
## Vyřešeno
|
||||
|
||||
- **PostgREST anon role:** `ems_anon`, read-only na vybrané views a tabulky (migrace `V009__postgrest_roles.sql` + repeatable `R__z_postgrest_ems_anon_grants.sql` kvůli pořadí Flyway); zápisy přes FastAPI. Compose / `.env`: `POSTGREST_ANON_ROLE=ems_anon`, PostgREST `PGRST_DB_ANON_ROLE`.
|
||||
- **PostgREST anon role:** `ems_anon`, read-only na vybrané views a tabulky (migrace `V009__postgrest_roles.sql` + repeatable `R__072_z_postgrest_ems_anon_grants.sql` kvůli pořadí Flyway); zápisy přes FastAPI. Compose / `.env`: `POSTGREST_ANON_ROLE=ems_anon`, PostgREST `PGRST_DB_ANON_ROLE`.
|
||||
|
||||
- **Multi-site (částečně):** OTE import jednou pro celý systém do `market_interval_price`; frontend výběr lokality (`SiteSelectionContext`, persist `ems.selected_site_id`), API `GET /api/v1/me/sites` (zatím všechny aktivní site). Chybí: mapování uživatel → site, JWT/RLS u PostgREST (viz otevřená otázka výše).
|
||||
|
||||
Reference in New Issue
Block a user