MQTT & Telemetrie
Konfigurationswege und Grenzen
Die MQTT-Anbindung verteilt sich auf drei klar getrennte Stellen:
- Umgebung:
FOUNDRY_MQTT_URLnennt den MQTT-Broker. Ein leerer Wert schaltet die MQTT-Bridge aus. Für den gemeinsamen Telemetriepfad müssen außerdem PostgreSQL und NATS konfiguriert sein. - HTTP-API: Admins pflegen MQTT-Zuordnungen unter
/api/mqtt-mappingsund Zustandsregeln unter/api/rules. - Oberfläche: Für MQTT-Zuordnungen und Zustandsregeln gibt es derzeit keinen Editor. Die Oberfläche zeigt Telemetrie in Ansichten unter der UI-Beschriftung „Maschinendaten“.
Die Broker-Adresse und eine Zuordnung erfüllen unterschiedliche Aufgaben. Die Umgebungsvariable verbindet WERKSPUR mit genau einem Broker. Eine MQTT-Zuordnung übersetzt danach genau ein Topic in eine Maschine und eine Metrik. Die Zuordnungs-API bietet keine Felder für Broker-Adresse, Benutzername, Zertifikate oder weitere Verbindungen.
Die Beispiele auf dieser Seite enthalten ausschließlich Platzhalter. Setzen Sie für einen eigenen Test eine nicht produktive Basisadresse und ein kurzlebiges Admin-Sitzungstoken ein:
export WERKSPUR='https://werkspur.internal.invalid'
export WERKSPUR_SESSION='<SESSION_TOKEN>'
Wie Sie ein Sitzungstoken erhalten und sicher verwenden, beschreibt API & Authentifizierung.
MQTT-Zuordnungen
Eine neue Zuordnung senden Sie als Admin an POST /api/mqtt-mappings:
curl -sS -X POST "$WERKSPUR/api/mqtt-mappings" \
-H "Authorization: Bearer $WERKSPUR_SESSION" \
-H 'Content-Type: application/json' \
-d '{
"topic": "plant/machine-01/spindle-rpm",
"machine_id": "machine-01",
"metric": "spindle_rpm",
"enabled": true
}'
Die vier beschreibbaren Felder haben folgende Bedeutung:
topicist das vollständige MQTT-Topic. Es muss nicht leer und im gesamten Zuordnungsregister eindeutig sein.machine_idist die Maschinen-ID, die im Telemetriepunkt gespeichert wird.metricist der Metrikname, der zusammen mit der Maschine den Messwert bezeichnet.enabledentscheidet, ob die Bridge das Topic abonniert. Fehlt das Feld im JSON, erhält Go den Wertfalse; setzen Sie es deshalb bewusst.
Beim internen Weiterleiten werden machine_id und metric zu Subject-Teilen. Buchstaben, Ziffern, Bindestrich und Unterstrich bleiben erhalten; andere Zeichen ersetzt die Implementierung durch _. Verwenden Sie deshalb für beide Felder nur diese Zeichen, damit gespeicherte Namen und Zustandsregeln eindeutig zusammenpassen. Maschinen-IDs aus dem Maschinenregister erfüllen diese Grenze bereits.
Die Antwort enthält zusätzlich die serverseitig vergebene numerische id. Mit GET /api/mqtt-mappings lesen Sie alle Zuordnungen. Mit DELETE /api/mqtt-mappings/{id} entfernen Sie eine. Einen Änderungs-Endpunkt gibt es nicht. Für eine Korrektur löschen Sie die alte Zuordnung und legen die neue an.
MQTT-Wildcards sind nicht unterstützt. Topics mit + oder # lehnt die API mit 400 ab. Sie brauchen deshalb für jedes exakte Topic eine eigene Zuordnung. Die Bridge gleicht aktive Abonnements alle 30 Sekunden mit den gespeicherten, aktivierten Zuordnungen ab. Rechnen Sie nach dem Anlegen oder Löschen daher mit dieser Verzögerung. Da es keinen Änderungs-Endpunkt gibt, erfordert auch ein Wechsel von enabled das Löschen und Neuanlegen der Zuordnung.
Zulässige Payloads
Ein MQTT-Publisher darf den Messwert als einzelne Zahl senden:
1480.5
Alternativ akzeptiert die Bridge ein JSON-Objekt mit einem numerischen Feld value:
{"value":1480.5}
Optional darf das Objekt einen Zeitstempel ts im RFC3339-Format enthalten:
{"value":1480.5,"ts":"2026-07-15T08:30:00Z"}
Ohne ts setzt WERKSPUR beim Weiterleiten die aktuelle UTC-Zeit. Ein String wie {"value":"1480.5"}, ein JSON-Objekt ohne value und beliebiger Nicht-JSON-Text sind ungültig. Die Bridge verwirft eine solche Nachricht und schreibt eine Warnung ins Anwendungsprotokoll. Der MQTT-Publisher erhält keine HTTP-Fehlerantwort; eine automatische Dead-Letter-Queue gibt es nicht.
Speicherung und Lesen
Die Bridge veröffentlicht gültige numerische Punkte in den internen Stream TELEMETRY. Der Telemetry Ingest speichert sie als Zeitreihe nach machine_id, metric, value und ts. Rohdaten sind keine Domain-Ereignisse. Erst eine tatsächliche Maschinenzustandsänderung wird als MachineStateChanged festgehalten.
Angemeldete Benutzer ab der Rolle operator lesen eine Zeitreihe über GET /api/telemetry. Der Parameter machine ist Pflicht. Mit metric erhalten Sie Zeitreihenpunkte. Ohne metric liefert derselbe Endpunkt den Snapshot des separaten Live-Anzeigepfads.
curl -sS \
-H "Authorization: Bearer $WERKSPUR_SESSION" \
"$WERKSPUR/api/telemetry?machine=machine-01&metric=spindle_rpm&window=1h"
window muss eine positive Go-Dauer bis einschließlich 744h sein. Alternativ setzen Sie from und optional to als RFC3339-Zeitpunkte. Die eingebaute Abfrage machine_telemetry_recent kann gespeicherte Zeitreihen in einer gewöhnlichen Ansicht darstellen.
Eine MQTT-Zuordnung erzeugt dagegen keine Zeile für das Live-Widget telemetry. Dieses Widget liest aktuelle, benannte Zeilen über Server-Sent Events. Diese Zeilen entstehen aus den separat gebundenen OPC-UA-Zielen. MQTT-Daten erscheinen dort nicht automatisch.
Zustandsregeln
Zustandsregeln sind ebenfalls reine Admin-API-Konfiguration. Eine Regel enthält genau diese fachlichen Felder:
machine_id: Maschine, deren Zustand geändert werden soll.metric: Metrik, die zur Zuordnung und zum Telemetriepunkt passen muss.op: einer der Operatoren==,!=,<,<=,>oder>=.threshold: numerischer Grenzwert.for_seconds: nicht negative Mindestdauer in Sekunden.0löst beim ersten passenden Punkt aus.to_state: einer der Werterunning,idle,downodermaintenance.reason: nicht leerer Grund für die Zustandsänderung.enabled: nur aktivierte Regeln werden ausgewertet.
Das folgende Beispiel schaltet eine Maschine auf down, wenn die Metrik mindestens 30 Sekunden lang kleiner oder gleich 100 bleibt:
curl -sS -X POST "$WERKSPUR/api/rules" \
-H "Authorization: Bearer $WERKSPUR_SESSION" \
-H 'Content-Type: application/json' \
-d '{
"machine_id": "machine-01",
"metric": "spindle_rpm",
"op": "<=",
"threshold": 100,
"for_seconds": 30,
"to_state": "down",
"reason": "Drehzahlgrenze unterschritten",
"enabled": true
}'
Mit GET /api/rules lesen Sie Regeln. Mit DELETE /api/rules/{id} löschen Sie eine. Einen Änderungs-Endpunkt gibt es nicht.
Die Dauer läuft anhand der Zeitstempel passender Messpunkte. Der erste passende Punkt startet die Haltezeit. Ein nicht passender Punkt setzt sie zurück. Ohne weitere Messpunkte läuft keine Regel allein durch verstrichene Wanduhrzeit ab. Der Evaluator darf seine Regelliste 30 Sekunden zwischenspeichern. Der erste ausgewertete Messpunkt nach Ablauf dieser Frist lädt die aktivierten Regeln neu; ohne Messpunkt gibt es weder Neuladen noch Auswertung.
Die API prüft das Format der Regel, aber sie gleicht machine_id und metric beim Anlegen nicht mit einem Registereintrag ab. Prüfen Sie beide Namen deshalb vorab. Wenn die Zielmaschine fehlt, kann die spätere Zustandsänderung nicht ausgeführt werden. Bleibt die Maschine bereits im gewünschten Zustand, erzeugt die wiederholt passende Regel kein weiteres Zustandsereignis.
Vollständiger Datenfluss
Die beiden OPC-UA-Pfade im Diagramm sind absichtlich getrennt. Eine Maschinenbindung speist numerische Punkte in denselben Zeitreihen- und Regelpfad wie MQTT. Ein benanntes OPC-UA-Ziel mit Telemetriebindung speist dagegen die aktuelle Live-Anzeige. Nur eine numerische Bindung vom Typ counter schreibt aus diesem Live-Pfad zusätzlich einen Zeitreihenpunkt; sie durchläuft dabei nicht die Zustandsregel-Auswertung.
flowchart LR
MP["MQTT-Publisher"] --> MM["Exakte MQTT-Zuordnung<br/>topic, machine_id, metric, enabled"]
OM["OPC-UA-Maschinenbindung"] --> OA["OPC-UA-Polling-Adapter"]
MM --> TS["Interner TELEMETRY-Stream"]
OA --> TS
TS --> IN["Telemetry Ingest"]
IN --> DB["Gespeicherte Zeitreihe"]
IN --> RE["Aktivierte Zustandsregeln"]
RE --> MS["Maschinenzustand"]
MS --> EV["MachineStateChanged-Ereignis"]
EV --> MW["Maschinenwand und Ereignis-Trigger"]
DB --> API["Telemetrie-API und gespeicherte Abfragen"]
API --> VW["Ansichten"]
OT["Benanntes OPC-UA-Ziel<br/>mit Telemetriebindung"] --> LR["Live-Abonnement"]
LR --> CR["Aktuelle Zeilen und Qualität"]
CR --> SSE["SSE"]
SSE --> UI["Widget Maschinendaten"]
LR -. "nur numerischer counter" .-> DB
Die wesentlichen Aussagen bleiben auch ohne Diagramm: MQTT und die OPC-UA-Maschinenbindung liefern numerische Punkte an denselben Telemetry Ingest. Dieser speichert Zeitreihen und wertet Zustandsregeln aus. Nur Zustandsänderungen werden Domain-Ereignisse und können Ereignis-Trigger auslösen. Das Live-Widget verwendet einen eigenen OPC-UA-Abonnementpfad mit Snapshot, Einzelupdates und Qualitätsstatus.
Für die Telemetriebindungen des Live-Pfads gibt es derzeit weder UI- noch HTTP-CRUD. Das Widget bindet nur eine Maschine, nicht direkt ein OPC-UA-Ziel. Verwechseln Sie diese interne Startkonfiguration nicht mit der Admin-API für MQTT-Zuordnungen oder OPC-UA-Ziele.
Nicht unterstützte Annahmen
- Eine MQTT-Zuordnung konfiguriert weder den Broker noch seine Anmeldung.
- MQTT-Wildcards, mehrere Broker über die Zuordnungs-API und ein Mapping-Update sind nicht verfügbar.
- Live-Telemetriebindungen lassen sich derzeit nicht über Oberfläche oder öffentliche HTTP-API anlegen oder ändern.
- MQTT-Payloads lösen nicht direkt eine Aktion aus. Dafür brauchen Sie eine Zustandsregel mit nachfolgendem Ereignis-Trigger oder eine andere ausdrücklich konfigurierte Ereigniskette.
- Telemetrie ersetzt keine Buchung und darf nicht als verbindlicher Material- oder Auftragszustand behandelt werden.
Die OPC-UA-Konfiguration erläutert OPC UA. Fehler entlang beider Pfade grenzen Sie mit Integration: Fehlersuche ein.