-
Notifications
You must be signed in to change notification settings - Fork 0
Software Konzept
Software Konzept:
- Deadline V1 12.03.2026, 12:00
- Deadline V2 19.03.2026, 12:00
- Deadline finale Version 30.04.2026, 18:00
[[TOC]]
ClimateCanary überwacht das Raumklima in Bürogebäuden über ein dreischichtiges IoT-System: Sensorstationen (Arduino) messen kontinuierlich und übertragen die Daten per BLE an einen Raspberry Pi pro Raum, der die Grenzwertlogik lokal ausführt und Daten datenschutzkonform an ein zentrales Spring Boot Backend weiterleitet. Nutzer sehen die Daten rollenabhängig in einer React-Webanwendung.
- ClimateCanary ist ein IoT-basiertes Monitoring-System, das Unternehmen eine kontinuierliche und automatisierte Überwachung des Raumklimas in Bürogebäuden ermöglicht.
- Das System erfasst Temperatur, Luftfeuchtigkeit, Luftdruck und Luftqualität in Echtzeit und stellt diese Daten rollenabhängig in einer zentralen Webanwendung dar.
- Kurzfristiges Ziel: Mitarbeiter:innen und Verwaltung sollen jederzeit informiert sein, wenn Raumklimawerte kritische Grenzwerte über- oder unterschreiten, und können entsprechend reagieren.
- Mittelfristiges Ziel: Langfristige Auswertungen der gesammelten Daten sollen als Entscheidungsgrundlage für gezielte Maßnahmen zur Raumklimaverbesserung dienen (z. B. Anschaffung von Klimaanlagen, Luftreinigern).
- Langfristiges Ziel (außerhalb des aktuellen Projektumfangs): Automatische Steuerung von Heizung, Jalousien und Fenstern auf Basis der gesammelten Klimadaten.
- Primäre Zielgruppe sind mittelständische bis große Unternehmen mit mehreren Büroräumen und Allgemeinflächen.
- Das System richtet sich an alle Mitarbeiter:innen eines Unternehmens, die das Raumklima an ihrem Arbeitsplatz überwachen möchten.
- Zusätzlich adressiert es Abteilungsleitungen, das höhere Management sowie die Gebäude- und Systemadministration, die das System konfigurieren und übergreifend auswerten.
- Mitarbeiter:in: Überwacht das Raumklima am eigenen Arbeitsplatz und in Allgemeinflächen der eigenen Abteilung. Verwaltet eigene Abwesenheiten.
- Abteilungsleitung: Erbt alle Rechte der Mitarbeiter:in. Erhält zusätzlich eine Übersicht aller Räume der eigenen Abteilung in reduzierter Datengranularität (Tagesdurchschnitte für Büroräume). Sieht Abwesenheiten der Mitarbeiter:innen.
- Geschäftsführung: Sieht firmenweite, aggregierte und anonymisierte Übersichten und Trendindikatoren. Kein Zugriff auf raumgenaue Daten.
- Hausverwalter: Sieht alle Raumklimadaten aller Räume, konfiguriert Grenzwerte und verwaltet Raumklima-Tipps. Kein Zugriff auf Userdaten oder Raumzuweisungen.
- Systemadministrator: Verwaltet Benutzer, Gebäudestruktur und Geräte (Raspberry Pis, Sensorstationen). Kein Zugriff auf Messdaten.
Wichtig: Hausverwalter und Systemadministrator sind strikt voneinander getrennt – diese Trennung ist der zentrale Datenschutzmechanismus des Systems. Der Hausverwalter sieht nie, welche User welchem Raum zugeordnet sind.
- Automatische Erfassung von Temperatur, Luftfeuchtigkeit, Luftdruck und Luftqualität durch Arduino-Sensorstationen (BME680/688 Sensor).
- Übertragung der Messdaten via Bluetooth Low Energy (BLE) an einen raumgebundenen Raspberry Pi. Das BLE-Protokoll (GATT-Profil) wird selbst definiert; nach der ersten erfolgreichen Verbindung koppelt sich der Arduino ausschließlich mit dem zugewiesenen Raspberry Pi.
- Lokal am Raspberry Pi: Grenzwertprüfung mit Noise-Filter (Hysterese/Zeitfenster), datenschutzkonforme Zwischenspeicherung in SQLite, Weiterleitung an den zentralen Webserver per REST.
- Visuelle Rückmeldung direkt an der Sensorstation: ampelartige RGB-LED mit den Kernfarben Türkis, Orange/Koralle und Rot sowie weiteren Farben bzw. Blinkmustern für spezielle Zustände; LCD-Display mit aktuellen Werten, Warnungen und Tipps.
- Zentrale Webanwendung (Spring Boot + React/TypeScript) mit rollenabhängigen Ansichten, Verlaufsdiagrammen, Grenzwertwarnungen und Konfigurationsoptionen.
- Datenschutzkonforme Datenhaltung: Bürodaten werden nur bei Mindestbelegung von 5 Personen persistent gespeichert. Transiente Verarbeitung am Raspberry Pi (z. B. für Grenzwertberechnung) ist immer erlaubt.
- Abwesenheitssystem zur Pflege von Urlaub, Krankheit etc., das automatisch die Datenschutzprüfung beeinflusst und den zuständigen Raspberry Pi benachrichtigt.

