ENPLDEPT
Flash
Alle Docs
LoRaWAN-Gateway

Dein Gateway hört ohnehin alles. Lass es für das Netzwerk arbeiten.

Zwei Wege. Direkt — der Forwarder sendet zusätzlich an sensmos.com:1700, und du koppelst das Gateway in der App mit deiner Wallet; es verdient und sendet Beacons. Passiv — ein Skript auf dem Gateway meldet, was es hört; am Gateway ändert sich nichts.

radio · 868 MHz · emergency frame
◈
Heard by a neighbour · 2.1 kmgarage · temp 3.4°C · door OPEN · 21:44

Weg 1 — direkt: mit der Wallet koppeln

Funktioniert mit jedem Gateway, dessen Packet Forwarder an mehr als einen Server senden kann (Crankk, RAK, Dragino, MikroTik, die meisten Hotspots aus der Helium-Zeit).

  1. Im Packet Forwarder des Gateways einen Server eintragen: sensmos.com, Port 1700 (UDP, Uplink und Downlink). Die anderen Server bleiben — der Forwarder sendet jeden Frame an jeden von ihnen.
  2. Eine Minute warten, bis das Gateway uns etwas gesendet hat.
  3. In der Sensmos-App: Dashboard → + → LoRaWAN-Gateway hinzufügen. Die EUI des Gateways eingeben (16 Hex-Zeichen, aus seinem Panel), optional einen Namen und eine Position — oder die Position deines Telefons, während du daneben stehst. Mit Wallet koppeln antippen.

Die App lehnt ab, wenn das Gateway länger als 10 Minuten geschwiegen hat (Servereintrag prüfen) oder schon mit einer anderen Wallet gekoppelt ist.

Was du bekommst: eine Karte im Dashboard — wie viele Nodes das Gateway hört und wie viele es hören (24 h), gehörte Sensmos-Frames in 24 h, der letzte Beacon, der Verdienst. Auf der Live-Karte hat das Gateway eine eigene Farbe und ein eigenes Panel. Name und Position bearbeitet es; Gateway entkoppeln auf der Karte gibt es frei.

Bis zur Kopplung: ein Gateway, das seit 10 Minuten an sensmos.com:1700 weiterleitet, arbeitet für das Netzwerk unter der Wallet des Projekts — seine Sensmos-Frames werden zugestellt, es sendet den Abdeckungs-Beacon und zählt in der Epoche. Die Kopplung verschiebt Karte und Verdienst zu dir; ein Gateway, das niemand koppelt, verdient weiter für das Projekt.

Was das Netzwerk damit macht: jeder gehörte Sensmos-Frame — Notfall-Aussendung, Sensor-Frame — wird dem Besitzer genauso zugestellt wie ein von einem Node gehörter Frame. Alle 5 Minuten sendet das Netzwerk über dein Gateway einen kurzen Beacon; Nodes, die ihn hören, bestätigen, dass das Gateway dort steht, wo es sagt.

Weg 2 — passiv: ein Skript, am Gateway ändert sich nichts

Für ein Gateway, das du nicht umkonfigurieren willst. Ein Python-Skript auf dem Gateway liest den Verkehr des Forwarders auf Loopback und meldet Funk-Metadaten. Es braucht einen Sensmos-Node im selben LAN, der dafür bürgt. Details folgen.

Für wen das ist

Jede Linux-Kiste mit einem einfachen Semtech Packet Forwarder (UDP, Port-1700-Stil), der auf einen entfernten Server zeigt: Helium-Hotspots und ihre Multi-Mining-Stacks, RAK, Dragino, Mikrotik, ein Raspberry Pi mit Concentrator-HAT. Läuft dein Gateway stattdessen mit ChirpStack Gateway Bridge, gibt es einen lokalen MQTT-Broker und ein anderer Agent kommt zum Einsatz.

