ENPLDEPT
Flash
Cała dokumentacja
Brama LoRaWAN

Twoja brama już słyszy wszystko. Niech pracuje dla sieci.

Dwie drogi. Bezpośrednia — forwarder wysyła też na sensmos.com:1700, a bramę parujesz z portfelem w apce; zarabia i nadaje beacony. Pasywna — jeden skrypt na bramie raportuje, co słyszy; na bramie nic się nie zmienia.

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

Droga 1 — bezpośrednio: sparuj z portfelem

Działa z każdą bramą, której packet forwarder umie wysyłać do więcej niż jednego serwera (Crankk, RAK, Dragino, MikroTik, większość hotspotów z czasów Helium).

  1. W packet forwarderze bramy dopisz serwer: sensmos.com, port 1700 (UDP, uplink i downlink). Zostaw pozostałe serwery — forwarder wysyła każdą ramkę do każdego z nich.
  2. Poczekaj minutę, aż brama coś do nas wyśle.
  3. W apce Sensmos: Panel → + → Dodaj bramę LoRaWAN. Wpisz EUI bramy (16 znaków szesnastkowych, z jej panelu), opcjonalnie nazwę i pozycję — albo użyj pozycji telefonu, stojąc obok niej. Stuknij Sparuj z portfelem.

Apka odmówi, jeśli brama milczy dłużej niż 10 minut (sprawdź wpis serwera) albo jest już sparowana z innym portfelem.

Co dostajesz: kartę w Panelu — ile nodów brama słyszy i ile ją słyszy (24 h), ramki Sensmos z 24 h, ostatni beacon, zarobek. Na mapie brama ma własny kolor i panel. Nazwa i pozycja edytuje ją; Odepnij bramę na karcie zwalnia ją.

Zanim ją sparujesz: brama, która od 10 minut wysyła do sensmos.com:1700, zaczyna pracować dla sieci pod portfelem projektu — jej ramki Sensmos są dostarczane, nadaje beacon zasięgu i liczy się w epoce. Parowanie przenosi kartę i zarobek do Ciebie; brama, której nikt nie sparuje, zarabia dla projektu.

Co robi z nią sieć: każda usłyszana ramka Sensmos — nadanie awaryjne, ramka czujnika — trafia do właściciela dokładnie tak, jak ramka usłyszana przez noda. Co 5 minut sieć nadaje przez Twoją bramę krótki beacon pokrycia; nody, które go usłyszą, potwierdzają, że brama jest tam, gdzie mówi.

Droga 2 — pasywnie: jeden skrypt, na bramie nic się nie zmienia

Dla bramy, której nie chcesz przekonfigurowywać. Skrypt w Pythonie na bramie czyta ruch forwardera na loopbacku i raportuje metadane radiowe. Potrzebuje jednego noda Sensmos w tej samej sieci, który za niego ręczy. Szczegóły niżej.

Dla kogo to jest

Dowolna maszyna z Linuksem, na której działa zwykły packet forwarder Semtech (UDP, port w stylu 1700) skierowany na zdalny serwer: hotspoty Helium i ich stacki multi-mining, RAK, Dragino, Mikrotik, Raspberry Pi z HAT-em koncentratora. Jeśli Twoja brama ma zamiast tego ChirpStack Gateway Bridge, jest tam lokalny broker MQTT i stosuje się inny agent.

Potrzebujesz też jednego noda Sensmos w tym samym LAN-ie co brama (dowolne ESP32 z firmware, radio niewymagane) i jego PIN-u. Node ręczy za bramę; bez niego backend nie wyda tokena.

Dlaczego pasywnie, a nie przekaźnik

Oczywisty sposób na podpięcie się pod forwarder to wstawić coś pośrodku — skierować forwarder na nas i przekazywać dalej. Celowo tego nie robimy. Na sprzęcie, który zarabia, nasza awaria stałaby się Twoją awarią. Forwarder i tak wysyła każdą ramkę do każdego skonfigurowanego serwera osobno przez loopback; skrypt po prostu czyta razem z nim na lo. Nie jest niczyim celem, niczego nie przekazuje i niczego nie opóźnia.

Szybki start

Wszystko to uruchom na bramie, nie na laptopie. Tylko Python 3 — bez pakietów pip, bez budowania. Root jest potrzebny, bo czytanie surowych pakietów wymaga CAP_NET_RAW.

# 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

