ISA-95-MQTT-Topics bringen die Anlagenhierarchie des Werks direkt in den Topic-Pfad, sodass acme/dallas/packaging/line-02/filler/telemetry jedem Subscriber genau sagt, woher ein Wert stammt. Diese Topic-Struktur ist das Rückgrat eines Unified Namespace (UNS), in dem MES, ERP, SCADA und Analysewerkzeuge dieselben Adressen auf dem MQTT-Broker nutzen. In diesem Leitfaden erfahren Sie, wie Sie jede ISA-95-Ebene kodieren, wie Sie das Blatt des Topics gestalten, wie Sie Wildcard-Abonnements planen, bevor Sie sie brauchen, und welche Fallstricke die meiste Nacharbeit verursachen, sobald ein Namespace produktiv ist.
Warum ISA-95 in MQTT-Topics kodieren
MQTT-Topics sind frei wählbare, durch Schrägstriche getrennte Zeichenketten, und der MQTT-Broker misst ihnen außer beim Abgleich von Abonnements keine Bedeutung bei. Diese Freiheit ist im Werksmaßstab gefährlich. Wenn jeder Integrator eine eigene Struktur erfindet, brauchen die Consumer am Ende eine Lookup-Tabelle pro Quelle.
Die ISA-95-Anlagenhierarchie löst das, indem sie eine Struktur liefert, die in der Werksdokumentation, im MES und im Instandhaltungssystem bereits existiert. Wenn Sie sie in Topics kodieren, erhalten Sie drei Eigenschaften gratis:
- Auffindbarkeit. Wer das Werk kennt, findet einen Wert, indem er durch den Baum navigiert.
- Kontext. Das Topic trägt die Asset-Adresse, sodass Payloads sie nicht wiederholen müssen.
- Gezieltes Abonnieren. Wildcards entsprechen ganz natürlich organisatorischen Bereichen: ein Standort, ein Bereich, jeder Abfüller.
Wenn Sie die Ebenen selbst auffrischen möchten, lesen Sie zuerst den Artikel zur ISA-95-Anlagenhierarchie.
Das Grundmuster
Das kanonische Muster ordnet die Ebenen von der breitesten zur engsten an, gefolgt von einem Namespace, der angibt, welche Art von Daten die Nachricht enthält:
<enterprise>/<site>/<area>/<work center>/<work unit>/<namespace>[/<detail>]
acme/dallas/packaging/line-02/filler/telemetry
acme/dallas/packaging/line-02/filler/state
acme/dallas/packaging/line-02/filler/alarms
acme/dallas/packaging/line-02/filler/events/batch-complete
acme/dallas/packaging/line-02/filler/cmd/stop
Regeln für jede Ebene
| Ebene | Regel | Beispiel |
|---|---|---|
| Unternehmen | Ein stabiler Kurzname; nur weglassen, wenn der Broker ein einziges Unternehmen bedient | acme |
| Standort | Standortcode, der Umorganisationen übersteht | dallas, izmir |
| Bereich | Funktions- oder Produktbereich | packaging, utilities |
| Arbeitszentrum | Linie, Zelle, Prozesszelle, Einheit oder Lagerzone | line-02, cell-03 |
| Arbeitseinheit | Maschine oder Teilanlage, idealerweise nach Asset-Tag | filler, cnc-01 |
| Namespace | Festes Vokabular | telemetry, state, alarms, events, cmd |
Mit deutschen Segmentnamen sieht dasselbe Muster etwa so aus: acme/werk-stuttgart/montage/linie-1/zelle-3/temperatur. Entscheidend ist nicht die Sprache, sondern dass ein Standard für den gesamten UNS gilt.
Halten Sie die Tiefe für Anlagen-Topics fest. Wenn jede Arbeitseinheit auf Ebene fünf liegt, liefert +/+/+/+/+/state den Zustand jeder Maschine im Unternehmen, und die Position jeder Ebene im Pfad ist garantiert.
Das Blatt gestalten
Beim Namespace und allem danach finden die meisten Designdebatten statt. Für Telemetrie gibt es zwei gängige Optionen.
Ein Objekt pro Anlage. Alle aktuellen Werte einer Maschine landen in einem einzigen JSON-Dokument auf .../filler/telemetry. Das ist kompakt, hält zusammengehörige Werte zeitlich konsistent und erfordert nur eine Retained Message pro Maschine.
{ "ts": "2026-10-16T08:15:02Z", "speed_bpm": 118.4, "temp_c": 41.2, "good_count": 18342, "v": 1 }
Ein Topic pro Metrik. Jeder Wert hat sein eigenes Topic, etwa .../filler/telemetry/speed_bpm, mit einer skalaren oder kleinen JSON-Payload. Das passt gut zu tagbasierten Tools wie SCADA-Systemen, und Consumer können genau die Signale abonnieren, die sie brauchen.
Beides ist zulässig. Entscheiden Sie pro Namespace und dokumentieren Sie es. Ein verbreiteter Mischansatz ist ein Objekt für Telemetrie und Retained-Werte pro Topic für state und einige zentrale KPIs.
Wildcard-Abonnements planen
Bevor Sie die Struktur festlegen, schreiben Sie die Abonnements auf, die Ihre Consumer brauchen werden, und prüfen Sie, ob jedes davon ein einziger Wildcard-Filter ist:
| Consumer | Bedarf | Abonnement |
|---|---|---|
| Standort-Dashboard | Alles an einem Standort | acme/dallas/# |
| Schichtleiter Verpackung | Alle Zustände in einem Bereich | acme/dallas/packaging/+/+/state |
| Flottenanalyse | Jeder Abfüller, überall | acme/+/+/+/filler/telemetry |
| Alarmdienst | Alle Alarme | acme/+/+/+/+/alarms |
| Historian | Gesamte Telemetrie | acme/+/+/+/+/telemetry |
Wenn ein benötigter Bereich mehrere Abonnements oder clientseitige Filterung erfordert, arbeitet die Struktur gegen Sie. Meist bedeutet das, dass eine Ebene fehlt, uneinheitlich angeordnet ist oder das Blattvokabular zu locker ist.
ISA-95-Topics aus Code publizieren
Wenn Topics an einer zentralen Stelle erzeugt werden, verhindern Sie, dass Tippfehler wilde Zweige entstehen lassen. Dieser Python-Helfer baut und validiert den Pfad und publiziert dann Retained State und Telemetrie. Installieren Sie den Client mit pip install "paho-mqtt>=2.0". Er nutzt den öffentlichen MQTT-Broker mit einem Demo-Präfix; auf einem privaten Broker setzen Sie PREFIX auf Ihren Unternehmensnamen.
import json
import re
import threading
from dataclasses import dataclass
from datetime import datetime, timezone
import paho.mqtt.client as mqtt
PREFIX = "connectmq/demo/r8t5" # auf Ihrem eigenen Broker: "acme"
SAFE = re.compile(r"^[a-z0-9]+(-[a-z0-9]+)*$")
NAMESPACES = {"telemetry", "state", "alarms", "events", "cmd"}
@dataclass(frozen=True)
class Asset:
site: str
area: str
work_center: str
work_unit: str
def topic(self, namespace: str) -> str:
for level in (self.site, self.area, self.work_center, self.work_unit):
if not SAFE.match(level):
raise ValueError(f"invalid level: {level!r}")
if namespace not in NAMESPACES:
raise ValueError(f"unknown namespace: {namespace!r}")
return f"{PREFIX}/{self.site}/{self.area}/{self.work_center}/{self.work_unit}/{namespace}"
filler = Asset("dallas", "packaging", "line-02", "filler")
connected = threading.Event()
def on_connect(client, userdata, flags, reason_code, properties):
print("connected:", reason_code)
connected.set()
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="isa95-pub-r8t5")
client.on_connect = on_connect
client.connect("broker.connectmq.com", 1883, keepalive=60)
client.loop_start()
connected.wait(timeout=10)
client.publish(filler.topic("state"), "running", qos=1, retain=True).wait_for_publish()
telemetry = {"ts": datetime.now(timezone.utc).isoformat(), "speed_bpm": 118.4, "temp_c": 41.2, "v": 1}
client.publish(filler.topic("telemetry"), json.dumps(telemetry), qos=1, retain=True).wait_for_publish()
print("published to", filler.topic("telemetry"))
client.loop_stop()
client.disconnect()
Prüfen Sie das Ergebnis mit einer Wildcard, die zur obigen Tabelle passt:
mosquitto_sub -h broker.connectmq.com -p 1883 -i isa95-sub-r8t5 -t "connectmq/demo/r8t5/+/packaging/+/+/state" -v
Der öffentliche MQTT-Broker ist für jeden lesbar, dient nur Tests und Prototypen und erlaubt 8 Topic-Ebenen; deshalb ersetzt hier das Demo-Präfix die Unternehmensebene. Echte Asset-Namen und Produktionsdaten gehören auf einen privaten Broker.
Sparkplug B in den ISA-95-Baum bringen
Sparkplug-B-Topics folgen einem festen Format, spBv1.0/<group>/<type>/<edge node>/<device>, mit Protobuf-Payloads. Sie folgen nicht ISA-95, und Consumer ohne Sparkplug-Unterstützung können sie nicht lesen. Statt Sparkplug an der Edge aufzugeben, publizieren Sie seine Daten erneut in Ihren ISA-95-Baum.
ConnectMQ erledigt das automatisch: Es dekodiert Sparkplug-B-Payloads, ob Protobuf oder JSON, und publiziert sie in ISA-95-Topics. So wird zum Beispiel spBv1.0/factory1/DDATA/line1/cnc1 als connectmq/factory1/production/line1/cnc1/telemetry erneut publiziert. Wählen Sie Sparkplug-Group- und Edge-Node-IDs mit aussagekräftigen Werksnamen, damit die resultierenden ISA-95-Pfade lesbar sind. Die Vor- und Nachteile beider Ansätze behandelt MQTT, Sparkplug B und der Unified Namespace.
Fallstricke, die Sie vermeiden sollten
- Führender Schrägstrich.
/acme/dallaserzeugt eine leere erste Ebene und spaltet Abonnements auf. - Gemischte Groß- und Kleinschreibung. Topics unterscheiden Groß- und Kleinschreibung;
Line-02undline-02sind verschiedene Zweige. - Protokoll- oder Herstellernamen im Pfad.
acme/dallas/opcua/...koppelt Consumer an die heutige Integrationstechnologie. - Variable Tiefe. Wird für eine Maschine eine Ebene übersprungen, funktionieren positionsbasierte Wildcards nicht mehr. Verwenden Sie stattdessen ein Platzhalter-Arbeitszentrum.
- Zeitstempel oder IDs in Topics. Topics wie
.../telemetry/20261016erzeugen unbegrenzt viele Zweige und ein Durcheinander an Retained Messages. - Ereignisse retainen. Retainen Sie Zustände, keine Ereignisströme; ein neuer Subscriber sollte kein veraltetes „Batch abgeschlossen“ erhalten.
- Befehle ohne Request und Response. Nutzen Sie für
cmddie Response Topics und Correlation Data von MQTT 5, damit der Anfragende weiß, ob der Befehl erfolgreich war. - Tiefe Pfade auf schmalbandigen Verbindungen. Lange Topics fügen jeder Nachricht Bytes hinzu. Topic Aliases in MQTT 5 reduzieren diesen Overhead, ohne das Design zu ändern.
Den Standard vor dem Rollout dokumentieren
Ein Topic-Standard, der nur im Kopf eines einzigen Ingenieurs existiert, wird spätestens vom zweiten Integrator gebrochen. Bevor das erste Gateway live geht, schreiben Sie einen einseitigen Standard, der Folgendes abdeckt:
- Die Reihenfolge der Ebenen und die zulässigen Zeichen für jede Ebene.
- Die Liste der Namespaces und was jeder enthalten darf, mit einer Beispiel-Payload.
- Welche Topics retained sind und welche nicht.
- Das Zeitstempelformat, die Zeitzone und die Einheitenkonvention.
- Wer neue Standorte, Bereiche und Arbeitszentren freigibt und wie Anträge gestellt werden.
Geben Sie diese Seite jedem Systemintegrator und Gateway-Hersteller zusammen mit dem obigen Topic-Helfer oder einem Gegenstück in deren Sprache. Wenn Standard und Code übereinstimmen, werden die meisten Fehler erkannt, bevor sie den Broker überhaupt erreichen.
Sicherheit verdient einen eigenen Hinweis: Vergeben Sie einen Zugang pro Gateway und Anwendung, damit jeder Publisher identifizierbar und widerrufbar ist, und nutzen Sie außerhalb des Labors überall TLS auf Port 8883. Unsere Best Practices für MQTT-Sicherheit behandeln den Rest.
Vollständige Bäume zum Kopieren finden Sie unter UNS-Topic-Struktur. Für die umgebende Architektur ist der Leitfaden zu Industrial IoT mit MQTT der richtige Einstieg.
ISA-95-MQTT-Topics auf ConnectMQ betreiben
ConnectMQ ist ein verwalteter MQTT-Broker, der industrielle Topic-Strukturen versteht: Er erkennt ISA-95- und UNS-Topics, zeigt Geräte im Portal nach ISA-95-Ebene an und publiziert Sparkplug B erneut in Ihren Baum. Erstellen Sie einen Broker im kostenlosen Serverless-Plan unter app.connectmq.com, ohne Kreditkarte, und publizieren Sie noch heute Ihren ersten ISA-95-Zweig.
Häufig gestellte Fragen
Sollte der Unternehmensname die erste Topic-Ebene sein?
Ja, wenn der Broker jemals mehr als ein Unternehmen oder einen Geschäftsbereich bedienen könnte. Bei einem Broker für ein einziges Unternehmen können Sie ihn weglassen, aber ein späteres Hinzufügen bedeutet, jedes Topic umzubenennen.
Wie gehe ich mit Maschinen um, die zu keiner Linie gehören?
Geben Sie ihnen ein Platzhalter-Arbeitszentrum wie standalone oder shared, damit sie auf derselben Tiefe liegen wie alles andere.
Darf ich Leerzeichen oder Großbuchstaben in ISA-95-MQTT-Topics verwenden?
MQTT erlaubt sie, aber sie verursachen subtile Fehler. Verwenden Sie nur Kleinbuchstaben, Ziffern und Bindestriche.
Funktionieren ISA-95-Topics mit MQTT 3.1.1?
Ja. Das Topic-Design ist versionsunabhängig. MQTT 5 bringt nützliche Extras wie Topic Aliases und Response Topics für Befehle.



