# Spezifikationen

# API Schnittstellenspezifikation

# API Anforderungen für Alarmierungen

**Version:** 1.2
**Stand:** März 2026
**Herausgeber:** Dexa Consult GmbH
**Produkt:** Safe Fire House (SFH)

---

## 1. Übersicht

Diese Spezifikation definiert die REST-API-Schnittstelle für die Übermittlung von Alarmdaten von der Safe Fire House Brandwarnanlage an externe Alarmierungsdienste. Die API ermöglicht sowohl die Erstmeldung eines Alarms als auch nachfolgende Updates bei Broadcast-Alarmen.

### 1.1 Alarmtypen

| Typ | Beschreibung | Methode |
|-----|--------------|---------|
| `ALARM` | Lokaler Rauchalarm – Einzelner Rauchsensor hat ausgelöst | POST |
| `ALARM` (Broadcast) | Folge-Alarm – Weitere Rauchsensoren in Funkreichweite | PUT |
| `TEST` | Schnittstellen-Test zur Validierung der Verbindung | POST |

---

## 2. API-Parameter

| Parameter | Wert |
|-----------|------|
| **Base-URL** | `https://{partner-domain}/api/v1` |
| **Content-Type** | `application/json; charset=UTF-8` |
| **Accept** | `application/json` |
| **Zeichenkodierung** | UTF-8 |

### 2.1 Authentifizierung

Die Authentifizierung erfolgt via **Bearer Token** im HTTP-Header:

```http
Authorization: Bearer {access_token}
```

| Parameter | Beschreibung |
|-----------|--------------|
| `access_token` | Vom Partner bereitgestellter API-Schlüssel (min. 32 Zeichen) |

**Hinweis:** Der Token wird pro Kunde/Standort vom Partner generiert und im SFH-System hinterlegt.

### 2.2 Rate Limiting

| Parameter | Wert |
|-----------|------|
| Max. Requests | 60 pro Minute |
| Retry-After | Bei HTTP 429 im Header angegeben |

---

## 3. Erstalarm (POST)

Sendet einen neuen Alarm an das Partner-System. Der Partner legt einen neuen Alarm-Datensatz an und gibt eine eindeutige `alarmId` zurück.

### 3.1 Request

```http
POST /api/v1/alarms HTTP/1.1
Host: {partner-domain}
Authorization: Bearer {access_token}
Content-Type: application/json
Accept: application/json
```

### 3.2 Request-Body

```json
{
  "externalCreatedAt": "2026-03-13T15:30:00Z",
  "externalId": "SFH-20260313-153000-001",
  "keyword": "ALARM",
  "keywordAddition": "RAUCHSENSOR-ALARM",
  "info": "Rauchsensor hat durch lokale Raucherkennung ausgelöst!",
  "priority": false,
  "send_push": true,
  "send_sms": false,
  "send_call": false,
  "group": "FW-Musterstadt-Zug1",
  "destination": {
    "objectName": "Feuerwehrgerätehaus Musterstadt",
    "info": "Fahrzeughalle",
    "street": "Hauptstraße",
    "houseNumber": "112",
    "zipCode": "12345",
    "city": "Musterstadt",
    "coordinates": {
      "latitude": 51.123456,
      "longitude": 7.654321
    },
    "fireAlarmSystem": "Safe Fire House"
  },
  "publisherInfos": {
    "systemName": "DXO-SFH-CU-X-02",
    "version": "2.0"
  },
  "reporter": [
    {
      "name": "HLF20-Kabine",
      "info": "Raucherkennung"
    }
  ]
}
```

### 3.3 Request-Felder

#### Root-Objekt

