IoT-Automatisierung

The Things Network MQTT-Integration: LoRaWAN-Uplinks an Ihren eigenen Broker weiterleiten

Abonnieren Sie den MQTT-Server von The Things Network, dekodieren Sie LoRaWAN-Uplinks mit einem Payload Formatter und veröffentlichen Sie sauberes Sensor-JSON mit einer kurzen Python-Bridge in Ihren eigenen Topic-Baum.

The-Things-Network-MQTT-Bridge, die LoRaWAN-Sensor-Uplinks von einem Gateway in den Topic-Baum eines Cloud-MQTT-Brokers überträgt
Probieren Sie es auf Ihrem eigenen MQTT-Broker ausHolen Sie sich im Free-Tarif einen privaten, verwalteten MQTT-Broker und starten Sie mit fertigen Codebeispielen.
Kostenlos testen Codebeispiele Keine Kreditkarte erforderlich

Der MQTT-Server von The Things Network liefert jeder Anwendung einen Live-Feed ihrer LoRaWAN-Uplinks und macht es damit leicht, Sensordaten mit großer Reichweite in Ihre eigenen Systeme zu holen. In diesem Tutorial schreiben Sie einen Payload Formatter, verbinden sich mit einem API-Schlüssel mit dem TTN-MQTT-Server und betreiben eine kleine Python-Bridge, die dekodierte Messwerte als sauberes JSON in den Topic-Baum Ihres eigenen Brokers veröffentlicht. Dort können Dashboards, Node-RED und Automatisierungen sie zusammen mit Ihren anderen Geräten nutzen.

Warum TTN an Ihren eigenen Broker anbinden

The Things Network (TTN) übernimmt die Funkseite von LoRaWAN: Gateways, Geräteaktivierung, Deduplizierung und Entschlüsselung. Sein MQTT-Server veröffentlicht jeden Uplink als großes JSON-Dokument mit Metadaten von jedem Gateway, das das Paket empfangen hat. Für die Fehlersuche ist das hervorragend, als langfristiges Datenmodell aber unhandlich:

  • die Topics gehören TTN (v3/<app>@ttn/devices/<device>/up), nicht Ihrer Standorthierarchie;
  • die Payloads sind groß und verschachtelt, während die meisten Verbraucher drei oder vier Werte wollen;
  • Ihre WLAN-Geräte, SPSen und Steuerungen leben bereits auf einem anderen Broker.

Eine Bridge löst alle drei Probleme. Sie abonniert TTN, extrahiert das Wesentliche und veröffentlicht kompakte Nachrichten in denselben Topic-Baum wie alles andere. Verbraucher brauchen nie TTN-Zugangsdaten, und wenn Sie später auf einen privaten Netzwerkserver wechseln, ändert sich nur die Bridge. Der Leitfaden zu Smart Farming IoT erklärt, wo das in ein betriebsweites Design passt.

Schritt 1: Die Payload in TTN dekodieren

LoRaWAN-Geräte senden kompakte Bytes. Fügen Sie in der TTN Console unter Applications > your app > Payload formatters > Uplink einen Payload Formatter vom Typ Custom Javascript formatter hinzu. Dieses Beispiel dekodiert einen Bodenknoten, der Feuchte (uint16, Zehntelprozent), Bodentemperatur (int16, Zehntelgrad) und Batterie (uint16, Millivolt) sendet:

function decodeUplink(input) {
  var b = input.bytes;
  if (input.fPort !== 1 || b.length < 6) {
    return { errors: ["unexpected port or length"] };
  }
  var moisture = ((b[0] << 8) | b[1]) / 10;
  var tRaw = (b[2] << 8) | b[3];
  if (tRaw & 0x8000) tRaw -= 0x10000;
  var battery = ((b[4] << 8) | b[5]) / 1000;
  return {
    data: {
      moisture_pct: moisture,
      soil_temp_c: tRaw / 10,
      battery_v: battery
    },
    warnings: [],
    errors: []
  };
}

Nutzen Sie das Panel Test mit einer Hex-Payload wie 0136 008C 0E74, um die Ausgabe zu prüfen, bevor ein Gerät ausgebracht wird. Das dekodierte Objekt erscheint in jedem Uplink als uplink_message.decoded_payload.

Schritt 2: MQTT-Zugangsdaten von TTN erhalten

Öffnen Sie in der Console Integrations > MQTT. Dort sehen Sie:

Einstellung Wert
Server Ihr Cluster, zum Beispiel eu1.cloud.thethings.network
Ports 1883 (unverschlüsselt) und 8883 (TLS)
Benutzername <application-id>@ttn
Passwort Ein API-Schlüssel; klicken Sie auf Generate new API key