Du brauchst außerdem einen Sensmos-Node im selben LAN wie der Gateway (jeder ESP32 mit der Firmware, kein Funkmodul nötig) und seine PIN. Der Node bürgt für den Gateway; ohne ihn stellt das Backend kein Token aus.

Warum passiv und kein Relay

Der naheliegende Weg, einen Forwarder anzuzapfen, ist, etwas dazwischenzuschalten — den Forwarder auf uns zeigen lassen und weiterleiten. Das tun wir absichtlich nicht. Auf Hardware, die verdient, würde unser Ausfall zu deinem Ausfall. Der Forwarder schickt ohnehin jeden Frame separat an jeden konfigurierten Server über Loopback; das Skript liest auf lo einfach mit. Es ist niemandes Ziel, leitet nichts weiter und verzögert nichts.

Schnellstart

Führe all das auf dem Gateway aus, nicht auf deinem Laptop. Nur Python 3 — keine pip-Pakete, nichts zu bauen. Root ist nötig, weil das Lesen roher Pakete CAP_NET_RAW erfordert.

# 1 — install the script
sudo curl -fsSL -o /usr/local/bin/sensmos-gw-udp.py https://raw.githubusercontent.com/Galusz/sensmos-gateway/main/sensmos-gw-udp.py
sudo chmod +x /usr/local/bin/sensmos-gw-udp.py

# 2 — see what would leave your box (sends nothing, needs no pairing)
sudo sensmos-gw-udp.py --dry-run

# 3 — find a Sensmos node on this network (prints the exact pair command)
sudo sensmos-gw-udp.py --find

# 4 — pair with it (address from step 3, PIN = the node's PIN)
sudo sensmos-gw-udp.py --pair NODE_IP --pin YOUR_PIN --name "rooftop RAK"

# 5 — install & start it as a boot-persistent service
sudo sensmos-gw-udp.py --install-service

# 6 — confirm
systemctl status sensmos-gw-udp --no-pager
journalctl -u sensmos-gw-udp -f

Schritt 6 sollte active (running) zeigen, und das Log gibt connection works — first batch accepted aus, sobald Frames fließen, danach jede Minute eine Statuszeile. In der App erscheint der Gateway unter den Attachments des Nodes; auf der Live-Karte bekommt der Node die RF-Ebene.

Schon gekoppelt, kein Dienst? Das Token bleibt erhalten; wiederhole Schritt 1 und 5. Nur wenn --install-service pair first meldet, wiederhole Schritt 4.

Schau nach, bevor du uns vertraust

--dry-run gibt als JSON genau die Frames aus, die es weiterleiten würde, und hört dort auf. Füge --log-tx hinzu, um auch zu sehen, wann dein Gateway sendet. Das Skript ist eine einzelne lesbare Datei; der Quellcode liegt auf GitHub.

Pairing — wie das Token funktioniert

Das Skript hat keine eigenen Zugangsdaten. Es bittet den Sensmos-Node in deinem LAN (mit der PIN des Nodes), für es zu bürgen; der Node leitet die Anfrage über seine eigene Verbindung ans Backend weiter, und das Backend stellt ein Token aus, das auf radio.frames beschränkt ist — empfangene Frames melden, sonst nichts. Das Token wird in /etc/sensmos-gw-udp.json (Modus 0600) gespeichert. Von da an spricht das Skript direkt mit dem Backend; der Node ist raus aus der Schleife.

  • Ein Node kann für bis zu vier Attachments bürgen.
  • Der Besitzer kann jedes davon aus der App widerrufen (Node → Attachments); das Skript wird sofort wirkungslos.
  • Ein Token lebt 30 Tage ab erster Nutzung, und das Skript verlängert es von selbst.

Der vollständige Vertrag (Endpunkte, Scopes, Formate) steht unter Attachments & die EXT-API.

Was es liest

Semtech GWMP über UDP, erkannt am Paket-Header, nicht am Port, damit es funktioniert, egal welche Ports dein Stack nutzt:

Byte
0Protokollversion (1 oder 2)
1–2Token
3Typ — 0 PUSH_DATA (empfangene Frames), 3 PULL_RESP (Gateway soll senden)
4–11Gateway-EUI
RestJSON

Aus PUSH_DATA nimmt es die rxpk-Einträge: Frequenz, Spreading Factor, RSSI, SNR, Größe, CRC-Ergebnis und die rohe PHY-Payload. Anwendungs-Payloads sind mit Schlüsseln verschlüsselt, die wir nicht haben; was das Netzwerk nutzt, sind die Funk-Metadaten und das Erkennen von Sensmos-Frames im Verkehr.

PULL_RESP — eine Aussendung, die dein Gateway gleich macht — wird nur gemeldet, wenn sie für andere hörbar ist (ipol = false, z. B. Coverage-Beacons, die manche Netze senden). Ein normaler LoRaWAN-Downlink nutzt invertiertes IQ, das niemand sonst hören kann, beweist nichts und wird übersprungen. Gemeldete sind der Beweis, dass der Gateway echt ist: Ihre Payload ist unvorhersehbar, sodass ein Sensmos-Node, der dieselben Bytes unabhängig hört, bestätigt, dass der Gateway tatsächlich gesendet hat.

Ein Multi-Server-Forwarder schickt den identischen Frame an jeden konfigurierten Server, sodass dieselbe Aussendung mehrfach auf Loopback auftaucht (RF packets received: 1 / PUSH_DATA datagrams sent: 2 in deinem Forwarder-Log). Das Skript dedupliziert; eine Aussendung wird einmal gemeldet. Frames werden gebündelt (einmal pro Sekunde oder alle 50 Frames) und an https://sensmos.com/v1/ext/radio/frames geschickt.

Flags

FlagBedeutung
--ifacezu beobachtende Schnittstelle, Standard lo
--dry-runausgeben, was gesendet würde, nichts senden
--log-txzusätzlich loggen, was dein Gateway sendet
--finddas LAN nach Sensmos-Nodes durchsuchen und den Pair-Befehl ausgeben
--pair IP --pin PIN --name "…"einmaliges Pairing über einen Node
--install-servicenach /usr/local/bin kopieren, systemd-Unit schreiben und aktivieren (wird dir vorher gezeigt)
--be URLalternatives Backend, zum Testen

Die Unit, die es schreibt, falls du es lieber von Hand machst:

# /etc/systemd/system/sensmos-gw-udp.service
[Unit]
Description=Sensmos passive gateway listener
After=network-online.target
Wants=network-online.target

[Service]
ExecStart=/usr/bin/python3 /usr/local/bin/sensmos-gw-udp.py
Restart=always
RestartSec=10
User=root

[Install]
WantedBy=multi-user.target

Docker und Container

Das Skript sniffit AF_PACKET auf dem Loopback des Hosts. Loopback ist pro Netzwerk-Namespace privat, ein isolierter Container sieht also ein leeres lo und hört nichts. In einem Container braucht es --network host und --cap-add NET_RAW. Der unterstützte Weg ist der systemd-Dienst auf dem Host; ein Container-Build ist deine Sache.

Updates

Das Skript aktualisiert sich nie selbst — mit Absicht. Es läuft als Root auf deinem Gateway, in deinem LAN; Code automatisch von einem Server zu ziehen würde diesen Server zu einem Weg in dein Netzwerk machen. Zum Aktualisieren wiederhole Schritt 1 und starte den Dienst neu:

sudo curl -fsSL -o /usr/local/bin/sensmos-gw-udp.py https://raw.githubusercontent.com/Galusz/sensmos-gateway/main/sensmos-gw-udp.py
sudo systemctl restart sensmos-gw-udp