| Feld | Typ | Pflicht | Beschreibung |
|------|-----|---------|--------------|
| `externalCreatedAt` | string | ✓ | Zeitstempel der Alarmerstellung (ISO 8601, UTC) |
| `externalId` | string | ✓ | Eindeutige Alarm-ID aus dem SFH-System (für Idempotenz) |
| `keyword` | string | ✓ | Alarmtyp: `ALARM` oder `TEST` |
| `keywordAddition` | string | ✓ | Detailbeschreibung: `RAUCHSENSOR-ALARM`, `SCHNITTSTELLEN-TEST` |
| `info` | string | ✓ | Freitext-Information zum Alarm |
| `priority` | boolean | ✓ | Prioritäts-Flag (reserviert für zukünftige Nutzung) |
| `send_push` | boolean | ✓ | Push-Benachrichtigung senden |
| `send_sms` | boolean | ✓ | SMS-Benachrichtigung senden |
| `send_call` | boolean | ✓ | Telefonanruf auslösen |
| `group` | string | ✓ | Alarmierungsgruppe/RIC beim Partner |
| `destination` | object | ✓ | Standort-Objekt (siehe unten) |
| `publisherInfos` | object | ✓ | System-Informationen (siehe unten) |
| `reporter` | array | ✓ | Array von Rauchsensor-Objekten (siehe unten) |

#### destination-Objekt

| Feld | Typ | Pflicht | Beschreibung |
|------|-----|---------|--------------|
| `objectName` | string | ✓ | Name des Gebäudes/Objekts |
| `info` | string | | Zusatzinformation zum Standort |
| `street` | string | ✓ | Straßenname |
| `houseNumber` | string | ✓ | Hausnummer |
| `zipCode` | string | ✓ | Postleitzahl |
| `city` | string | ✓ | Stadt/Ort |
| `coordinates` | object | ✓ | Koordinaten-Objekt mit `latitude` und `longitude` |
| `fireAlarmSystem` | string | ✓ | Systemkennung, immer `Safe Fire House` |

#### coordinates-Objekt

| Feld | Typ | Pflicht | Beschreibung |
|------|-----|---------|--------------|
| `latitude` | number | ✓ | Breitengrad (WGS84, Dezimalgrad) |
| `longitude` | number | ✓ | Längengrad (WGS84, Dezimalgrad) |

#### publisherInfos-Objekt

| Feld | Typ | Pflicht | Beschreibung |
|------|-----|---------|--------------|
| `systemName` | string | ✓ | Produktkennung, z.B. `DXO-SFH-CU-X-02` |
| `version` | string | ✓ | Produktversion: `1.0` oder `2.0` |

#### reporter-Objekt (Array-Element)

| Feld | Typ | Pflicht | Beschreibung |
|------|-----|---------|--------------|
| `name` | string | ✓ | Gerätename/OPTA des auslösenden Rauchsensors |
| `info` | string | ✓ | Art der Erkennung, z.B. `Raucherkennung` |

### 3.4 Response (Erfolg)

```http
HTTP/1.1 201 Created
Content-Type: application/json
```

```json
{
  "status": "created",
  "alarmId": "550e8400-e29b-41d4-a716-446655440000",
  "received": "2026-03-13T15:30:01Z"
}
```

| Feld | Typ | Beschreibung |
|------|-----|--------------|
| `status` | string | `created` bei erfolgreichem Anlegen |
| `alarmId` | string | **Eindeutige ID des angelegten Alarms** (UUID oder PK) – wird für PUT benötigt! |
| `received` | string | Zeitstempel der Verarbeitung beim Partner (ISO 8601, UTC) |

---

## 4. Alarm-Update (PUT)

Aktualisiert einen bestehenden Alarm (z.B. bei Broadcast-Alarm, wenn weitere Rauchsensoren auslösen). Die `alarmId` aus der POST-Response wird im URL-Pfad übergeben.

### 4.1 Request

```http
PUT /api/v1/alarms/{alarmId} HTTP/1.1
Host: {partner-domain}
Authorization: Bearer {access_token}
Content-Type: application/json
Accept: application/json
```

**URL-Parameter:**

| Parameter | Beschreibung |
|-----------|--------------|
| `alarmId` | Die vom Partner beim POST zurückgegebene Alarm-ID |

### 4.2 Request-Body

