Repository navigation
Entwickler WebSocket Events
wss://einsatzcockpit.com/ws/incident/{incident_id}
Die Verbindung erfordert eine aktive Session (Session-Cookie). Ohne Login wird die Verbindung abgelehnt.
Channel 0 ist der globale Channel (neue Einsätze, systemweite Meldungen).
Alle Events sind JSON-Objekte mit einem type-Feld.
{
"type": "event_name",
"...": "weitere Felder"
}Neuer Einsatz wurde über die API angelegt.
{
"type": "incident_created",
"incident_id": 42,
"alarm": "T3",
"address": "Teststraße 1, Wolfurt",
"url": "/einsatz/42"
}Ein Partial des Boards wurde geändert (Fahrzeug verschoben, Auftrag erledigt, etc.).
{
"type": "board_update",
"target": "#vehicle-card-7",
"html": "<div id='vehicle-card-7'>...</div>"
}target ist ein CSS-Selektor. Das Frontend swappt den HTML-Inhalt (htmx.swap).
5-Minuten- oder 10-Minuten-Warnung.
{
"type": "alarm_popup",
"title": "10-Minuten-Meldung",
"message_id": 15,
"text": "Zweite Lagemeldung an Leitstelle"
}Eine Warnschwelle wurde für einen Atemschutztrupp überschritten. Wird vom Server-Watchdog (alle 5 s) gesendet, sobald eine neue Schwelle erreicht ist.
kind kann sein:
-
"one_third"– 1/3 der Einsatzzeit verstrichen, keine Lagemeldung seit Einsatzbeginn -
"withdraw"– Rückzugsdruck unterschritten -
"max_time"– Max-Einsatzzeit überschritten
{
"type": "troop_warning",
"troop_id": 3,
"kind": "withdraw"
}Eine Warnung wurde manuell quittiert (via POST /atemschutz/{troop_id}/ack).
{
"type": "troop_warning_acked",
"troop_id": 3,
"kind": "one_third"
}Eine Lagemeldung (Freitext) wurde abgesetzt.
{
"type": "troop_meldung",
"troop_id": 3,
"text": "Trupp im Treppenhaus 2. OG",
"time_warning": "ok"
}Standort eines Trupps wurde aktualisiert.
{
"type": "troop_standort",
"troop_id": 3,
"location_text": "Treppenhaus Süd"
}Einsatz wurde abgeschlossen.
{
"type": "incident_closed",
"incident_id": 42
}ws.onmessage = (event) => {
const data = JSON.parse(event.data);
switch (data.type) {
case 'board_update':
htmx.swap(data.target, data.html, { swapStyle: 'outerHTML' });
break;
case 'alarm_popup':
Alpine.store('app').showTimerAlert(data);
break;
case 'troop_warning':
Alpine.store('app').showTroopWarning(data);
break;
case 'incident_created':
Alpine.store('app').showNewIncidentToast(data);
break;
}
};Bei Verbindungsabbruch: Exponentielles Backoff (1s → 2s → 4s → max 30s).
Nach Reconnect: Vollständiger Reload des Board-Inhalts (hx-get auf den Board-Endpoint).
Bei mehreren Gunicorn-Workern halten verschiedene Worker verschiedene WebSocket-Verbindungen. Wenn Worker A eine Änderung macht, muss Worker B die Verbindungen von Worker A nicht kennen.
Lösung für Produktion: Redis Pub/Sub als gemeinsamen Message-Bus nutzen.
Empfehlung für Einzelserver: -w 1. SMS-Gateway-Sockets leben pro Worker, und der
SMS-Versand sieht auch mit Redis nur die Gateways seines eigenen Workers; Alarm-SMS benötigen
deshalb einen Worker. DIBOS, LIS, Alarm-Outbox und SMS-Nachversand werden über den Leader-Lock
(LEADER_LOCK_PATH, Standard app_storage/background-leader.lock) nur einmal gestartet.
Einsatz führen
Im Einsatz
Einsatzbegleitend
Verwaltung & Planung
Auswertung
Großschadenslage
Verwaltung
Systemadministration
- Überblick und Inbetriebnahme
- Systemdiagnose
- Datenbank: Snapshot-Isolation
- System-Admin-MCP
- Zwei-Faktor-Authentifizierung
Mehr