Kopieren Sie den API-Schlüssel sofort; TTN zeigt ihn nur einmal an. Verwenden Sie zu TTN immer Port 8883, da der Schlüssel Zugriff auf Ihre Anwendungsdaten gewährt. Der Abschnitt zum MQTT-Server in der offiziellen Dokumentation von The Things Stack listet alle Topics auf, einschließlich Join-, Downlink- und Service-Ereignissen.

Das Uplink-Topic für eine Anwendung lautet:

v3/<application-id>@ttn/devices/<device-id>/up

Sie können den Feed prüfen, bevor Sie Code schreiben:

mosquitto_sub -h eu1.cloud.thethings.network -p 8883 --capath /etc/ssl/certs \
  -u 'my-farm-app@ttn' -P 'NNSXS.YOUR_TTN_API_KEY' \
  -t 'v3/my-farm-app@ttn/devices/+/up' -v

Schritt 3: Die The-Things-Network-MQTT-Bridge in Python

Die Bridge nutzt zwei paho-mqtt-2.x-Clients: einen, der TTN abonniert, und einen, der an Ihren Broker veröffentlicht. Betreiben Sie sie zunächst mit dem öffentlichen MQTT-Broker und ersetzen Sie t6n1b4 durch Ihre eigene Zufallszeichenfolge, denn der öffentliche MQTT-Broker ist für jeden lesbar und nur für Tests und Prototypen gedacht, nicht für Produktivdaten.

import json
import os
import ssl

import paho.mqtt.client as mqtt

TTN_HOST = "eu1.cloud.thethings.network"
TTN_APP = os.environ.get("TTN_APP", "my-farm-app")
TTN_KEY = os.environ["TTN_API_KEY"]

OUT_HOST = os.environ.get("OUT_HOST", "broker.connectmq.com")
OUT_PORT = int(os.environ.get("OUT_PORT", "1883"))
OUT_USER = os.environ.get("OUT_USER")          # im Produktivbetrieb setzen
OUT_PASS = os.environ.get("OUT_PASS")
OUT_CLIENT_ID = os.environ.get("OUT_CLIENT_ID", "ttn-bridge-out-t6n1b4")
OUT_PREFIX = os.environ.get("OUT_PREFIX", "connectmq/demo/t6n1b4/farm")

# --- ausgehender Broker -------------------------------------------------------
out = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=OUT_CLIENT_ID)
if OUT_USER:
    out.username_pw_set(OUT_USER, OUT_PASS)
if OUT_PORT == 8883:
    out.tls_set(cert_reqs=ssl.CERT_REQUIRED)
out.will_set(f"{OUT_PREFIX}/bridge/status", "offline", qos=1, retain=True)

def out_on_connect(client, userdata, flags, reason_code, properties):
    print("out broker:", reason_code)
    client.publish(f"{OUT_PREFIX}/bridge/status", "online", qos=1, retain=True)

out.on_connect = out_on_connect
out.connect(OUT_HOST, OUT_PORT, keepalive=60)
out.loop_start()

# --- TTN ---------------------------------------------------------------------
def ttn_on_connect(client, userdata, flags, reason_code, properties):
    print("ttn:", reason_code)
    client.subscribe(f"v3/{TTN_APP}@ttn/devices/+/up", qos=1)

def ttn_on_message(client, userdata, msg):
    try:
        up = json.loads(msg.payload)
        device = up["end_device_ids"]["device_id"]
        um = up["uplink_message"]
        decoded = um.get("decoded_payload")
    except (ValueError, KeyError) as exc:
        print("skipping malformed uplink:", exc)
        return
    if not decoded:
        print(f"{device}: no decoded payload (check the formatter)")
        return

    rx = um.get("rx_metadata", [])
    best = max(rx, key=lambda g: g.get("rssi", -999)) if rx else {}
    record = {
        "ts": up.get("received_at"),
        **decoded,
        "rssi": best.get("rssi"),
        "snr": best.get("snr"),
        "gateways": len(rx),
        "f_cnt": um.get("f_cnt"),
    }
    topic = f"{OUT_PREFIX}/{device}/telemetry"
    out.publish(topic, json.dumps(record), qos=1, retain=True)
    print(topic, record)

ttn = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
                  client_id=f"ttn-bridge-in-{TTN_APP}")
ttn.username_pw_set(f"{TTN_APP}@ttn", TTN_KEY)
ttn.tls_set(cert_reqs=ssl.CERT_REQUIRED)
ttn.on_connect = ttn_on_connect
ttn.on_message = ttn_on_message
ttn.connect(TTN_HOST, 8883, keepalive=60)
ttn.loop_forever()

