232 lines
7.6 KiB
Markdown
232 lines
7.6 KiB
Markdown
# 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Č │
|
||
└────────────────┴────────────────────┴──────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 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
|
||
R__fn_plan_day.sql
|
||
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
|
||
|
||
```properties
|
||
# 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`.
|