Fehlerbehebung

  • root required: run with sudo — Raw-Capture braucht CAP_NET_RAW. Nutze sudo (oder setcap cap_net_raw+ep auf der Python-Binary, was es jedem Python-Programm gewährt — sudo ist sauberer).
  • Verbunden, aber keine Frames — prüfe, ob der Verkehr wirklich auf Loopback läuft: sudo tcpdump -i lo -n -c 10 udp. Spricht dein Forwarder über das Netzwerk mit einem entfernten Server statt mit einer lokalen Bridge, zeig das Skript auf diese Schnittstelle: --iface eth0.
  • AF_PACKET is Linux only — ist es. Das läuft auf dem Gateway, nicht auf einem Mac.
  • --find findet nichts — der Node muss im selben LAN-Segment und online sein (sein /info muss mit ws_connected: true antworten). Gib stattdessen die IP des Nodes aus der App an.
  • pair first bei --install-service — das Pairing ist nicht durchgelaufen; prüfe die PIN und dass der Node online ist.

Deinstallieren

sudo systemctl disable --now sensmos-gw-udp
sudo rm /etc/systemd/system/sensmos-gw-udp.service /usr/local/bin/sensmos-gw-udp.py /etc/sensmos-gw-udp.json

Widerrufe das Attachment auch in der App. Sonst wurde nie etwas geändert, also gibt es nichts weiter rückgängig zu machen.

Im Netzwerk heute

Der erste fremde Gateway kam im August 2026 dazu (Deutschland), verbürgt durch einen Node ohne eigenes Funkmodul. Frames, die er hört — Emergency-Aussendungen und Sensor-Frames von Nodes in Reichweite — werden zugestellt wie Frames, die irgendein Node hört. Details dazu, was LoRa für einen Node-Besitzer tut: LoRa.

Fragen, klare Antworten

Welchen Weg soll ich nehmen?

Direkt, wenn du im Packet Forwarder einen Server eintragen kannst — zwei Minuten, das Gateway bekommt eine eigene Karte und verdient. Passiv, wenn du die Konfiguration des Forwarders nicht anfassen willst oder das Gateway zu einem Netz gehört, das es verbietet.

Verdient ein gekoppeltes Gateway GALU?

Ja, wie ein Node mit Gewicht 0,3 — es nimmt am Reward-Pool teil, erhöht aber nicht die Ausschüttung. Unabhängig davon gehen 70 % der Gebühr an dich, wenn ein bezahlter Sensor-Frame-Empfang dem ersten fremden Hörer des Tages gutgeschrieben wird und dieser Hörer dein Gateway ist.

Sendet mein Gateway beim direkten Weg?

Ja — alle 5 Minuten einen kurzen Sensmos-Beacon, über den Forwarder wie jeder Downlink, innerhalb des Duty Cycle der Region. Nodes, die ihn hören, bestätigen, dass das Gateway echt ist. Das passive Skript sendet nie.

Ist die Position Pflicht?

Nein. Ohne Position wird eine ungefähre aus der Verbindung des Gateways genommen. Eine eingegebene Position muss im selben Land wie diese Verbindung liegen und höchstens 500 km entfernt sein.

Brauche ich ein Konto?

Nein. Der direkte Weg koppelt das Gateway in der App mit deiner Wallet. Für den passiven Weg bürgt ein Sensmos-Node im selben LAN, und das Gateway bekommt ein enges Token nur zum Melden von Frames; der Node-Besitzer kann es in der App widerrufen.

Was bekommt das Netzwerk?

Jeden LoRa-Frame, den das Gateway hört, als Funk-Metadaten plus Rohbytes. Sensmos-Frames (Notfall-Aussendungen, Sensor-Frames) werden erkannt und an ihre Besitzer zugestellt; fremder LoRaWAN-Verkehr zählt nur als Spektrum-Statistik — die Inhalte sind verschlüsselt, wir haben keine Schlüssel.

Mein Gateway nutzt ChirpStack Gateway Bridge, keinen reinen Forwarder

Für den direkten Weg egal — trag den Server in der Bridge ein. Für den passiven Weg gibt es einen anderen Agenten (sensmos-gw-mqtt.py, im selben Repository) — ungetestet: wir haben kein solches Gateway zum Prüfen.

Aktualisiert: 2026-09-30