Krok 6 powinien pokazać active (running), a log wypisuje connection works — first batch accepted, gdy popłyną ramki, potem linię statusu co minutę. W apce brama pojawia się w Przystawkach noda; na mapie na żywo node zyskuje warstwę RF.

Już sparowane, brak usługi? Token przetrwał; powtórz kroki 1 i 5. Tylko jeśli --install-service mówi pair first, powtórz krok 4.

Zajrzyj, zanim nam zaufasz

--dry-run wypisuje jako JSON dokładnie te ramki, które by przekazał, i na tym poprzestaje. Dodaj --log-tx, żeby zobaczyć też, kiedy Twoja brama nadaje. Skrypt to jeden czytelny plik; źródło jest na GitHubie.

Parowanie — jak działa token

Skrypt nie ma własnych poświadczeń. Prosi noda Sensmos w Twoim LAN-ie (z PIN-em noda), żeby za niego poręczył; node przekazuje żądanie do backendu przez własne łącze, a backend wydaje token ograniczony do radio.frames — raportowanie odebranych ramek, nic więcej. Token jest przechowywany w /etc/sensmos-gw-udp.json (tryb 0600). Od tej chwili skrypt rozmawia z backendem bezpośrednio; node jest poza pętlą.

  • Jeden node może poręczyć za maksymalnie cztery przystawki.
  • Właściciel może odwołać każdą z nich z apki (node → Przystawki); skrypt natychmiast staje się bezczynny.
  • Token żyje 30 dni od pierwszego użycia, a skrypt odnawia go sam.

Pełny kontrakt (endpointy, zakresy, formaty) jest na Przystawki i EXT API.

Co czyta

Semtech GWMP przez UDP, rozpoznawany po nagłówku pakietu, nie po porcie, więc działa niezależnie od tego, jakich portów używa Twój stack:

bajt
0wersja protokołu (1 albo 2)
1–2token
3typ — 0 PUSH_DATA (odebrane ramki), 3 PULL_RESP (brama poproszona o nadanie)
4–11EUI bramy
resztaJSON

Z PUSH_DATA bierze wpisy rxpk: częstotliwość, spreading factor, RSSI, SNR, rozmiar, wynik CRC i surowy payload PHY. Payloady aplikacyjne są zaszyfrowane kluczami, których nie mamy; sieć używa metadanych radiowych i rozpoznawania ramek Sensmos w ruchu.

PULL_RESP — nadanie, które Twoja brama zaraz wykona — jest raportowane tylko wtedy, gdy jest słyszalne dla innych (ipol = false, np. beacony pokrycia, które nadają niektóre sieci). Zwykły downlink LoRaWAN używa odwróconego IQ, którego nikt inny nie słyszy, niczego nie dowodzi i jest pomijany. Raportowane nadania są dowodem, że brama jest prawdziwa: ich payload jest nieprzewidywalny, więc node Sensmos, który niezależnie usłyszy te same bajty, potwierdza, że brama faktycznie nadała.

Forwarder wieloserwerowy wysyła identyczną ramkę do każdego skonfigurowanego serwera, więc to samo nadanie pojawia się na loopbacku kilka razy (RF packets received: 1 / PUSH_DATA datagrams sent: 2 w logu Twojego forwardera). Skrypt deduplikuje; jedno nadanie jest raportowane raz. Ramki są grupowane (raz na sekundę albo co 50 ramek) i wysyłane na https://sensmos.com/v1/ext/radio/frames.

Flagi

flagaznaczenie
--ifaceinterfejs do obserwowania, domyślnie lo
--dry-runwypisz, co byłoby wysłane, nie wysyłaj nic
--log-txloguj też, co nadaje Twoja brama
--findprzeskanuj LAN w poszukiwaniu nodów Sensmos i wypisz komendę parowania
--pair IP --pin PIN --name "…"jednorazowe parowanie przez noda
--install-serviceskopiuj do /usr/local/bin, zapisz i włącz unit systemd (najpierw Ci go pokaże)
--be URLalternatywny backend, do testów

Unit, który zapisuje, gdybyś wolał zrobić to ręcznie:

# /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 i kontenery

Skrypt sniffuje AF_PACKET na loopbacku hosta. Loopback jest prywatny per przestrzeń nazw sieciowych, więc izolowany kontener widzi puste lo i nic nie słyszy. Uruchomienie w kontenerze wymaga --network host i --cap-add NET_RAW. Wspierany sposób to usługa systemd na hoście; build kontenerowy utrzymujesz na własną rękę.

