Tutorials

MQTT-Daten in Grafana visualisieren mit der MQTT-Datenquelle

MQTT-Topics direkt in Grafana streamen: Installiere das MQTT-Data-Source-Plugin, verbinde es per TLS mit deinem Broker, parse JSON und baue Live-Panels.

Aktualisiert · 8 Min. Lesezeit

MQTT-Daten in Grafana visualisieren mit der MQTT-Datenquelle

Grafana kann einen MQTT-Broker direkt abonnieren. Mit dem offiziellen MQTT-Data-Source-Plugin (grafana-mqtt-datasource) ist jede Panel-Abfrage ein Topic-Abonnement, und neue Nachrichten erscheinen kurz nach dem Publish im Dashboard – ganz ohne Datenbank dazwischen. Schneller bekommst du keinen Live-Gauge oder Live-Chart für Sensordaten.

Dieses Tutorial installiert das Plugin, verbindet es per TLS mit einem Broker, publiziert Testtelemetrie und baut Live-Panels. Es behandelt auch den Punkt, den viele zu spät bemerken: Die Datenquelle streamt, sie speichert nicht.

So funktioniert die MQTT-Datenquelle

Das Plugin läuft im Grafana-Server. Wenn ein Panel Daten anfordert, öffnet das Backend eine MQTT-Verbindung (eine pro Datenquelle), abonniert das Topic aus der Abfrage und leitet jede Nachricht über Grafana Live, den WebSocket-Streaming-Kanal von Grafana, an den Browser weiter.

AspektVerhalten
Transport zum BrokerMQTT über TCP oder TLS vom Grafana-Server aus (nicht vom Browser)
Transport zum BrowserGrafana Live (WebSocket), Push-basiert – kein Dashboard-Refresh nötig
Payload-ParsingJSON-Objekte werden zu Feldern; eine einfache Zahl wird zu einem einzelnen Wertfeld
HistorieKeine – nur Nachrichten, die eintreffen, während das Panel offen ist
Ideal fürLive-Betriebsansichten, Inbetriebnahme, Demos, Debugging

Da der Grafana-Server der MQTT-Client ist, muss der Broker von dort aus erreichbar sein, wo Grafana läuft, und die Zugangsdaten liegen in den Einstellungen der Datenquelle, nicht im Browser.

Grafana mit dem Plugin starten

Am schnellsten geht es mit Docker. Das Plugin wird beim Start aus dem Grafana-Plugin-Katalog installiert:

Grafana mit dem MQTT-Plugin starten
docker run -d --name grafana -p 3000:3000 \
  -e GF_INSTALL_PLUGINS=grafana-mqtt-datasource \
  grafana/grafana:latest

In aktuellen Grafana-Releases ist GF_PLUGINS_PREINSTALL=grafana-mqtt-datasource der neuere Weg für dasselbe. Bei einer bestehenden Installation nutzt du die CLI und startest den Dienst neu:

Installation bei paketbasiertem Grafana
grafana cli plugins install grafana-mqtt-datasource
sudo systemctl restart grafana-server

Öffne http://localhost:3000, melde dich an (Standard admin / admin, danach ändern) und gehe zu Connections → Data sources → Add data source → MQTT.

Datenquelle mit dem Broker verbinden

Die Einstellungsseite fragt nach einer URI, optionalen Zugangsdaten und TLS-Optionen:

  • URI – tcp://broker.connectmq.com:1883 für einen schnellen unverschlüsselten Test, tls://broker.connectmq.com:8883 für TLS (manche Plugin-Versionen akzeptieren auch ssl://). Nutze TLS für alles, was über eine Demo hinausgeht.
  • Username / Password – die Zugangsdaten deines Brokers. Mit Topic-ACLs gibst du diesem Benutzer nur Lesezugriff auf die Topics, die die Dashboards brauchen.
  • TLS – aktiviere „With CA Cert“, wenn dein Broker eine private CA nutzt, oder Client-Zertifikate für mTLS.

