# API-Anforderungen für Telemetrie-Upload

**Version:** 1.1  
**Stand:** März 2026  
**Herausgeber:** Dexa Solutions GmbH  
**Produkt:** Safe Fire House (SFH)  

---

## 1. Übersicht

Dieses Dokument beschreibt die REST-API-Anforderungen für die Übermittlung von Telemetriedaten der Safe Fire House Brandwarnanlage. Die Zentrale sendet stündlich die aktuellen Daten der Anlage an einen REST-API-Endpoint.

Folgende Parameter müssen unterstützt werden:

| Parameter        | Wert                                           |
| ---------------- | ---------------------------------------------- |
| **Method**       | `POST`                                         |
| **Content-Type** | `application/json`                             |
| **Accept**       | `application/json`                             |
| **Frequenz**     | Zyklisch (stündlich) 24/7, azyklisch bei Alarm |
| **Rate Limit**   | Max. 60 Requests/Minute                        |

### 1.1 Authentifizierung

Eine der folgenden Authentifizierungsmethoden muss unterstützt werden:

| Methode                     | Header / Mechanismus    | Beispiel                                        |
| --------------------------- | ----------------------- | ----------------------------------------------- |
| **API-Key**                 | `X-API-Key`             | `X-API-Key: sk_live_abc123...`                  |
| **Bearer Token (JWT)**      | `Authorization: Bearer` | `Authorization: Bearer eyJhbGciOiJIUzI1NiIs...` |
| **X.509 Client-Zertifikat** | mTLS (Mutual TLS)       | Client-Zertifikat im TLS-Handshake              |

---

## 2. Payload-Struktur

```
Root
├── timestamp
├── fireStation
├── deviceId
└── vehicles[]
    ├── vehicleId
    ├── sign
    ├── callSign
    ├── vehicleType
    └── smokeDetectors[]
        ├── name
        ├── address
        ├── type
        └── ...
```

---

## 3. 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               |
| `vehicles`    | Auflistung der Fahrzeuge   | `array`  | Array von Vehicle-Objekten            |

**Beispiel:**

```json
{
  "timestamp": "2026-03-13T11:24:13Z",
  "fireStation": "Feuerwehr Feuerstadt, Hauptstr. 112, 01234 Feuerstadt",
  "deviceId": "001A2B3C4D5E6F",
  "vehicles": [ ... ]
}
```

---

## 4. Vehicle-Objekt

| Key              | Description                          | Type     | Constraints                      |
| ---------------- | ------------------------------------ | -------- | -------------------------------- |
| `vehicleId`      | Fahrzeug-Identifikationsnummer (VIN) | `string` | 17 Zeichen                       |
| `sign`           | Kennzeichen                          | `string` | Max. 10 Zeichen                  |
| `callSign`       | Funkrufname                          | `string` | Max. 50 Zeichen                  |
| `vehicleType`    | Fahrzeugtyp                          | `string` | Max. 50 Zeichen                  |
| `smokeDetectors` | Auflistung der Rauchsensoren         | `array`  | Array von SmokeDetector-Objekten |

**Beispiel:**

```json
{
  "vehicleId": "WVWZZZ3CZWE123456",
  "sign": "FS-FW 112",
  "callSign": "1-HLF20-1",
  "vehicleType": "HLF20",
  "smokeDetectors": [ ... ]
}
```

---

## 5. SmokeDetector-Objekt