Aktualizacje

Skrypt nigdy nie aktualizuje się sam — celowo. Działa jako root na Twojej bramie, w Twoim LAN-ie; automatyczne pobieranie kodu z serwera zrobiłoby z tego serwera drogę do Twojej sieci. Żeby zaktualizować, powtórz krok 1 i zrestartuj usługę:

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

Rozwiązywanie problemów

  • root required: run with sudo — surowe przechwytywanie wymaga CAP_NET_RAW. Użyj sudo (albo setcap cap_net_raw+ep na binarce Pythona, co nadaje to każdemu programowi w Pythonie — sudo jest czystsze).
  • Połączony, ale brak ramek — sprawdź, czy ruch naprawdę jest na loopbacku: sudo tcpdump -i lo -n -c 10 udp. Jeśli Twój forwarder rozmawia ze zdalnym serwerem przez sieć, a nie z lokalnym mostkiem, skieruj skrypt na ten interfejs: --iface eth0.
  • AF_PACKET is Linux only — zgadza się. To działa na bramie, nie na Macu.
  • --find nic nie znajduje — node musi być w tym samym segmencie LAN i online (jego /info musi odpowiadać ws_connected: true). Zamiast tego podaj IP noda z apki.
  • pair first przy --install-service — parowanie się nie dokończyło; sprawdź PIN i czy node jest online.

Odinstalowanie

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

Odwołaj też przystawkę w apce. Nic innego nigdy nie zostało zmienione, więc nie ma nic więcej do cofnięcia.

W sieci dziś

Pierwsza obca brama dołączyła w sierpniu 2026 (Niemcy), poręczona przez noda bez własnego radia. Ramki, które słyszy — nadania awaryjne i ramki czujników nodów w zasięgu — są dostarczane jak ramki usłyszane przez dowolnego noda. Szczegóły tego, co LoRa daje właścicielowi noda: LoRa.

Pytania i proste odpowiedzi

Którą drogę wybrać?

Bezpośrednią, jeśli możesz dopisać serwer w packet forwarderze — to dwie minuty, brama dostaje własną kartę i zarabia. Pasywną, jeśli nie chcesz ruszać konfiguracji forwardera albo brama należy do sieci, która tego zabrania.

Czy sparowana brama zarabia GALU?

Tak, jak node z wagą 0,3 — bierze udział w puli nagród, ale nie zwiększa emisji. Niezależnie od tego, gdy płatny odbiór ramki czujnika trafia do pierwszego obcego słuchacza w danym dniu i tym słuchaczem jest Twoja brama, 70% opłaty idzie do Ciebie.

Czy droga bezpośrednia sprawia, że brama nadaje?

Tak — krótki beacon pokrycia Sensmos co 5 minut, wysyłany przez forwarder jak każdy downlink, w granicach duty cycle regionu. Nody, które go usłyszą, potwierdzają, że brama jest prawdziwa. Skrypt pasywny nigdy nie nadaje.

Czy pozycja jest wymagana?

Nie. Bez niej używana jest przybliżona pozycja z łącza bramy. Wpisana pozycja musi być w tym samym kraju co to łącze i nie dalej niż 500 km od niego.

Potrzebuję konta?

Nie. Droga bezpośrednia paruje bramę z Twoim portfelem w apce. Za drogę pasywną ręczy node Sensmos w tej samej sieci, a brama dostaje wąski token tylko do raportowania ramek; właściciel noda może go odwołać z apki.

Co dostaje sieć?

Każdą ramkę LoRa, którą brama słyszy — metadane radiowe i surowe bajty. Ramki Sensmos (nadania awaryjne, ramki czujników) są rozpoznawane i dostarczane właścicielom; obcy ruch LoRaWAN liczy się tylko jako statystyka widma — treść jest szyfrowana, a my nie mamy kluczy.

Moja brama ma ChirpStack Gateway Bridge, nie goły forwarder

Dla drogi bezpośredniej to bez znaczenia — dopisz serwer w bridge'u. Dla drogi pasywnej jest inny agent (sensmos-gw-mqtt.py, w tym samym repozytorium) — niesprawdzony: nie mamy takiej bramy, żeby go zweryfikować.

Aktualizacja: 2026-09-30