Klicke auf Save & test. Ein erfolgreicher Test bedeutet, dass der Grafana-Server eine MQTT-Verbindung öffnen konnte. Schlägt er fehl, ist der Fehler das CONNACK des Brokers oder ein Netzwerkfehler – siehe MQTT-Verbindungsfehler und schlage Codes mit dem Reason-Code-Tool nach.

Für reproduzierbare Setups provisionierst du die Datenquelle per Datei, statt zu klicken:

provisioning/datasources/mqtt.yaml
apiVersion: 1
datasources:
  - name: MQTT
    type: grafana-mqtt-datasource
    access: proxy
    jsonData:
      uri: tls://broker.connectmq.com:8883
      username: ${MQTT_USER}
    secureJsonData:
      password: ${MQTT_PASS}

Grafana expandiert Umgebungsvariablen in Provisioning-Dateien, das Passwort landet also nie in Git. Die Feldnamen können sich zwischen Plugin-Versionen leicht unterscheiden; wird ein Wert ignoriert, konfiguriere ihn einmal in der Oberfläche und vergleiche mit dem README des Plugins.

Testtelemetrie publizieren

Ein Panel zeigt nur Nachrichten, die eintreffen, während es offen ist – du brauchst also einen stetigen Datenstrom zum Gestalten. Dieses Skript mit paho-mqtt 2.x publiziert jede Sekunde einen JSON-Messwert:

fake_sensor.py
import json, math, os, random, time
import paho.mqtt.client as mqtt

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="grafana-demo-sensor")
client.username_pw_set(os.environ["MQTT_USER"], os.environ["MQTT_PASS"])
client.tls_set()                       # CA-Store des Systems
client.connect("broker.connectmq.com", 8883)
client.loop_start()

