Messwerte verstehen. Abweichungen erkennen.
SensorBoard ist ein eigenständiges Full-Stack-Portfolio-Projekt zur Überwachung simulierter Industrieanlagen. Die deutschsprachige Oberfläche verbindet aktuelle Messwerte, historische Verläufe und ein nachvollziehbares Ereignisprotokoll.
Ein einzelner Messwert zeigt nicht, ob eine Anlage stabil läuft. Bediener müssen erkennen können, wann Grenzwerte verletzt werden und wann Daten fehlen. SensorBoard führt diese Informationen zusammen: Ein Hintergrunddienst erzeugt Messwerte, das Backend bewertet deren Zustand und Angular zeigt Verlauf und Handlungsbedarf an.
Die Anwendung veranschaulicht industrielle Datenvisualisierung. Sie ist keine echte Anlagensteuerung und kein Projekt eines Unternehmens. Alle Anlagen und Daten sind fiktiv.
- Vier simulierte Sensoren für Temperatur, Druck und Luftfeuchtigkeit; neue Messwerte alle drei Sekunden.
- Live-Aktualisierung mit SignalR; zusätzlicher HTTP-Abruf alle fünf Sekunden als Rückfallebene.
- Historische Diagramme für 15 Minuten, eine Stunde, 24 Stunden oder sieben Tage.
- Serverseitige Aggregation in ca. 300 Zeitfenster; Minimum und Maximum erhalten sichtbare Spitzen.
- Einstellbare Unter- und Obergrenzen mit Validierung.
- Erkennung fehlender Messwerte nach über 15 Sekunden.
- Ereignisprotokoll mit getrennten Zuständen für „beendet“ und „bestätigt“.
- Drei Demonstrationsmodi pro Sensor: Normalbetrieb, Grenzwertüberschreitung, Verbindungsunterbrechung.
- Persistente Speicherung, automatische Bereinigung von Messwerten nach sieben Tagen.
| Bereich | Technologien |
|---|---|
| Backend | C#, .NET 10, ASP.NET Core Minimal APIs, BackgroundService |
| Daten | Entity Framework Core 10, PostgreSQL 17; SQLite für lokalen Start |
| Echtzeit | ASP.NET Core SignalR |
| Frontend | Angular 21, TypeScript, Signals, Chart.js, responsives CSS |
| Qualität | xUnit, relationale SQLite-Integrationstests, API-Smoke-Test, GitHub Actions |
| Betrieb | Docker, Docker Compose, mehrstufiger Image-Build |
Simulator / Messwert-API
↓
BoardService → Zustandsbewertung → Datenbank
↓
SignalR-Benachrichtigung
↓
Angular → REST-Abfragen → Karten, Diagramme, Ereignisse
Keine Warnungsflut: Eine anhaltende Grenzwertverletzung erzeugt genau ein aktives Ereignis. Ein Zustandswechsel beendet das alte Ereignis. Bestätigen bedeutet „zur Kenntnis genommen“ und behebt keine Störung.
Idempotente Annahme: Jeder externe Messwert trägt eine Ereignis-ID. Ein erneuter Aufruf mit derselben ID erzeugt keinen weiteren Datensatz. Ein eindeutiger Datenbankindex sichert die ID zusätzlich ab. IDs müssen über alle Sensoren hinweg eindeutig sein.
Konsistente Schreiboperationen: Ein gemeinsames Semaphore serialisiert Simulator- und API-Schreibzugriffe innerhalb einer Instanz. Messwert, Sensorzustand und Ereignisänderungen werden mit einem gemeinsamen EF-Core-SaveChanges atomar gespeichert. Die Architektur ist bewusst für genau eine laufende Backend-Instanz ausgelegt.
Zeit und Darstellung: Zeitstempel werden serverseitig in UTC erzeugt. Die Oberfläche zeigt sie in der lokalen Browser-Zeitzone. Ungültige Grenzwerte werden sowohl im Frontend als auch im Backend abgelehnt.
Einfacher Einstieg: Lokal läuft SQLite ohne Datenbankinstallation. Docker Compose verwendet PostgreSQL. Das initiale Schema wird über EnsureCreated angelegt; Schemaänderungen benötigen künftig EF-Migrationen oder eine neu angelegte Demo-Datenbank.
Voraussetzungen: .NET SDK 10 und Node.js 24 mit npm. Ein Runtime-Paket allein genügt nicht. Beim ersten Start ist Internet für die Abhängigkeiten nötig.
dotnet --version
node --version
cd sensorboard
bash start.shNach der Meldung Now listening on: http://localhost:5080 im Browser http://localhost:5080 öffnen. Das Skript installiert npm-Abhängigkeiten, baut Angular und startet das Backend. Beenden mit Ctrl+C. Beim ersten Start werden sechs Minuten fiktive Messhistorie erzeugt. Es ist kein Benutzerkonto nötig.
Windows: dieselben Voraussetzungen installieren und im Projektordner start.cmd ausführen.
Das Backend legt backend/data/sensorboard.db an, wenn es über die Startskripte gestartet wird. Die Daten bleiben nach einem Neustart erhalten. Zum Zurücksetzen die Anwendung stoppen und den lokalen data-Ordner des Backends löschen. Damit gehen alle lokalen Demo-Daten verloren.
Docker Desktop muss laufen. Im Projektstamm:
cp .env.example .env
# In .env ein eigenes POSTGRES_PASSWORD setzen.
docker compose up --build -d
docker compose logs -f appUnter Windows kann .env.example mit dem Dateimanager nach .env kopiert werden. Danach http://localhost:5080 öffnen. Die Bindung ist absichtlich auf den lokalen Rechner beschränkt.
docker compose downStoppt die Container und erhält das Datenbank-Volume. docker compose down -v löscht zusätzlich sämtliche Demo-Daten. Bereits initialisierte PostgreSQL-Volumes übernehmen keine Passwortänderung aus .env automatisch.
- Normalbetrieb: Vier Sensorkarten und laufend aktualisierte Diagramme sehen. Einen Sensor auswählen und den Zeitraum wechseln.
- Grenzwert: „Grenzwert überschreiten“ auswählen. Nach spätestens dem nächsten Messzyklus erscheint eine Warnung und ein Ereignis.
- Dauerhafte Störung: Einige Zyklen warten. Es entsteht kein neues Ereignis pro Messwert.
- Bestätigung: Im Ereignisprotokoll „Bestätigen“ klicken. Die Warnung bleibt aktiv, ist aber bestätigt.
- Erholung: Auf „Normalbetrieb“ wechseln. Bei passenden Grenzen wird das Ereignis beendet; die Historie bleibt erhalten.
- Verbindungsverlust: „Verbindung unterbrechen“ wählen. Nach 15–20 Sekunden steht der Sensor auf „Keine Verbindung“. Der zuletzt empfangene Wert bleibt sichtbar.
- Validierung: Eine Untergrenze größer als die Obergrenze eingeben. Speichern wird mit einer verständlichen Fehlermeldung abgelehnt.
- Persistenz: Anwendung stoppen und erneut starten. Grenzwerte und Ereignisse bleiben gespeichert. Auch der zuletzt gewählte Simulationsmodus bleibt erhalten.
Für C# eignet sich JetBrains Rider oder Visual Studio Code mit C# Dev Kit. SensorBoard.sln öffnet Backend und Tests als gemeinsame Solution. IntelliJ IDEA ist nicht die passende C#-IDE. Für den Start per Terminal ist keine IDE erforderlich.
dotnet test tests/SensorBoard.Tests.csprojDie Tests prüfen Grenzwerte, Vorrang des Verbindungsverlusts, idempotente Messwerte sowie Entstehung und Beendigung von Warnungen gegen eine relationale In-Memory-SQLite-Datenbank.
Mit laufender Anwendung kann zusätzlich der API-Test ausgeführt werden (Python 3 erforderlich). Er erzeugt Demo-Ereignisse und stellt die ursprünglichen Grenzen und den Modus wieder her:
python3 scripts/smoke_test.pyFür getrennte Entwicklung in zwei Terminals:
# Terminal 1, Projektstamm
dotnet run --project backend/SensorBoard.csproj -- --urls http://localhost:5080
# Terminal 2
cd frontend
npm ci
npm startDann http://localhost:4200 öffnen. Der Angular-Proxy leitet API und SignalR an das Backend weiter.
| Methode | Pfad | Zweck |
|---|---|---|
| GET | /api/health |
Erreichbarkeit |
| GET | /api/sensors |
Messwerte und aktueller Zustand |
| GET | /api/sensors/{id}/history?minutes=60 |
Aggregierte Historie |
| GET | /api/alerts |
Neueste 200 Ereignisse |
| PUT | /api/sensors/{id}/limits |
JSON: lower, upper |
| PUT | /api/sensors/{id}/mode |
JSON: mode: normal, high, offline |
| POST | /api/sensors/{id}/measurements |
JSON: eventId (UUID), value |
| POST | /api/alerts/{id}/acknowledge |
Ereignis bestätigen |
SignalR-Endpunkt: /hubs/live, Ereignisname: updated.
Diese Version ist eine lokal ausführbare Portfolio-Demo ohne Anmeldung oder Rollen. Alle Besucher einer Instanz teilen dieselben Daten und können Grenzen und Simulationsmodi ändern. Für öffentlichen Produktivbetrieb fehlen insbesondere Authentifizierung, Autorisierung, HTTPS-Konfiguration, Rate-Limits und ein Backup-Konzept. Kein Anschluss an echte Anlagen; keine sicherheitskritische Steuerung.
Messwerte werden sieben Tage aufbewahrt; Ereignisse bleiben gespeichert. Die API liefert maximal 200 Ereignisse. Die initiale Historie besteht aus synthetischen Werten. Die Aggregation reduziert die Antwortgröße, lädt in dieser Demo aber die Werte des gewählten Zeitraums zunächst ins Backend. Für große Anlagen wären SQL-Aggregation und eine abgestimmte Aufbewahrungsstrategie nächste Schritte.
