API-Beschreibung für Telemetrie-Abruf (GET)

Version: 1.5 
 Stand: Juni 2026 
 Herausgeber: Dexa Solutions GmbH 
 Produkt: Safe Fire House (SFH) 
 
 1. Übersicht 
 Dieses Dokument beschreibt den REST-API-Endpoint, über den ein externes System die aktuellen Telemetriedaten der Safe Fire House Brandwarnanlage aktiv abruft (Pull). Die Zentrale ist hier der Server , das abrufende System der Client . Die Antwort enthält den Datenbaum aus Wache, Fahrzeugen und Rauchsensoren. 
 
 
 
 Parameter 
 Wert 
 
 
 
 
 Method 
 GET 
 
 
 Pfad 
 /api/health/telemetry (mit oder ohne abschließenden / ) 
 
 
 Accept 
 application/json 
 
 
 Response-Type 
 application/json; charset=utf-8 
 
 
 Frequenz 
 On-Demand (Client-gesteuert) 
 
 
 Rate Limit 
 5 Requests/Sekunde pro Client-IP, Burst 10 (sonst 429 ) 
 
 
 Caching 
 Antwort bis zu 20 s serverseitig gecacht (siehe Abschnitt 9) 
 
 
 
 1.1 Authentifizierung 
 Der Endpoint erfordert ein Bearer-Token im Authorization -Header. Das Token wird je Zentrale vergeben und vertraulich an das abrufende System übergeben. 
 
 
 
 Methode 
 Header / Mechanismus 
 Beispiel 
 
 
 
 
 Bearer Token 
 Authorization: Bearer 
 Authorization: Bearer bffdc50d5a1173159... 
 
 
 
 Fehlt der Header oder ist das Token ungültig, antwortet der Endpoint mit 401 . Ist serverseitig kein Token konfiguriert, antwortet er mit 503 (fail-closed, keine Datenausgabe). 
 
 2. Endpoint 
 GET https://<zentrale-host>/api/health/telemetry
 
 
 <zentrale-host> = IP oder Hostname der Zentrale im lokalen Netz (z. B. 192.168.1.16 ). 
 Erreichbar über den Reverse-Proxy der Zentrale; der Authorization -Header wird unverändert durchgereicht. 
 Der abschließende Slash ist optional ( /api/health/telemetry und /api/health/telemetry/ sind gleichwertig). 
 
 
 3. Request 
 Es wird kein Request-Body gesendet. Erforderlicher Header: 
 
 
 
 Header 
 Pflicht 
 Wert 
 
 
 
 
 Authorization 
 ja 
 Bearer <token> 
 
 
 
 Beispiel: 
 curl --location 'https://192.168.1.16/api/health/telemetry/' \
 --header 'Authorization: Bearer <token>'
 
 
 4. Payload-Struktur (Response) 
 Root