```json
{
  "alarmId": "550e8400-e29b-41d4-a716-446655440000",
  "externalId": "SFH-20260313-153000-001",
  "externalUpdatedAt": "2026-03-13T15:30:10Z",
  "keyword": "ALARM",
  "keywordAddition": "RAUCHSENSOR-ALARM (BROADCAST)",
  "info": "Weitere Rauchsensoren haben durch Broadcast-Alarm ausgelöst!",
  "priority": false,
  "send_push": true,
  "send_sms": false,
  "send_call": false,
  "group": "FW-Musterstadt-Zug1",
  "destination": {
    "objectName": "Feuerwehrgerätehaus Musterstadt",
    "info": "Fahrzeughalle",
    "street": "Hauptstraße",
    "houseNumber": "112",
    "zipCode": "12345",
    "city": "Musterstadt",
    "coordinates": {
      "latitude": 51.123456,
      "longitude": 7.654321
    },
    "fireAlarmSystem": "Safe Fire House"
  },
  "publisherInfos": {
    "systemName": "DXO-SFH-CU-X-02",
    "version": "2.0"
  },
  "reporter": [
    {
      "name": "HLF20-Kabine",
      "info": "Raucherkennung"
    },
    {
      "name": "HLF20-Mannschaftsraum",
      "info": "Raucherkennung (Broadcast)"
    }
  ]
}
```

### 4.3 Unterschiede zum POST

| Feld | POST | PUT |
|------|------|-----|
| `alarmId` | Nicht vorhanden | ✓ Pflicht (im Body UND URL) |
| `externalCreatedAt` | ✓ | Nicht vorhanden |
| `externalUpdatedAt` | Nicht vorhanden | ✓ Pflicht |
| `keywordAddition` | `RAUCHSENSOR-ALARM` | `RAUCHSENSOR-ALARM (BROADCAST)` |
| `reporter` | 1 Rauchsensor | 1+ Rauchsensoren (kumulativ) |

### 4.4 Response (Erfolg)

```http
HTTP/1.1 200 OK
Content-Type: application/json
```

```json
{
  "status": "updated",
  "alarmId": "550e8400-e29b-41d4-a716-446655440000",
  "received": "2026-03-13T15:30:11Z"
}
```

---

## 5. Alarm-Status abrufen (GET)

Ruft den aktuellen Status eines Alarms ab, einschließlich der Rückmeldungen der alarmierten Einsatzkräfte.

### 5.1 Request

```http
GET /api/v1/alarms/{alarmId} HTTP/1.1
Host: {partner-domain}
Authorization: Bearer {access_token}
Accept: application/json
```

**URL-Parameter:**

| Parameter | Beschreibung |
|-----------|--------------|
| `alarmId` | Die vom Partner beim POST zurückgegebene Alarm-ID |

### 5.2 Response (Erfolg)

```http
HTTP/1.1 200 OK
Content-Type: application/json
```

```json
{
  "status": "ok",
  "alarmId": "550e8400-e29b-41d4-a716-446655440000",
  "externalId": "SFH-20260313-153000-001",
  "alarmStatus": "active",
  "createdAt": "2026-03-13T15:30:01Z",
  "updatedAt": "2026-03-13T15:30:11Z",
  "feedback": {
    "total": 12,
    "responses": [
      {
        "type": "coming",
        "label": "Komme",
        "count": 7
      },
      {
        "type": "coming_delayed",
        "label": "Komme später",
        "count": 2,
        "details": [
          { "eta": 5, "count": 1 },
          { "eta": 10, "count": 1 }
        ]
      },
      {
        "type": "not_available",
        "label": "Nicht verfügbar",
        "count": 3
      }
    ],
    "pending": 5
  },
  "received": "2026-03-13T15:31:00Z"
}
```

### 5.3 Response-Felder

#### Root-Objekt

| Feld | Typ | Beschreibung |
|------|-----|--------------|
| `status` | string | `ok` bei erfolgreicher Abfrage |
| `alarmId` | string | Partner-interne Alarm-ID (UUID/PK) |
| `externalId` | string | Ursprüngliche ID aus dem SFH-System (für Abgleich) |
| `alarmStatus` | string | Aktueller Alarmstatus (siehe Enum) |
| `createdAt` | string | Zeitpunkt der Alarmerstellung beim Partner (ISO 8601) |
| `updatedAt` | string | Zeitpunkt der letzten Aktualisierung (ISO 8601) |
| `feedback` | object | Rückmeldungs-Objekt (siehe unten) |
| `received` | string | Zeitstempel dieser Abfrage (ISO 8601) |