| Key                 | Description                           | Type      | Constraints                        |
| ------------------- | ------------------------------------- | --------- | ---------------------------------- |
| `name`              | Rauchsensorbezeichnung                | `string`  | Max. 30 Zeichen                    |
| `address`           | Rauchsensoradresse                    | `string`  | 14 Zeichen, hexadezimal            |
| `type`              | Rauchsensortyp                        | `string`  | Max. 20 Zeichen                    |
| `version`           | Hardware-Version                      | `integer` | ≥ 1                                |
| `firmware`          | Firmware-Version                      | `string`  | Max. 9 Zeichen, Pattern: `[0-9.]+` |
| `group`             | Gruppierung                           | `string`  | `0`–`9` oder leer                  |
| `teams`             | Reserviert                            | `array`   | —                                  |
| `rssiDevice`        | Funkempfangswert Gerät (dBm)          | `integer` | −128 bis 128                       |
| `rssiPeer`          | Funkempfangswert Sender (dBm)         | `integer` | −128 bis 128                       |
| `unreachState`      | Flag: Gerät nicht erreichbar          | `boolean` | `true` / `false`                   |
| `unreachCumulative` | Kumulierte Nichterreichbarkeit (Tage) | `integer` | 0–9999                             |
| `operationtime`     | Betriebszeit (Tage)                   | `integer` | 0–9999                             |
| `battery`           | Flag: Batterieleistung niedrig        | `boolean` | `true` / `false`                   |
| `voltage`           | Batteriespannung (V)                  | `float`   | 0.0–3.2                            |
| `errorcode`         | Fehlercode                            | `integer` | 0–99                               |
| `alarmstate`        | Alarmstatus                           | `integer` | 0–3 (siehe Enum)                   |
| `smokelevel`        | Raucherkennungsgrad (%)               | `float`   | 0.0–100.0                          |
| `dirtlevel`         | Verschmutzungsgrad (%)                | `float`   | 0.0–100.0                          |
| `chamber`           | Flag: Rauchkammer verschmutzt         | `boolean` | `true` / `false`                   |

**Beispiel:**

```json
{
  "name": "1-HLF20-1 RM1",
  "address": "00AABBCCDDEE11",
  "type": "DXO-SFH-SD-XX-02",
  "version": 1,
  "group": "",
  "teams": [],
  "firmware": "1.0.6",
  "rssiDevice": -65,
  "rssiPeer": 0,
  "battery": false,
  "unreachState": false,
  "unreachCumulative": 0,
  "operationtime": 180,
  "dirtlevel": 0.0,
  "smokelevel": 0.0,
  "alarmstate": 0,
  "voltage": 3.0,
  "chamber": false,
  "errorcode": 0
}
```

---

## 6. Enums

### 6.1 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. 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. Response

### 8.1 Erwartete HTTP Status Codes

| Code                        | Bedeutung                                 |
| --------------------------- | ----------------------------------------- |
| `200 OK`                    | Erfolgreich verarbeitet                   |
| `400 Bad Request`           | Ungültiger Payload                        |
| `401 Unauthorized`          | Fehlende oder ungültige Authentifizierung |
| `403 Forbidden`             | Keine Berechtigung                        |
| `429 Too Many Requests`     | Rate Limit überschritten                  |
| `500 Internal Server Error` | Serverfehler                              |
| `503 Service Unavailable`   | Service nicht verfügbar                   |

### 8.2 Success Response

```json
{
  "status": "ok",
  "received": "2026-03-13T11:24:13Z"
}
```

### 8.3 Error Response

```json
{
  "error": "invalid_payload",
  "message": "Field 'address' invalid"
}
```

---

## 9. Vollständiges Payload-Beispiel

```json
{
  "timestamp": "2026-03-13T11:24:13Z",
  "fireStation": "Feuerwehr Feuerstadt, Hauptstr. 112, 01234 Feuerstadt",
  "deviceId": "001A2B3C4D5E6F",
  "vehicles": [
    {
      "vehicleId": "WVWZZZ3CZWE123456",
      "sign": "FS-FW 112",
      "callSign": "1-HLF20-1",
      "vehicleType": "HLF20",
      "smokeDetectors": [
        {
          "name": "1-HLF20-1 RM1",
          "address": "00AABBCCDDEE11",
          "type": "DXO-SFH-SD-XX-02",
          "version": 1,
          "group": "",
          "teams": [],
          "firmware": "1.0.6",
          "rssiDevice": -65,
          "rssiPeer": 0,
          "battery": false,
          "unreachState": false,
          "unreachCumulative": 0,
          "operationtime": 180,
          "dirtlevel": 0.0,
          "smokelevel": 0.0,
          "alarmstate": 0,
          "voltage": 3.0,
          "chamber": false,
          "errorcode": 0
        },
        {
          "name": "1-HLF20-1 RM2",
          "address": "00AABBCCDDEE22",
          "type": "DXO-SFH-SD-XX-02",
          "version": 1,
          "group": "",
          "teams": [],
          "firmware": "1.0.6",
          "rssiDevice": -72,
          "rssiPeer": 0,
          "battery": false,
          "unreachState": false,
          "unreachCumulative": 0,
          "operationtime": 180,
          "dirtlevel": 0.0,
          "smokelevel": 0.0,
          "alarmstate": 0,
          "voltage": 3.0,
          "chamber": false,
          "errorcode": 0
        }
      ]
    }
  ]
}
```

---