├── timestamp
├── fireStation
├── deviceId
└── objects[]
 ├── type (vehicle | room | hall)
 ├── vehicleId
 ├── sign
 ├── callSign
 ├── vehicleType
 └── smokeDetectors[]
 ├── name
 ├── address
 ├── type
 └── ...
 
 
 Hinweis zu Wertetypen: Alle Schlüssel sind camelCase . Alle skalaren Werte werden als JSON-String ausgegeben (auch Zahlen und Flags, z. B. "rssiDevice": "-71" , "battery": "false" , "alarmState": "0" ). objects und smokeDetectors sind echte JSON-Arrays. 
 
 
 5. Root-Objekt 
 
 
 
 Key 
 Description 
 Type 
 Constraints 
 
 
 
 
 timestamp 
 Zeitstempel der Erstellung 
 string 
 ISO 8601 UTC ( YYYY-MM-DDTHH:mm:ssZ ) 
 
 
 fireStation 
 Wache (Name, Adresse) 
 string 
 Max. 150 Zeichen 
 
 
 deviceId 
 Seriennummer der Zentrale 
 string 
 14 Zeichen, hexadezimal 
 
 
 objects 
 Auflistung der Objekte (Fahrzeug/Raum/Halle) 
 array 
 Array von Objekt-Einträgen (siehe Abschnitt 6) 
 
 
 
 Beispiel: 
 {
 "timestamp": "2026-06-09T11:24:13Z",
 "fireStation": "Feuerwehr Feuerstadt, Hauptstr. 112, 01234 Feuerstadt",
 "deviceId": "001A2B3C4D5E6F",
 "objects": [ ... ]
}
 
 
 6. Objekt-Eintrag 
 Ein Objekt-Eintrag bündelt die Rauchsensoren eines Trägers. Das Feld type unterscheidet die Träger-Art. Die fahrzeugspezifischen Felder ( vehicleId , sign , callSign , vehicleType ) sind bei type = "vehicle" befüllt; für room / hall können sie leer bzw. "n.a." sein. 
 
 
 
 Key 
 Description 
 Type 
 Constraints 
 
 
 
 
 type 
 Art des Trägers 
 string 
 Enum: "vehicle" | "room" | "hall" (derzeit nur "vehicle" belegt) 
 
 
 vehicleId 
 Fahrzeug-Identifikationsnummer (VIN) 
 string 
 17 Zeichen; "n.a." falls nicht hinterlegt (siehe 8.1) 
 
 
 sign 
 Kennzeichen 
 string 
 Max. 10 Zeichen; "n.a." falls nicht hinterlegt (siehe 8.1) 
 
 
 callSign 
 Funkrufname 
 string 
 Max. 50 Zeichen 
 
 
 vehicleType 
 Fahrzeugtyp 
 string 
 Max. 50 Zeichen; "n.a." falls nicht hinterlegt (siehe 8.1) 
 
 
 smokeDetectors 
 Auflistung der Rauchsensoren 
 array 
 Array von SmokeDetector-Objekten; [] falls keine Melder zugeordnet (siehe 8.2) 
 
 
 
 Beispiel: 
 {
 "type": "vehicle",
 "vehicleId": "WVWZZZ3CZWE123456",
 "sign": "FS-FW 112",
 "callSign": "1-HLF20-1",
 "vehicleType": "HLF20",
 "smokeDetectors": [ ... ]
}
 
 
 7. SmokeDetector-Objekt 
 Alle Werte sind Strings (siehe Hinweis in Abschnitt 4). Fehlt ein einzelner Datapoint, wird ein typ-konformer Default geliefert (nie null ) — siehe Abschnitt 8.3. 
 
 
 
 Key 
 Description 
 Type 
 Constraints 
 
 
 
 
 name 
 Rauchsensorbezeichnung 
 string 
 Max. 30 Zeichen 
 
 
 address 
 Rauchsensoradresse 
 string 
 14 Zeichen, hexadezimal 
 
 
 type 
 Rauchsensortyp 
 string 
 Konstant "SFHSS02" 
 
 
 version 
 Hardware-Version 
 string 
 numerisch, ≥ 1 
 
 
 group 
 Gruppierung 
 string 
 0 – 9 oder leer 
 
 
 teams 
 Reserviert 
 string 
 i. d. R. leer 
 
 
 firmware 
 Firmware-Version 
 string 
 Max. 9 Zeichen, Pattern [0-9.]+ 
 
 
 rssiDevice 
 Funkempfangswert Gerät (dBm) 
 string 
 numerisch, −128 bis 128 
 
 
 rssiPeer 
 Funkempfangswert Sender (dBm) 
 string 
 numerisch, −128 bis 128 
 
 
 battery 
 Flag: Batterieleistung niedrig 
 string 
 "true" / "false" 
 
 
 unreachState 
 Flag: Gerät nicht erreichbar 
 string 
 "true" / "false" 
 
 
 unreachCumulative 
 Kumulierte Nichterreichbarkeit (Tage) 
 string 
 numerisch (0–9999) oder "n.a." (siehe 8.2) 
 
 
 operationTime 
 Betriebszeit (Tage) 
 string 
 numerisch, 0–9999 
 
 
 dirtLevel 
 Verschmutzungsgrad 
 string 
 float-String (z. B. "0.000000" ) 
 
 
 smokeLevel 
 Raucherkennungsgrad 
 string 
 float-String (z. B. "0.000000" ) 
 
 
 alarmState 
 Alarmstatus 
 string 
 "0" – "3" (siehe Enum, Abschnitt 7.1) 
 
 
 voltage 
 Batteriespannung (V) 
 string 
 float-String (0.0–3.2) 
 
 
 chamber 
 Flag: Rauchkammer verschmutzt 
 string 
 "true" / "false" 
 
 
 errorCode 
 Fehlercode 
 string 
 numerisch, 0–99 
 
 
 
 Beispiel: 
 {
 "name": "1-HLF20-1 RM1",
 "address": "00AABBCCDDEE11",
 "type": "SFHSS02",
 "version": "1",
 "group": "",
 "teams": "",
 "firmware": "1.0.6",
 "rssiDevice": "-65",
 "rssiPeer": "0",
 "battery": "false",
 "unreachState": "false",
 "unreachCumulative": "0",
 "operationTime": "180",
 "dirtLevel": "0.000000",
 "smokeLevel": "0.000000",
 "alarmState": "0",
 "voltage": "3.000000",
 "chamber": "false",
 "errorCode": "0"
}
 
 7.1 Enum: alarmState 
 
 
 
 Wert 
 Bedeutung 
 
 
 
 
 "0" 
 Ruhezustand – Kein Rauch erkannt 
 
 
 "1" 
 Lokaler Alarm – Rauch erkannt 
 
 
 "2" 
 Reserviert 
 
 
 "3" 
 Broadcast Alarm – Anderer Sensor in Funkreichweite hat Rauch erkannt 
 
 
 
 7.2 Flag-Logik 
 
 
 
 Flag 
 Bedeutung wenn "true" 
 Zusatzinfo 
 
 
 
 
 chamber 
 Rauchkammer verschmutzt 
 Siehe dirtLevel 
 
 
 battery 
 Batterieleistung niedrig 
 Siehe voltage (V) 
 
 
 unreachState 
 Gerät nicht erreichbar 
 Siehe unreachCumulative (Tage) 
 
 
 
 
 8. Sonderfälle & Defaults 
 8.1 Fahrzeug-Metadaten nicht deklariert 
 vehicleId , sign und vehicleType werden je callSign aus der Fahrzeug-Stammdatenpflege der Zentrale gelesen. Verhalten pro Feld (einzeln): 
 
 
 
 Situation 
 Ausgabe 
 
 
 
 
 callSign fehlt in der Stammdatenpflege 
 "n.a." 
 
 
 Eintrag vorhanden, Wert leer 
 "" (leerer String) 
 
 
 Eintrag + Wert vorhanden 
 der Wert 
 
 
 
 callSign selbst stammt aus der Fahrzeugliste und ist immer gesetzt. 
 8.2 Gerät nicht erreichbar / nicht gepairt 
 
 
 
 Fall 
 Verhalten 
 
 
 
 
 Melder gepairt, aber offline 
 erscheint im Baum; unreachState = "true" ; unreachCumulative = Tage seit letztem Kontakt bzw. "n.a." ; übrige Werte = zuletzt bekannter Stand (kein Live-Funk-Poll beim Abruf) 
 
 
 Melder nicht (mehr) gepairt 
 Melder fehlt im Array. Ein Fahrzeug ohne zugeordnete Melder liefert "smokeDetectors": [] 
 
 
 
 
 unreachCumulative = "n.a." bedeutet „nicht in der Erreichbarkeits-Historie der Zentrale geführt", nicht zwingend „erreichbar". 
 
 8.3 Fehlender Datapoint → typ-konformer Default 
 Existiert ein einzelner Sensor-Datapoint nicht (abweichendes Geräteprofil o. Ä.), wird statt null ein Default ausgegeben: 
 
 
 
 Feld(er) 
 Default 
 
 
 
 
 battery , unreachState , chamber 
 "false" 
 
 
 rssiDevice , rssiPeer , errorCode , operationTime , alarmState 
 "0" 
 
 
 voltage , smokeLevel , dirtLevel 
 "0.000000" 
 
 
 firmware , group , version , teams (keine Geräte-Metadaten) 
 "" 
 
 
 unreachCumulative (keine Historie) 
 "n.a." 
 
 
 
 
 9. Caching & Nebenläufigkeit 
 
 TTL-Cache: Die Antwort wird serverseitig bis zu 20 s zwischengespeichert. Aufeinanderfolgende Abrufe innerhalb dieses Fensters liefern denselben (bis zu 20 s alten) Stand, ohne die Zentrale erneut abzufragen. 
 Single-Flight: Pro Cache-Miss läuft höchstens eine Datenerhebung. Treffen mehrere Abrufe gleichzeitig ein, teilen sie sich das laufende Ergebnis; es werden keine parallelen Erhebungen gestartet. 
 Die Werte spiegeln den zuletzt in der Zentrale bekannten Zustand der Sensoren wider (kein aktiver Funk-Poll der Geräte beim Abruf). 
 
 
 10. Response (HTTP) 
 10.1 Status Codes 
 
 
 
 Code 
 Bedeutung 
 
 
 
 
 200 OK 
 Telemetrie erfolgreich geliefert (Body = Datenbaum) 
 
 
 401 Unauthorized 
 Fehlender oder ungültiger Authorization -Header 
 
 
 429 Too Many Requests 
 Rate Limit überschritten 
 
 
 502 Bad Gateway 
 Telemetrie nicht lesbar (Zentrale nicht erreichbar) 
 
 
 503 Service Unavailable 
 Serverseitig kein API-Token konfiguriert 
 
 
 
 10.2 Success Response 
 Body ist der vollständige Telemetrie-Datenbaum (siehe Abschnitt 11). 
 10.3 Error Response 
 {
 "error": "unauthorized"
}
 
 {
 "error": "telemetryUnavailable",
 "detail": "telemetry source returned HTTP 500"
}
 
 
 
 
 error 
 HTTP 
 Bedeutung 
 
 
 
 
 unauthorized 
 401 
 Token fehlt/falsch 
 
 
 telemetryUnavailable 
 502 
 Datenerhebung fehlgeschlagen ( detail ) 
 
 
 apiTokenNotConfigured 
 503 
 Kein Token gesetzt 
 
 
 
 
 11. Vollständiges Response-Beispiel 
 {
 "timestamp": "2026-06-09T11:24:13Z",
 "fireStation": "Feuerwehr Feuerstadt, Hauptstr. 112, 01234 Feuerstadt",
 "deviceId": "001A2B3C4D5E6F",
 "objects": [
 {
 "type": "vehicle",
 "vehicleId": "WVWZZZ3CZWE123456",
 "sign": "FS-FW 112",
 "callSign": "1-HLF20-1",
 "vehicleType": "HLF20",
 "smokeDetectors": [
 {
 "name": "1-HLF20-1 RM1",
 "address": "00AABBCCDDEE11",
 "type": "SFHSS02",
 "version": "1",
 "group": "",
 "teams": "",
 "firmware": "1.0.6",
 "rssiDevice": "-65",
 "rssiPeer": "0",
 "battery": "false",
 "unreachState": "false",
 "unreachCumulative": "0",
 "operationTime": "180",
 "dirtLevel": "0.000000",
 "smokeLevel": "0.000000",
 "alarmState": "0",
 "voltage": "3.000000",
 "chamber": "false",
 "errorCode": "0"
 },
 {
 "name": "1-HLF20-1 RM2",
 "address": "00AABBCCDDEE22",
 "type": "SFHSS02",
 "version": "1",
 "group": "",
 "teams": "",
 "firmware": "1.0.6",
 "rssiDevice": "-72",
 "rssiPeer": "0",
 "battery": "false",
 "unreachState": "false",
 "unreachCumulative": "0",
 "operationTime": "180",
 "dirtLevel": "0.000000",
 "smokeLevel": "0.000000",
 "alarmState": "0",
 "voltage": "3.000000",
 "chamber": "false",
 "errorCode": "0"
 }
 ]
 }
 ]
}