Das vollständige Use Case Diagramm befindet sich als separates PNG im Projekt Repo -Ordner (Datei: /docs/Softwarekonzept_Finalversion/Use Case Diagramm V2.png).
| Akteur | Typ | Beschreibung |
|---|---|---|
| Raumnutzer:in (vor Ort) | Mensch | Interagiert physisch mit der Sensorstation; kein Webapp-Zugang. |
| Mitarbeiter:in | Mensch | Basisrolle; Zugriff auf eigenes Büro (bei Mindestbelegung ≥ 5) und Allgemeinflächen der Abteilung. |
| Abteilungsleitung | Mensch | Erbt Rechte der Mitarbeiter:in; zusätzlich Abteilungsübersicht mit reduzierter Granularität. |
| Geschäftsführung | Mensch | Nur aggregierte, firmenweite Sicht; keine Raumdetails, keine Userdaten. |
| Hausverwalter | Mensch | Vollzugriff auf Raumklimadaten und Konfiguration; keine Nutzer-Raum-Zuordnungen oder Abwesenheiten sichtbar. |
| Systemadministrator | Mensch | Benutzer- und Geräteverwaltung; kein Zugriff auf Messdaten oder Grenzwertkonfiguration. |
| «system» Deployment | System | Legt beim ersten Start den ersten Systemadministrator an. |
| «system» Raspberry Pi | System | Empfängt Messdaten via BLE, prüft Grenzwerte, leitet Daten datenschutzkonform an die Webapp weiter. |
| «system» Sensorstation (Arduino) | System | Misst Raumklimaparameter und sendet diese via BLE an den zugewiesenen Raspberry Pi. |
| Akteur | Use Cases |
|---|---|
| Raumnutzer:in | Messwerte / Warnungen / Fehlerzustand am Display ablesen, Navigation (Buttons), Anzeigemodus wechseln, LED-Status ablesen |
| Mitarbeiter:in | Anmelden/Abmelden, aktuelle & historische Messungen eigenes Büro (nur bei Mindestbelegung ≥ 5), aktuelle & historische Messungen Allgemeinflächen, Echtzeitalarme lesen, eigene Abwesenheiten verwalten |
| Abteilungsleitung | Abteilungsübersicht (Raumvergleich, Verletzungshäufigkeit), historische Bürodaten (Tagesdurchschnitte), Grenzwertverletzungen der Abteilung einsehen, Abwesenheiten der Abteilung einsehen |
| Geschäftsführung | Unternehmensweites Dashboard, Trendindikatoren, anonymisierte Verletzungsstatistiken pro Abteilung |
| Hausverwalter | Alle Raumdaten einsehen (volle Granularität, ohne Nutzerzuordnung), Grenzwertverletzungen aller Räume, Grenzwerte konfigurieren, Verbesserungstipps verwalten, Geräteausfälle einsehen |
| Systemadministrator | Gebäude/Abteilungen/Räume verwalten, Raspberry Pis & Sensorstationen registrieren & zuweisen, Geräte konfigurieren, Benutzer verwalten, Rollen zuweisen (inkl. Abteilungsleiter:in ernennen), Geräteausfälle einsehen |
| «system» Deployment | Ersten Systemadmin anlegen |
| «system» Raspberry Pi | Konfigurationsänderungen empfangen, Messdaten empfangen & zwischenspeichern (BLE → SQLite), Grenzwertverletzungen prüfen & Warnungen auslösen, Messdaten an Webapp weiterleiten |
| «system» Sensorstation | Messdaten erfassen & an Raspberry Pi übertragen, Warnungen empfangen & anzeigen, Grenzwertüberschreitungen via LED signalisieren |
- Akteur: Mitarbeiter:in
- Vorbedingung: Nutzer:in ist eingeloggt und einem Büroraum zugeordnet.
-
Normalablauf:
- Nutzer:in öffnet die Raumansicht des eigenen Büros.
- Das System prüft die aktuelle Belegung des Raums anhand der eingetragenen Abwesenheiten: Es berechnet, wie viele dem Raum zugeordnete Personen aktuell nicht als abwesend erfasst sind. Diese Prüfung ist notwendig, da aus hochfrequenten Messdaten (Minutenwerte) Rückschlüsse auf das Verhalten einzelner Personen möglich wären – die Datenschutzanforderung legt daher fest, dass Bürodaten nur bei einer Mindestbelegung von 5 Personen angezeigt werden dürfen.
- Wenn die Belegung ≥ 5 Personen beträgt: Das System zeigt aktuelle Messwerte (Temperatur, Luftfeuchtigkeit, Luftqualität) an.
- Konfigurierte Grenzwerte sind als Referenzlinien sichtbar.
- Aktive Grenzwertwarnungen werden prominent angezeigt, inklusive Raumklima-Tipps.
-
Alternativablauf – Mindestbelegung nicht erfüllt:
- Das System erkennt, dass die aktuelle Belegung unter 5 Personen liegt (mindestens eine Person hat eine Abwesenheit eingetragen, sodass die Gesamtzahl anwesender Personen des Raums unter die Mindestgrenze fällt).
- Das System zeigt den Hinweis: „Keine Daten verfügbar – Datenschutzbedingungen nicht erfüllt."
- Es werden keine aktuellen Messdaten angezeigt.
-
Alternativablauf – Verbindungsausfall:
- Für einen bestimmten Zeitraum fehlen Messdaten (z. B. Raspberry Pi offline).
- Das System zeigt eine Meldung, dass die Sensorstation aktuell offline ist.
- Akteur: Mitarbeiter:in
- Vorbedingung: Nutzer:in ist eingeloggt und einem Büroraum zugeordnet.
-
Normalablauf:
- Nutzer:in navigiert zur Verlaufsansicht des eigenen Büros und wählt einen Zeitraum (Tag / Woche / Monat).
- Das System zeigt Verlaufsdiagramme (Temperatur, Luftfeuchtigkeit, Luftqualität) für den gewählten Zeitraum an.
- Konfigurierte Grenzwerte sind als Referenzlinien in den Diagrammen sichtbar.
- Zeitabschnitte, in denen die Mindestbelegung unterschritten war oder die Sensorstation offline war, werden als grau hinterlegte Lücken markiert („Daten nicht verfügbar").
- Hinweis: Es werden nur Messdaten angezeigt, die zum Zeitpunkt der Erfassung unter datenschutzkonformen Bedingungen (Mindestbelegung ≥ 5) persistent gespeichert wurden. Zeiträume ohne persistente Daten erscheinen als Lücken.
- Akteur: Mitarbeiter:in
- Vorbedingung: Nutzer:in ist eingeloggt und einem Büroraum zugeordnet.
-
Normalablauf:
- Nutzer:in öffnet die Übersicht der Grenzwertverletzungen des eigenen Büros.
- Das System zeigt eine Liste aktiver und vergangener Grenzwertverletzungen des Raums an (Zeitpunkt, Metrik, Wert, Status:
ACTIVE/RESOLVED/DISABLED). - Nutzer:in kann eine Verletzung auswählen, um Details (betroffene Messgröße, Dauer, Verlauf) einzusehen.
- Akteur: Mitarbeiter:in, Abteilungsleitung
- Vorbedingung: Nutzer:in ist eingeloggt und einer Abteilung zugeordnet.
-
Normalablauf:
- Nutzer:in wählt eine Allgemeinfläche (Konferenzraum, Aufenthaltsraum etc.) der eigenen Abteilung aus.
- Das System zeigt aktuelle Messwerte und Verlaufsdiagramme in voller Granularität an.
- Es gelten keine Datenschutzeinschränkungen – die Daten sind immer verfügbar.
- Akteur: Abteilungsleitung
- Vorbedingung: Nutzer:in ist als Abteilungsleitung eingeloggt.
-
Normalablauf:
- Die Abteilungsleitung öffnet die Abteilungsübersicht.
- Das System zeigt eine vergleichende Darstellung aller Räume der Abteilung (aktuelle Messwerte, Anzahl aktiver Warnungen).
- Für Büroräume, deren aktuelle Belegung ≥ 5 beträgt, werden Verlaufsansichten in reduzierter Granularität (Tagesdurchschnitte) angezeigt. Die reduzierte Granularität ist eine bewusste Datenschutzentscheidung: Tagesdurchschnitte verhindern, dass aus Minutenwerten Rückschlüsse auf das Verhalten einzelner Personen gezogen werden können.
- Für Allgemeinflächen werden Verlaufsansichten in voller Granularität angezeigt.
- Aktive und vergangene Grenzwertverletzungen auf Raumebene sind einsehbar.
- Die Abteilungsleitung sieht Abwesenheiten der Mitarbeiter:innen ihrer Abteilung (ohne Zuordnung von Personen zu Räumen – diese Information ist ausschließlich dem Systemadmin zugänglich).
- Akteur: Raspberry Pi (technisch), Mitarbeiter:in / Abteilungsleitung (sichtbar)
- Vorbedingung: Grenzwerte sind für den betroffenen Raum konfiguriert. Die Sensorstation ist aktiv und mit dem Raspberry Pi verbunden.
-
Normalablauf:
- Der Raspberry Pi empfängt Messdaten von der Sensorstation via BLE.
- Der Raspberry Pi prüft die Messwerte gegen konfigurierte Grenzwerte mit Noise-Filter: Eine Warnung wird erst ausgelöst, wenn der Grenzwert über fünf Minuten überschritten wird. Einzelne Ausreißer (kurzes Öffnen eines Fensters, Atemstoß auf den Sensor) lösen keine Warnung aus.
- Bei bestätigter Grenzwertüberschreitung setzt der Raspberry Pi den Warnstatus, übermittelt diesen an die Sensorstation (via BLE) und sendet einen
POST /api/cpi/{piId}/violationan das Backend der Webapp (via REST – der Raspberry Pi agiert dabei als REST-Client). - An der Sensorstation wechselt die LED auf Rot, das Display zeigt den Warnmodus mit Hinweis und Tipp.
- In der Webapp wird die Warnung prominent für alle Nutzer:innen des betroffenen Raums angezeigt (z. B. als farblich hervorgehobenes Banner), inklusive konfigurierter Raumklima-Tipps.
- Die Abteilungsleitung sieht die Warnung in der Abteilungsübersicht.
- Alternativablauf – Warnung aufheben: Warnungen können entweder manuell aufgehoben werden oder automatisch, wenn die Messwerte wieder in den Normalbereich zurückkehren.
Manuelles Aufheben
- User hebt die Warnung im Frontend auf.
- Backend schickt schickt mit POST eine ViolationResolvedDTO an /api/spi/{piId}/violation/resolve auf den Raspberry.
- Basierend auf der DTO deaktiviert der Raspberry die betroffenen Violation, informiert den Arduino und updated seine eigene Datenbank (gleiche Logik wie bei automatischer Deaktivierung der Grenzwertwarnung)
Automatisches Aufheben
- Die Messwerte kehren dauerhaft in den Normalbereich zurück.
- Der Raspberry Pi hebt den Warnstatus auf und informiert Sensorstation und Webapp.
- Die LED wechselt auf Türkis, die Warnmeldung in der Webapp verschwindet. Die vergangene Verletzung bleibt historisch gespeichert (
violationStatus = RESOLVED).
- Designentscheidung: Die Länge des Zeitfensters für die Durchschnittsberechnung beträgt 5min.
- Akteur: Hausverwalter
- Vorbedingung: Nutzer:in ist als Hausverwalter eingeloggt. Raum und Sensorstation sind im System angelegt.
-
Normalablauf:
- Der Hausverwalter öffnet die Konfigurationsansicht eines Raums.
- Die Admin-Person setzt oder ändert obere Grenzwerte für Temperatur, Luftfeuchtigkeit, Luftdruck und Luftqualität. Untere Grenzwerte sind optional.
- Das System speichert die neuen Grenzwerte in der PostgreSQL-Datenbank.
- Der zuständige Raspberry Pi wird vom Backend per
POST/api/spi/{piId}/config/thresholds über Grenzwertänderungen informiert. - Der Raspberry Pi speichert die neuen Grenzwerte lokal in der SQLite-Datenbank und wendet sie ab der nächsten Messung an.
- Akteur: Mitarbeiter:in
- Vorbedingung: Nutzer:in ist eingeloggt und einem Büroraum zugeordnet.
-
Normalablauf:
- Mitarbeiter:in trägt eine Abwesenheit (Urlaub, Krankheit etc.) stunden- oder tageweise ein.
- Das System speichert die neue Abwesenheit in der Datenbank.
- Ein gescheduledter Ablauf wird alle 5 Minuten ausgeführt.
- Der Ablauf fragt die relevanten Datenbankeinträge ab.
- Das System prüft anhand der Datenbankeinträge, ob durch Abwesenheiten die Mindestbelegung (5 Personen) in einem Büroraum unterschritten wird.
- Der Ablauf informiert alle Raspberry Pis darüber, ob der PrivacyMode aktualisiert werden muss über Endpunkt /api/spi/{piId}/occupancy.
- Wenn die Mindestbelegung unterschritten wird, aktiviert der betroffene Raspberry Pi den PrivacyMode und persistiert ab diesem Zeitpunkt keine Messdaten mehr.
- Wenn die Mindestbelegung nicht unterschritten wird, bleibt das Datenspeicherverhalten unverändert.
- Akteur: Systemadministrator
- Vorbedingung: Nutzer:in ist als Systemadministrator eingeloggt. Die Gebäudestruktur (Gebäude, Abteilungen, Räume) ist bereits im System angelegt. Der physische Raspberry Pi ist aufgestellt und hat eine SD-Karte.
-
Normalablauf:
- Der Systemadministrator öffnet die Geräteverwaltung in der Webapp und wählt „Neuen Raspberry Pi registrieren".
- Das Backend speichert die vom User definierten Infos in einem neuen RaspberryPiDTO und setzt den Status auf
OFFLINE. - Das Backend bereitet dem Systemadmin eine
config.yaml-Datei vor, die alle relevanten Setup-Infos für den Raspberry Pi enthält, und ermöglicht deren Download. - Der Systemadministrator kopiert die
config.yamlauf die SD-Karte des RPI. - Der RPI updated seine Infos mit Hilfe der Infos aus der
config.yaml. - Der RPI sendet eine
POST /api/cpi/{piId}/booted-Request an das Backend, dessen URL er auch aus derconfig.yamlentnimmt. - Das Backend lernt durch diese Request die IP des RPI kennen und updated das RPI-Objekt.
- Der Systemadministrator klickt den
check for connection-Button neben dem RPI, der ihm auf der Benutzeroberfläche angezeigt wird, und das RPI erscheint als connected.
-
Alternativablauf – Raum bereits belegt:
- Versucht der Systemadministrator, einen Raum zuzuordnen, dem bereits ein aktiver Raspberry Pi zugewiesen ist, zeigt das System eine Fehlermeldung: „Diesem Raum ist bereits ein Raspberry Pi zugeordnet."
- Der Systemadministrator kann den bestehenden Raspberry Pi zuerst aus dem Raum entfernen oder einen anderen Raum auswählen.
-
Alternativablauf – Raspberry Pi bleibt offline:
- Falls der Raspberry Pi nach der Registrierung keinen Kontakt mit dem Backend aufnimmt (z. B. Netzwerkproblem, falsche IP,
conf.yamlnoch nicht aktualisiert), bleibt der Status aufOFFLINE. - Der Systemadministrator sieht den Status in der Geräteverwaltung und kann die Konfiguration prüfen.
- Falls der Raspberry Pi nach der Registrierung keinen Kontakt mit dem Backend aufnimmt (z. B. Netzwerkproblem, falsche IP,
- Akteur: Systemadministrator
-
Vorbedingung:
Die Nutzerin bzw. der Nutzer ist als Systemadministrator eingeloggt. Der Ziel-Raspberry-Pi ist bereits registriert, einem Raum zugeordnet und hat den StatusONLINEoderOFFLINE. Der physische Arduino ist mit Strom versorgt und sendet BLE-Advertising-Pakete.
- Der Systemadministrator öffnet die Geräteverwaltung und wählt „Neue Sensorstation registrieren“ aus.
- Das Frontend sendet eine
POST-Request an/api/sensorstation/findan das Backend. Das Backend leitet die Anfrage über einePOST-Request an/api/spi/{piId}/scanan den Raspberry-Pi weiter. - Der Raspberry-Pi scannt per BLE nach möglichen Verbindungspartnern, die den
deviceSetupServiceadvertisen. - Alle Sensorstationen besitzen initial denselben Namen, denselben advertised Service und dieselben Herstellerinformationen. Sie unterscheiden sich zunächst nur durch ihre Bluetooth-Adressen, die beim erstmaligen Setup als Identifikator dienen.
- Die Sensorstationen zeigen ihre Bluetooth-Adressen auf dem Display an. Gleichzeitig sendet der Raspberry-Pi eine
POST-Request an/api/cpi/{piId}/discoveredan das Backend. Diese enthält die BLE-MAC-Adressen aller potenziellen Verbindungspartner. - Das Backend erstellt temporäre Sensorstation-Objekte mit dem Status
AVAILABLEund weist diese dem aktuellen Raspberry-Pi zu. - Der Systemadministrator klickt auf den Button „Check for available sensor stations“. Dadurch wird eine
GET-Request an/api/bpi/{id}/availablesensorstationsausgelöst. Die Antwort enthält alle verfügbaren Sensorstationen. - Der Systemadministrator wählt aus, mit welcher Station er sich verbinden möchte, und füllt alle relevanten Daten aus.
- Der Systemadministrator klickt auf den Button „Verbinden“. Dadurch wird eine
POST-Request an/api/sensorstationmit einemSensorStationCreateDTOausgelöst. - Das Backend empfängt diese Request, erstellt die Sensorstation dauerhaft und löst anschließend eine
POST-Request an/api/spi/{piId}/stationsaus. - Der Raspberry-Pi baut nun eine BLE-Verbindung zu der durch das
SensorStationDTOspezifizierten Sensorstation auf. - Im Zuge der Erstverbindung beschreibt der Raspberry-Pi die Characteristic
deviceSetupCharacteristicmit seiner Identität alsTrustedRpiIdund demMeasurementInterval. Diese Informationen werden persistent auf der Sensorstation gespeichert und dienen weiterhin der Ausfallsicherheit und Authentifizierung. - Die Sensorstation rebootet und beginnt anschließend, den
environmentalSensingServicezu advertisen. - Der Raspberry-Pi verbindet sich erneut mit der Sensorstation und schreibt seine eigene ID sowie den Raumnamen in die
warningAuthCharacteristic. - Die Sensorstation überprüft, ob die ID mit der gespeicherten
TrustedRpiIdübereinstimmt, und authentifiziert die Verbindung für den Datenaustausch. - Der Raspberry-Pi abonniert die
sensorDataCharacteristicund sendet nach dem ersten empfangenen Datenpaket einePATCH-Request an/api/cpi/{piId}/{sensorStationId}, um den Status der Sensorstation aufCONNECTEDzu aktualisieren. - Der Systemadministrator klickt auf „Check connection“. Dadurch wird eine
GET-Request an/api/bpi/{id}ausgelöst, die alle Sensorstationen zurückgibt, die mit dem aktuellen Raspberry-Pi verbunden sind. - Der Systemadministrator sieht bei der soeben registrierten Sensorstation den Status
CONNECTED.
- Falls der Raspberry-Pi nach dem Start des Registrierungsvorgangs kein passendes BLE-Advertising-Paket empfängt, beispielsweise weil der Arduino nicht eingeschaltet ist oder sich außerhalb der Reichweite befindet, scannt der Raspberry-Pi für einen begrenzten Zeitraum weiter.
- Wird auch nach längerem Scannen keine Sensorstation gefunden, protokolliert der Raspberry-Pi einen
WARN-Eintrag. - Sobald das Problem behoben ist, kann der Scanvorgang erneut gestartet werden, damit die neue Sensorstation wie vorgesehen eingebunden werden kann.
- Erkennt der Raspberry-Pi beim Scan eine Sensorstation, deren advertised Service UUID nicht der erwarteten UUID entspricht, ignoriert er diese Sensorstation.
- Soll die Sensorstation einem anderen Raspberry-Pi zugeordnet werden, muss entweder die Firmware neu geflasht oder ein Reset ausgelöst werden, indem alle drei Knöpfe gleichzeitig gedrückt werden. Dadurch werden
TrustedRpiIdundMeasurementIntervalzurückgesetzt.
- Falls der Raspberry-Pi keine BLE-Verbindung zur ausgewählten Sensorstation aufbauen kann, sendet er eine
PATCH-Request an das Backend via/api/cpi/{piId}/{sensorStationId}. - Dabei wird der Status der Sensorstation auf
CONNECTION_FAILEDgesetzt. - Das Frontend kann diesen Status beim nächsten Abruf über
/api/bpi/{id}anzeigen.
- Falls die BLE-Verbindung erfolgreich aufgebaut wurde, das Schreiben der Setup-Daten in die
deviceSetupCharacteristicjedoch fehlschlägt, trennt der Raspberry-Pi die Verbindung zur Sensorstation. - Anschließend sendet der Raspberry-Pi eine
PATCH-Request an/api/cpi/{piId}/{sensorStationId}. - Dabei wird der Status der Sensorstation auf
CONNECTION_FAILEDgesetzt. - Das Frontend kann diesen Status beim nächsten Abruf über
/api/bpi/{id}anzeigen.
Da alle Sensorstationen mit demselben Firmware-Stand betrieben werden, entfällt das individuelle Flashen pro Gerät. Die Exklusivität der BLE-Verbindung wird stattdessen über die Characteristic deviceSetupCharacteristic sichergestellt. Diese wird beim ersten erfolgreichen Verbindungsaufbau durch den Raspberry-Pi mit TrustedRpiId und MeasurementInterval beschrieben und anschließend persistent auf dem Arduino gespeichert.
Dadurch wird verhindert, dass sich fremde Raspberry-Pis, beispielsweise aus anderen Teams oder Testumgebungen, versehentlich mit einer bereits zugeordneten Sensorstation verbinden. Gleichzeitig werden ungewollte Reconnects oder fehlerhafte Neu-Zuordnungen nach einem Neustart vermieden.

Das vollständige Klassendiagramm befindet sich als PNG im Projekt Repo (Datei: /docs/Softwarekonzept_Finalversion/climate-canary-webapp-backend.png).
-
ViolationStatus – Enum:
ACTIVE,RESOLVED,DISABLED -
UserxRole – Enum:
SYSTEM_ADMIN,BUILDING_ADMIN,DEPARTMENT_LEAD,MANAGEMENT,EMPLOYEE -
AbsenceType – Enum:
HOLIDAY,SICKNESS,PARENTAL_LEAVE,OTHER -
AbsenceStatus – Enum:
PLANNED,APPROVED,REJECTED,CANCELLED -
RoomType – Enum:
OFFICE,COMMON_AREAS -
DeviceStatus – Enum:
ONLINE,OFFLINE,MAINTENANCE,DEGRADED,DECOMMISSIONED,AVAILABLE,CONNECTED,CONNECTION_FAILED -
Metric – Enum:
TEMPERATURE,HUMIDITY,PRESSURE,IAQ -
ThresholdType – Enum:
LOWER,UPPER -
Userx – Repräsentiert einen Systembenutzer.
Attribute:id: Long,username: String,password: String,firstName: String,lastName: String,email: String,phone: String,roles: Set<UserxRole>,enabled: boolean,createDate: LocalDateTime,updateDate: LocalDateTime
Assoziationen: hat mehrere Abwesenheiten, kann genau ein EmployeeProfile besitzen und kann als Department Lead einer oder mehreren Abteilungen zugeordnet sein. Zusätzlich kann ein User alscreateUseroderupdateUserandere Userx-Objekte referenzieren. -
EmployeeProfile – Repräsentiert das Mitarbeiterprofil eines Users.
Attribute:id: Long
Assoziationen: referenziert genau einen Userx, eine Department und einen Room. -
Absence – Repräsentiert eine Abwesenheit eines Users.
Attribute:id: Long,startDate: LocalDateTime,endDate: LocalDateTime,absenceType: AbsenceType,absenceStatus: AbsenceStatus
Assoziationen: referenziert genau einen Userx. -
Building – Repräsentiert ein Gebäude.
Attribute:id: Long,name: String
Assoziationen: hat genau eine Address und kann mehrere Rooms besitzen. -
Address – Repräsentiert eine Adresse.
Attribute:id: Long,country: String,zipCode: String,city: String,street: String,houseNumber: String,extra: String -
Department – Repräsentiert eine Abteilung.
Attribute:id: Long,name: String
Assoziationen: kann von einem Userx geleitet werden und wird von mehreren EmployeeProfiles und Räumen referenziert. -
Room – Repräsentiert einen Raum.
Attribute:id: Long,name: String,roomType: RoomType,privacyMode: Boolean,active: boolean
privacyModedefiniert, ob Messwerte gespeichert werden dürfen.
Assoziationen: gehört zu einer Department und einem Building, kann maximal einen Raspberry Pi haben und wird von EmployeeProfiles, SensorStations, Measurements, Thresholds und ThresholdViolations referenziert. -
RaspberryPi – Repräsentiert einen Raspberry Pi.
Attribute:id: Long,hostName: String,ipAddress: String,deviceStatus: DeviceStatus
Assoziationen: ist genau einem Room zugeordnet und verwaltet mehrere SensorStations. -
SensorStation – Repräsentiert eine Sensorstation.
Attribute:id: Long,name: String,deviceStatus: DeviceStatus,measurementInterval: Integer,bleMac: String
Assoziationen: gehört zu genau einem RaspberryPi, ist genau einem Room zugeordnet und wird von Measurements referenziert. -
Measurement – Repräsentiert einen einzelnen Messdatenpunkt.
Attribute:id: Long,timestamp: LocalDateTime,measurement: Float,metric: Metric
Assoziationen: gehört zu genau einer SensorStation, ist genau einem Room zugeordnet und kann von einer oder mehreren ThresholdViolations referenziert werden.
Wird nur bei erfüllter Datenschutzbedingung persistent gespeichert. -
Threshold – Repräsentiert Grenzwerte für einen Raum pro Messgröße.
Attribute:id: Long,metric: Metric,enabled: boolean,boundValue: Float,thresholdType: ThresholdType
Assoziationen: gehört zu genau einem Room, kann von mehreren ThresholdViolations referenziert werden und kann mit einem oder mehreren ClimateHints verknüpft sein. -
ThresholdViolation – Repräsentiert eine aktive oder historische Grenzwertverletzung.
Attribute:id: Long,metric: Metric,value: Float,violationStatus: ViolationStatus,startTime: LocalDateTime,endTime: LocalDateTime
endTimeistnull, solange die Verletzung aktiv ist.
Assoziationen: referenziert genau einen Room, genau einen Threshold und eine oder mehrere Measurements.
Designentscheidung: Mehrere Measurements müssen herangezogen werden, um kurze Extremwerte zu filtern. Eine Verletzung wird erst bestätigt, wenn 5 Minuten lang die Messungen den Grenzwert überschreiten. -
ClimateHint – Repräsentiert einen Raumklima-Tipp.
Attribute:id: Long,metric: Metric,hintText: String
Wird bei Grenzwertverletzungen auf dem LCD-Display der Sensorstation und in der Webapp angezeigt.
Assoziationen: wird von einem oder mehreren Thresholds referenziert.
-
Userx1--*Absence: Ein User kann mehrere Abwesenheiten haben. -
Userx1--0..1EmployeeProfile: Ein User kann genau ein EmployeeProfile besitzen. -
Department1--*EmployeeProfile: Eine Abteilung hat mehrere EmployeeProfiles. -
Room1--*EmployeeProfile: Ein Raum kann mehreren EmployeeProfiles zugeordnet sein. -
Department1--*Room: Eine Abteilung hat mehrere Räume. -
Building1--*Room: Ein Gebäude kann mehrere Räume besitzen. -
Department*--0..1Userx: Eine Abteilung kann genau einen Department Lead haben; ein User kann mehrere Departments leiten. -
Room1--0..1RaspberryPi: Ein Raum hat maximal einen Raspberry Pi. -
RaspberryPi1--*SensorStation: Ein Raspberry Pi kann mehrere SensorStations verwalten. -
SensorStation1--*Measurement: Eine SensorStation produziert viele Messdaten. -
Room1--*Measurement: Ein Raum hat viele Messdaten. -
Room1--*Threshold: Ein Raum hat Grenzwerte pro Messgröße. -
Threshold1--*ThresholdViolation: Ein Grenzwert kann mehrfach verletzt werden. -
Room1--*ThresholdViolation: Eine Grenzwertverletzung gehört zu genau einem Raum. -
Measurement*--*ThresholdViolation: Mehrere Measurements können eine Verletzung belegen. -
Threshold*--*ClimateHint: Grenzwerte können mit einem oder mehreren Hinweisen verknüpft sein. -
Building1--1Address: Ein Gebäude hat genau eine Adresse.
- Wird ein User gelöscht, werden seine Abwesenheiten ebenfalls gelöscht (
CASCADE). - Wird eine Sensorstation gelöscht, bleiben ihre bereits persistent gespeicherten Messdaten erhalten – Messdaten gelten als raumhistorische Daten und sind von der Existenz der Sensorstation entkoppelt. Die
roomId-Referenz inThresholdViolationbleibt ebenfalls bestehen. - Wird ein Raum gelöscht, werden alle zugehörigen Messdaten, Grenzwerte und Grenzwertverletzungen gelöscht (
CASCADE). - Wird ein Raspberry Pi aus einem Raum entfernt oder gelöscht, bleiben historische Messdaten und Grenzwertverletzungen erhalten (Referenz über
roomId); der Raspberry-Pi-Eintrag bleibt im System, bis er explizit gelöscht wird. - Messdaten, die aufgrund der Datenschutzbedingung (Mindestbelegung unterschritten) nie persistent gespeichert wurden, existieren nicht persistent und müssen daher nicht gelöscht werden.
Teil Konzept V2, Deadline 19.03.2026, 12:00
In diesem Abschnitt wird die Laufzeitsicht des Systems dokumentiert, also die Abläufe und Beziehungen zwischen den einzelnen Komponenten zur Laufzeit. Neben den geforderten Mindestabläufen werden auch weitere relevante Abläufe modelliert, um zentrale Designentscheidungen und Kommunikationswege im System sichtbar zu machen.
Folgende Sequenzdiagramme werden in diesem Abschnitt dokumentiert:
- Sequenzdiagramm – Allgemeiner Messzyklus (Overview)
- Sequenzdiagramm – Grenzwertverletzung des gesamten Systems
- Sequenzdiagramm – Belegungs-Mindestgrenze
- Sequenzdiagramm – Verbindungsaufbau und -konfiguration zwischen Arduino, Raspberry Pi und Webapp
Das folgende Diagramm zeigt den typischen Ablauf eines Messzyklus im System – von der Messung auf der Sensorstation (Arduino) über die Verarbeitung am Raspberry Pi bis zur Speicherung im Backend und der Darstellung in der Webanwendung.
Der Ablauf umfasst:
- periodische Messung von Temperatur, Luftfeuchtigkeit und Luftqualität
- Übertragung der Messdaten via BLE an den Raspberry Pi
- Grenzwertprüfung und lokale Verarbeitung
- Übermittlung relevanter Daten an das Backend
- Darstellung der Messwerte und Warnungen in der Webapp

Das vollständige Diagramm befindet sich als PNG im Projekt Repo (Datei: /docs/Softwarekonzept_Finalversion/normalbetrieb.png).
Das folgende Sequenzdiagramm zeigt, was passiert, wenn ein Klimawert in einem Büroraum einen festgelegten Grenzwert überschreitet – beispielsweise wenn die Temperatur zu hoch oder die Luftqualität zu schlecht wird. Es beschreibt den gesamten Ablauf: von der ersten Erkennung auf dem Raspberry Pi über die Meldung ans Backend bis hin zur Anzeige im Frontend und der Aufhebung der Warnung.
Der Ablauf gliedert sich in fünf Phasen:
- Konfiguration beim Start: Der Raspberry Pi lädt beim Hochfahren die konfigurierten Grenzwerte – also die erlaubten Ober- und Untergrenzen für jeden Messwert. Falls noch keine Werte in der lokalen Datenbank vorhanden sind, werden Standardwerte verwendet. Das Backend kann die Grenzwerte jederzeit aktualisieren.
- Laufender Messbetrieb: Die Sensorstation misst kontinuierlich Temperatur, Luftfeuchtigkeit, Luftdruck und Luftqualität (IAQ) und sendet die Daten per Funk (BLE) an den Raspberry Pi. Dieser speichert die Werte lokal und prüft regelmäßig, ob der Durchschnitt der letzten fünf Minuten einen Grenzwert verletzt. Gleichzeitig wird der aktuelle Zustand an die Sensorstation zurückgemeldet, sodass die LED-Anzeige stets den aktuellen Status widerspiegelt.
- Grenzwertverletzung erkannt: Wird eine Überschreitung festgestellt und liegt für diesen Messwert noch keine offene Warnung vor, wird ein Warnungseintrag erzeugt und ans Backend gemeldet. Zusätzlich sendet der Raspberry Pi einen Warnhinweis (ClimateHint) an die Sensorstation – diese zeigt den Text auf dem Display an und schaltet die LED auf Rot.
- Automatische Auflösung: Sobald der betroffene Messwert wieder dauerhaft im normalen Bereich liegt, wird die Warnung automatisch aufgehoben. Backend und Sensorstation werden informiert, die LED wechselt zurück auf Türkis.
- Manuelle Quittierung: Ein Benutzer kann eine aktive Warnung im Dashboard manuell quittieren. Das System informiert daraufhin den Raspberry Pi und die Sensorstation – die LED wechselt auf Dunkelrot/Violett als Bestätigung der Kenntnisnahme.

Das vollständige Diagramm befindet sich als PNG im Projekt Repo (Datei: /docs/Softwarekonzept_Finalversion/sequenz_diagram_threshold_violation.png).
Das folgende Sequenzdiagramm beschreibt, was passiert, wenn in einem Büroraum zu wenige Personen anwesend sind, um Klimadaten datenschutzkonform zu erheben und zu speichern. Es zeigt den gesamten Ablauf – von der Erkennung der Unterschreitung über das eingeschränkte Systemverhalten bis zur Rückkehr in den normalen Betrieb.
Der Ablauf gliedert sich in vier Phasen:
- Start und Erstkonfiguration: Beim Hochfahren holt sich der Raspberry Pi die aktuelle Konfiguration vom Backend – darunter auch, ob der Datenschutzmodus aktiviert sein soll.
- Belegungsänderung: Wenn sich die Anwesenheit im Raum ändert – zum Beispiel durch das Eintragen einer Abwesenheit oder das Entfernen einer Person aus dem Raum – berechnet das Backend die aktuelle Belegung neu. Liegt diese unterhalb der festgelegten Mindestgrenze, wird der Raspberry Pi informiert und schaltet in den Datenschutzmodus.
- Betrieb im Datenschutzmodus: Solange zu wenige Personen anwesend sind, werden keine Messdaten gespeichert und nicht ans Backend weitergeleitet. Die Sensorstation misst und prüft dennoch weiterhin, ob Grenzwerte überschritten werden – bei einer Überschreitung wird lokal gewarnt (LED und Display), aber kein Ereignis ans Backend gemeldet. Das Dashboard zeigt für diesen Raum keine Daten an.
- Rückkehr in den Normalbetrieb: Sobald wieder genügend Personen im Raum sind, hebt das Backend den Datenschutzmodus auf und informiert den Raspberry Pi. Dieser speichert Messdaten wieder lokal und übermittelt sie ans Backend. Das Dashboard steht anschließend wieder zur Verfügung – die Zeit ohne Daten wird dabei als Lücke kenntlich gemacht.

Das vollständige Diagramm befindet sich als PNG im Projekt Repo (Datei: /docs/Softwarekonzept_Finalversion/sequenz_diagramm_mindestbelegung.png).
Das folgende Sequenzdiagramm beschreibt den Ablauf, bei dem ein Systemadministrator einen Raspberry Pi und eine Sensorstation erstmals im System registriert und einen diese miteinander verbindet. Der genaue Ablauf wird außerdem in UC-10 beschrieben.

Das vollständige Diagramm befindet sich als PNG im Projekt Repo (Datei: /docs/Softwarekonzept_Finalversion/setup_sequence_diagram.png).
- Fehlerbehandlung - GlobalExceptionHandler: Zur zentralen Behandlung aller auftretenden Fehler wird im Projekt ein GlobalExceptionHandler eingesetzt. Dieser fängt sämtliche Exceptions ab und verarbeitet sie einheitlich. Die Fehler werden dabei in verschiedene Kategorien eingeteilt: NotFoundException (404), ConflictException (409) sowie Bad Request-Fehler (400), insbesondere IllegalArgumentException und IllegalStateException. Zusätzlich wird die AuthorizationDeniedException als Forbidden (403) behandelt. Darüber hinaus überwacht der GlobalExceptionHandler auch MethodArgumentNotValidException. Tritt eine Verletzung der Jakarta-Validation auf, wird eine strukturierte Map mit den entsprechenden Validierungsfehlern zurückgegeben. Für unvorhersehbare Fehler existiert außerdem eine generische Fallback-Exception, um auch nicht explizit behandelte Ausnahmen sauber abzufangen. Alle Exceptions basieren auf einem einheitlichen ApiErrorResponse-DTO, das Felder wie path, timestamp, error code und error message enthält. Diese Designentscheidung ermöglicht es, Fehler in größere Kategorien zu bündeln, wodurch das Exception-Handling übersichtlich und skalierbar bleibt, ohne eine Vielzahl einzelner Exception-Klassen pflegen zu müssen.
- Role-Based Access Endpoints: Alle Basis-Endpunkte unter /api/** sind auf der ersten Ebene geschützt, d. h. ein Zugriff ist nur für authentifizierte Nutzer möglich. Darauf aufbauend erfolgt die Autorisierung rollenbasiert: Benutzer können ausschließlich auf die Endpunkte zugreifen, für die sie die entsprechenden Berechtigungen besitzen. Beispielsweise haben System-Administratoren vollständigen Zugriff auf alle Endpunkte sowie exklusiven Zugriff auf spezielle Admin-Endpunkte. User-Self-Endpunkte hingegen sind strikt auf den jeweils aktuell im AuthenticationContext authentifizierten Benutzer beschränkt, sodass Nutzer nur auf ihre eigenen Ressourcen zugreifen können. Die Zuordnung der erforderlichen Rollen zu einzelnen Endpunkten orientiert sich an den fachlichen Anforderungen und kann aus dem Use-Case-Diagramm abgeleitet werden.
Die vollständige Dokumentation aller REST-API-Schnittstellen, die im System verwendet werden, ist in der Wiki-Page REST-Spezifikation bzw. in der Datei REST-Spezifikation dokumentiert.
Problem: Messdaten von Büroräumen dürfen nur persistent gespeichert und an das Backend weitergeleitet werden, wenn mindestens 5 Personen anwesend sind. Die Logik muss klar zwischen transienter Verarbeitung (immer erlaubt) und persistenter Speicherung (nur bei ausreichender Belegung) unterscheiden.
Die aktuelle Belegung eines Raums wird vom Backend berechnet als:
aktuelle Belegung = Gesamtanzahl zugeordneter User
− Anzahl User mit aktiver Abwesenheit
Eine Abwesenheit gilt als aktiv, wenn absenceStatus = APPROVED und das aktuelle Datum im Intervall [startDate, endDate] liegt.
Fällt die berechnete Belegung unter den konfigurierten Schwellwert minOccupancy (Standard: 5 für RoomType.OFFICE), sendet das Backend eine Request an den RPI, um die Konfiguration zu aktualisieren (Daten werden dann nicht mehr persistent gespeichert).
Die Belegungsberechnung erfolgt ausschließlich im Backend als Single Source of Truth. Der Raspberry Pi führt keine eigene Belegungslogik durch – er reagiert ausschließlich auf die vom Backend kommunizierten Informationen. Das vermeidet Inkonsistenzen bei gleichzeitigen Abwesenheitsänderungen mehrerer User.
Ändert sich die Belegungssituation eines Raums (d. h. privacyMode wechselt seinen Wert), wird der RPI per POST /api/spi/{piId}/occupancy vom Backend über die relevante Änderung informiert. Die globale Variable privacy_mode im RP wird entsprechend gesetzt.
Da ein Raspberry Pi einem konkreten Raum zugeordnet ist und mehrere Sensorstationen verwalten kann, werden Änderungen an der Persistierung der Messwerte auf alle eingehenden Sensordaten des jeweiligen Raums angewendet. Es werden also entweder alle oder keine Daten persistiert.
Wechselt ein Raum in den Zustand aktuelle Belegung < 5, wird der Privacy Mode im RPI durch einen POST aktiviert. Dann gilt Folgendes für alle Sensorstationen dieses Raums:
- Messdaten werden weiterhin von den Sensorstationen empfangen und transient im Arbeitsspeicher gehalten.
- Es werden keine Messdaten in SQLite geschrieben.
- Es werden keine Messdaten an das Backend übermittelt.
- Grenzwertprüfungen sowie lokale LED- und Display-Warnungen an der Sensorstation laufen unverändert weiter – der Datenschutz betrifft ausschließlich die Persistierung, nicht die Echtzeitanzeige vor Ort.
Kehrt die Belegung über den Schwellwert zurück, verlässt der Raspberry Pi den Privacy Mode und nimmt die normale Speicher- und Übertragungslogik wieder auf.
Für Räume vom Typ RoomType.COMMON_AREA gilt der Privacy Mode nie. Allgemeinflächen (Konferenzräume, Aufenthaltsräume etc.) werden unabhängig von ihrer Belegung immer gespeichert und weitergeleitet.
Problem: Wenn der Raspberry Pi nach einem Backend-Ausfall gepufferte Messdaten nachträglich überträgt, könnten Duplikate entstehen (z. B. wenn eine Übertragung halb ankam und wiederholt wird).
Lösungsansatz:
- Jeder
Measurement-Datensatz erhält einentimestamp, den der Raspberry Pi bereits beim Schreiben in SQLite vergibt – nicht erst das Backend. - Beim Upload prüft das Backend die eingehende Kombination aus
timestamp, Sensorstation und Metrik gegen die PostgreSQL-Datenbank. Bereits vorhandene Kombinationen werden mitHTTP 200 OK(idempotent) quittiert, aber nicht doppelt gespeichert. - Jeder Eintrag in der SQLite-Tabelle
sensor_databesitzt einsent-Flag (0 = noch nicht übertragen, 1 = erfolgreich übertragen). Der Raspberry Pi überträgt gepufferte Daten nach Wiederherstellung chronologisch (älteste zuerst) in Batches von maximal 50 Einträgen pro Zyklus. Übertragen werden die Einträge einzeln. Bei einer erfolgreichen Antwort (2xx) wird das Flag auf sent=1 gesetzt und der Eintrag anschließend gelöscht. Bleibt die Übertragung erfolglos, verbleibt der Eintrag mit sent=0 und wird im nächsten Zyklus erneut versucht – es gehen somit keine Daten verloren.
Designentscheidung: Der Timestamp wird bereits am Raspberry Pi beim Erfassen bzw. Puffern der Messung vergeben. Dadurch bleibt derselbe Messdatensatz auch bei wiederholten Upload-Versuchen eindeutig wiedererkennbar, ohne dass das Backend nachträglich eine eigene ID erzeugen muss.
Problem: Das Arduino-Display und die RGB-LED müssen den aktuellen Systemzustand korrekt widerspiegeln, auch wenn keine BLE-Verbindung besteht oder eine Grenzwertwarnung vom User quittiert wurde.
Der Arduino hält intern einen einfachen Zustandsautomaten. Die Zustandswechsel werden hauptsächlich vom Raspberry Pi per BLE GATT Write ausgelöst; lokal reagiert der Arduino zusätzlich auf BLE-Verbindungsereignisse und Button-Eingaben.
| Logischer Zustand | Arduino-State im Code | LED | Display |
|---|---|---|---|
NORMAL |
CONNECTED_ALL_VALID_DATA |
Türkis, dauerhaft | Raumname + aktuelle Messwerte; Alternativansicht: „NO ACTIVE WARNINGS!“ |
INTERMEDIATE |
CONNECTED_SOME_SHORT_INVALID_DATA |
Orange/Koralle, dauerhaft | Raumname + aktuelle Messwerte; betroffene Werte werden hervorgehoben |
WARNING |
CONNECTED_ACTIVE_WARNING |
Rot, schnell blinkend | Warnmeldung(en) + ClimateHint-/Warntext; während Übertragung: „RECEIVING MESSAGES...“ |
WARNING_ACKNOWLEDGED |
ACTIVE_WARNING_ACKNOWLEDGED |
Dunkelrot/Violett, dauerhaft | Quittierte Warnmeldung(en); User kann weiter durch die Texte blättern |
BLE_DISCONNECTED |
WAITING_FOR_KNOWN_CONNECTION |
Amber/Gelb, blinkend | „DISCONNECTED“ + Verbindungsstatus; Alternativansicht zeigt weiterhin Rohmesswerte |
Zusätzlich gibt es technische Zwischenzustände:
| Arduino-State | Bedeutung | LED |
|---|---|---|
WAITING_FOR_AUTHENTICATION |
BLE verbunden, aber Raspberry Pi noch nicht authentifiziert | Aqua/Grün, schnell blinkend |
WAITING_FOR_NEW_CONNECTION |
Ersteinrichtung/Pairing-Modus | Magenta blinkend |
Im Zustand BLE_DISCONNECTED misst der Arduino weiter und speichert Messwerte in einem lokalen Ringbuffer für die spätere Übertragung. Eine Grenzwertprüfung findet dort nicht statt, da diese Logik ausschließlich am Raspberry Pi liegt. Beim Verbindungsabbruch setzt der aktuelle Code statusCode und warningStatus lokal zurück; bereits empfangene Warntexte bleiben zwar im RAM, werden aber nicht als aktiver Warnzustand weitergeführt.
Ein User kann eine aktive Grenzwertwarnung sowohl im Frontend der Webapp als auch direkt an der Sensorstation quittieren:
-
Quittierung im Frontend: Das Backend aktualisiert den Warnstatus und informiert den zuständigen Raspberry Pi. Dieser schreibt die Quittierung per BLE auf die
warningAcknowledgedCharacteristic. Der Arduino wechselt bei vollständig empfangener Warnung inACTIVE_WARNING_ACKNOWLEDGED. -
Quittierung an der Sensorstation: Der User blättert mit den Buttons durch die empfangenen Warntexte. Nach dem letzten Warntext setzt der Arduino
warningStatus = 3, wechselt inACTIVE_WARNING_ACKNOWLEDGEDund schreibt die Quittierung ebenfalls auf die BLE-Characteristic zurück.
Ist die zugrundeliegende Grenzwertverletzung weiterhin aktiv, verbleibt der Arduino im quittierten Warnzustand, bis der Raspberry Pi neue Statusdaten übermittelt. Bei einer neuen Warnmeldung wird die bisherige Warnliste geleert und der Zustand wieder auf CONNECTED_ACTIVE_WARNING gesetzt.
ClimateHint- bzw. Warntexte werden vom Raspberry Pi per BLE an den Arduino übertragen. Die Übertragung erfolgt paketweise über Länge und einzelne Zeichen-Chunks. Der Arduino puffert die empfangenen Texte in currentWarningMessages und zeigt sie im Warnzustand auf dem Display an.
Designentscheidung: Der Arduino ist ein reines Anzeige- und Eingabegerät für den Endnutzer. Die Grenzwertlogik liegt am Raspberry Pi; der Arduino verarbeitet nur BLE-Statuscodes, Warntexte, Button-Eingaben, LED-Farben und Display-Ausgabe. Dadurch bleibt der Arduino-Code vergleichsweise einfach und testbar.
Problem: Grenzwertverletzungen müssen zuverlässig erkannt, ans Backend gemeldet und auch explizit aufgehoben werden können – sowohl automatisch (Wert normalisiert sich) als auch manuell (Grenzwert wird deaktiviert).
Die Grenzwertprüfung erfolgt am Raspberry Pi. Der Arduino führt selbst keine Grenzwertprüfung durch, sondern erhält vom Raspberry Pi einen kompakten statusCode per BLE. Darin ist pro Metrik codiert, ob der Wert gültig ist oder kurzzeitig bzw. langfristig außerhalb des erlaubten Bereichs liegt.
Der Raspberry Pi berechnet für jede Metrik einen gleitenden Durchschnitt (Sliding Window) über die letzten 5 Minuten. Da das Messintervall der Sensorstationen zwischen mindestens 3 Sekunden (hardwareseitig limitiert) und maximal 60 Sekunden liegt, befinden sich im Fenster stets mindestens 5 Messwerte. Einzelne Ausreißer beeinflussen den Durchschnitt damit nur geringfügig.
Kurzzeitige Abweichungen - d.h. der gleitende Durchschnitt überschreitet kurz einen Grenzwert, kehrt aber rasch zurück - werden auf dem Arduino als CONNECTED_SOME_SHORT_INVALID_DATA dargestellt. Erst wenn der Durchschnitt über das gesamte 5-Minuten-Fenster hinweg außerhalb des erlaubten Bereichs verbleibt, gilt die Verletzung als bestätigt: Warntexte werden an den Arduino übertragen und der Zustand wechselt zu CONNECTED_ACTIVE_WARNING.
Erkennt der Raspberry Pi eine bestätigte Grenzwertverletzung, sendet er einen Alert per REST ans Backend. Das Backend:
- loggt den Alert mit Timestamp,
- speichert die letzte aktive Verletzung pro Raum und Metrik explizit mit Timestamp,
- markiert die Verletzung als aktiv (
violationStatus = ACTIVE).
Um Alert-Flooding zu vermeiden, sendet der Raspberry Pi für eine bereits aktive Verletzung keinen erneuten Alert, solange der vorherige Alert weniger als 15 Minuten zurückliegt. Ist die Verletzung weiterhin aktiv und die 15-Minuten-Frist abgelaufen, kann ein neuer Alert bzw. Reminder gesendet werden.
Eine Grenzwertverletzung wird aufgehoben, wenn:
-
der Messwert in den Normalbereich zurückkehrt: Der Raspberry Pi erkennt dies und sendet eine Aufhebungs-Meldung per REST ans Backend. Zusätzlich übermittelt er dem Arduino wieder einen gültigen
statusCode. Der Arduino setzt daraufhin die lokale Warnanzeige zurück und wechselt zuCONNECTED_ALL_VALID_DATA. -
der Grenzwert manuell deaktiviert wird: Ein Hausverwalter kann einen Grenzwert im Frontend bearbeiten. Das Backend setzt den Grenzwert auf
enabled = falseund laufende ThresholdViolations dieses Grenzwerts aufviolationStatus = DISABLED. Der Raspberry Pi erhält diese Änderung vom Backend und propagiert relevante Statusänderungen per BLE an die verbundenen Sensorstationen.
Der Arduino unterscheidet dabei nicht selbst zwischen RESOLVED und DISABLED. Er reagiert nur auf die vom Raspberry Pi gelieferten Statuscodes, Warntexte und Quittierungsinformationen.
Problem: Räume können im laufenden Betrieb einer anderen Abteilung zugeordnet werden. Diese Änderung muss konsistent in allen betroffenen Ansichten und Zuordnungen reflektiert werden, ohne historische Daten zu verlieren.
Wird ein Raum einer neuen Abteilung zugeordnet, aktualisiert das Backend die roomIds die im Department verwaltet werden. Die Referenz zum übergeordneten Gebäude (buildingId) bleibt dabei unverändert – ein Raumwechsel betrifft ausschließlich die Abteilungszugehörigkeit, nicht die physische Gebäudezuordnung.
Folgende Konsequenzen ergeben sich automatisch:
- Die Raumlisten beider betroffener Abteilungen (alte und neue) werden aktualisiert.
- User, die dem Raum fix zugeordnet sind, bleiben dem Raum zugeordnet; ihre Abteilungszugehörigkeit wird jedoch nicht automatisch geändert – das erfordert einen separaten administrativen Schritt.
- Historische Messdaten des Raums bleiben erhalten und sind weiterhin über die Raumreferenz abrufbar, unabhängig von der aktuellen Abteilungszugehörigkeit.
- Aktive Grenzwertkonfigurationen und laufende Alerts des Raums bleiben bestehen.
Designentscheidung: Räume sind das zentrale Datenobjekt im System – Messdaten, Grenzwerte und Alerts sind stets an einen Raum, nicht an eine Abteilung gebunden. Abteilungen dienen primär der organisatorischen Gruppierung und Zugriffskontrolle. Ein Abteilungswechsel eines Raums ist daher eine reine Metadaten-Änderung ohne Auswirkung auf die Messkontinuität.
Problem: Das System muss zu jeder Zeit wissen, ob Raspberry Pis und die ihnen zugeordneten Sensorstationen erreichbar und funktionsfähig sind. Ausfälle sollen zeitnah erkannt und im Frontend sowie an den Sensorstationen sichtbar gemacht werden.
Das Backend spricht den Raspberry Pi regelmäßig über einen dedizierten Heartbeat-Endpunkt (/api/spi/{piId}/heartbeat GET) an. Der Raspberry Pi antwortet mit einem strukturierten Status-Objekt, das folgende Informationen enthält:
- Eigener Gerätestatus (
ONLINE/DEGRADED/OFFLINE/MAINTENANCE) - Für jede zugeordnete Sensorstation: BLE-Verbindungsstatus (
AVAILABLE/CONNECTED/CONNECTION_FAILED), letzte empfangene Messung mit Timestamp, aktiver Warnzustand - Systeminformationen (z. B. freier Speicher, SQLite-Puffergröße) – Details werden in der Implementierungsphase festgelegt
Das Backend wertet die Heartbeat-Antwort aus, aktualisiert die deviceStatus-Felder der betroffenen Geräte in PostgreSQL und stellt die Statusinformationen im Frontend bereit.
Bleibt eine Heartbeat-Antwort aus (Timeout), setzt das Backend den deviceStatus des Raspberry Pi auf OFFLINE und alle ihm zugeordneten Sensorstationen ebenfalls auf OFFLINE.
Statusänderungen (wie aktualisierte Warnzustände, Quittierungen oder neue Warntexte) werden vom Raspberry Pi per BLE GATT Write an verbundene Sensorstationen übertragen. Dies setzt eine aktive BLE-Verbindung voraus.
Ein Verlust der BLE-Verbindung wird jedoch nicht aktiv an den Arduino propagiert, da in diesem Fall keine BLE-Kommunikation mehr möglich ist. Stattdessen erkennt der Arduino den Verbindungsabbruch eigenständig über das lokale BLE-Disconnect-Event und wechselt selbstständig in den Zustand WAITING_FOR_KNOWN_CONNECTION bzw. BLE_DISCONNECTED. Dabei zeigt er den Verbindungsverlust auf Display und LED an und misst lokal weiter.
Der Raspberry Pi meldet seinerseits den veränderten BLE-Verbindungsstatus der betroffenen Sensorstation im nächsten Heartbeat ans Backend. Das Backend aktualisiert daraufhin den Geräte- und Sensorstationsstatus in PostgreSQL, der anschließend im Frontend sichtbar wird.
Der Verbindungs- und Warnstatus aller Geräte ist im Frontend für berechtigte Rollen (Systemadministrator, Gebäudeadministrator) in der Geräteverwaltung einsehbar. Nutzer:innen sehen im Kontext ihres eigenen Raums, ob die Sensorstation aktuell verbunden ist.
Problem: Raspberry Pis und Sensorstationen müssen sowohl im Backend als auch auf den physischen Geräten eindeutig identifizierbar sein. Die ID-Vergabe und die initiale Konfiguration müssen daher einen klaren und möglichst fehlerarmen Ablauf definieren. Außerdem muss sichergestellt werden, dass nur zuvor im System registrierte Geräte mit dem Backend kommunizieren bzw. dauerhaft einem Raspberry Pi zugeordnet werden können.
- Raspberry Pi IDs werden vom Backend eindeutig generiert und einem konkreten Raum zugeordnet.
- Sensorstation IDs werden bereits während des Scan-Prozesses temporär im Backend erzeugt. Vom Raspberry Pi gefundene Sensorstationen werden nach dem Scan vorläufig der jeweiligen Raspberry-Pi-Instanz zugeordnet und erhalten eigene IDs. Wird keine Verbindung gestartet, läuft ein definierter Timeout ab oder wird ein neuer Scan gestartet, werden diese temporären Sensorstation-Einträge wieder gelöscht.
- Die dauerhafte Bindung zwischen Raspberry Pi und Sensorstation entsteht erst nach erfolgreicher Auswahl und Verbindungsherstellung im Registrierungsprozess. Die Assoziation zwischen BLE-Adresse und System-ID erfolgt dabei per
POST /sensorstationbei der Erstaufsetzung. Der Arduino selbst speichert seine eigene System-ID nicht, sie dient ausschließlich der sauberen Speicherung im Backend und wird der BLE-Adresse sowie dem Anzeige-Namen des Geräts zugeordnet. Am Arduino-Display wird die BLE-Adresse angezeigt, sodass eine eindeutige physische Zuordnung im Feld möglich ist. - Der Arduino speichert ausschließlich die
TrustedRpiId(4 Bytes, persistent) sowie dasMeasurementInterval. Diese werden beim ersten erfolgreichen Verbindungsaufbau durch den Raspberry Pi beschrieben. Muss ein Arduino mit einem neuen Raspberry Pi verbunden werden, ist ein Hardware-Reset des Arduino erforderlich (alle 3 Tasten gleichzeitig), wodurch die gespeicherteTrustedRpiIdzurückgesetzt wird.
Die Erstkonfiguration eines Raspberry Pi erfolgt, nachdem der Systemadministrator ihn in der Webapp registriert und einem Raum zugeordnet hat. Dabei legt das Backend bereits ein Raspberry-Pi-Objekt an, setzt den deviceStatus zunächst auf OFFLINE und stellt eine config.yaml mit den benötigten Konfigurationsdaten bereit.
Der Systemadministrator kopiert diese config.yaml auf die SD-Karte des Raspberry Pi. Die darin enthaltenen Parameter werden beim Start als globale Variablen eingelesen und im Arbeitsspeicher gehalten, eine persistente Speicherung auf dem Gerät selbst findet nicht statt. Nach dem Start liest der Raspberry Pi die Konfigurationsdatei ein und sendet anschließend eine POST /api/cpi/{piId}/booted-Request an das Backend. Erst durch diese Anfrage lernt das Backend die aktuelle IP-Adresse des Geräts kennen und kann den registrierten Raspberry Pi als erreichbar behandeln. Sobald die Verbindung erfolgreich geprüft wurde, kann der Raspberry Pi im System als ONLINE geführt werden.
Das Backend akzeptiert dabei nur Anfragen von Raspberry Pis, die zuvor im System registriert wurden und sich mit einem bekannten piId melden.
Folgende Informationen müssen vor dem ersten Start auf dem Raspberry Pi verfügbar sein:
ROOM_ID: "<Backend-ID des vom User ausgewählten Raums>"
ROOM_NAME: "<Name des vom User ausgewählten Raums>"
BACKEND_URL: "http://<IP-Adresse>:<Port>"
PI_ID: "<Eigene Backend-ID des Raspberry Pi>"
HOST_NAME: "<Vom User definierter Name des Raspberry Pi>"
PRIVACY_MODE: "<Vom Backend generierter Privacy-Mode-Status für den gewählten Raum>"
Sensorstationen werden mit identischem Firmware-Stand betrieben und benötigen vorab keine individuelle fachliche Konfiguration. Für das erstmalige Setup senden alle Sensorstationen denselben Namen, denselben advertised Service und dieselben Manufacturer Data. Sie unterscheiden sich in diesem Zustand nur über ihre Bluetooth-Adresse, die während des Registrierungsprozesses als temporärer Identifikator dient.
Die Erstkonfiguration erfolgt im Rahmen des Registrierungsablaufs durch den Systemadministrator:
- Der Raspberry Pi scannt auf Anforderung des Backends per BLE nach verfügbaren Sensorstationen.
- Die gefundenen Geräte werden anhand ihrer Bluetooth-Adressen an das Backend gemeldet, dort temporär dem Raspberry Pi zugeordnet und mit dem Status
AVAILABLEangelegt. - Der Systemadministrator wählt im Frontend die gewünschte Sensorstation aus.
- Der Raspberry Pi baut eine BLE-Verbindung zur ausgewählten Sensorstation auf.
- Im Zuge dieser Erstverbindung schreibt der Raspberry Pi seine eigene Identität in die Characteristic
TrustedRpiIdsowie das konfigurierteMeasurementIntervalauf den Arduino. - Die Sensorstation führt anschließend einen Reboot durch. Dabei wechselt sie vollständig ihren BLE-Auftritt: Name, Manufacturer Data und advertised Service UUID werden auf die Normalbetrieb-Werte umgestellt.
- Nach dem Reboot advertised die Sensorstation mit aktualisierten BLE-Daten, neuem Namen, neuer Vendor-Data sowie angepasstem Service und Characteristic. Der Raspberry Pi verbindet sich weiterhin anhand der bekannten Bluetooth-Adresse.
- Zur Authentifizierung schreibt der Raspberry Pi die
TrustedRpiIderneut auf die Sensorstation. Erst danach gilt die Verbindung als autorisiert. - Sobald der Raspberry Pi die ersten Sensordaten von der Sensorstation empfangen hat, aktualisiert er den Status der Sensorstation im Backend auf
CONNECTED.
Designentscheidung: Gefundene Sensorstationen werden bereits während des Scan-Prozesses als temporäre Objekte im Backend angelegt und dem suchenden Raspberry Pi mit Status AVAILABLE zugeordnet. Dadurch kann der Registrierungsprozess im Frontend mit konkreten Backend-Objekten arbeiten. Nicht ausgewählte oder nicht erfolgreich verbundene Sensorstationen werden nach Timeout oder bei einem neuen Scan wieder gelöscht. Erst nach erfolgreicher Verbindung, Authentifizierung über TrustedRpiId und Empfang erster Sensordaten gilt eine Sensorstation als vollständig registriert und wird dauerhaft mit dem Raspberry Pi verknüpft.
Dieser Abschnitt beschreibt typische Ausfallszenarien des Systems sowie die Maßnahmen zur Sicherstellung von Datenkonsistenz, Wiederherstellung und Benutzerinformation.
| Aspekt | Beschreibung |
|---|---|
| Datenkonsistenz | Der Raspberry Pi erkennt den Ausfall über einen BLE-Verbindungs-Timeout. Da keine neuen Messdaten eintreffen, werden keine fehlerhaften oder unvollständigen Einträge in die SQLite-Datenbank geschrieben. Bereits gepufferte Daten bleiben erhalten. |
| Logging | Der Raspberry Pi schreibt einen ERROR-Eintrag in sein lokales Logfile (sensor_offline, Sensor-ID, Timestamp). Die Wiederverbindung wird auf INFO-Level protokolliert. |
| Wiederaufnahme | Sobald die Sensorstation wieder BLE-Advertising mit ihrer bekannten ID sendet, baut der Raspberry Pi automatisch die Verbindung wieder auf; kein manuelles Eingreifen ist notwendig. |
| Informationsaustausch | Das Backend fragt den Status der Raspberry Pis sowie der angebundenen Sensorstationen regelmäßig über den Heartbeat Endpunkt (GET /api/rpi/{piId}/heartbeat) ab. Diese Abfrage erfolgt periodisch über einen Scheduler (z. B. mittels @Scheduled). Dabei werden auch Verbindungsinformationen einzelner Sensorstationen übermittelt. Das Backend verarbeitet die empfangenen Statusdaten und stellt sie dem Frontend zur Verfügung |
| User-Information |
Mitarbeiter:innen / Abteilungsleitung: Hinweis im Dashboard, dass die Sensorstation offline ist; Zeitlücke im Verlaufsdiagramm als „Daten nicht verfügbar“ markiert. Systemadmins: Gerätestatus in der Verwaltungsansicht zeigt Ausfall; Logs einsehbar. Gebäudeadmins: Keine direkten Geräteinformationen, aber fehlende Messdaten im Raumverlauf sichtbar. |

Das vollständige Diagramm befindet sich als PNG im Projekt Repo (Datei: /docs/Softwarekonzept_Finalversion/scenarios/S1_Sensor_Station_Failure.png).
| Aspekt | Beschreibung |
|---|---|
| Datenkonsistenz | Die Sensorstation puffert Messwerte lokal im Arduino-Speicher, solange die BLE-Verbindung instabil ist. Dies erfolgt über einen Ringpuffer nach dem FIFO-Prinzip (First In – First Out). |
| Logging | Verbindungsprobleme werden auf WARN-Level im Raspberry-Pi-Logfile festgehalten, inklusive Anzahl verworfener Pakete und Dauer der Instabilität. Sobald die Verbindung wieder stabil ist, wird dies auf INFO-Level geloggt. |
| Wiederaufnahme | Nach Stabilisierung der BLE-Verbindung überträgt die Sensorstation die gepufferten Messwerte kumuliert. Der Raspberry Pi ergänzt Zeitstempel und verarbeitet die Daten regulär weiter. Dabei approximiert der Raspberry Pi fehlende Zeitstempel basierend auf dem Zeitstempel der letzten erfolgreichen Kommunikation mit der Sensorstation vor dem Verbindungsabbruch. Zusätzlich werden relative Zeitstempel aus den gepufferten Arduino-Daten berechnet, indem diese mit parallel empfangenen aktuellen Daten abgeglichen werden. Gepufferte Daten verfügen über einen ACK-Workflow und können mit aktuellen Daten interleaved verarbeitet werden. Die Zeitstempel werden in Mikrosekunden angegeben und können überlaufen (Overflow). |
| Informationsaustausch | Während der Instabilität werden keine unvollständigen Daten an die Webapp weitergeleitet. Nach Wiederherstellung erfolgt die Übertragung der aufgelaufenen Daten über ein API-Endpoint. |
| User-Information |
Mitarbeiter:innen / Abteilungsleitung: Lücke im Verlaufsdiagramm als „Daten fehlen (Verbindungsproblem)“ markiert. Systemadmins: Verbindungsstatus in der Geräteverwaltung sichtbar; WARN-Einträge in den Logs. |

Das vollständige Diagramm befindet sich als PNG im Projekt Repo (Datei: /docs/Softwarekonzept_Finalversion/scenarios/S2_Restricted_BLE_Communication.png).
| Aspekt | Beschreibung |
|---|---|
| Datenkonsistenz | Alle Datenbankoperationen in SQLite werden als ACID-konforme Transaktionen ausgeführt. Beim Start des Systems wird die Datenbank automatisch erstellt. Anschließend wird überprüft, ob die Struktur und Konfiguration korrekt sind. |
| Logging | Der Neustart wird beim Start des Dienstes als WARN-Eintrag protokolliert. Der Webserver loggt den Reconnect auf INFO-Level. |
| Wiederaufnahme | Beim Start führt der Raspberry Pi folgende Schritte aus: 1. Der Pi liest die IP des Webservers aus der zuletzt lokal zwischengespeicherten conf.yaml. 2. Anschließend wird eine GET-Request an das Backend gesendet, um die aktuelle Konfiguration abzurufen. 3. Danach erfolgt der Aufbau der BLE-Verbindungen zu den Sensorstationen. |
| Informationsaustausch | Nach dem Reconnect sendet der Raspberry Pi einen initialen Config-Request an das Backend. Das Backend übermittelt dabei die vollständige conf.yaml. Im Frontend sieht der Systemadministrator in der Geräteverwaltung den Status aller Raspberry Pis. Betroffene Nutzer erhalten im Dashboard einen Hinweis in Form eines Banners mit der Meldung „Raspberry Pi nicht erreichbar“. Im Verlaufsdiagramm wird der Ausfall durch eine graue Lücke dargestellt. |
| User-Information |
Systemadmins / Gebäudeadmins: kurzer Ausfall in Logs und Gerätestatus sichtbar. Alle Rollen: Datenlücke im Dashboard markiert. |

Das vollständige Diagramm befindet sich als PNG im Projekt Repo (Datei: /docs/Softwarekonzept_Finalversion/scenarios/S3_Raspberry_Pi_Restart.png).
| Aspekt | Beschreibung |
|---|---|
| Datenkonsistenz | Der Raspberry Pi puffert alle Messdaten mit Timestamps in SQLite. Doppelte Übertragungen werden durch eine sent-Flag in der Raspberry-Pi-Datenbank verhindert, die nach erfolgreicher Übertragung gesetzt wird. Dadurch wird sichergestellt, dass jede Messung nur einmal erfolgreich an das Backend übertragen wird. |
| Logging | Fehlgeschlagene Übertragungen werden auf ERROR-Level geloggt. Wiederherstellung der Verbindung wird auf INFO-Level festgehalten. |
| Wiederaufnahme | Falls die Übertragung an das Backend fehlschlägt, versucht der Raspberry Pi erneut, alle Messungen mit sent = 0 zu übertragen. Dabei werden wie im Normalbetrieb maximal 50 Messungen gleichzeitig aus der Datenbank geladen und anschließend einzeln an das Backend gesendet. |
| Informationsaustausch | Während des Backend-Ausfalls speichert der Raspberry Pi alle Messdaten lokal in der SQLite-Datenbank. Es erfolgt keine Datenweiterleitung an das Backend. Nach Wiederherstellung der Verbindung werden die zuvor nicht übertragenen Messungen automatisch nachträglich gesendet. Im Frontend wird der Ausfall im Verlaufsdiagramm durch eine graue Lücke dargestellt. |
| User-Information |
Mitarbeiter:innen / Abteilungsleitung: Hinweis auf fehlende Daten im Dashboard. Systemadmins: Verbindungsstatus und Retry-Versuche in Logs sichtbar. |

Das vollständige Diagramm befindet sich als PNG im Projekt Repo (Datei: /docs/Softwarekonzept_Finalversion/scenarios/S4_Pi_to_Backend_Outage.png).
| Aspekt | Beschreibung |
|---|---|
| Datenkonsistenz | Messdaten werden lokal in SQLite auf den Raspberry Pis gepuffert. Nach Wiederherstellung des Backends werden die gespeicherten Daten aus der lokalen Datenbank in die PostgreSQL-Datenbank übertragen. Dabei werden nur noch nicht übertragene Datensätze berücksichtigt, um doppelte Einträge zu vermeiden (sent Flag). Die Übertragung erfolgt in Batches und wird fortgesetzt, bis alle gepufferten Daten synchronisiert sind. |
| Logging | Der Webserver loggt beim Hochfahren einen INFO-Eintrag. |
| Wiederaufnahme | Nach dem Neustart authentifizieren sich die Raspberry Pis automatisch erneut und senden ihre gepufferten Daten. |
| Informationsaustausch | Während des Ausfalls arbeiten Sensorstation und Raspberry Pi autonom weiter. Grenzwertprüfungen und lokale Warnungen funktionieren weiterhin. |
| User-Information |
Webapp-Nutzer: generische Fehlermeldung (HTTP 503 Service Unavailable). Sensorstation: Warnungen über LEDs und Display funktionieren weiterhin. Systemadmins: Ausfallzeitraum und Health-Check-Status in Logs sichtbar. |

Das vollständige Diagramm befindet sich als PNG im Projekt Repo (Datei: /docs/Softwarekonzept_Finalversion/scenarios/S5_Central_Backend_Failure.png).
Die GUI wurde zunächst als Papierprototyp entwickelt, um die wichtigsten Abläufe frühzeitig zu visualisieren.
Die vollständigen Prototypen befinden sich im Repository unter /docs/images/gui_prototype/.
- Einfache Login-Maske mit E-Mail und Passwort
- Validierung falscher Eingaben
- Nach erfolgreichem Login erfolgt eine Weiterleitung auf ein rollenabhängiges Dashboard

Der vollständige Prototyp befindet sich als PNG im Projekt Repo (Datei: /docs/Softwarekonzept_Finalversion/gui_prototype/Paperprototype_login.png)._
Das Dashboard für Mitarbeiter:innen zeigt die aktuellen Klimadaten des eigenen Büros.
Funktionen:
- Anzeige von Temperatur, Luftfeuchtigkeit und Luftqualität
- Visualisierung der Luftqualität über Farbindikatoren
- Prominente Warnanzeige bei Grenzwertverletzungen
- Anzeige von Raumklima-Tipps bei Problemen
- Navigation zu Verlaufsansicht und Abwesenheitsverwaltung

Der vollständige Prototyp befindet sich als PNG im Projekt Repo (Datei: /docs/Softwarekonzept_Finalversion/gui_prototype/Paperprototype_MA_Dashboard.png)._
Die Verlaufsansicht zeigt historische Messdaten eines Raumes.
Eigenschaften:
- Liniendiagramme für Temperatur, Luftfeuchtigkeit und Luftqualität
- Zeitraum wählbar (Tag / Woche / Monat)
- Grenzwerte werden als Referenzlinien angezeigt
- Grenzwertverletzungen werden farblich markiert
- Datenlücken (z. B. Datenschutz oder Geräteausfall) werden als graue Bereiche dargestellt

Der vollständige Prototyp befindet sich als PNG im Projekt Repo (Datei: /docs/Softwarekonzept_Finalversion/gui_prototype/Paperprototype_MA_Dashboard2.png)._
Die Granularität der Daten hängt von der Rolle ab:
- Mitarbeiter:innen sehen Rohdaten ihres eigenen Büros
- Abteilungsleitung sieht aggregierte Tagesdurchschnitte für Büroräume
Die Abteilungsleitung erhält eine Übersicht über alle Räume ihrer Abteilung.
Funktionen:
- Rasteransicht aller Räume
- Anzeige aktueller Messwerte pro Raum
- Warnstatus bei Grenzwertverletzungen
- Navigation zur Raumdetailansicht

Der vollständige Prototyp befindet sich als PNG im Projekt Repo (Datei: /docs/Softwarekonzept_Finalversion/gui_prototype/Paperprototype_Manager_Dashboard.png)._
Die Geschäftsführung sieht ausschließlich aggregierte Daten auf Abteilungsebene.
Funktionen:
- Balkendiagramm mit Anzahl der Grenzwertverletzungen pro Abteilung
- Trendanalyse über Wochen oder Monate
- Keine raumbezogenen Einzelwerte (Datenschutz)
Der Hausverwalter kann die Raumkonfiguration und Grenzwerte verwalten.
Funktionen:
- Liste aller Räume
- Anzeige aktueller Grenzwerte
- Bearbeitung der Grenzwerte pro Raum
- Verwaltung von Raumklima-Tipps

Der vollständige Prototyp befindet sich als PNG im Projekt Repo (Datei: /docs/Softwarekonzept_Finalversion/gui_prototype/Paperprototype_GF_Verw.png)._
Die Systemadministration verwaltet die physische Infrastruktur.
Funktionen:
- Übersicht aller Raspberry Pis und Sensorstationen
- Statusanzeige (Online / Offline / Maintenance)
- Registrierung neuer Geräte
- Zuordnung von Sensorstationen zu Raspberry Pis und Räumen
- Benutzerverwaltung und Rollenzuweisung

Der vollständige Prototyp befindet sich als PNG im Projekt Repo (Datei: /docs/Softwarekonzept_Finalversion/gui_prototype/Paperprototype_Managment.png)._
| Person | Zuständigkeit |
|---|---|
| Maria Kuhn | Arduino-Entwicklung (C/C++, Display/LED/Buttons), Frontend (React/TypeScript) |
| Fabienne Schedler | Frontend (React/TypeScript, PrimeReact, GUI-Prototyp) |
| Emma Danko | Raspberry Pi (Python, REST-Schnittstellen, BLE Central, SQLite, Docker) |
| Prahbdip Singh | Raspberry Pi (REST-Schnittstellen, BLE Central, SQLite, Docker), Backend |
| Adriano Paganini | Arduino-Entwicklung (C/C++, Display/LED/Buttons), Backend |
| Alle | Softwarekonzept, Testing, Dokumentation, Code Review |
| Datum | Meilenstein | Inhalt | | ---------- | ----------------------------------------- | --------------------------------------------------------------------------- | --- | | 12.03.2026 | Softwarekonzept V1 | Systemüberblick, Use Cases, Klassendiagramm V1, GUI-Prototyp, Projektplan | | 19.03.2026 | Softwarekonzept V2 | Sequenzdiagramme, API Dokumentation, Ausfallssicherheit, Klassendiagramm V2 | | 19.03.2026 | Arduino Anschlussplan | Pinout und Verdrahtungsplan der Sensorstation | | 23.03.2026 | Durchstich Demonstration (PS-Einheit) | Kommunikation zwischen Backend/Frontend – Raspberry Pi – Arduino | | 27.03.2026 | Softwarekonzept finale Version | Überarbeitetes Gesamtkonzept nach Feedback | | 28.05.2026 | Slides für Ergebnispräsentation | Präsentationsfolien | | 28.05.2026 | Projektergebnisse Abnahmetests | Abnahmetests der Projektergebnisse | | 01.06.2026 | Ergebnispräsentation (PS-Einheit) | Projektpräsentation | | 05.06.2026 | Dokumentation Abnahmetests | Schriftliche Dokumentation der Abnahmetests | | 25.06.2026 | Finale Abgabe Projektergebnisse | Vollständige Abgabe aller Projektergebnisse | |
| Zeitraum | Meilenstein | Inhalt |
|---|---|---|
| 13.03. – 23.03.2026 | M1: Hardware Setup | Arduino + Sensoren funktionsfähig; BLE-Übertragung zum Raspberry Pi; Raspberry Pi OS + Docker eingerichtet; Basis-REST-API (OpenAPI) |
| 24.03. – 12.04.2026 | M2: Backend Grundgerüst | Spring Boot Skeleton aufgesetzt; PostgreSQL-Datenbankschema implementiert; Login und Rollenverwaltung; ID-Generierungsablauf definieren (RPI, Arduino) |
| 24.03. – 03.05.2026 | M3: Datenfluss End-to-End | Kompletter Datenfluss Arduino → Raspberry Pi → Backend funktionsfähig; Grenzwertberechnung am Raspberry Pi; Datenschutzlogik |
| 24.03. – 24.05.2026 | M4: Frontend + Warnungen | Rollenabhängige Dashboards; Verlaufsdiagramme; Grenzwertwarnungen in Webapp und auf Sensorstation |
| 25.05. – 05.06.2026 | M5: Ausfallssicherheit + Testing | Ausfallszenarien abgesichert; SonarQube integriert; mindestens 65 % Testabdeckung; Abnahmetests (28.05.) und Dokumentation (05.06.) |
| 06.06. – 25.06.2026 | M6: Finalisierung | Bugfixes; vollständige Dokumentation; Ergebnispräsentation (01.06.); finale Abgabe (25.06.2026) |
Organisatorische Maßnahmen:
- Wöchentliche Team-Synchronisationsmeetings zur Besprechung von Fortschritt und Blockern
- Nutzung von GitLab Issues zur Aufgabenverwaltung
- Merge Requests und Code Reviews für Änderungen
- Dokumentation des Softwarekonzepts im GitLab Wiki
- Integration von SonarQube ab Beginn der Backend-Entwicklung zur kontinuierlichen Qualitätskontrolle