Skip to content

WebSocket

Die REST-API eignet sich gut, um auf ausgelöste Requests Daten gezielt abzufragen und zurückzugeben. Allerdings hat das Konzept einen entscheidenden Nachteil um die Benutzeroberfläche aktuell zu halten. Ein Dashboard müsste dafür ständig Anfragen an den Server senden (Polling), was Last erzeugt und in den meisten Fällen nur die CPU blockiert und keine Änderungen zurückgibt, da es keine gibt.

Deshalb ergänz eine WebSocket-Schnittstelle die REST-API: Über diese kann das Backend Aktualisierungen direkt an die Oberflächen senden, sobald sie auftreten.

Für diese und weitere Funktionalitäten wird Socket.IO als Framework genutzt.

Verbindungsaufbau

Die WebSocket-Verbindung wird über die URL api/v1/ws aufgebaut. Nach dem Verbindungsaufbau empfängt der Client zunächst keine Daten sondern registriert erst, für welche Geräte dieser Aktualisierungen erhält.

Abonnements

Damit ein Client nicht die Telemetrie und Aktualisierungen aller Geräte empfängt stellt Socket.IO ein Abonnement-Modell zur Verfügung. Für jedes Gerät existiert intern ein eigener Raum (device:<uuid>). Somit kann ein Client den jeweiligen Raum der eingebundenen Geräte abonnieren und bekommt auch nur diese Daten.

Ereignis (Client → Server) Bedeutung
subscribe mit uuid Gerät abonnieren: Raum beitreten
unsubscribe mit uuid Abonnement beenden: Raum verlassen

Server-Ereignisse

Für jedes abonnierte Gerät sendet der Server drei Arten von Ereignissen:

Ereignis (Server → Client) Nutzlast Bedeutung
telemetry { uuid, data, timestamp } Neue Messwerte des Geräts
status { uuid, status } Verbindungsstatus wechselt (online/offline)
invalidate { uuid } Das Thing Model hat sich geändert

Bei einer Neuanmeldung eines Geräts wird ein invalidate-Event gesendet. Dieses signalisiert den Frontends, die das Gerät eingebunden haben, dass das Thing Model möglicherweise nicht mehr aktuell ist. Dies kann beispielsweise der Fall sein, wenn das Gerät zwischenzeitlich verändert oder neu geflasht wurde. Die betroffenen Clients können anschließend über die REST-API das aktualisierte Thing Model abrufen.

Zusammenspiel mit MQTT

  • Telemetrie wird ausgelöst, wenn ein Gerät Werte per MQTT sendet. Das Backend sendet daraufhin das telemetry-Ereignis dabei vor dem Schreiben in die Datenbank, damit die Daten möglichst schnell in der Oberfläche aktualisiert werden.
  • Status ergibt sich aus dem Verbindungszustand des Geräts. Verliert ein Gerät die Verbindung, meldet der Broker dies über die LWT-Nachricht. Das Backend gibt den Wechsel als status-Ereignis an die Oberflächen weiter.
sequenceDiagram
    participant Geraet as Gerät
    participant MQTT as MQTT-Broker
    participant Backend as Backend
    participant UI as Oberfläche

    UI->>Backend: subscribe(uuid)

    Geraet->>MQTT: Telemetrie publizieren
    MQTT->>Backend: Telemetrie
    Backend-->>UI: telemetry
    Backend->>Backend: Queue + DB

    Geraet--xMQTT: Verbindung verloren
    MQTT->>Backend: Last Will (offline)
    Backend-->>UI: status (offline)