#### alarmStatus Enum

| Wert | Beschreibung |
|------|--------------|
| `active` | Alarm ist aktiv, Alarmierung läuft |
| `acknowledged` | Alarm wurde quittiert |
| `closed` | Alarm wurde abgeschlossen |
| `cancelled` | Alarm wurde storniert |

#### feedback-Objekt

| Feld | Typ | Beschreibung |
|------|-----|--------------|
| `total` | integer | Gesamtzahl der alarmierten Einsatzkräfte |
| `responses` | array | Array von Rückmelde-Objekten (siehe unten) |
| `pending` | integer | Anzahl noch ausstehender Rückmeldungen |

#### responses-Objekt (Array-Element)

| Feld | Typ | Pflicht | Beschreibung |
|------|-----|---------|--------------|
| `type` | string | ✓ | Maschinenlesbarer Rückmeldetyp (siehe Enum) |
| `label` | string | ✓ | Menschenlesbarer Text (Sprache des Partners) |
| `count` | integer | ✓ | Anzahl der Rückmeldungen dieses Typs |
| `details` | array | | Optional: Detailierte Aufschlüsselung (z.B. ETA-Zeiten) |

#### response.type Enum (Standardisiert)

| Typ | Beschreibung |
|-----|--------------|
| `coming` | Kommt zum Einsatz |
| `coming_delayed` | Kommt später (mit ETA) |
| `not_available` | Nicht verfügbar / Kommt nicht |
| `standby` | Bereitschaft / Evtl. verfügbar |
| `on_scene` | Bereits vor Ort |
| `unknown` | Sonstiger/Unbekannter Status |

#### details-Objekt (Optional, für coming_delayed)

| Feld | Typ | Beschreibung |
|------|-----|--------------|
| `eta` | integer | Geschätzte Ankunftszeit in Minuten |
| `count` | integer | Anzahl mit dieser ETA |

### 5.4 Beispiel: Status-Abfrage

```bash
curl -X GET "https://partner.example.com/api/v1/alarms/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Accept: application/json"
```

**Response:**
```json
{
  "status": "ok",
  "alarmId": "550e8400-e29b-41d4-a716-446655440000",
  "externalId": "SFH-20260313-153000-001",
  "alarmStatus": "active",
  "createdAt": "2026-03-13T15:30:01Z",
  "updatedAt": "2026-03-13T15:30:11Z",
  "feedback": {
    "total": 12,
    "responses": [
      { "type": "coming", "label": "Komme", "count": 7 },
      { "type": "coming_delayed", "label": "Komme später", "count": 2, "details": [{ "eta": 5, "count": 1 }, { "eta": 10, "count": 1 }] },
      { "type": "not_available", "label": "Nicht verfügbar", "count": 3 }
    ],
    "pending": 5
  },
  "received": "2026-03-13T15:31:00Z"
}
```

---

## 6. Fehlerbehandlung

### 6.1 HTTP-Statuscodes

| Code | Bedeutung | Beschreibung |
|------|-----------|--------------|
| `200` | OK | Alarm erfolgreich aktualisiert (PUT) |
| `201` | Created | Alarm erfolgreich angelegt (POST) |
| `400` | Bad Request | Ungültiger Request-Body oder fehlende Pflichtfelder |
| `401` | Unauthorized | Fehlender oder ungültiger Bearer Token |
| `403` | Forbidden | Token gültig, aber keine Berechtigung für diese Ressource |
| `404` | Not Found | Alarm-ID nicht gefunden (bei PUT) |
| `409` | Conflict | Alarm mit dieser `externalId` existiert bereits (bei POST) |
| `429` | Too Many Requests | Rate Limit überschritten |
| `500` | Internal Server Error | Serverfehler beim Partner |
| `503` | Service Unavailable | Partner-System temporär nicht verfügbar |

### 6.2 Fehler-Response

```json
{
  "status": "error",
  "error": "invalid_payload",
  "message": "Field 'externalId' is required",
  "received": "2026-03-13T15:30:01Z"
}
```

