MTConnect zu MQTT ist der kürzeste Weg von den standardisierten Daten einer CNC-Maschine zu Live-Dashboards, Alarmen und Auslastungsberichten. In diesem Tutorial erfahren Sie, wie ein MTConnect-Agent Daten bereitstellt, und bauen dann eine Python-Brücke, die den Sequenznummern des Agents folgt, ohne Beobachtungen zu verpassen, Datenelemente wie Ausführungszustand, Spindeldrehzahl und Stückzahl auf lesbare Topics abbildet und sie per MQTT veröffentlicht. Dieselbe Brücke funktioniert für eine Maschine ebenso wie für eine ganze Zelle.
Wie MTConnect Maschinendaten bereitstellt
MTConnect ist ein offener Standard für Fertigungsanlagen, insbesondere Werkzeugmaschinen. Er definiert ein Vokabular (was „Execution", „SpindleSpeed" oder „PartCount" bedeuten) und eine nur lesende HTTP-Schnittstelle, die von einem Agent bereitgestellt wird. Maschinen sprechen über einen Adapter mit dem Agent, der oft vom Steuerungshersteller geliefert wird oder in die Steuerung integriert ist, und Clients lesen vom Agent. Im DACH-Raum stellen viele Werkzeugmaschinen ihre Daten zusätzlich oder alternativ über OPC UA bereit, etwa nach den umati-Spezifikationen; beide Quellen lassen sich im selben Topic-Baum zusammenführen, wie das OPC UA MQTT Gateway zeigt.
Der Agent bietet drei Hauptanfragen:
| Anfrage | Liefert | Wofür |
|---|---|---|
/probe |
Das Gerätemodell: Komponenten und Datenelemente mit IDs, Typen, Einheiten | Einmaliger Aufbau eines Katalogs der Datenelemente beim Start |
/current |
Den neuesten Wert jedes Datenelements plus Sequenzinformationen im Header | Anfangszustand und Neusynchronisierung nach Fehlern |
/sample?from=N&count=M |
Jede Beobachtung ab Sequenz N, bis zu M Elemente | Änderungen verfolgen, ohne eine zu verpassen |
Jede Beobachtung trägt eine vom Agent vergebene sequence-Nummer, einen timestamp und eine dataItemId. Der Header der Antwort enthält firstSequence, lastSequence, nextSequence und eine instanceId. Diese vier Werte sind der Schlüssel zu einer zuverlässigen Brücke: Sie starten mit /current, merken sich nextSequence und fragen ab dort nach Samples.
MTConnect-Beobachtungen gibt es in drei Kategorien, die sich gut darauf abbilden lassen, wie Sie sie in MQTT behandeln sollten:
- Samples sind numerische Messwerte wie Spindeldrehzahl, Last oder Position.
- Events sind diskrete Zustände oder Werte wie Ausführungszustand, Steuerungsmodus, Programmname oder Stückzahl.
- Conditions beschreiben den Gesundheitszustand:
Normal,Warning,FaultoderUnavailable, oft mit einem nativen Alarmcode.
Ein Datenelement, dessen Wert unbekannt ist, meldet UNAVAILABLE. Ihre Brücke sollte das durchreichen und nicht verbergen, denn „die Maschine ist aus oder getrennt" ist eine wichtige Information.
Warum MTConnect mit MQTT verbinden
MTConnect arbeitet nach dem Pull-Prinzip und ist XML-lastig. Für ein Dashboard ist das in Ordnung, aber jeder neue Konsument pollt den Agent separat und muss XML parsen. Eine Brücke zu MQTT liefert Ihnen Push-Zustellung, ein konsumentenfreundliches JSON-Format, retained aktuellen Zustand für Nachzügler und die Möglichkeit, Maschinendaten mit SPS-, Energie- und Qualitätsdaten in einer gemeinsamen Topic-Hierarchie zu kombinieren. Wenn Sie einen Unified Namespace (UNS) aufbauen, werden MTConnect-Maschinen zu einer weiteren Quelle, die ihn speist. Die ISA-95-Hierarchie (Enterprise → Site → Area → Line → Cell) wird dabei zur Topic-Struktur auf dem Broker, und ein Bearbeitungszentrum landet etwa unter acme/werk-stuttgart/zerspanung/linie-2/zelle-1/.... Unser Leitfaden zu ISA-95-MQTT-Topics zeigt, wo die Maschinen hingehören, und MQTT, Sparkplug B und der Unified Namespace ordnet das Konzept ein.
Neuere Versionen des MTConnect-Referenz-Agents können über einen eingebauten MQTT-Sink auch direkt an einen MQTT Broker veröffentlichen. Unterstützt Ihre Agent-Version das, lohnt sich eine Prüfung; die Konfigurationsschlüssel unterscheiden sich zwischen Versionen, folgen Sie daher der Dokumentation des Agents. Die Brücke in diesem Tutorial funktioniert mit jeder Agent-Version und gibt Ihnen volle Kontrolle über Topic-Namen und Payload-Aufbau.
Voraussetzungen
- Python 3.10 oder neuer mit
requestsundpaho-mqtt2.x. - Eine MTConnect-Agent-URL, etwa
http://192.168.10.50:5000. Ist keine Maschine angebunden, enthält das Projekt des Referenz-Agents Beispielkonfigurationen und einen Simulator, den Sie lokal ausführen können. - Ein Broker. Zum Testen nutzen Sie den kostenlosen öffentlichen MQTT-Broker mit einem eindeutigen Topic-Präfix; er ist nur für Tests gedacht, nicht für Produktionsdaten.
pip install requests "paho-mqtt>=2.0"
curl -s http://localhost:5000/probe | head -40 # prüfen, ob der Agent antwortet, und Datenelemente auflisten
Schritt 1: Die Datenelemente auswählen
Eine moderne CNC kann Hunderte von Datenelementen bereitstellen. Veröffentlichen Sie, was Konsumenten brauchen, nicht alles. Ein praxistauglicher Startsatz für Auslastungs- und Status-Dashboards:
| MTConnect-Typ | Kategorie | Beispielwerte | Warum er wichtig ist |
|---|---|---|---|
| AVAILABILITY | Event | AVAILABLE, UNAVAILABLE | Ist die Maschine überhaupt verbunden |
| EXECUTION | Event | ACTIVE, READY, INTERRUPTED, FEED_HOLD, STOPPED | Kern der Auslastungserfassung |
| CONTROLLER_MODE | Event | AUTOMATIC, MANUAL, MANUAL_DATA_INPUT | Trennt Produktion von Einrichtung |
| PROGRAM | Event | O1234 | Welcher Auftrag läuft |
| PART_COUNT | Event | 1843 | Ausbringung |
| ROTARY_VELOCITY (Spindel) | Sample | 12000 | Zerspanungsaktivität |
| PATH_FEEDRATE_OVERRIDE | Event oder Sample | 100 | Eingriff des Bedieners |
| System- und Logik-Conditions | Condition | Normal, Warning, Fault | Alarme |
Führen Sie /probe gegen Ihren Agent aus und notieren Sie die id jedes gewünschten Datenelements. IDs werden von demjenigen vergeben, der den Agent konfiguriert hat, und unterscheiden sich daher zwischen Installationen.
Schritt 2: Die Brücke von MTConnect zu MQTT
Die Brücke ordnet Datenelement-IDs Topic-Namen zu, liest /current für den Anfangszustand und läuft dann in einer Schleife über /sample. Sie erkennt Neustarts des Agents (eine neue instanceId) und Pufferüberläufe (ein from, das älter als firstSequence ist) und synchronisiert sich in beiden Fällen neu.
# mtconnect_mqtt_bridge.py - einem MTConnect-Agent folgen und Beobachtungen an MQTT veröffentlichen
import json, logging, time, uuid
import xml.etree.ElementTree as ET
import paho.mqtt.client as mqtt
import requests
logging.basicConfig(level=logging.INFO)
log = logging.getLogger("mtc")
AGENT = "http://localhost:5000"
TOPIC_ROOT = "connectmq/demo/f40b/shop1/cnc" # eigene Zufalls-ID verwenden
INTERVAL = 1.0 # Sekunden zwischen /sample-Anfragen
MQTT_HOST, MQTT_PORT = "broker.connectmq.com", 1883 # Produktion: 8883 mit TLS
MQTT_USER, MQTT_PASS = None, None # Produktion: "YOUR_USERNAME", "YOUR_PASSWORD"
CLIENT_ID = f"mtc-bridge-{uuid.uuid4().hex[:8]}" # Produktion: "YOUR_CLIENT_ID"
# dataItemId -> Topic-Blatt. Die IDs stammen aus der /probe-Ausgabe Ihres Agents.
WATCH = {
"avail": "availability",
"exec": "execution",
"mode": "controller_mode",
"program": "program",
"pc": "part_count",
"Sspeed": "spindle_speed",
"logic_cond": "logic_condition",
}
CONDITION_TAGS = {"Normal", "Warning", "Fault", "Unavailable"}
def local(tag):
"""Entfernt den versionierten MTConnect-XML-Namespace aus einem Tag-Namen."""
return tag.rsplit("}", 1)[-1]
def fetch(path):
r = requests.get(f"{AGENT}{path}", timeout=10)
r.raise_for_status()
return ET.fromstring(r.content)
def parse(root):
header = next(e for e in root.iter() if local(e.tag) == "Header")
observations = []
for stream in root.iter():
if local(stream.tag) != "DeviceStream":
continue
device = stream.get("name")
for el in stream.iter():
item_id = el.get("dataItemId")
if item_id is None:
continue
tag = local(el.tag)
if tag in CONDITION_TAGS:
value = {"level": tag, "native_code": el.get("nativeCode"), "text": (el.text or "").strip()}
else:
value = (el.text or "").strip()
observations.append({
"device": device, "id": item_id, "value": value,
"ts": el.get("timestamp"), "seq": int(el.get("sequence", 0)),
})
observations.sort(key=lambda o: o["seq"])
return header, observations
def coerce(value):
if isinstance(value, dict) or value == "UNAVAILABLE":
return value
try:
return float(value) if "." in value else int(value)
except ValueError:
return value
def publish(mq, obs):
leaf = WATCH.get(obs["id"])
if not leaf:
return
topic = f"{TOPIC_ROOT}/{obs['device']}/{leaf}"
payload = {"value": coerce(obs["value"]), "ts": obs["ts"], "seq": obs["seq"]}
mq.publish(topic, json.dumps(payload), qos=1, retain=True)
log.info("%s = %s", topic, payload["value"])
def main():
mq = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=CLIENT_ID)
if MQTT_USER:
mq.username_pw_set(MQTT_USER, MQTT_PASS)
mq.tls_set()
mq.will_set(f"{TOPIC_ROOT}/bridge", "offline", qos=1, retain=True)
mq.on_connect = lambda c, u, f, rc, p: c.publish(f"{TOPIC_ROOT}/bridge", "online", qos=1, retain=True)
mq.connect(MQTT_HOST, MQTT_PORT, keepalive=30)
mq.loop_start()
instance, next_seq = None, None
while True:
try:
if next_seq is None: # (neu) synchronisieren über /current
header, obs = parse(fetch("/current"))
instance, next_seq = header.get("instanceId"), int(header.get("nextSequence"))
for o in obs:
publish(mq, o)
log.info("synchronised: instance %s, next %s", instance, next_seq)
else:
header, obs = parse(fetch(f"/sample?from={next_seq}&count=1000"))
if header.get("instanceId") != instance:
log.warning("agent restarted, resynchronising")
next_seq = None
continue
for o in obs:
publish(mq, o)
next_seq = int(header.get("nextSequence"))
except (ET.ParseError, StopIteration, TypeError) as exc:
# Fehlerhaftes XML oder ein MTConnectError-Dokument ohne normalen Header.
log.error("unexpected agent response: %s", exc)
next_seq = None
except requests.RequestException as exc:
# Netzwerkfehler oder ein Fehlerstatus wie ein "from" außerhalb des Bereichs.
log.error("agent request failed: %s", exc)
next_seq = None
time.sleep(5)
time.sleep(INTERVAL)
if __name__ == "__main__":
main()
Einige Punkte zum Design:
- Sortieren nach Sequenz garantiert, dass Beobachtungen in der Reihenfolge veröffentlicht werden, in der der Agent sie erfasst hat, auch wenn das XML sie nach Komponenten gruppiert.
- Retained Messages sorgen dafür, dass ein mitten in der Schicht geöffnetes Dashboard sofort den aktuellen Ausführungszustand, das Programm und die Stückzahl zeigt.
- Conditions werden zu Objekten mit Stufe und nativem Alarmcode, sodass Konsumenten eine Warnung von einem Fehler unterscheiden können.
- Neusynchronisierung bei Fehlern ist sicher:
/currentveröffentlicht den neuesten Zustand erneut, sodass Konsumenten am Ende korrekte Daten haben, auch wenn einige Zwischen-Samples verloren gingen.
Schritt 3: Ausführen und beobachten
python mtconnect_mqtt_bridge.py
mosquitto_sub -h broker.connectmq.com -p 1883 -i mtc-viewer-f40b -t "connectmq/demo/f40b/#" -v
connectmq/demo/f40b/shop1/cnc/VMC-3Axis/execution {"value": "ACTIVE", "ts": "2026-10-16T11:02:44.501Z", "seq": 90213}
connectmq/demo/f40b/shop1/cnc/VMC-3Axis/spindle_speed {"value": 11980.0, "ts": "2026-10-16T11:02:44.612Z", "seq": 90215}
Der öffentliche Broker erlaubt zehn Nachrichten pro Sekunde und Client, was für Zustandsereignisse reichlich ist, von sich schnell ändernden Samples wie Achspositionen aber überschritten werden kann. Halten Sie WATCH fokussiert oder ergänzen Sie ein Totband für Samples, wie in unserem Artikel zu Report by Exception erklärt.
Ein Maschinenstatus-Dashboard bauen
Mit Ausführung, Modus und Verfügbarkeit in MQTT ist eine einfache Auslastungsansicht, die Grundlage für OEE-Kennzahlen, nur noch eine Frage des Abonnierens und der Zeitmessung von Zustandswechseln. Eine verbreitete vereinfachte Zuordnung:
- Läuft: Verfügbarkeit AVAILABLE, Modus AUTOMATIC, Ausführung ACTIVE.
- Leerlauf: verfügbar, Ausführung READY oder STOPPED.
- Unterbrochen: Ausführung INTERRUPTED, FEED_HOLD oder OPTIONAL_STOP, oft ein Warten auf den Bediener.
- Alarm: eine beliebige Condition auf Fault-Stufe.
- Offline: Verfügbarkeit UNAVAILABLE oder das Status-Topic der Brücke zeigt
offline.
Jedes MQTT-fähige Dashboard-Werkzeug kann diese Zustände berechnen, und ein Historian, der dieselben Topics abonniert, liefert Ihnen Schicht- und Auftragsberichte. Unser Leitfaden zum MQTT-Historian behandelt das Speichern des Datenstroms.
Hinweise für die Produktion
- Platzierung im Netzwerk. Betreiben Sie die Brücke im Werkstattnetz neben dem Agent und lassen Sie sie sich ausgehend auf Port 8883 mit dem Broker verbinden. Stellen Sie den HTTP-Port des Agents nicht ins Internet.
- Mehrere Maschinen. Ein Agent bedient oft mehrere Geräte; die Brücke verarbeitet bereits mehrere
DeviceStream-Elemente und legt jedes Gerät in einen eigenen Zweig. - Uhrzeitqualität. MTConnect-Zeitstempel stammen vom Agent oder Adapter. Stellen Sie sicher, dass diese Hosts NTP nutzen, sonst driften Dauerberechnungen.
- Privater Broker. Der öffentliche Broker ist für alle sichtbar, echte Maschinendaten gehören daher auf einen privaten, verwalteten MQTT-Broker. Bei ConnectMQ gruppiert die Geräteansicht Ihre Maschinen nach ISA-95-Ebene, und die 3D-Digital-Twin-Demo zeigt, welche Art von Live-CNC-Visualisierung Sie auf Basis von Secure WebSockets bauen können.
Für das Gesamtbild, wie Maschinendaten, SPSen und Gateways zusammenpassen, lesen Sie den Leitfaden zu Industrial IoT mit MQTT.
Starten Sie mit ConnectMQ
Bringen Sie Ihre CNC-Daten in wenigen Minuten auf einen privaten Broker. Registrieren Sie sich unter app.connectmq.com, wählen Sie den kostenlosen Serverless-Plan (ohne Kreditkarte), legen Sie einen Broker an und fügen Sie den generierten Benutzernamen, das Passwort und die Client ID in die Brücke ein. Legen Sie dann im ConnectMQ-Portal eine Regel für Schwellwert-Alarme an, zum Beispiel für die Spindeldrehzahl, und beobachten Sie das Alarmprotokoll, während die Maschine läuft.
Häufig gestellte Fragen
Unterstützt MTConnect MQTT nativ?
Der MTConnect-Standard ist um eine HTTP-Schnittstelle herum aufgebaut, neuere Versionen des Referenz-Agents enthalten aber einen MQTT-Sink, der Beobachtungen an einen Broker veröffentlicht. Eine kleine Brücke wie die obige funktioniert mit jeder Agent-Version.
Warum /sample statt /current pollen?
Das Pollen von /current zeigt nur den neuesten Wert und kann kurze Zustände zwischen den Abfragen verpassen. Wenn Sie /sample ab nextSequence folgen, erhalten Sie jede Beobachtung in der richtigen Reihenfolge, sodass kurze Alarme oder Stopps nicht verloren gehen.
Was bedeutet UNAVAILABLE in MTConnect?
Es bedeutet, dass der Agent den Wert derzeit nicht kennt, meist weil Maschine oder Adapter getrennt sind. Veröffentlichen Sie es unverändert, damit Dashboards die Maschine als offline anzeigen können.
Kann ich über MTConnect auf eine CNC schreiben?
Nein. MTConnect ist ein nur lesender Standard für die Überwachung. Befehle an die Maschine erfordern die eigenen Schnittstellen des Steuerungsherstellers.



