docs: add design specification for ESP32 E-Paper display system
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8d5e4106d6
commit
7ffad8364b
@ -0,0 +1,437 @@
|
|||||||
|
# ESP32 E-Paper Anzeigesystem — Design-Spezifikation
|
||||||
|
|
||||||
|
## 1. Übersicht
|
||||||
|
|
||||||
|
Modulares System zur Anzeige von Daten aus MQTT-Brokern und PostgreSQL-Datenbanken auf einem ESP32-basierten E-Paper-Display (Waveshare 7.5" V2, 800×480, schwarz/weiß).
|
||||||
|
|
||||||
|
**Komponenten:**
|
||||||
|
- **Middleware** (Node.js/Express/TypeScript) — Datensammlung, Verarbeitung, API
|
||||||
|
- **Webinterface** (React/TypeScript) — Konfiguration und Verwaltung
|
||||||
|
- **ESP32 Firmware** (PlatformIO/Arduino) — Display-Rendering
|
||||||
|
|
||||||
|
**Architektur:** Modularer Monolith — ein Express-Server mit klar getrennten internen Modulen. React SPA wird als Static Files ausgeliefert.
|
||||||
|
|
||||||
|
**Datenbank:** SQLite (Config, Datenpunkte, Layouts)
|
||||||
|
|
||||||
|
**Deployment:** Proxmox LXC-Container, Deploy via Git Clone
|
||||||
|
|
||||||
|
## 2. Systemarchitektur
|
||||||
|
|
||||||
|
```
|
||||||
|
Datenquellen (MQTT, PostgreSQL)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Middleware
|
||||||
|
(Node.js/Express/TS)
|
||||||
|
┌─────────────────────────────┐
|
||||||
|
│ MQTT Module │
|
||||||
|
│ PostgreSQL Module │
|
||||||
|
│ Datapoint Manager │
|
||||||
|
│ Display Module │
|
||||||
|
│ REST API (JWT Auth) │
|
||||||
|
│ SQLite DB │
|
||||||
|
└──────────┬──────────────────┘
|
||||||
|
│
|
||||||
|
├──► Webinterface (React SPA)
|
||||||
|
│
|
||||||
|
└──► ESP32 (E-Paper)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.1 Module
|
||||||
|
|
||||||
|
| Modul | Verantwortung |
|
||||||
|
|-------|---------------|
|
||||||
|
| **MQTT Module** | Broker-Verbindungen, Topic Discovery (Wildcard + Prefix), Payload-Parsing (JSON-Pfade), Werte an Datapoint Manager weiterleiten |
|
||||||
|
| **PostgreSQL Module** | DB-Connections verwalten, konfigurierte Queries periodisch ausführen, Ergebnisse auf Datenpunkte mappen |
|
||||||
|
| **Datapoint Manager** | Zentrale Registry aller Datenpunkte mit Name, Einheit, Wert, Timestamp, Status. Transformationen (Runden, Skalieren, Mapping). SQLite-Persistenz |
|
||||||
|
| **Display Module** | Layout-Templates, Zuordnung Datenpunkte → Layout-Elemente, JSON-Builder für ESP32 API. Unterstützt freie Positionierung und Grid-Modus |
|
||||||
|
| **REST API** | Express-Router mit JWT-Auth, CRUD für alle Entitäten, Display-Endpoint für ESP32 |
|
||||||
|
|
||||||
|
## 3. Datenmodell (SQLite)
|
||||||
|
|
||||||
|
### 3.1 mqtt_brokers
|
||||||
|
|
||||||
|
| Spalte | Typ | Beschreibung |
|
||||||
|
|--------|-----|--------------|
|
||||||
|
| id | INTEGER PK | Auto-Increment |
|
||||||
|
| name | TEXT NOT NULL | Anzeigename |
|
||||||
|
| host | TEXT NOT NULL | Broker-Hostname |
|
||||||
|
| port | INTEGER DEFAULT 1883 | Port |
|
||||||
|
| username | TEXT NULL | Auth |
|
||||||
|
| password | TEXT NULL | Auth (verschlüsselt gespeichert) |
|
||||||
|
| use_tls | BOOLEAN DEFAULT false | TLS aktivieren |
|
||||||
|
| enabled | BOOLEAN DEFAULT true | Broker aktiv |
|
||||||
|
| status | TEXT DEFAULT 'disconnected' | Verbindungsstatus |
|
||||||
|
| created_at | DATETIME | Erstellzeitpunkt |
|
||||||
|
| updated_at | DATETIME | Letzte Änderung |
|
||||||
|
|
||||||
|
### 3.2 mqtt_topics
|
||||||
|
|
||||||
|
| Spalte | Typ | Beschreibung |
|
||||||
|
|--------|-----|--------------|
|
||||||
|
| id | INTEGER PK | Auto-Increment |
|
||||||
|
| broker_id | INTEGER FK | Referenz auf mqtt_brokers |
|
||||||
|
| topic | TEXT NOT NULL | Topic-Pfad |
|
||||||
|
| json_path | TEXT NULL | JSON-Pfad für Wert-Extraktion (z.B. `$.value`) |
|
||||||
|
| selected | BOOLEAN DEFAULT false | Vom User ausgewählt |
|
||||||
|
| ignored | BOOLEAN DEFAULT false | Vom User ignoriert |
|
||||||
|
| last_payload | TEXT NULL | Letzte empfangene Payload |
|
||||||
|
| discovered_at | DATETIME | Entdeckungszeitpunkt |
|
||||||
|
|
||||||
|
### 3.3 pg_sources
|
||||||
|
|
||||||
|
| Spalte | Typ | Beschreibung |
|
||||||
|
|--------|-----|--------------|
|
||||||
|
| id | INTEGER PK | Auto-Increment |
|
||||||
|
| name | TEXT NOT NULL | Anzeigename |
|
||||||
|
| host | TEXT NOT NULL | DB-Host |
|
||||||
|
| port | INTEGER DEFAULT 5432 | Port |
|
||||||
|
| database | TEXT NOT NULL | Datenbankname |
|
||||||
|
| username | TEXT NOT NULL | DB-User |
|
||||||
|
| password | TEXT NOT NULL | DB-Passwort (verschlüsselt) |
|
||||||
|
| use_tls | BOOLEAN DEFAULT false | TLS |
|
||||||
|
| enabled | BOOLEAN DEFAULT true | Aktiv |
|
||||||
|
| status | TEXT DEFAULT 'disconnected' | Verbindungsstatus |
|
||||||
|
| created_at | DATETIME | Erstellzeitpunkt |
|
||||||
|
|
||||||
|
### 3.4 pg_queries
|
||||||
|
|
||||||
|
| Spalte | Typ | Beschreibung |
|
||||||
|
|--------|-----|--------------|
|
||||||
|
| id | INTEGER PK | Auto-Increment |
|
||||||
|
| source_id | INTEGER FK | Referenz auf pg_sources |
|
||||||
|
| name | TEXT NOT NULL | Anzeigename |
|
||||||
|
| query | TEXT NOT NULL | SQL-Abfrage (read-only) |
|
||||||
|
| interval_sec | INTEGER DEFAULT 60 | Abfrage-Intervall |
|
||||||
|
| result_column | TEXT NOT NULL | Spaltenname für den Wert |
|
||||||
|
| last_result | TEXT NULL | Letztes Ergebnis |
|
||||||
|
| last_run_at | DATETIME NULL | Letzte Ausführung |
|
||||||
|
|
||||||
|
### 3.5 datapoints
|
||||||
|
|
||||||
|
| Spalte | Typ | Beschreibung |
|
||||||
|
|--------|-----|--------------|
|
||||||
|
| id | INTEGER PK | Auto-Increment |
|
||||||
|
| name | TEXT NOT NULL | Technischer Name |
|
||||||
|
| label | TEXT NOT NULL | Anzeigename |
|
||||||
|
| unit | TEXT NULL | Einheit (°C, %, ppm, ...) |
|
||||||
|
| value | TEXT NULL | Letzter Wert |
|
||||||
|
| status | TEXT DEFAULT 'unknown' | ok / error / stale |
|
||||||
|
| source_type | TEXT NOT NULL | 'mqtt' oder 'postgresql' |
|
||||||
|
| source_id | INTEGER NOT NULL | FK auf Broker oder PG-Source |
|
||||||
|
| topic_id | INTEGER NULL | FK auf mqtt_topics (nur bei MQTT) |
|
||||||
|
| query_id | INTEGER NULL | FK auf pg_queries (nur bei PG) |
|
||||||
|
| transform | TEXT NULL | JSON: `{"round": 1, "scale": 1.0, "map": {}}` |
|
||||||
|
| enabled | BOOLEAN DEFAULT true | Aktiv |
|
||||||
|
| updated_at | DATETIME | Letztes Update |
|
||||||
|
|
||||||
|
### 3.6 displays
|
||||||
|
|
||||||
|
| Spalte | Typ | Beschreibung |
|
||||||
|
|--------|-----|--------------|
|
||||||
|
| id | INTEGER PK | Auto-Increment |
|
||||||
|
| name | TEXT NOT NULL | Anzeigename |
|
||||||
|
| description | TEXT NULL | Beschreibung |
|
||||||
|
| layout_id | INTEGER FK | Referenz auf layouts |
|
||||||
|
| api_token | TEXT NULL | Optionaler API-Token für ESP32 |
|
||||||
|
| last_seen | DATETIME NULL | Letzter ESP32-Abruf |
|
||||||
|
| refresh_sec | INTEGER DEFAULT 300 | Update-Intervall (5 Min) |
|
||||||
|
| created_at | DATETIME | Erstellzeitpunkt |
|
||||||
|
|
||||||
|
### 3.7 layouts
|
||||||
|
|
||||||
|
| Spalte | Typ | Beschreibung |
|
||||||
|
|--------|-----|--------------|
|
||||||
|
| id | INTEGER PK | Auto-Increment |
|
||||||
|
| name | TEXT NOT NULL | Layout-Name |
|
||||||
|
| type | TEXT DEFAULT 'free' | 'free' (freie Positionierung) oder 'grid' |
|
||||||
|
| width | INTEGER DEFAULT 800 | Display-Breite |
|
||||||
|
| height | INTEGER DEFAULT 480 | Display-Höhe |
|
||||||
|
| grid_cols | INTEGER NULL | Spalten bei Grid-Modus |
|
||||||
|
| grid_rows | INTEGER NULL | Zeilen bei Grid-Modus |
|
||||||
|
| created_at | DATETIME | Erstellzeitpunkt |
|
||||||
|
|
||||||
|
### 3.8 layout_elements
|
||||||
|
|
||||||
|
| Spalte | Typ | Beschreibung |
|
||||||
|
|--------|-----|--------------|
|
||||||
|
| id | INTEGER PK | Auto-Increment |
|
||||||
|
| layout_id | INTEGER FK | Referenz auf layouts |
|
||||||
|
| datapoint_id | INTEGER FK NULL | Zugewiesener Datenpunkt |
|
||||||
|
| type | TEXT NOT NULL | 'value', 'label', 'line', 'rect' |
|
||||||
|
| x | INTEGER NOT NULL | X-Position |
|
||||||
|
| y | INTEGER NOT NULL | Y-Position |
|
||||||
|
| width | INTEGER NULL | Breite (für Karten, Linien, Rects) |
|
||||||
|
| height | INTEGER NULL | Höhe |
|
||||||
|
| font_size | INTEGER DEFAULT 24 | Schriftgröße |
|
||||||
|
| font_weight | TEXT DEFAULT 'normal' | 'normal' oder 'bold' |
|
||||||
|
| text_align | TEXT DEFAULT 'left' | 'left', 'center', 'right' |
|
||||||
|
| icon | TEXT NULL | Icon-Name (thermometer, droplet, ...) |
|
||||||
|
| style | TEXT DEFAULT 'plain' | 'plain' (nur Text) oder 'card' (mit Rahmen) |
|
||||||
|
| static_text | TEXT NULL | Fester Text für Labels/Titel |
|
||||||
|
| grid_col | INTEGER NULL | Spalte im Grid-Modus |
|
||||||
|
| grid_row | INTEGER NULL | Zeile im Grid-Modus |
|
||||||
|
| sort_order | INTEGER DEFAULT 0 | Reihenfolge |
|
||||||
|
|
||||||
|
### 3.9 users
|
||||||
|
|
||||||
|
| Spalte | Typ | Beschreibung |
|
||||||
|
|--------|-----|--------------|
|
||||||
|
| id | INTEGER PK | Auto-Increment |
|
||||||
|
| username | TEXT UNIQUE NOT NULL | Benutzername |
|
||||||
|
| password_hash | TEXT NOT NULL | bcrypt-Hash |
|
||||||
|
| created_at | DATETIME | Erstellzeitpunkt |
|
||||||
|
|
||||||
|
## 4. REST API
|
||||||
|
|
||||||
|
### 4.1 Authentifizierung
|
||||||
|
|
||||||
|
- Login: `POST /api/auth/login` → JWT Token
|
||||||
|
- Alle `/api/*` Endpunkte (außer Display-Endpoint) erfordern JWT im `Authorization: Bearer <token>` Header
|
||||||
|
- Display-Endpoint optional per Query-Param: `?token=xxx`
|
||||||
|
|
||||||
|
### 4.2 Endpunkte
|
||||||
|
|
||||||
|
| Methode | Pfad | Beschreibung |
|
||||||
|
|---------|------|--------------|
|
||||||
|
| **Auth** | | |
|
||||||
|
| POST | `/api/auth/login` | Login → JWT |
|
||||||
|
| **MQTT Broker** | | |
|
||||||
|
| GET | `/api/mqtt/brokers` | Alle Broker auflisten |
|
||||||
|
| POST | `/api/mqtt/brokers` | Broker hinzufügen |
|
||||||
|
| PUT | `/api/mqtt/brokers/:id` | Broker bearbeiten |
|
||||||
|
| DELETE | `/api/mqtt/brokers/:id` | Broker löschen |
|
||||||
|
| POST | `/api/mqtt/brokers/:id/test` | Verbindung testen |
|
||||||
|
| **MQTT Topics** | | |
|
||||||
|
| GET | `/api/mqtt/brokers/:id/topics` | Topics eines Brokers |
|
||||||
|
| PUT | `/api/mqtt/topics/:id` | Topic bearbeiten |
|
||||||
|
| POST | `/api/mqtt/brokers/:id/discover` | Discovery starten |
|
||||||
|
| **PostgreSQL** | | |
|
||||||
|
| GET/POST | `/api/pg/sources` | PG-Verbindungen |
|
||||||
|
| PUT/DELETE | `/api/pg/sources/:id` | PG-Verbindung bearbeiten/löschen |
|
||||||
|
| POST | `/api/pg/sources/:id/test` | Verbindung testen |
|
||||||
|
| GET/POST | `/api/pg/sources/:id/queries` | Queries verwalten |
|
||||||
|
| PUT/DELETE | `/api/pg/queries/:id` | Query bearbeiten/löschen |
|
||||||
|
| **Datenpunkte** | | |
|
||||||
|
| GET | `/api/datapoints` | Alle Datenpunkte |
|
||||||
|
| PUT | `/api/datapoints/:id` | Datenpunkt bearbeiten |
|
||||||
|
| **Displays** | | |
|
||||||
|
| GET/POST | `/api/displays` | Displays verwalten |
|
||||||
|
| PUT/DELETE | `/api/displays/:id` | Display bearbeiten/löschen |
|
||||||
|
| **Layouts** | | |
|
||||||
|
| GET/POST | `/api/layouts` | Layouts verwalten |
|
||||||
|
| GET | `/api/layouts/:id` | Layout mit Elementen |
|
||||||
|
| PUT/DELETE | `/api/layouts/:id` | Layout bearbeiten/löschen |
|
||||||
|
| POST | `/api/layouts/:id/elements` | Element hinzufügen |
|
||||||
|
| PUT/DELETE | `/api/layouts/elements/:id` | Element bearbeiten/löschen |
|
||||||
|
| **ESP32 Display** | | |
|
||||||
|
| **GET** | **`/api/display/:id`** | **Display-Daten für ESP32** |
|
||||||
|
|
||||||
|
### 4.3 ESP32 JSON-Format
|
||||||
|
|
||||||
|
`GET /api/display/1` Response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"display": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "Werkstatt",
|
||||||
|
"width": 800,
|
||||||
|
"height": 480,
|
||||||
|
"refresh_sec": 300
|
||||||
|
},
|
||||||
|
"layout": {
|
||||||
|
"type": "free"
|
||||||
|
},
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "label",
|
||||||
|
"x": 400, "y": 20,
|
||||||
|
"font_size": 28, "font_weight": "bold",
|
||||||
|
"text_align": "center",
|
||||||
|
"text": "Werkstatt Monitor"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "value",
|
||||||
|
"x": 20, "y": 80,
|
||||||
|
"width": 380, "height": 90,
|
||||||
|
"font_size": 32, "font_weight": "bold",
|
||||||
|
"icon": "thermometer",
|
||||||
|
"style": "card",
|
||||||
|
"label": "Temperatur",
|
||||||
|
"value": "23.5",
|
||||||
|
"unit": "°C"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "value",
|
||||||
|
"x": 410, "y": 80,
|
||||||
|
"width": 380, "height": 90,
|
||||||
|
"font_size": 32, "font_weight": "bold",
|
||||||
|
"icon": "droplet",
|
||||||
|
"style": "card",
|
||||||
|
"label": "Luftfeuchte",
|
||||||
|
"value": "48",
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "line",
|
||||||
|
"x": 0, "y": 60,
|
||||||
|
"width": 800, "height": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "label",
|
||||||
|
"x": 400, "y": 465,
|
||||||
|
"font_size": 12, "text_align": "center",
|
||||||
|
"text": "Aktualisiert: 06.04.2026 10:15"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Für Grid-Layouts enthält `layout` zusätzlich `grid_cols` und `grid_rows`, und die Elemente werden automatisch positioniert.
|
||||||
|
|
||||||
|
## 5. Webinterface (React SPA)
|
||||||
|
|
||||||
|
### 5.1 Seiten
|
||||||
|
|
||||||
|
| Seite | Funktionalität |
|
||||||
|
|-------|---------------|
|
||||||
|
| **Dashboard** | Status-Kacheln (Broker, Datenpunkte, Displays), Event-Log |
|
||||||
|
| **MQTT Broker** | CRUD für Broker, Verbindungstest, Status |
|
||||||
|
| **Topics** | Topic-Liste mit Checkbox, Filter/Suche, Payload-Vorschau, JSON-Pfad |
|
||||||
|
| **PostgreSQL** | CRUD für Connections + Queries, Test-Ausführung |
|
||||||
|
| **Datenpunkte** | Tabelle aller Punkte, Label/Einheit/Transform bearbeiten |
|
||||||
|
| **Displays** | Display-Verwaltung, Layout-Zuweisung, API-Token, Refresh-Intervall |
|
||||||
|
| **Layouts** | Layout-Editor: Typ wählen (free/grid), Elemente positionieren, Datenpunkte zuweisen, Icons wählen, Style (card/plain) |
|
||||||
|
| **Vorschau** | E-Paper-Simulation (schwarz/weiß, 800×480 proportional) |
|
||||||
|
|
||||||
|
### 5.2 UI-Design
|
||||||
|
|
||||||
|
- Sidebar-Navigation (fixiert, links)
|
||||||
|
- Responsives Layout
|
||||||
|
- Dunkle Sidebar (#1a1a2e), heller Content-Bereich
|
||||||
|
- Status-Farben: Grün (verbunden/ok), Orange (warning), Rot (error)
|
||||||
|
|
||||||
|
### 5.3 Topic Discovery
|
||||||
|
|
||||||
|
- Prefix-basiert als Default: User gibt Prefix ein (z.B. `sensor/`), System subscribed auf `sensor/#`
|
||||||
|
- Optional: volle Discovery mit `#` (Wildcard)
|
||||||
|
- Entdeckte Topics werden in Liste angezeigt mit Checkbox (auswählen/ignorieren)
|
||||||
|
- Payload-Vorschau zeigt letzte Message + JSON-Pfad-Konfiguration
|
||||||
|
|
||||||
|
## 6. ESP32 Firmware
|
||||||
|
|
||||||
|
### 6.1 Hardware
|
||||||
|
|
||||||
|
- **Board:** Waveshare e-Paper ESP32 Driver Board
|
||||||
|
- **Display:** Waveshare 7.5" V2 (800×480, schwarz/weiß)
|
||||||
|
- **Interface:** SPI
|
||||||
|
|
||||||
|
### 6.2 PlatformIO-Projekt
|
||||||
|
|
||||||
|
**Libraries:**
|
||||||
|
- `GxEPD2` — E-Paper Display-Treiber
|
||||||
|
- `ArduinoJson` — JSON-Parsing
|
||||||
|
- `Adafruit GFX` — Grafik-Primitives
|
||||||
|
- `WiFi` (built-in) — WiFi-Stack
|
||||||
|
- `HTTPClient` (built-in) — HTTP-Requests
|
||||||
|
|
||||||
|
### 6.3 Ablauf
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Boot / Wake from Deep Sleep
|
||||||
|
2. WiFi verbinden (3 Versuche, sonst Fehlermeldung auf Display)
|
||||||
|
3. HTTP GET /api/display/{id}?token=xxx
|
||||||
|
4. JSON parsen
|
||||||
|
5. Display rendern:
|
||||||
|
- Elemente iterieren
|
||||||
|
- Je nach type: Text, Linie, Rechteck, Icon zeichnen
|
||||||
|
- Card-Style: Rahmen mit abgerundeten Ecken
|
||||||
|
- Grid-Mode: automatische Positionierung
|
||||||
|
6. Deep Sleep für refresh_sec Sekunden
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.4 Renderer
|
||||||
|
|
||||||
|
Der Renderer iteriert über das `elements[]`-Array und zeichnet je nach `type`:
|
||||||
|
|
||||||
|
- **label**: Text an x/y mit font_size, font_weight, text_align
|
||||||
|
- **value**: Label + Wert + Einheit, optional mit Icon und Card-Rahmen
|
||||||
|
- **line**: Horizontale/vertikale Linie
|
||||||
|
- **rect**: Rechteck (gefüllt oder Outline)
|
||||||
|
|
||||||
|
**Icons:** 12 vordefinierte Bitmaps (24×24 px) im Flash:
|
||||||
|
thermometer, droplet, wind, pressure, sun, bolt, gauge, wifi, battery, check, warning, clock
|
||||||
|
|
||||||
|
### 6.5 Konfiguration (Captive Portal)
|
||||||
|
|
||||||
|
Beim ersten Start oder wenn kein WiFi konfiguriert:
|
||||||
|
1. ESP32 startet als Access Point ("EPaper-Setup")
|
||||||
|
2. Captive Portal mit Konfigurationsseite
|
||||||
|
3. Eingabefelder: WiFi SSID, Passwort, API-URL, Display-ID, optionaler Token
|
||||||
|
4. Gespeichert im NVS (Non-Volatile Storage)
|
||||||
|
5. Reboot und Verbindung
|
||||||
|
|
||||||
|
### 6.6 Fehlerbehandlung
|
||||||
|
|
||||||
|
| Situation | Verhalten |
|
||||||
|
|-----------|-----------|
|
||||||
|
| WiFi-Fehler | 3 Versuche, dann Fehlermeldung auf Display, Deep Sleep 60s |
|
||||||
|
| API-Fehler | Letzte gültige Anzeige behalten, "Offline" im Footer, Deep Sleep 60s |
|
||||||
|
| JSON-Fehler | Fehlermeldung auf Display, letzte Anzeige beibehalten |
|
||||||
|
|
||||||
|
## 7. Deployment
|
||||||
|
|
||||||
|
- **Ziel:** Neuer Proxmox LXC-Container
|
||||||
|
- **Provisionierung:** Per `/proxmox-lxc` Skill
|
||||||
|
- **Deploy:** Git Clone auf LXC, `npm install`, `npm run build`, systemd Service
|
||||||
|
- **Webinterface:** React Build als Static Files im Express-Server
|
||||||
|
- **Port:** 4000 (Backend + Frontend)
|
||||||
|
|
||||||
|
## 8. Projektstruktur
|
||||||
|
|
||||||
|
```
|
||||||
|
display/
|
||||||
|
├── middleware/ # Node.js Backend
|
||||||
|
│ ├── src/
|
||||||
|
│ │ ├── modules/
|
||||||
|
│ │ │ ├── mqtt/ # MQTT Module
|
||||||
|
│ │ │ ├── postgres/ # PostgreSQL Module
|
||||||
|
│ │ │ ├── datapoints/ # Datapoint Manager
|
||||||
|
│ │ │ └── display/ # Display/Layout Module
|
||||||
|
│ │ ├── api/
|
||||||
|
│ │ │ ├── routes/ # Express Routes
|
||||||
|
│ │ │ ├── middleware/ # Auth, Error Handler
|
||||||
|
│ │ │ └── index.ts # API Setup
|
||||||
|
│ │ ├── db/
|
||||||
|
│ │ │ ├── migrations/ # SQLite Migrations
|
||||||
|
│ │ │ └── index.ts # DB Connection
|
||||||
|
│ │ └── index.ts # Entry Point
|
||||||
|
│ ├── package.json
|
||||||
|
│ └── tsconfig.json
|
||||||
|
├── frontend/ # React SPA
|
||||||
|
│ ├── src/
|
||||||
|
│ │ ├── pages/ # Dashboard, Broker, Topics, ...
|
||||||
|
│ │ ├── components/ # Shared Components
|
||||||
|
│ │ ├── api/ # API Client
|
||||||
|
│ │ └── App.tsx
|
||||||
|
│ ├── package.json
|
||||||
|
│ └── tsconfig.json
|
||||||
|
├── esp32/ # PlatformIO Projekt
|
||||||
|
│ ├── src/
|
||||||
|
│ │ └── main.cpp
|
||||||
|
│ ├── include/
|
||||||
|
│ │ └── icons.h # Icon Bitmaps
|
||||||
|
│ └── platformio.ini
|
||||||
|
└── docs/
|
||||||
|
```
|
||||||
|
|
||||||
|
## 9. MVP-Scope
|
||||||
|
|
||||||
|
Für den ersten Test:
|
||||||
|
- 1 MQTT-Broker anbinden
|
||||||
|
- 5 Datenpunkte konfigurieren
|
||||||
|
- 1 Layout mit 5 Werten (gemischt: 2er-Reihen + 1er-Reihe)
|
||||||
|
- 1 Display
|
||||||
|
- ESP32 ruft Daten ab und zeigt sie an
|
||||||
|
- Webinterface: Dashboard, Broker-Config, Topic-Auswahl, Datenpunkte, Layout-Editor, Vorschau
|
||||||
Loading…
x
Reference in New Issue
Block a user