t = 0
while True:
    reading = {
        "temperature": round(21 + 3 * math.sin(t / 30) + random.uniform(-0.3, 0.3), 2),
        "humidity": round(45 + random.uniform(-2, 2), 1),
        "battery": max(0, 100 - t // 60),
    }
    client.publish("testmqtt/grafana/room1/telemetry", json.dumps(reading), qos=0)
    t += 1
    time.sleep(1)

Bevor du Grafana anfasst, prüfe den Datenstrom mit dem Online-MQTT-Client: Abonniere testmqtt/grafana/# und beobachte die eingehenden Nachrichten. Erscheinen sie dort, aber nicht in Grafana, liegt das Problem bei der Datenquelle, nicht beim Publisher.

Testtelemetrie im Browser ansehen

Live-Panels bauen

Lege ein Dashboard an, füge eine Visualisierung hinzu und wähle die MQTT-Datenquelle. Der Abfrage-Editor hat ein wichtiges Feld, Topic: Trage testmqtt/grafana/room1/telemetry ein.

  1. Time series – der Standard. Jeder JSON-Schlüssel (temperature, humidity, battery) wird zu einer Serie. Setze den Zeitbereich des Dashboards auf Last 5 minutes, damit der Chart scrollt, statt sich zu stauchen.
  2. Gauge – Visualisierung wechseln, Calculation auf Last setzen und unter Fields das Feld temperature wählen. Schwellwerte hinzufügen (grün unter 25, rot über 28).
  3. Stat – gut für battery; Last und die Einheit Prozent verwenden.

Wenn du nur ein Feld in einem Panel brauchst, nutze die Transformation Organize fields oder Filter fields by name, statt separate Topics zu publizieren.

Payload-Formate, die funktionieren

PayloadErgebnis in Grafana
23.5Ein numerisches Feld (value)
{"temperature": 23.5, "humidity": 41}Zwei numerische Felder
{"env": {"temp": 23.5}}Verschachtelte Schlüssel werden zu Feldnamen abgeflacht
{"status": "ok"}Ein String-Feld – gut für eine Tabelle, nicht für einen Chart
Binär, CBOR, ProtobufWird nicht geparst – vorher dekodieren

Der Zeitstempel ist der Zeitpunkt, zu dem Grafana die Nachricht empfangen hat, nicht ein Zeitfeld in deinem Payload. Puffern Geräte und senden verspätet, zeigt der Chart die Ankunftszeit; siehe Zeitstempel-Probleme.

Wildcards und viele Geräte

Aktuelle Plugin-Versionen akzeptieren + und # im Topic-Feld, sodass testmqtt/grafana/+/telemetry ein Panel mit allen Räumen füttern kann. Prüfe mit dem Topic-Matcher, welche Topics ein Filter trifft, bevor du ihn speicherst – ein unbedachtes # auf einem stark genutzten Broker streamt weit mehr Daten in den Browser, als ein Panel zeichnen kann. Für große Flotten nimm lieber ein Panel pro Gerätegruppe oder aggregiere auf dem Gerät und publiziere ein Summary-Topic. Wie du Topics so entwirfst, dass Dashboards sauber filtern können, steht in Topics und Wildcards.

Fehlerbehebung

  • „No data“ in einem neuen Panel – seit dem Öffnen des Panels wurde nichts publiziert. Das Plugin spielt keine alten Nachrichten ab, und Retained Messages helfen nur, wenn der Publisher das Retain-Flag setzt. Starte den Test-Publisher und warte eine Sekunde.
  • Save & test schlägt fehl – prüfe, ob der Grafana-Server (oder Container) den Broker erreicht: docker exec grafana nc -vz broker.connectmq.com 8883. Firmen-Egress-Regeln blockieren 8883 oft, selbst wenn dein Laptop verbinden kann.
  • Daten erscheinen und stoppen dann – ein anderer Client mit derselben Client-ID wirft Grafana raus, oder dem Benutzer fehlt die Leseberechtigung und der Broker verwirft das Abonnement stillschweigend. Sieh in die Broker-Logs und prüfe die ACLs.
  • Zahlen erscheinen als Strings – der Publisher sendet "23.5" in Anführungszeichen. Korrigiere den Payload oder füge eine Convert field type-Transformation hinzu.
  • Panel hängt hinterher oder der Tab friert ein – der Topic-Filter ist zu breit oder die Geräte publizieren schneller als nötig. Senke die Publish-Rate oder aggregiere vorher.

Wenn du Historie brauchst

Die MQTT-Datenquelle ist perfekt für „Was passiert gerade?“. Sobald jemand fragt „Was ist letzte Nacht passiert?“, brauchst du Speicher. Das übliche Muster: Live-Panel behalten und eine zweite Datenquelle hinzufügen:

Grafana zeigt beides im selben Dashboard: oben ein Live-MQTT-Stat, darunter historische InfluxDB- oder SQL-Charts. Suchst du ein reines Browser-Dashboard ohne Grafana, sieh dir ein Live-MQTT-Dashboard bauen an.

Die MQTT-Datenquelle macht aus einem Topic in Minuten ein Live-Panel. Verbinde sie mit einem Broker-Benutzer mit reinem Lesezugriff, halte Payloads als flache JSON-Zahlen, prüfe den Datenstrom zuerst mit einem MQTT-Client und ergänze eine Datenbank, sobald sich das Dashboard etwas merken soll.

Häufig gestellte Fragen

Speichert die Grafana-MQTT-Datenquelle eine Historie?

Nein. Sie abonniert Topics und streamt neue Nachrichten über Grafana Live in die Panels. Die Daten liegen nur im Puffer des Browsers, nach einem Neuladen ist das Panel also leer. Für Historie schreibst du die MQTT-Daten in eine Datenbank wie InfluxDB oder TimescaleDB und fragst diese ab.

Kann ich im Topic-Feld von Grafana MQTT Wildcards verwenden?

Aktuelle Versionen des Plugins akzeptieren die Wildcards + und #. Ältere Releases abonnieren nur exakte Topics. Zeigt eine Wildcard-Abfrage keine Daten, aktualisiere das Plugin oder frage zuerst ein konkretes Topic ab, um die Verbindung zu prüfen.

Warum zeigt mein Grafana-MQTT-Panel 'No data'?

Meist passt das Topic nicht zu dem, was die Geräte publizieren, gerade wird nichts publiziert (das Plugin zeigt nur neue Nachrichten) oder der Payload ist weder JSON noch eine einfache Zahl. Publiziere bei geöffnetem Panel eine Testnachricht mit einem MQTT-Client, um das Problem einzugrenzen.