# SE Local Trenddata SE Local Trenddata ist eine webbasierte Trend-, Dashboard- und Quellenverwaltung fuer lokale Anlagen- und WAGO-Daten. Das Projekt besteht aus einem React-Frontend, einer Node.js/Express-API, MariaDB, Redis und einem Collector-Service fuer Protokollquellen wie Modbus TCP, OPC UA, BACnet IP und KNX IP. Das Ziel ist, bestehende breite Trendtabellen wie `isp01`, `isp02` usw. weiter nutzen zu koennen und zusaetzlich neue Quellen sauber ueber eine Weboberflaeche anzulegen, zu scannen, zu loggen und im Dashboard oder in der Trendansicht auszuwerten. --- ## Inhaltsverzeichnis - [Projektaufbau](#projektaufbau) - [Architektur](#architektur) - [Services und Ports](#services-und-ports) - [Schnellstart mit Docker Compose](#schnellstart-mit-docker-compose) - [Lokale Entwicklung](#lokale-entwicklung) - [Konfiguration](#konfiguration) - [Login, Benutzer und Rollen](#login-benutzer-und-rollen) - [Frontend-Funktionen](#frontend-funktionen) - [API-Funktionen](#api-funktionen) - [Collector-Funktionen](#collector-funktionen) - [Datenbank und Speicher](#datenbank-und-speicher) - [WAGO- oder SD-Karten-Betrieb](#wago--oder-sd-karten-betrieb) - [Backup und Restore](#backup-und-restore) - [Deployment-Hinweise](#deployment-hinweise) - [Troubleshooting](#troubleshooting) - [Sicherheits-Checkliste](#sicherheits-checkliste) --- ## Projektaufbau ```text SeLTD/ ├── .env.example ├── docker-compose.yml ├── docker-compose.wago.yml ├── docker/ │ └── redis/ │ └── redis.conf ├── api/ │ ├── Dockerfile │ ├── package.json │ └── src/ │ ├── index.js │ ├── auth.js │ ├── config.js │ ├── db.js │ ├── redis.js │ └── lib/ │ ├── isp.js │ └── store.js ├── collector/ │ ├── Dockerfile │ ├── package.json │ └── src/ │ └── index.js └── web/ ├── Dockerfile ├── package.json ├── vite.config.js ├── public/ │ └── logo.png └── src/ ├── App.jsx ├── api.js ├── main.jsx ├── styles.css └── components/ ├── Gauge.jsx └── TrendChart.jsx ``` ### Hauptbereiche | Bereich | Aufgabe | | --- | --- | | `web/` | React/Vite-Frontend fuer Login, Dashboard, Trends, Admin-Bereich, Quellen, Rollen und Benutzer | | `api/` | Express-API fuer Auth, Rollen, Aliase, Trendabfragen, Dashboard, SQL-Import und Benutzerverwaltung | | `collector/` | HTTP-Service fuer Protokollquellen, Datenpunkte, Scans, Imports und zyklisches Logging | | `mariadb` | Persistente Trenddaten und Benutzer-Tabelle | | `redis` | Metadaten, Aliase, Rollen, Einheiten, Dashboards, Auswahlen und User-Praeferenzen | | `dockhand` | Docker-Verwaltung ueber Weboberflaeche | | `cadvisor` | Container-Metriken fuer Monitoring | --- ## Architektur ```text Browser │ │ http://localhost:5173 ▼ React/Vite Frontend (web) │ ├── API-Aufrufe: http://localhost:18080/api/... │ ▼ │ Express API (api, intern Port 8080) │ ├── MariaDB: Benutzer, Trendtabellen, SQL-Daten │ └── Redis: Rollen, Einheiten, Aliase, Dashboard, Auswahlen │ └── Collector-Aufrufe: http://localhost:18110/... ▼ Collector-Service ├── sources.json unter /app/data ├── Modbus TCP / OPC UA / BACnet / KNX └── schreibt aktive Datenpunkte in MariaDB-Trendtabellen ``` Wichtig: Die API laeuft im Container intern auf Port `8080`, wird aber nach aussen auf `18080` gemappt. Das Frontend muss deshalb im Browser auf `http://localhost:18080/api` zugreifen. --- ## Services und Ports | Service | Container | Interner Port | Host-Port | Zweck | | --- | --- | ---: | ---: | --- | | Web | `seltd-web` | 5173 | 5173 | React/Vite-Oberflaeche | | API | `seltd-api` | 8080 | 18080 | REST-API | | Collector | `seltd-collector` | 18110 | 18110 | Quellen, Datenpunkte, Scans, Polling | | MariaDB | `seltd-mariadb` | 3306 | 3306 | Trend- und Benutzerdaten | | Redis | `seltd-redis` | 6379 | 6379 | Metadaten und App-State | | Dockhand | `dockhand` | 3000 | 3000 | Docker-Webverwaltung | | cAdvisor | `cadvisor_ltd` | 8080 | 9090 | Container-Metriken | --- ## Schnellstart mit Docker Compose Du solltest WSL installiert haben. Falls du das nicht hast: ```powershell wsl --install Ubuntu ``` Dann kannst du Docker Desktop installieren: https://docs.docker.com/desktop/setup/install/windows-install/ Die Installation einfach durchklicken und wenn du gefragt wirst ob du Hyper-V oder WSL verwenden möchtest, wähle WSL. ### 1. Repository vorbereiten Wenn du git auf deinem rechner installiert hast, dann öffne eine Powershell in dem Ordner, in dem du das LTD-System haben willst. (rechtsklick im Windowsexplorer ins leere --> "In Terminal öffnen") ```powershell git clone https://git.portal.se-cloud.de/Hannes/SE-LTD cd ./SeLTD ``` Powershell nicht schließen, brauchst du gleich noch. ### 2. Stack bauen und starten Falls du Powershell geschlossen hast: (rechtsklick im Windowsexplorer ins leere --> "In Terminal öffnen") ```powershell docker compose build --no-cache web api collector docker compose up -d --force-recreate ``` Die lokalen Images werden jetzt gebaut und die Onlineimages werden heruntrergeladen. Wenn das fertig ist müssen alle 7 Container gestartet sein. Im Nachgang kannst du dies in der Powershell mit... ```powershell docker ps -a ``` ...überprüfen ### 3. Aufrufen Nun stehen dir mehrere Tools zur Verfügung: Frontend | `http://localhost:5173` --> Das ist die normale Weboberfläche zum anschauen, editieren und anpassen von Trends. API Healthcheck | `http://localhost:18080/api/health` --> hier kannst du schauen ob die API läuft Collector Healthcheck | `http://localhost:18110/health` --> hier kannst du schauen ob der Collector läuft, was nur wichtig ist, wenn du Datenpunkte per OPC,KNX, Modbus oder Bacnet angebunden hast. Dockhand | `http://localhost:3000` --> Dockhand ist Container verwaltungstool, dass es dir ermöglicht, auch grafisch den Zustand deiner Container und deines Stacks zu sehen. Der Vorteil hier, im Gegensatz zur normalen Docker Desktopoberfläche: Du kannst es auf jedem beliebigen anderen Rechner, der auf dein Netzwerk zugriff hat, öffnen. cAdvisor | `http://localhost:9090` --> Cadvisor stellt alle Containerdaten für Monitoring und Analyticprogramme bereit. So kann bei einer größeren Anlage, das Dockersystem mitr Prometheus oder ähnlichem überwacht werden. Cadvisor stellt di Daten per html bereit, kannst du dir gern anschauen, ist aber ziemlich unübersichtlich. ### 4. Standard-Login ```text Username: admin Passwort: SE3112 ``` --- ## Konfiguration Die wichtigsten Variablen liegen in `.env`. | Variable | Beispiel | Beschreibung | | --- | --- | --- | | `JWT_SECRET` | `change-me` | Signatur fuer Login-Tokens. In Produktion unbedingt aendern. | | `ADMIN_USERNAME` | `admin` | Initialer Admin-Username | | `ADMIN_EMAIL` | `admin@example.com` | Initiale Admin-E-Mail | | `ADMIN_PASSWORD` | `ChangeMe123!` | Initiales Admin-Passwort | | `ADMIN_NAME` | `System Admin` | Anzeigename des Admins | | `MARIADB_ROOT_PASSWORD` | `SE3112` | MariaDB-Root-Passwort | | `DB_PASSWORD_FALLBACK` | `root` | Fallback fuer alte Entwicklungsvolumes | | `CORS_ORIGIN` | `*` | Erlaubter Browser-Ursprung fuer API-Aufrufe | | `VITE_API_PORT` | `18080` | API-Port, den das Frontend im Browser nutzt | | `POLL_TICK_MS` | `1000` | Collector-Tick fuer Polling-Pruefung | ## Login, Benutzer und Rollen Die API legt beim Start automatisch einen Admin-Benutzer an oder aktualisiert den vorhandenen Admin. ### Systemrollen | Rolle | Rechte | | --- | --- | | `viewer` | Dashboard anzeigen, Trendansicht anzeigen | | `technician` | Dashboard, Trends, Aliase, Quellen, Debug | | `admin` | Alle Rechte inkl. Benutzer- und Rollenverwaltung | ### Rechtekatalog | Recht | Bedeutung | | --- | --- | | `view_dashboard` | Dashboard anzeigen und speichern | | `view_trends` | Trends anzeigen, Auswahlen nutzen | | `edit_aliases` | Aliase und Einheiten bearbeiten | | `manage_sources` | Quellen und Datenpunkte verwalten | | `manage_users` | Benutzer anlegen und bearbeiten | | `manage_roles` | Rollen und Rechte verwalten | | `view_debug` | Collector-Debug sehen | Benutzer, Rollen und Passwoerter werden ueber den Admin-Bereich verwaltet. --- ## Frontend-Funktionen ### Login - Username-basierter Login - JWT-Token wird im Browser gespeichert - Passwortwechsel ueber Einstellungen - Rollenbasierte Navigation ### Dashboard - Widgets aus aktueller Auswahl oder gespeicherter Auswahl - Widget-Typen: - Graph - Zahl - Zeigermanometer - Dashboard wird pro Benutzer gespeichert ### Trendansicht - Datenpunkte aus mehreren Trendtabellen kombinierbar - Auswahl speicherbar und optional fuer andere Benutzer freigebbar - Zeitraeume als Presets von 5 Minuten bis 30 Tage - Eigener Start-/Endzeitraum moeglich - Aktuelle Werte werden separat angezeigt - Fokusmodus fuer den Graphen ### Trend-Export Der Trendgraph kann exportiert werden als: - CSV - XLSX - PNG - JPG - SVG - PDF ### Admin: Aliase - Anzeigename und Beschreibung pro Trendtabelle - Alias, Einheit, Faktor, Typ, Min/Max und Farbe pro Wert - CSV-Import und CSV-Export - Encoding-/Grad-Celsius-Bereinigung ### Admin: Einheiten - Systemeinheiten wie `°C`, `%`, `K`, `V`, `A`, `Pa` - Eigene Einheiten wie `bar`, `m³/h`, `Hz` usw. - Einheitenauswahl bei Aliasen und Datenpunkten ### Admin: Quellen - Protokollquellen anlegen und bearbeiten - Unterstuetzte Protokolle in der UI: - Modbus TCP - OPC UA - BACnet IP - KNX IP - Poll-Intervall und Schreibmodus konfigurierbar - Scan-Ergebnisse und importierte Punkte koennen ins Logging uebernommen werden - Manuelle Datenpunkte koennen erstellt und bearbeitet werden --- ## API-Funktionen Die API laeuft unter: ```text http://localhost:18080/api ``` ### Authentifizierung | Methode | Pfad | Beschreibung | | --- | --- | --- | | `POST` | `/api/auth/login` | Login mit Username/Passwort | | `GET` | `/api/auth/me` | Aktuellen Benutzer lesen | | `POST` | `/api/auth/change-password` | Passwort aendern | ### Trends und ISPs | Methode | Pfad | Beschreibung | | --- | --- | --- | | `GET` | `/api/isps` | Verfuegbare Trendtabellen lesen | | `GET` | `/api/isps/:isp/aliases` | Alias-Metadaten lesen | | `PUT` | `/api/isps/:isp/aliases` | Alias-Metadaten speichern | | `POST` | `/api/trend-tables` | Neue Trendtabelle anlegen | | `POST` | `/api/trends/query` | Trenddaten abfragen | | `POST` | `/api/points/latest` | Letzte Werte lesen | ### Einheiten | Methode | Pfad | Beschreibung | | --- | --- | --- | | `GET` | `/api/units` | Einheiten lesen | | `POST` | `/api/units` | Einheit anlegen | | `PATCH` | `/api/units/:symbol` | Einheit bearbeiten | ### Benutzer und Rollen | Methode | Pfad | Beschreibung | | --- | --- | --- | | `GET` | `/api/users` | Benutzerliste | | `POST` | `/api/users` | Benutzer anlegen | | `PATCH` | `/api/users/:id` | Benutzer bearbeiten | | `GET` | `/api/roles` | Rollenliste inkl. Rechtekatalog | | `POST` | `/api/roles` | Rolle anlegen | | `PATCH` | `/api/roles/:name` | Rolle bearbeiten | ### Auswahlen und Dashboard | Methode | Pfad | Beschreibung | | --- | --- | --- | | `GET` | `/api/selections` | Gespeicherte Auswahlen lesen | | `POST` | `/api/selections` | Auswahl speichern | | `PUT` | `/api/selections/:selectionId` | Auswahl aktualisieren | | `DELETE` | `/api/selections/:selectionId` | Auswahl loeschen | | `GET` | `/api/dashboard` | Dashboard laden | | `PUT` | `/api/dashboard` | Dashboard speichern | | `POST` | `/api/dashboard/data` | Widget-Daten laden | | `GET` | `/api/preferences` | Benutzerpraeferenzen laden | | `PUT` | `/api/preferences` | Benutzerpraeferenzen speichern | --- ## Collector-Funktionen Der Collector laeuft unter: ```text http://localhost:18110 ``` Er verwaltet Quellen und Datenpunkte in einer JSON-Datei (`/app/data/sources.json`) und schreibt aktive Punkte zyklisch in MariaDB. ### Collector-Endpunkte | Methode | Pfad | Beschreibung | | --- | --- | --- | | `GET` | `/health` | Healthcheck | | `GET` | `/capabilities` | Unterstuetzte Protokolle/Funktionen | | `GET` | `/sources` | Quellen lesen | | `POST` | `/sources` | Quelle anlegen | | `PUT` | `/sources/:id` | Quelle bearbeiten | | `DELETE` | `/sources/:id` | Quelle loeschen | | `GET` | `/datapoints` | Datenpunkte lesen | | `POST` | `/datapoints/manual` | Datenpunkt manuell anlegen | | `PATCH` | `/datapoints/:id` | Datenpunkt bearbeiten, aktivieren, deaktivieren | | `POST` | `/datapoints/:id/read` | Live-Wert lesen | | `POST` | `/imports/modbus-csv` | Modbus-CSV importieren | | `POST` | `/imports/knx-xml` | KNX-XML importieren | | `POST` | `/scan/opcua` | OPC-UA-Scan starten | | `POST` | `/scan/bacnet` | BACnet-Scan starten | | `GET` | `/debug` | Debugdaten lesen | ### Schreibmodus | Modus | Bedeutung | | --- | --- | | `interval` | Jeder Poll wird geschrieben | | `cov` | Nur bei Wertaenderung wird geschrieben | ### Aktive vs. inaktive Datenpunkte - Inaktive Datenpunkte sind gefunden/importiert, werden aber nicht geloggt. - Aktive Datenpunkte werden vom Collector gepollt und in die zugehoerige Trendtabelle geschrieben. - In der Weboberflaeche entspricht das der Trennung zwischen „Gefunden / importiert“ und „Wird geloggt“. --- ## Datenbank und Speicher ### MariaDB MariaDB speichert: - `app_users` - bestehende `isp...` Tabellen - neue `trend_...` Tabellen - Registry-Tabellen fuer Quellen und Datenpunkte, falls vom Collector/API genutzt Die API kann bestehende breite Tabellen mit `Wert1`, `Wert2`, ... lesen. Neue lokale Trendtabellen koennen bis zu 2000 Werte unterstuetzen. ### Redis Redis speichert: - Rollen - Einheiten - Aliase und Tabellen-Metadaten - Auswahlen - Dashboard-Konfiguration - Benutzerpraeferenzen Redis sollte deshalb ebenfalls gebackupt werden, nicht nur MariaDB. --- ### MariaDB Backup ```powershell docker exec seltd-mariadb mariadb-dump -uroot -pSE3112 --all-databases > seltd-mariadb-backup.sql ``` Restore: ```powershell type .\seltd-mariadb-backup.sql | docker exec -i seltd-mariadb mariadb -uroot -pSE3112 ``` ### Redis Backup Redis nutzt ein Docker-Volume. Fuer ein einfaches Dateibackup: ```powershell docker run --rm -v seltd_redis_data:/data -v ${PWD}:/backup alpine tar czf /backup/seltd-redis-backup.tar.gz -C /data . ``` ### Collector Backup ```powershell docker run --rm -v seltd_collector_data:/data -v ${PWD}:/backup alpine tar czf /backup/seltd-collector-backup.tar.gz -C /data . ``` --- ### Browsercache Bei alten JavaScript-Fehlern nach einem Fix: ```text Strg + F5 ``` ### Nginx Proxy Manager Wenn das Frontend hinter Nginx laeuft, muessen die API- und Collector-URLs sauber erreichbar sein. Entweder: - Frontend, API und Collector unter eigenen Subdomains veroeffentlichen, oder - Nginx so konfigurieren, dass `/api` zur API und `/collector` zum Collector weitergeleitet wird. In diesem Fall kann `VITE_API_URL` statt `VITE_API_PORT` gesetzt werden: ```env VITE_API_URL=https://trend-api.example.local/api VITE_COLLECTOR_URL=https://trend-collector.example.local ``` --- ## Troubleshooting ### Fehler: `NetworkError when attempting to fetch resource` Ursachen: - API-Container laeuft nicht - falscher Port im Frontend - CORS nicht korrekt - Browser ruft alte Version auf Pruefen: ```powershell docker ps curl http://localhost:18080/api/health ``` Wenn Frontend lokal auf `localhost:5173` laeuft: ```env CORS_ORIGIN=* ``` Danach API neu starten: ```powershell docker compose restart api ``` ### Fehler: Browser zeigt alte React-Fehler nach Fix Sehr wahrscheinlich wurde das Docker-Image nicht neu gebaut. ```powershell docker compose down docker compose build --no-cache web api collector docker compose up -d ``` Danach im Browser `Strg + F5`. ### MariaDB Login oder DB-Verbindung fehlgeschlagen Logs ansehen: ```powershell docker logs seltd-api --tail 100 docker logs seltd-mariadb --tail 100 ``` Pruefen, ob MariaDB healthy ist: ```powershell docker ps ``` ### Redis-Probleme ```powershell docker exec seltd-redis redis-cli ping ``` Erwartet: ```text PONG ``` --- ## Nuetzliche Befehle ### Alle Container anzeigen ```powershell docker compose ps ``` ### Logs live verfolgen ```powershell docker compose logs -f ``` Nur API: ```powershell docker logs seltd-api -f ``` Nur Frontend: ```powershell docker logs seltd-web -f ``` Nur Collector: ```powershell docker logs seltd-collector -f ``` ### Komplett neu starten ```powershell docker compose restart ``` ### Komplett neu bauen ```powershell docker compose down docker compose build --no-cache docker compose up -d ``` ### Volumes loeschen Achtung: Dadurch gehen Daten verloren. ```powershell docker compose down -v ``` --- ## Sicherheits-Checkliste Vor produktiver Nutzung: - [ ] `JWT_SECRET` auf langen zufaelligen Wert setzen - [ ] Admin-Passwort aendern - [ ] MariaDB-Root-Passwort aendern - [ ] MariaDB-Port `3306` nicht ungeschuetzt ins Internet veroeffentlichen - [ ] Redis-Port `6379` nicht ungeschuetzt ins Internet veroeffentlichen - [ ] Dockhand absichern oder nur intern bereitstellen - [ ] Backups fuer MariaDB, Redis und Collector-Daten einrichten - [ ] Reverse Proxy mit HTTPS verwenden --- ## Bekannte Hinweise - Leere Trendtabellen erscheinen nicht in der Trendauswahl, aber im Admin-Bereich. - Bestehende breite `isp...` Tabellen bleiben kompatibel. - Neue lokale Tabellen koennen als `trend_...` Tabellen angelegt werden. - Der Collector speichert seine Quellen/Datenpunkte aktuell dateibasiert in `sources.json`. - Fuer vollstaendige Protokollintegration muessen je nach Feldbus noch Details wie Adressierung, Datentyp, Byteorder und Authentifizierung sauber projektspezifisch gepflegt werden. ---