| Feld | Typ | Beschreibung |
|------|-----|--------------|
| `status` | string | Immer `error` |
| `error` | string | Fehlercode (siehe unten) |
| `message` | string | Menschenlesbare Fehlerbeschreibung |
| `received` | string | Zeitstempel der Fehlerverarbeitung |

### 6.3 Fehlercodes

| Code | Beschreibung |
|------|--------------|
| `invalid_payload` | JSON-Syntax ungültig oder Pflichtfeld fehlt |
| `invalid_field` | Feldwert entspricht nicht dem erwarteten Format |
| `unauthorized` | Token fehlt oder ist ungültig |
| `forbidden` | Keine Berechtigung für diese Operation |
| `not_found` | Ressource (Alarm) nicht gefunden |
| `duplicate` | Alarm mit dieser `externalId` existiert bereits |
| `rate_limited` | Zu viele Anfragen |
| `internal_error` | Interner Serverfehler |

---

## 7. Idempotenz & Retry-Verhalten

### 7.1 Idempotenz

Das Feld `externalId` dient der Idempotenz-Sicherung:

- Bei wiederholtem POST mit gleicher `externalId` sollte der Partner **HTTP 409 Conflict** zurückgeben
- Alternativ kann der Partner ein Upsert-Verhalten implementieren (Update statt Insert)

### 7.2 Retry-Strategie (SFH-seitig)

| Fehlertyp | Retry | Wartezeit |
|-----------|-------|-----------|
| Netzwerkfehler | Ja | 5s, 10s, 30s |
| HTTP 5xx | Ja | 5s, 10s, 30s |
| HTTP 429 | Ja | Retry-After Header beachten |
| HTTP 4xx (außer 429) | Nein | – |

---

## 8. Sicherheitsanforderungen

| Anforderung | Beschreibung |
|-------------|--------------|
| **Transport** | Ausschließlich HTTPS (TLS 1.2+) |
| **Token-Speicherung** | Access Token verschlüsselt auf der SFH-Zentrale |
| **Token-Rotation** | Empfohlen: Jährliche Erneuerung |
| **IP-Whitelisting** | Optional: Partner kann SFH-IPs whitelisten |

---

## 9. Beispiel: Vollständiger Alarm-Flow

### 9.1 Schritt 1: Lokaler Alarm (POST)

Ein Rauchsensor im HLF20 löst aus:

```bash
curl -X POST "https://partner.example.com/api/v1/alarms" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "externalCreatedAt": "2026-03-13T15:30:00Z",
    "externalId": "SFH-20260313-153000-001",
    "keyword": "ALARM",
    "keywordAddition": "RAUCHSENSOR-ALARM",
    "info": "Rauchsensor hat durch lokale Raucherkennung ausgelöst!",
    "priority": false,
    "send_push": true,
    "send_sms": false,
    "send_call": false,
    "group": "FW-Musterstadt-Zug1",
    "destination": {
      "objectName": "Feuerwehrgerätehaus Musterstadt",
      "info": "Fahrzeughalle",
      "street": "Hauptstraße",
      "houseNumber": "112",
      "zipCode": "12345",
      "city": "Musterstadt",
      "coordinates": { "latitude": 51.123456, "longitude": 7.654321 },
      "fireAlarmSystem": "Safe Fire House"
    },
    "publisherInfos": { "systemName": "DXO-SFH-CU-X-02", "version": "2.0" },
    "reporter": [{ "name": "HLF20-Kabine", "info": "Raucherkennung" }]
  }'
```

**Response:**
```json
{
  "status": "created",
  "alarmId": "550e8400-e29b-41d4-a716-446655440000",
  "received": "2026-03-13T15:30:01Z"
}
```

### 9.2 Schritt 2: Broadcast-Alarm (PUT)

~10 Sekunden später lösen weitere Rauchsensoren im Fahrzeug aus:

```bash
curl -X PUT "https://partner.example.com/api/v1/alarms/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "alarmId": "550e8400-e29b-41d4-a716-446655440000",
    "externalId": "SFH-20260313-153000-001",
    "externalUpdatedAt": "2026-03-13T15:30:10Z",
    "keyword": "ALARM",
    "keywordAddition": "RAUCHSENSOR-ALARM (BROADCAST)",
    "info": "Weitere Rauchsensoren haben durch Broadcast-Alarm ausgelöst!",
    "priority": false,
    "send_push": true,
    "send_sms": false,
    "send_call": false,
    "group": "FW-Musterstadt-Zug1",
    "destination": {
      "objectName": "Feuerwehrgerätehaus Musterstadt",
      "info": "Fahrzeughalle",
      "street": "Hauptstraße",
      "houseNumber": "112",
      "zipCode": "12345",
      "city": "Musterstadt",
      "coordinates": { "latitude": 51.123456, "longitude": 7.654321 },
      "fireAlarmSystem": "Safe Fire House"
    },
    "publisherInfos": { "systemName": "DXO-SFH-CU-X-02", "version": "2.0" },
    "reporter": [
      { "name": "HLF20-Kabine", "info": "Raucherkennung" },
      { "name": "HLF20-Mannschaftsraum", "info": "Raucherkennung (Broadcast)" }
    ]
  }'
```

**Response:**
```json
{
  "status": "updated",
  "alarmId": "550e8400-e29b-41d4-a716-446655440000",
  "received": "2026-03-13T15:30:11Z"
}
```

---

## Anhang A: Constraints

| Feld | Constraint |
|------|------------|
| `externalId` | Max. 50 Zeichen, Pattern: `[A-Za-z0-9\-]+` |
| `keyword` | Enum: `ALARM`, `TEST` |
| `keywordAddition` | Max. 50 Zeichen |
| `info` | Max. 500 Zeichen |
| `group` | Max. 100 Zeichen |
| `destination.street` | Max. 100 Zeichen |
| `destination.houseNumber` | Max. 10 Zeichen |
| `destination.zipCode` | 5 Zeichen (DE) |
| `destination.city` | Max. 100 Zeichen |
| `coordinates.latitude` | -90.0 bis 90.0 |
| `coordinates.longitude` | -180.0 bis 180.0 |
| `reporter[].name` | Max. 50 Zeichen |
| `reporter` Array | Min. 1 Element |

---

# API Anforderungen für Telemetrie-Upload

