MQTT-Telemetrie in der Wasserversorgung bringt verstreute Pumpwerke, Hochbehälter, Druckerhöhungsanlagen und Abwasserhebewerke in eine gemeinsame Live-Datenschicht, die Betriebspersonal, Ingenieure und Planungswerkzeuge gleichermaßen abonnieren können. Dieser Leitfaden zeigt, wie Sie diese Telemetrie strukturieren, welche Signale Sie wie veröffentlichen und wie Sie Schwellwert-Alarme für Füllstände und Drücke auslösen, bevor ein Hochbehälter leerläuft oder ein Pumpensumpf überläuft. Außerdem führen Sie einen kleinen Stationssimulator und einen Alarm-Helfer aus, die Sie an echte Anlagen anpassen können.
Das Telemetrieproblem in Wassernetzen
Ein typischer Versorger betreibt Dutzende bis Hunderte Außenstationen, verteilt über sein Versorgungsgebiet. Viele wurden über Jahrzehnte mit unterschiedlichen RTUs, Funkgeräten und Protokollen angebunden und von einem zentralen SCADA-Master gepollt. Diese Anordnung funktioniert, erzeugt aber bekannte Schmerzpunkte:
- Langsame Scans über gemeinsam genutzten Funk. Wird jede Station der Reihe nach gepollt, wartet ein Füllstandsalarm unter Umständen auf den nächsten Scan.
- Im SCADA eingeschlossene Daten. Asset-Management, hydraulische Modellierung und Energieteams fordern Exporte an oder bauen fragile Punkt-zu-Punkt-Schnittstellen.
- Gemischte Gerätegenerationen. Jeder neue Stationstyp bringt einen weiteren Treiber und eine weitere Registertabelle.
- Überall Mobilfunkstationen. Neuere Stationen nutzen Mobilfunkmodems, die vom Gerät initiierte, ausgehende Verbindungen statt eingehendem Polling begünstigen.
MQTT kehrt die Richtung um: Jede Station veröffentlicht ihre eigenen Änderungen an einen Broker, und jeder Konsument, einschließlich SCADA, abonniert. Wenn Sie die SCADA-Seite dieses Wechsels planen, lesen Sie parallel zu diesem Leitfaden MQTT in SCADA-Systemen.
Was jede Station veröffentlichen sollte
Gehen Sie von den betrieblichen Fragen aus, nicht von der Registerliste der RTU. Die folgende Tabelle ist eine praxistaugliche Grundlage für Stationen der Wasserversorgung und Abwasserentsorgung.
| Stationstyp | Signal | Einheit | Publish-Regel | Alarmidee |
|---|---|---|---|---|
| Hochbehälter / Tank | Füllstand | m | Totband 2 bis 5 cm, Heartbeat 15 min | Niedriger und hoher Füllstand |
| Hochbehälter / Tank | Stellung Zulaufventil | % | Bei Änderung um 2 % | Ventil klemmt, während der Füllstand sinkt |
| Druckerhöhungsanlage oder Pumpwerk | Förderdruck | bar | Totband 0,05 bis 0,1 bar | Hoher und niedriger Druck |
| Druckerhöhungsanlage oder Pumpwerk | Durchfluss | m3/h | Totband 2 bis 5 % des Messbereichs | Durchfluss bei gestoppter Pumpe |
| Druckerhöhungsanlage oder Pumpwerk | Pumpenbetriebsstatus | bool | Jede Änderung | Zu viele Starts pro Stunde |
| Abwasserhebewerk | Füllstand Pumpensumpf | m | Totband 2 cm, schnellerer Heartbeat | Hoher Füllstand, Überlaufgefahr |
| Alle Stationen | Netzstrom, Einbruch, Kommunikation | bool | Jede Änderung, retained | Jede Änderung |
| Aufbereitungspunkte | Chlor-Restgehalt | mg/L | Totband 0,02 mg/L | Unter- oder oberhalb des Sollbands |
Zwei Regeln lassen diese Tabelle funktionieren. Veröffentlichen Sie Analogwerte per Exception mit einem Totband, das sich an der Messgenauigkeit orientiert, und veröffentlichen Sie jede Zustandsänderung sofort. Der Leitfaden zu Report by Exception erklärt die Bemessung von Totbändern und warum ein Heartbeat dennoch nötig ist.
Topics für ein Wassernetz entwerfen
Topics sollten widerspiegeln, wie das Betriebspersonal über das Netz denkt: Region, Station, Anlage, Messgröße. Eine Hierarchie im Sinne von ISA-95 (IEC 62264) hält das konsistent und wird zur Struktur eines Unified Namespace (UNS) auf dem Broker: Die ISA-95-Ebenen Enterprise, Site, Area und Unit entsprechen hier Versorger, Region, Station und Anlage, sodass jedes System Live-Daten am selben, vorhersehbaren Ort findet. Wie Sparkplug B in dieses Bild passt, erklärt MQTT, Sparkplug B und der Unified Namespace.
waterco/north/reservoir-hilltop/tank1/level
waterco/north/booster-ridge/pump2/running
waterco/north/booster-ridge/discharge/pressure
waterco/south/lift-station-07/wetwell/level
waterco/south/lift-station-07/site/status
Richtlinien, die sich später auszahlen:
- Halten Sie Stations- und Anlagennamen stabil und kleingeschrieben; sie werden zu Bezeichnern in jedem nachgelagerten System.
- Legen Sie eine Messgröße pro Topic oder ein kleines JSON-Objekt pro Anlage ab, und wählen Sie versorgerweit einen Ansatz.
- Geben Sie jeder Station ein Retained-Topic
site/statusmit Last Will, damit eine verlorene Mobilfunkverbindung alsofflineerscheint statt als eingefrorene Werte. - Kodieren Sie keine RTU-Registernummern in Topics. Legen Sie sie in einem Feld
sourceab, falls Ingenieure sie brauchen.
Folgen vorhandene SCADA-Tag-Namen bereits einer Konvention, bilden Sie sie im Gateway auf die neue Hierarchie ab, statt Datenpunkte im SCADA umzubenennen. Das Betriebspersonal behält die vertrauten Namen, und jeder neue Konsument erhält saubere, vorhersehbare Topics. Dokumentieren Sie die Zuordnung einmal und überprüfen Sie sie bei jeder neuen Station, denn Inkonsistenzen lassen sich bei der zweiten Station weit günstiger beheben als bei der fünfzigsten.
Beispiel: Pumpwerk-Simulator
Das folgende Skript simuliert eine Druckerhöhungsanlage mit dem von ihr gespeisten Hochbehälter: zwei Pumpen, Förderdruck und Behälterfüllstand. Es veröffentlicht per Exception mit Heartbeats und Last Will und eignet sich damit gut als Platzhalter, während Sie Dashboards und Alarme entwerfen. Es nutzt den öffentlichen MQTT-Broker, der nur für Tests gedacht ist, und sendet daher ausschließlich simulierte Werte unter einem zufälligen Präfix.
import json
import random
import time
import uuid
import paho.mqtt.client as mqtt
BROKER, PORT = "broker.connectmq.com", 1883 # Produktion: Ihr Broker, Port 8883 + TLS
CLIENT_ID = f"booster-sim-{uuid.uuid4().hex[:6]}" # Produktion: "YOUR_CLIENT_ID"
BASE = f"connectmq/demo/{uuid.uuid4().hex[:6]}/north/booster-ridge"
HEARTBEAT = 300
def on_connect(client, userdata, flags, reason_code, properties):
print("Connected:", reason_code, "- publishing under", BASE)
client.publish(f"{BASE}/site/status", "online", qos=1, retain=True)
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=CLIENT_ID)
client.will_set(f"{BASE}/site/status", "offline", qos=1, retain=True)
client.on_connect = on_connect
client.connect(BROKER, PORT, keepalive=60)
client.loop_start()
level, pumps = 3.2, [False, False]
last = {}
last_full = 0.0
def publish(name, value, deadband=None, unit=None, retain=False):
prev = last.get(name)
if prev is not None and not force:
if deadband is None and value == prev:
return
if deadband is not None and abs(value - prev) < deadband:
return
payload = {"value": value, "ts": int(time.time())}
if unit:
payload["unit"] = unit
client.publish(f"{BASE}/{name}", json.dumps(payload), qos=1, retain=retain)
last[name] = value
while True:
force = time.time() - last_full >= HEARTBEAT
demand = random.uniform(0.010, 0.020)
supply = 0.018 * sum(pumps)
level = round(max(0.0, level + supply - demand), 3)
# Einfache Füllstandsregelung: Pumpen starten, wenn der Behälter sinkt, stoppen, wenn er voll ist
if level < 2.8:
pumps = [True, level < 2.4]
elif level > 3.6:
pumps = [False, False]
pressure = round(1.2 + 2.1 * sum(pumps) + random.uniform(-0.03, 0.03), 2)
publish("reservoir/level", level, deadband=0.03, unit="m")
publish("discharge/pressure", pressure, deadband=0.08, unit="bar")
publish("pump1/running", pumps[0], retain=True)
publish("pump2/running", pumps[1], retain=True)
if force:
last_full = time.time()
time.sleep(5)
Beobachten Sie die Station in einem anderen Terminal:
mosquitto_sub -h broker.connectmq.com -p 1883 -i booster-watch-01 \
-t 'connectmq/demo/+/north/booster-ridge/#' -v
Sie sehen, wie der Behälter langsam sinkt, die Pumpen anlaufen, der Förderdruck springt und der Füllstand sich erholt, mit nur wenigen Nachrichten pro Minute trotz einer Schleife im Fünf-Sekunden-Takt.
Schwellwert-Alarme für Füllstände und Drücke
Telemetrie zahlt sich aus, wenn sie jemanden frühzeitig über ein Problem informiert. Auf einem privaten ConnectMQ-Broker können Sie im Portal Schwellwert-Alarmregeln anlegen, etwa einen Behälterfüllstand unter 1,5 m oder einen Förderdruck über 6 bar, und jeden ausgelösten Alarm im Alarmprotokoll nachvollziehen. Das gibt Ingenieuren während eines Pilotprojekts oder parallel zum SCADA einen schnellen, unabhängigen Blick auf kritische Grenzwerte.
Manche Bedingungen sind kein einzelner Schwellwert. Das Takten einer Pumpe ist zum Beispiel eine Anzahl von Starts über die Zeit. Das ehrliche Muster für solche Logik ist ein kleiner Abonnentendienst, der sich als gewöhnlicher MQTT-Client mit dem Broker verbindet:
import json
import time
from collections import deque
import paho.mqtt.client as mqtt
MAX_STARTS_PER_HOUR = 6
starts = {} # Topic -> deque mit Start-Zeitstempeln
state = {}
def on_connect(client, userdata, flags, reason_code, properties):
client.subscribe("connectmq/demo/+/north/+/+/running", qos=1)
def on_message(client, userdata, msg):
running = json.loads(msg.payload)["value"]
was_running = state.get(msg.topic, running)
state[msg.topic] = running
if running and not was_running:
window = starts.setdefault(msg.topic, deque())
now = time.time()
window.append(now)
while window and now - window[0] > 3600:
window.popleft()
if len(window) > MAX_STARTS_PER_HOUR:
print(f"ALERT short-cycling: {msg.topic} started {len(window)} times in 1 h")
# Hier an Ihr Paging-, SMS- oder Ticketsystem weiterleiten.
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=f"shortcycle-{time.time_ns() % 1000000}")
client.on_connect = on_connect
client.on_message = on_message
client.connect("broker.connectmq.com", 1883, keepalive=60)
client.loop_forever()
Derselbe Ansatz funktioniert mit Node-RED oder jedem anderen MQTT-fähigen Werkzeug. Die Zustellung der Benachrichtigungen bleibt in dem Werkzeug, das Ihr Betriebsteam bereits nutzt.
Checkliste für Sicherheit und Zuverlässigkeit
Wasserversorger sind kritische Infrastruktur und fallen in der EU unter NIS2; die Messlatte liegt also höher als bei einem typischen IoT-Projekt. IEC 62443 liefert dafür einen bewährten Rahmen für die OT-Sicherheit.
- TLS auf Port 8883 für jede Station; senden Sie Telemetrie niemals im Klartext über Mobilfunk oder öffentliche Netze.
- Eindeutiger Benutzername, eigenes Passwort und eigene Client-ID pro Station, einzeln widerrufbar.
- Nur ausgehende Verbindungen von den Stationen; keine offenen eingehenden Ports an Modems.
- Überwachung getrennt von Steuerung. Befehle an Pumpen und Ventile bleiben mit ihren Verriegelungen im SCADA, sofern kein geprüftes Design etwas anderes vorsieht.
- Retained-Stationsstatus mit Last Will und Alarme bei unerwartetem
offline. - Lokale Pufferung in den Stationen, damit kurze Ausfälle keine Lücken in nachweisrelevanten Daten erzeugen.
- Zeitsynchronisation an der Quelle für korrekte Ereignisfolgen.
- Ein dokumentierter Topic-Standard, verantwortet von einem Team und auf jede neue Station angewendet.
Wo der Broker laufen sollte
Versorger mit gemischter Konnektivität, manche Stationen über eigenen Funk, andere über Mobilfunk, profitieren von einem Broker, der von überall per TLS erreichbar ist. Ein verwalteter MQTT-Broker nimmt dem Versorger Patches und Zertifikatserneuerungen ab. ConnectMQ bietet MQTT 3.1.1 und 5.0, eine ISA-95-Geräteansicht, die Stationen und Anlagen gruppiert, sowie Dedicated- oder BYOC-Optionen für Versorger, die einen isolierten Cluster oder ein Deployment in ihrem eigenen Cloud-Konto benötigen. Zur Architekturwahl zwischen Stations-SPSen, Gateways und SCADA-Weiterleitung siehe SPS-Anbindung an die Cloud; zum Verhalten von Mobilfunkmodems MQTT über Mobilfunk. Der Leitfaden zu Industrial IoT mit MQTT verbindet diese Bausteine.
Starten Sie einen Telemetrie-Pilot für die Wasserversorgung mit ConnectMQ
Wählen Sie einen Hochbehälter und ein Pumpwerk, verbinden Sie sie mit einem Cloud-MQTT-Broker und legen Sie Alarme für die wichtigsten Füllstände und Drücke an. Erstellen Sie unter app.connectmq.com einen kostenlosen Serverless-Broker, ganz ohne Kreditkarte, und haben Sie noch heute Live-Stationsdaten im Topic-Explorer.
Häufig gestellte Fragen
Kann MQTT unser SCADA-System in der Wasserversorgung ersetzen?
MQTT ersetzt in der Regel den Telemetrietransport, nicht die SCADA-Funktionen. Das SCADA abonniert den Broker für den Betrieb, während andere Teams dieselben Daten unabhängig nutzen.
Woher wissen wir, dass ein Pumpwerk die Kommunikation verloren hat?
Geben Sie jeder Station einen Last Will auf einem Retained-Status-Topic. Läuft ihr Keep Alive ab, veröffentlicht der Broker offline, und Abonnenten oder Alarmregeln reagieren sofort.
Welches Totband sollten wir für Behälterfüllstände verwenden?
Einige Zentimeter sind üblich, abhängig von der Messgenauigkeit und davon, wie schnell sich der Füllstand ändert. Kombinieren Sie es mit einem periodischen Heartbeat, damit auch ein konstanter Füllstand belegt, dass die Station lebt.
Ist MQTT sicher genug für kritische Wasserinfrastruktur?
MQTT mit TLS, Zugangsdaten pro Station, ausschließlich ausgehenden Verbindungen und einer Trennung von Überwachung und Steuerung ist eine starke Grundlage. Kombinieren Sie es mit dem übergreifenden Cybersicherheitsprogramm Ihres Versorgers.



