Wie es funktioniert
Protokoll
Zwei Strecken, zwei Protokolle. JSON über MQTT mit TLS zum Server, binär über CAN zu den Modulen.
Auf dieser Seite
MQTT: Hub und Server
MQTT verbindet nur Hub und Server, dazu die Anzeigen im WLAN mit dem Server. Es läuft immer über
TLS, am Port 8883 des Servers. Nachrichten sind JSON. Die Felder stehen als Schemata im Paket
packages/protocol und werden auf beiden Seiten geprüft. Der Browser spricht nie MQTT, sondern
HTTPS und WebSocket mit dem Backend.
Topics
| Topic | Richtung | retained | Inhalt |
|---|---|---|---|
sb/<hub>/status |
Hub → Server | ja | online oder offline, zugleich Last Will |
sb/<hub>/discovery |
Hub → Server | ja | erkannte, noch nicht übernommene Module |
sb/<hub>/config |
Server → Hub | ja | Konfiguration des Hubs |
sb/<hub>/<modul>/status |
Hub → Server | ja | Modulstatus mit Selbstbeschreibung |
sb/<hub>/<modul>/<kanal>/state |
Hub → Server | nein | Messwert oder Zustand |
sb/<hub>/<modul>/<kanal>/cmd |
Server → Hub | nein | Befehl an einen Aktor |
sb/<hub>/controller/<name>/setpoint |
Server → Hub | ja | Sollwerte |
sb/<hub>/controller/<name>/state |
Hub → Server | nein | was ein Regler gerade tut |
sb/<hub>/event |
Hub → Server | nein | Alarme, Sicherheitsabschaltungen, Begründungen |
sb/<hub>/update |
Server → Hub | nein | Hinweis auf neue Firmware, die Datei kommt per HTTPS |
sb/<hub>/resource/<id>/cmd |
Server → Hub | nein | Befehl an eine Ressource, etwa „Auffüllen“ |
sb/<hub>/weather |
Server → Hub | nein | Wind und Böen für den Windschutz |
sb/<hub>/alarms |
Server → Hub | ja | offene Alarme für die Anzeigen, zugleich Lebenszeichen des Servers |
sb/<hub>/<modul>/ui |
Hub → Server | ja | was eine Anzeige am Bus gerade zeigt |
sb/provision/<serial>/hello |
Hub → Server | nein | Anmeldung eines Hubs, der noch nicht übernommen ist |
sb/provision/<serial>/credentials |
Server → Hub | nein | Zugangsdaten bei der Übernahme |
<modul> ist die Seriennummer des Moduls. Die Busadresse vergibt der Hub, sie kann sich ändern.
Die Seriennummer bleibt, deshalb hängen Verläufe an ihr. Das Hub-eigene Modul heißt hub.
<kanal> ist die Kennung aus der Selbstbeschreibung, zum Beispiel temp oder out1.i.
Befehle, Konfiguration, Sollwerte, Ereignisse, Status, Wetter und Alarme gehen mit QoS 1, Messwerte und der Bildschirm der Anzeige mit QoS 0.
Online und offline
Der Keepalive ist seit 0.10.0 10 Sekunden statt 30. Der Broker trennt einen stummen Hub nach 15 Sekunden und veröffentlicht seinen Last Will: Ein Hub ohne Strom ist nach höchstens etwa 15 Sekunden offline. Ein Stromausfall schickt kein Abschiedswort. Meldet sich ein Hub nach einem Neustart wieder an, veröffentlicht der Broker sofort den Last Will der alten Verbindung, gleich danach meldet der Hub wieder online.
Ein Modul zählt beim Server nur als online, solange sein Hub online ist. Meldet der Hub offline, setzt der Server alle seine Module auf offline. Ein aufbewahrter Status eines Moduls holt es nicht zurück, bis der Hub wieder online ist.
In der anderen Richtung hört jeder Hub, der online ist, spätestens alle 40 Sekunden etwas vom Server: Ging 30 Sekunden lang nichts an ihn, schickt der Server ihm seine Alarmliste erneut, auch leer. Das verstehen alle Hub-Firmwares ab 0.4.0. Bleibt ein Hub trotzdem 80 Sekunden im autonomen Betrieb, kommt bei ihm nichts an, etwa wegen der Rechte am Broker. Der Server meldet dann „Hub empfängt nichts vom Server“.
Befehle und ihre Antwort
Jeder Befehl trägt eine eigene Kennung. Der Hub antwortet mit einem Ereignis, das sagt, ob der Befehl ausgeführt wurde, und wenn nicht, warum.
{
"id": "e-1",
"t": 1727430001,
"severity": "info",
"code": "cmd_result",
"cmdId": "c-42",
"ok": false,
"cause": { "kind": "interlock", "code": "tank_low", "values": { "level": 6, "min": 10 } }
}
Ausschalten wird nie abgelehnt.
Befehle an einen Ausgang
| Befehl | Wirkung |
|---|---|
set |
Stellwert setzen, von Hand mit Dauer |
unlock |
Sperre freigeben |
teach |
Normalstrom einlernen, an einem Antrieb der Kalibrierlauf |
calibrate |
Kalibrierlauf eines Antriebs starten |
mark |
während des Laufs: „Jetzt offen“ oder „Jetzt zu“ |
cancel |
Kalibrierlauf abbrechen, der Antrieb bleibt stehen |
Das Ergebnis eines Kalibrierlaufs kommt später als eigenes Ereignis mit der Kennung des Befehls. Die Abläufe stehen unter Antriebe und Kalibrieren.
Wetter für den Windschutz
Ohne Windmodul nutzt der Hub das Wetter vom Server:
{ "t": 1727430001, "windMs": 3.4, "gustMs": 7.9, "validS": 3600 }
Die Nachricht gilt ab dem Empfang so lange, wie validS sagt. Der Hub braucht dafür keine
gestellte Uhr. Sie ist nicht retained, damit ein Hub nach einem Neustart keine alte Lage für neu
hält.
Einen Hub übernehmen
Geräte werden nicht konfiguriert, sondern übernommen.
-
Eingetragene Adresse, sonst mDNS, sonst Suche im eigenen Netz nach Port 8443 und 443. Jeden Kandidaten prüft er über HTTPS: Das CA-Zertifikat muss zum Server-Schlüssel im Einrichtungscode passen. Die Netzsuche kann bis etwa drei Minuten dauern.
-
Der Hub verbindet sich per MQTT über TLS als Einrichtungsbenutzer. Das Passwort ist der Einrichtungscode, den Admins in der Oberfläche sehen. Alle 10 Sekunden meldet er sich.
-
Der Code allein gibt keinen Zugriff. Übernehmen muss immer ein Admin.
-
Der Server legt im Broker einen Benutzer an, der nur die Topics dieses Hubs lesen und schreiben darf, und schickt dem Hub die Zugangsdaten.
-
Der Hub speichert die Zugangsdaten, trennt und verbindet sich unter seiner eigenen Kennung. Er meldet Status und Selbstbeschreibung.
-
Der Server schickt die Konfiguration. Ab jetzt kommen Messwerte.
Einrichtungscode und Server-Schlüssel
Der Einrichtungscode unter „Geräte“ hat am Ende vier weitere Gruppen, den Server-Schlüssel. Er ist aus dem CA-Zertifikat der eigenen CA des Servers berechnet. Daran erkennt der Hub seinen Server und heftet dessen CA an. Ohne Einrichtungscode mit TLS verbindet er sich mit nichts, und ein abgelehntes Zertifikat führt nie zu einer Verbindung ohne Prüfung. Den Grund zeigt der Hub im Einrichtungs-WLAN. Hat der Server ein öffentliches Zertifikat, fehlt der Server-Schlüssel, und die Server-Adresse ist Pflicht.
Nach dem Start verbindet sich ein Hub mit bekannter Adresse seit 0.10.0 sofort per MQTT über TLS, ohne vorher über HTTPS zu prüfen. Kommt in 20 Sekunden keine Verbindung zustande, prüft er die Adresse und sucht sonst weiter.
Lehnt der Broker die eigenen Zugangsdaten eines Hubs ab, etwa weil das Konto gelöscht wurde, versucht der Hub es mit wachsendem Abstand weiter. Erst nach mindestens 5 Ablehnungen über mindestens 60 Sekunden vergisst er sie und meldet sich wieder als neuer Hub.
Ein Modul übernehmen
- Das Modul wird an den Bus gesteckt und meldet sich beim Hub an.
- Der Hub fragt die Selbstbeschreibung ab, ab 0.10.0 auch, welche Sensoren das Modul erkannt hat, und nimmt das Modul in die Liste der erkannten Module auf.
- Der Server zeigt „Neues Modul gefunden“ mit dem Typ und dem, was erkannt wurde.
- Ein Admin klickt „Übernehmen“ und vergibt Namen, Zone, den Ort der Sensoren und den Modultyp.
- Der Server nimmt das Modul in die Konfiguration des Hubs auf.
- Der Hub vergibt die Busadresse. Danach kommen die Messwerte.
Nicht übernommene Module senden keine Messwerte an den Server. Der Server muss den Modultyp vorher nicht kennen, denn jedes Modul beschreibt sich selbst. Den Typ setzt der Hub ab 0.10.0 aus seiner Konfiguration; weicht er vom Vorschlag ab, startet das Modul einmal neu. Mehr unter Module.
CAN: Module und Hub
| Eigenschaft | Wert |
|---|---|
| Rate | 250 kbit/s |
| Rahmen | erweitert, 29 Bit Kennung, bis 8 Byte Daten |
| Abschluss | 120 Ω an beiden Enden |
| Kabel | vieradrig: 24 V, Masse, CAN-H, CAN-L |
| Byte-Reihenfolge | Little Endian |
| Zahlen | IEEE-754 float, 32 Bit |
Kennung
| Bits | Feld | Werte |
|---|---|---|
| 28 bis 26 | Priorität | 0 ist die höchste |
| 25 bis 21 | Nachrichtentyp | 1 bis 8 |
| 20 bis 13 | Absender | 0 Hub, 1 bis 250 Modul, 254 ohne Adresse |
| 12 bis 5 | Empfänger | 255 für alle |
| 4 bis 0 | Teilnummer | Kanalindex oder Folgenummer |
Nachrichten
| Nachricht | Priorität | Richtung | Zweck |
|---|---|---|---|
| Ereignis | 0 | Modul → Hub | Endschalter, Überstrom, Notabschaltung |
| Stellbefehl | 1 | Hub → Modul | Ausgang setzen |
| Lebenszeichen | 2 | beide | Ausfallerkennung in beide Richtungen |
| Messwert | 3 | Modul → Hub | regelmäßig und bei Änderung |
| Anmeldung | 4 | Modul → Hub | Seriennummer und Typ, solange das Modul keine Adresse hat |
| Adresszuweisung | 4 | Hub → Modul | nach der Übernahme |
| Beschreibung | 5 | beide | Kanalliste, Firmware-Version |
| Update | 7 | Hub → Modul | Firmware in Blöcken |
Ein Messwert passt in einen Rahmen: Kanalindex, Güte, Wert als float und das Alter in 10-Millisekunden-Schritten.
Anmeldung eines Moduls
- Ein Modul ohne Adresse sendet alle 2 Sekunden eine Anmeldung.
- Der Hub merkt sich Seriennummer und Typ und fragt die Beschreibung ab.
- Nach der Übernahme sendet der Hub die Adresszuweisung.
- Das Modul speichert die Adresse dauerhaft und sendet Lebenszeichen.
- Nach einem Neustart meldet sich das Modul mit seiner gespeicherten Adresse. Kennt der Hub die Adresse nicht mehr, vergisst das Modul sie und meldet sich neu an.
Damit zwei neue Module nicht zur selben Zeit dieselbe Kennung senden, leitet jedes Modul Teilnummer und Versatz seines 2-Sekunden-Takts aus der eigenen Seriennummer ab.
Blockübertragung
Beschreibung und Firmware sind länger als 8 Byte und werden in Blöcken übertragen.
| Rahmen | Inhalt |
|---|---|
| Erster Rahmen | Gesamtlänge und CRC32 |
| Folgerahmen | bis 8 Byte Nutzlast, Teilnummer 1 bis 31 umlaufend |
| Bestätigung | alle 16 Rahmen vom Empfänger: die nächste erwartete Position |
Fehlt ein Rahmen, bestätigt der Empfänger sofort die erwartete Position, und der Sender setzt dort wieder auf. Stimmt die CRC32 am Ende nicht, beginnt der Sender von vorn. Ohne Bestätigung wiederholt er nach 500 Millisekunden, höchstens fünfmal.
Selbstbeschreibung
Die Beschreibung eines Moduls ist binär. Sie nennt Modultyp, Firmware- und Hardware-Version und je Kanal Rolle, Messgröße, Messbereich, Kennung und Namen. Je Ausgang nennt sie die Art, die Sicherung und die zugehörigen Kanäle für Stellwert, Strom, Spannung und Zustand.
Je Kanal gibt es Merker: beschreibbar, geschätzt, neu startbar, braucht Kalibrierung. Den letzten setzen Füllstand und Bodenfeuchte. So bringt ein künftiger Sensor die Kalibrierpflicht selbst mit, ohne dass Hub oder Server ihn kennen müssen.