**Version:** 1.1
**Stand:** März 2026
**Herausgeber:** Dexa Consult 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
        }
      ]
    }
  ]
}
```

---

# Funktionserfüllung Safe Fire House Anlage

### 1. Preiskalkulation

- Angebot eines All-Inklusive-Preises, unabhängig von Anzahl, Art und Beschaffenheit der Komponenten, Standorte oder Fahrzeuge.
- Preis unabhängig von Kommunikationsschnittstellen oder auszuführenden Aktionen – stets inkludiert – als Pauschalpreis pro Fahrzeug, Halle oder Raum, mit Bruttopreissumme.
- Inkludierung aller Service-Nebenkosten und Stundensätze, außer Reisekosten. Keine laufenden bzw. konsumtiven Kosten oder Lizenzen.
- Inkludierung aller Kosten für laufenden Betrieb, Projektierung, Programmierung, Installation, Inbetriebnahme und Dokumentation.

### 2. Systemaufbau

- Modularer, individueller und flexibler Aufbau entsprechend den Anforderungen von Fahrzeugen und Standorten.
- Verwendung namhafter Komponentenhersteller
- Betrieb ausschließlich on-premise (nicht cloud-basiert). Keine Abhängigkeit von Mobilfunk- oder Clouddiensten bei der Verbindung von Meldern/Sensoren zu Alarmsystemen, oder Angebot einer gleichwertigen lokalen Redundanz.
- Permanente Überwachung aller Komponenten und Kommunikationswege, die größtenteils redundant ausgelegt werden müssen.
- Ausführbar als Mehr-Standort-Lösung, sprich standortübergreifende Überwachung von Fahrzeugen ohne manuellen Eingriff, ohne An- oder Abmelden bzw. An- oder Ablernen. Alarmierung inklusive aktueller Standortdaten (Rauchalarm in Fahrzeug X, Melder Y aktuell an Standort Z).
- Keine manuelle Eingriffsnotwendigkeit bei Verlassen des Standortes, keine Notwendigkeit zu quittieren. Auch bei Wechsel des Fahrzeugs an einen anderen überwachten Standort.
- Anlage nahtlos erweiterbar von 1 Fahrzeug (bzw. Halle oder Raum) an 1 Standort bis zu 1.000 Fahrzeugen (bzw. Halle oder Raum) an 200 Standorten.
- TCP/IP-Kommunikation als Grundarchitektur, alle Kommunikationswege (auch Funk) sind bidirektional, verschlüsselt und protokollierbar auszuführen. Ausführung aller IT-Komponenten in PoE.
- Anbindungsmöglichkeit an alle gängigen Leitstellensysteme aus dem BOS-Bereich.
- Anbindungsmöglichkeit an Brandmeldeanlagen über potenzialfreien Schaltkontakt. Aufschaltung auf eine Kreisleitstelle mit behördlicher Genehmigung im Rahmen der geltenden Aufschaltbedingungen möglich.
- Auslegung der Anlage als Gefahrenwarnanlage in Anlehnung an VDE 0826.
- Anbindungsmöglichkeit an gängige Gebäudeleitsysteme (BUS- oder TCP/IP-basiert).
- Schriftliche Bestätigung des Herstellers des Gesamtsystems, dass es zum Einsatzzweck der Überwachung der Fahrzeuginnenräume geeignet ist, zur Haftungssicherheit.
- Testat einer namhaften Prüforganisation über die Eignung zum Einsatz in Einsatzfahrzeugen.
- Regel-Lebensdauer der Anlage von bis zu 10 Jahren, wartungsfrei.

### 3. Branderkennung und Alarmverarbeitung

- Zentrales Alarmmanagement
- Photoelektrische Erkennung
- Batterielebensdauer: ausgelegt auf bis zu 10 Jahre
- Kommunikationsprotokolle: bidirektionales Funkband (z. B. 868 MHz) und TCP/IP
- Verschlüsselung: AES (mind. 128 Bit), optional HMAC
- Reichweite: bis zu 300 m (Freifeld), mehrfach erweiterbar durch Repeater
- Zertifizierungen der Rauchmelder (nur bei Meldern in Gebäuden, nicht in Fahrzeugen): VdS, Q-Label, DIN EN 14604/14676
- Schutzklassen: IP20 bis IP44 (je nach Komponente)
- Alarmierung: Piezo-Signalgeber (85 dB/3 m), zusätzlich auch ausführbar in leise (50 dB/3 m) und stumm
- (Optional): Server-Variante (Central Unit Pro) zur Installation in einem 19-Zoll Server-Rack für große Installationen zur Virtualisierung des Systems.
- Selbstkalibrierend
- Selbsttestfunktion, Watchdog-Funktion, zentrale Batterieüberwachung
- Hochpräzise Sensoren für Partikelerkennung, erweiterter Insektenschutz
- LED-Notbeleuchtung bei Alarm
- Autarker Betrieb der Rauchsensoren bei Zentralenausfall – lokale Alarmierung weiter möglich
- (Optional): Infrastrukturmodul: Schaltkasten oder mobiler Koffer mit unterbrechungsfreier Batteriepufferung (USV) bis zu 72 Stunden und redundanter Internetanbindung (WAN + LTE/5G) im M2M-Betrieb für höchste Ausfallsicherheit.
- (Optional): Alarmsirene: Externe LED-Alarmsirene zur optischen und akustischen Signalisierung, außeninstallationstauglich (IP44), Batterie-/Solar- oder 230V-Betrieb, mit integrierter Blitzleuchte
- (Optional): Schaltkontakt: Potenzialfreier Schaltkontakt zur Anbindung von Brandmeldeanlagen und Gebäudeleittechnik, verfügbar als 1-fach und 4-fach Variante mit bis zu 4 Eingangs- und 4 Ausgangskanälen
- Erweiterte API-Unterstützung: REST-API (POST/PUT/GET), MQTT optional, Webhooks
- Bidirektionale Anbindung von Schnittstellen: Alle gängigen Alarmsysteme aus dem BOS-Bereich, z. B. DIVERA24/7, Alamos, Groupalarm, Dräger, WeberRescue, Feuersoftware, Fireboard, Feuernetz, DE-Alarm, alarmdispatcher, FF-Agent, Handyalarm.com, Solaris/Blaulicht SMS, …
- Anbindung an Verwaltungssysteme wie Fireplan, Solaris, FWPortal, MPFeuer
- Wartungsinformationen als Schnittstellenanbindung zu Flottenmanagement- und Rettungsdienst-Systemen, z. B. ZF Rescue Connect, Dräger Smart Rescue System, Weber Rescue RetterAlarm
- Alarmanbindung durch Softwareschnittstellen für TR-BOS-konforme digitale Meldeempfänger, zum Beispiel über LTE (Swissphone oder Oelmann Electronics) über die Dexa Pager Plattform
- Leitstellenanbindung: gängige Leitstellensysteme, z. B. ISE Cobra4, CKS Celios, VivaSecur LVS, ELIS, Hexagon, …
- Schaltanbindung an Brandmeldeanlagen über potenzialfreien Schaltkontakt
- Niederschwellige Alarmwege wie Telefonansage mit Rückmeldestatus, SMS, E-Mail
- Alarmüberlauf auf andere Gruppen und Schnittstellen, abhängig von Rückmeldungen der alarmierten Einheiten
- Mindestens wöchentlicher Statusbericht bei Nichterreichbarkeit von Schnittstellen oder Komponenten
- Mindestens monatlicher Statusbericht über alle Komponenten mit Batterieständen, Verschmutzungsgraden und weiteren Zuständen
- Sichere Anbringung in Fahrzeugen (z. B. 3M Dual-Lock o.ä.) oder Verschraubung
- Gebäudeleittechnik: anbindbar mit TCP/IP, Webhooks, an KNX, Home Assistant, Symcon, DALI, BACnet, MODBUS
- (Optional): Mini-Display mit E-Ink-Technologie zur Alarmanzeige, auch als konfigurierbares Taster-Element nutzbar, 230V-stromversorgt
- (Optional): Fest installierbares Netzwerkdisplay (PoE) zur Alarmanzeige, Steuerung und Überwachung der Anlage in verschiedenen Größen und Formfaktoren, versorgt über PoE, mit Möglichkeit zur Alarmquittierung, Anlagenkonfiguration und Unscharfschaltung
- Netzwerkkompatibilität im Enterprise-Umfeld, Firewall-Betrieb (z. B. Sophos)
- Grafische Bedienoberfläche aus internem und externem Netzwerk über Internetfreigabe (verschlüsselt und geschützt) erreichbar.
- Umfangreiche Zustandsüberwachung und Steuerung über digitales Bedientableau und grafische Oberfläche (GUI) möglich (GUI verfügbar im Rahmen einer Wartungsvereinbarung)

### 4. Installation und Inbetriebnahme

- Durchführung durch erfahrene technische Angestellte mit Erfahrung in TGA-, ITK-Systemen und/oder Fahrzeugtechnik
- Individuelle standortabhängige Programmierung
- Vorab-Tests und Simulationen zur Funktionssicherung
- Schulungen für Bedienpersonal, Wartungstechniker und IT-Administratoren

### 5. Dokumentation und Güte

- Vollständige technische Dokumentation: Installation, Betriebstest, Messwerte, Konfiguration, Nachweis eines Alarmtests
- Positiver Prüfbericht einer namhaften Prüfstelle für Brandschutztechnik, in diesem Falle der Prüfstelle für Brandschutztechnik des Österreichischen Bundesfeuerwehrverbandes (Prüfbericht-Nr. FT 14/953/25, gültig bis 02.12.2027).

### 6. Service

- Dediziertes Supportteam, optional Vor-Ort-Service und Remote-Unterstützung
- Umfassende Möglichkeiten zur Fernwartung
- Optionale Möglichkeit zum Abschluss einer Wartungsvereinbarung für erweiterte Funktionalitäten und externes Monitoring der Anlagenverfügbarkeit
- Zentrales Service-Logbuch zur Überwachung der Systemzuverlässigkeit durch Anbieter