8.2 KiB
8.2 KiB
EMS Platform – Architektura
Vrstvy systému
┌─────────────────────────────────────────────┐
│ React Frontend (Vite + TypeScript) │
│ Dashboard, plány, telemetrie; výběr site │
│ (combobox → /api/v1/me/sites + PostgREST) │
└─────────────┬───────────────────────────────┘
│ HTTP/REST
┌─────────────▼───────────────────────────────┐
│ PostgREST │
│ Auto-REST API z PostgreSQL schématu ems │
│ Read: views, tabulky │
│ Write: insert/update přes API │
└─────────────┬───────────────────────────────┘
│ SQL
┌─────────────▼───────────────────────────────┐
│ PostgreSQL 16 + TimescaleDB │
│ Schéma: ems │
│ Funkce, views, hypertables │
└─────────────┬───────────────────────────────┘
│
┌─────────────▼───────────────────────────────┐
│ FastAPI (Python) │
│ – Scheduled tasks (APScheduler) │
│ – telemetry_collector (každých 60s) │
│ – price_importer (13:30, 14:00, 00:05) │
│ – forecast_service (každé 2h, minute 05)│
│ – planning_engine (denně 15:00) │
│ – control_exporter (každých 15min) │
│ – audit_filler (každých 15min) │
│ – verify_modbus (každé 2 min) │
└──────┬──────────────────────────┬────────────┘
│ Modbus TCP │ HTTP
┌──────▼──────┐ ┌───────▼────────────┐
│ Waveshare │ │ Loxone Miniserver │
│ WS-ETH │ │ (setpoint přijímač)│
└──────┬──────┘ └────────────────────┘
│ RS485
┌──────┼──────────────────────────────┐
│ Deye SUN-20K │ Teltonika 2× │ Samsung TČ │
└────────────────┴────────────────────┴──────────────┘
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.
Komponenty
| Komponenta | Technologie | Port | Popis |
|---|---|---|---|
db |
PostgreSQL 16 + TimescaleDB | 5432 | Datová vrstva |
postgrest |
PostgREST 12 | 3000 | Auto-REST API |
backend |
Python 3.12 / FastAPI | 8000 | Logika, scheduled tasks |
frontend |
React + Vite + TypeScript | 5173 (dev) / 80 (prod) | UI |
Adresář projektu
ems-platform/
CLAUDE.md
docker-compose.yml
docker-compose.dev.yml
.env.example
.env ← gitignore!
db/
migration/
V001__init_schema.sql
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
(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__vw_actual_baseline.sql
R__vw_audit_summary.sql
R__vw_heat_pump_cop_history.sql
flyway.conf
backend/
Dockerfile
requirements.txt
app/
main.py ← FastAPI app + scheduler setup
config.py ← settings z env
database.py ← asyncpg connection pool
services/
telemetry_collector.py
price_importer.py
forecast_service.py
planning_engine.py ← volá ems.fn_create_planning_run()
control_exporter.py
audit_filler.py
modbus/
deye_client.py
ev_charger_client.py
heat_pump_client.py
models/
site.py
assets.py
setpoints.py
frontend/
Dockerfile
package.json
vite.config.ts
src/
main.tsx
App.tsx
api/
postgrest.ts ← PostgREST client
backend.ts ← FastAPI client (/me/sites, …)
context/
SiteSelectionContext.tsx ← výběr lokality, localStorage
pages/
Dashboard.tsx
Planning.tsx
Telemetry.tsx
Settings.tsx
components/
PowerFlowChart.tsx
PriceChart.tsx
SocGauge.tsx
OverridePanel.tsx
docs/
01-overview.md
02-architecture.md ← tento soubor
03-data-model.md
04-modules/
market-prices.md
forecast.md
consumption.md
heat-pump.md
telemetry.md
control.md
planning.md
06-open-questions.md
Komunikační toky
Sběr dat (každých 60s)
Zařízení → Waveshare → Modbus TCP → telemetry_collector → PostgreSQL
Denní plánování (15:00)
PostgreSQL (ceny + forecast) → fn_create_planning_run() → planning_interval
Operátorské manuální akce (UI)
Browser → FastAPI:
GET /api/v1/me/sites ← seznam aktivních lokalit (UI combobox; bez auth zatím = všechny aktivní)
POST /api/v1/sites/{site_id}/prices/import?date=YYYY-MM-DD ← zapisuje globální market_interval_price; site_id jen validace URL
POST /api/v1/sites/{site_id}/forecast/run
POST /api/v1/sites/{site_id}/plan/run?type=daily|rolling
Export setpointů (každých 15min)
PostgreSQL (planning_interval + overrides) → control_exporter
→ Modbus TCP → Waveshare → Deye / Teltonika / Samsung
→ HTTP → Loxone
Frontend
Browser → PostgREST (čtení views/tabulek, filtr site_id dle výběru v UI)
Browser → FastAPI (seznam lokalit /me/sites, triggery: replanning, import cen, …)
Deployment: single-site (výchozí)
Vše na jednom stroji (x86 mini PC nebo silnější RPi 5):
Docker Compose:
db (PostgreSQL + TimescaleDB)
postgrest (PostgREST)
backend (FastAPI + všechny services)
frontend (Nginx + React build)
flyway (migrace při startu)
Minimální HW požadavky
| Parametr | Minimum | Doporučeno |
|---|---|---|
| CPU | 2 jádra | 4 jádra (x86) |
| RAM | 4 GB | 8 GB |
| Storage | SSD 64 GB | NVMe 256 GB |
| OS | Debian 12 / Ubuntu 22.04 | Ubuntu 22.04 LTS |
| Síť | 100 Mbps | Gigabit Ethernet |
Raspberry Pi 5 (8GB): Použitelné pro single-site s SSD přes USB 3 nebo NVMe HAT. Nedoporučovat microSD – TimescaleDB zápisy microSD rychle opotřebují.
Flyway konfigurace
# db/flyway.conf
flyway.url=jdbc:postgresql://db:5432/ems
flyway.user=${DB_USER}
flyway.password=${DB_PASSWORD}
flyway.schemas=ems
flyway.locations=filesystem:/flyway/migration,filesystem:/flyway/routines,filesystem:/flyway/views
flyway.validateOnMigrate=true
flyway.outOfOrder=false
Flyway se spouští jako jednorázový kontejner při docker-compose up.