Starten Sie sie:

pip install paho-mqtt
export TTN_API_KEY='NNSXS.YOUR_TTN_API_KEY'
python ttn_bridge.py

Und beobachten Sie die saubere Ausgabe in einem zweiten Terminal:

mosquitto_sub -h broker.connectmq.com -p 1883 -i watch-t6n1b4 \
  -t 'connectmq/demo/t6n1b4/farm/#' -v

Jeder Uplink wird zu einer retained Nachricht wie {"ts":"2026-10-16T06:15:02Z","moisture_pct":31.0,"soil_temp_c":14.0,"battery_v":3.7,"rssi":-108,"snr":4.5,"gateways":2,"f_cnt":412}. Da sie retained ist, sieht auch ein später gestartetes Dashboard sofort den letzten Messwert jedes Sensors; das ist wichtig bei Geräten, die nur alle 15 Minuten melden.

Hinweise zum Design

Warum RSSI, SNR und Gateway-Anzahl mitsenden? Sie sind die früheste Warnung vor einer defekten Antenne, einem versetzten Gateway oder einem Sensor, der im Schlamm versinkt. Sie zu speichern kostet fast nichts.

Warum retained Messages? LoRaWAN-Geräte sind die meiste Zeit still. Ohne Retain sieht jeder Verbraucher, der sich zwischen zwei Uplinks verbindet, bis zum nächsten nichts.

Warum QoS 1 auf beiden Seiten? Die Bridge könnte neu starten, während TTN zustellt; QoS 1 mit einem sich neu verbindenden Client verringert Lücken. Die Abwägungen erläutert MQTT-QoS-Stufen erklärt.

Topic-Tiefe. connectmq/demo/t6n1b4/farm/<device>/telemetry hat sechs Ebenen und liegt damit bequem innerhalb des Limits von acht Ebenen des öffentlichen MQTT-Brokers. Im Produktivbetrieb verwenden Sie Ihre eigene Hierarchie, etwa farm1/north/<device>/telemetry. In Industrieumgebungen ordnen Sie LoRaWAN-Sensoren auf dieselbe Weise in einen Unified Namespace (UNS) nach ISA-95 ein, zum Beispiel acme/werk-muenchen/aussenlager/tank-2/telemetry, sodass Funk- und SPS-Daten im selben Topic-Baum nebeneinanderliegen.

Nachrichtengröße. Ein roher TTN-Uplink mit Metadaten mehrerer Gateways kann einige Kilobyte groß sein. Der neu veröffentlichte Datensatz umfasst ein paar hundert Byte, weit unter dem Limit von 64 KB des öffentlichen MQTT-Brokers und dem Limit von 256 KB des kostenlosen ConnectMQ-Plans, und ist für Dashboards und mobile Clients mit Akkubetrieb viel günstiger zu verarbeiten.

Umgang mit Lücken und Duplikaten

LoRaWAN ist konstruktionsbedingt eine verlustbehaftete Funkverbindung: Geräte senden ohne Bestätigung, und ein Paket, das kein Gateway empfängt, ist einfach verloren. Der in jedem Datensatz enthaltene Frame Counter (f_cnt) ermöglicht es Verbrauchern, Lücken zu erkennen. Springt der Zähler von 410 auf 413, gingen zwei Uplinks auf der Funkstrecke verloren, nicht in MQTT. Diese Unterscheidung spart Zeit, wenn jemand fehlende Daten meldet.

Die Bridge kann denselben Uplink auch zweimal sehen, wenn sie sich mit TTN neu verbindet, während eine QoS-1-Nachricht unterwegs ist. Verbraucher, die Daten speichern, sollten die Kombination aus Geräte-ID und Frame Counter als eindeutigen Schlüssel behandeln und Wiederholungen ignorieren. Beachten Sie, dass der Zähler zurückgesetzt wird, wenn ein Gerät dem Netz erneut beitritt; nutzen Sie ihn daher zur Lückenerkennung über kurze Zeiträume und nicht als dauerhafte Kennung.

Um einen Befehl an ein Gerät zu senden (zum Beispiel ein neues Meldeintervall), kann die Bridge ein Befehls-Topic auf Ihrem Broker abonnieren und es an das Downlink-Topic von TTN weiterleiten:

import base64

def forward_downlink(device_id, port, raw_bytes):
    body = {"downlinks": [{
        "f_port": port,
        "frm_payload": base64.b64encode(raw_bytes).decode(),
        "priority": "NORMAL",
    }]}
    ttn.publish(f"v3/{TTN_APP}@ttn/devices/{device_id}/down/push",
                json.dumps(body), qos=1)

# Beispiel: Intervall auf 30 Minuten setzen (ein Byte) auf Port 2
# forward_downlink("soil-node-07", 2, bytes([30]))

Geräte der Klasse A empfangen Downlinks erst nach ihrem nächsten Uplink, sodass Befehle mit einer Verzögerung in Höhe des Meldeintervalls ankommen. Halten Sie Downlinks selten; Sendezeit- und Duty-Cycle-Regeln machen sie bei LoRaWAN teuer.

Zuverlässiger Betrieb

  1. Betreiben Sie die Bridge als systemd-Dienst oder Container mit automatischem Neustart.
  2. Bewahren Sie den TTN-API-Schlüssel in einer Umgebungsvariable oder einem Secret Store auf, niemals im Skript.
  3. Geben Sie dem API-Schlüssel nur die Rechte, die er braucht (Lesen des Anwendungsverkehrs und, falls genutzt, Schreiben von Downlinks).
  4. Überwachen Sie bridge/status: Der Last Will setzt es auf offline, wenn der Prozess abstürzt.
  5. Denken Sie an die Fair-Use-Richtlinie von TTN für das Community-Netz; es ist für Sensoren mit niedriger Sendefrequenz gedacht, nicht für gesprächige Geräte.

Produktivbetrieb auf einem privaten Broker

Setzen Sie OUT_HOST=broker.connectmq.com, OUT_PORT=8883, OUT_USER, OUT_PASS und OUT_CLIENT_ID auf die Zugangsdaten Ihres privaten Brokers und ändern Sie OUT_PREFIX auf Ihre eigene Hierarchie. Der Rest des Skripts bleibt gleich. Ein verwalteter MQTT-Broker gibt Ihren LoRaWAN-Daten, WLAN-Sensoren und Steuerungen ein gemeinsames, verschlüsseltes Zuhause, das Sie nicht selbst warten müssen. Wenn Sie statt TTN einen eigenen Netzwerkserver betreiben, zeigt das Tutorial ChirpStack MQTT die entsprechende Bridge, und der Bau eines Bodenfeuchtesensors mit MQTT ist eine WLAN-Alternative für Felder in Gebäudenähe. Weitere Muster finden Sie im Leitfaden zur IoT-Automatisierung, und die Grundlagen dazu, was ein MQTT-Broker macht, helfen, wenn MQTT neu für Sie ist.

Bringen Sie Ihre LoRaWAN-Daten zu ConnectMQ

ConnectMQ gibt Ihren über die Bridge übertragenen TTN-Daten einen privaten MQTT-Broker mit TLS, einen Live-Topic-Explorer, ein Dashboard und Schwellwert-Alarmregeln für Werte wie niedrigen Batteriestand oder trockenen Boden. Erstellen Sie unter app.connectmq.com einen kostenlosen Serverless-Broker, ohne Kreditkarte, und richten Sie die Ausgabe der Bridge darauf aus.

Häufig gestellte Fragen

Wie lauten Benutzername und Passwort für TTN MQTT?

Der Benutzername ist Ihre Application ID gefolgt von @ttn (für die Community Edition von The Things Network), und das Passwort ist ein API-Schlüssel, den Sie unter Integrations > MQTT erzeugen.

Es ist kein Uplink Payload Formatter konfiguriert, oder er hat einen Fehler ausgelöst. Testen Sie ihn im Formatter-Panel der Console mit einer echten Hex-Payload.

Kann ich TTN ohne Code direkt mit einem anderen Broker verbinden?

TTN bietet Webhooks und andere Integrationen, aber um in Ihren eigenen MQTT-Broker mit Ihrer eigenen Topic-Struktur zu veröffentlichen, ist eine kleine Bridge wie diese die einfachste und transparenteste Lösung.

Muss die Bridge in der Nähe des Gateways laufen?

Nein. Beide Verbindungen laufen über das Internet, sodass sie auf jedem Server, einem Raspberry Pi oder in einem Container laufen kann.

Verwandte Artikel

Zigbee2MQTT einrichten: Vom Koordinator bis zum Dashboard

Installieren Sie Zigbee2MQTT mit Docker, konfigurieren Sie Koordinator und MQTT-Verbindung, lernen Sie Geräte an und benennen Sie sie um, steuern Sie sie per MQTT und zeigen Sie ihre Zustände auf einem Dashboard an, zuerst getestet auf einem kostenlosen öffentlichen MQTT-Broker.

8 Min. Lesezeit

Alle Artikel →

Ihr privater MQTT-Broker ist nur wenige Klicks entfernt

Konto anlegen, Broker-Zugangsdaten erhalten und das erste Gerät verbinden — ohne Server, die installiert, gepatcht oder skaliert werden müssen.