Brama UDP między Wi-Fi a LoRa

Tworzymy bramę między Wi-Fi a LoRa dla UDP

Brama UDP między Wi-Fi a LoRa

Miałem dziecięce marzenie — dać każdemu urządzeniu „bez Wi-Fi” bilet do sieci, tj. adres IP i port. Po pewnym czasie zrozumiałem, że nie warto odkładać. Trzeba po prostu to zrobić.

Zadanie techniczne

Zrealizować jako bramę M5Stack z zainstalowanym modułem LoRa (rysunek 1). Bramę podłączymy do sieci Wi-Fi, gdzie otrzyma lokalny adres IP przez DHCP. Bramę w określonych interwałach czasowych będzie nadawać w „LoRa-eter” swoją nazwę (analog SSID dla Wi-Fi) oraz zakres dozwolonych portów, aby inne urządzenia wiedziały, że istnieje taka sieć, do której można się podłączyć oraz w jakim zakresie można wybrać wolny port. Ponieważ będzie to prototyp, tym razem nie będzie autoryzacji. Nowe urządzenia-klienty znajdą dostępna sieć LoRa i przekażą jej wybrany port. Po otrzymaniu od nowego klienta portu, brama sprawdzi, czy jest on wolny, a jeśli tak, zarejestruje nowego klienta i zacznie nasłuchiwać na tym porcie na własnym asynchronicznym serwerze UDP. Po rejestracji klient otrzyma zgodę lub odmowę na użycie zgłaszanego portu. Kolejność działań przedstawiona jest w tabeli 1.

Brama UDP między Wi-Fi a LoRa
Rysunek 1

Tabela 1

strona
kierunek i dane
strona
sesja

[ klient ]
<— sygnał-bodziec —
[ brama ]
0xA1

[ klient ]
— wybrany port —>
[ brama ]
0xB1

[ klient ]
<— zgoda lub odmowa —
[ brama ]
0xA2

[ klient ]
— pakiet UDP —>
[ brama ]
0xB2

[ klient ]
<— pakiet UDP —
[ brama ]
0xA3

[ sieć ]
<— pakiet UDP —
[ brama ]
0xC1

Na moim stole leżą różne moduły do M5Stack i się nudzą. Weźmy LoRę i zabawmy się z nią. Sam pomysł modułów jest wspaniały! Co tu powiedzieć? Jednak moduły, które mam, to pierwsza rewizja, w których straszna zintegrowana antena, wykonana na giętkiej płytce drukowanej i przyklejona do bocznej ściany obudowy. Kiedyś przeprowadzałem testy terenowe takich modułów (można je zobaczyć na rosyjskim kanale na YouTube):

Odtwarzaj wideo

Oczywiście musiałem usunąć te resztki i wlutować standardowe anteny spiralne, które znajdują się w komplecie z Ra-01. Po takiej przeróbce zasięg komunikacji znacznie się poprawił, ale pojawił się efekt uboczny — antena ma większą średnicę niż dopuszczalna odległość między modułami. Musiałem zrezygnować z ostatniego modułu na czas projektu.

Pierwsze trudności od synchronicznej sztywności

Wydawałoby się, że wystarczy wziąć bibliotekę WiFiUdp.h, gdzie wszystko jest do komfortowego działania serwera UDP, niestety nie. Biblioteka jest zaprojektowana do uruchomienia synchronizowanego serwera, który, niestety, nie może obsługiwać wielu połączeń jednocześnie w jednym wątku. Taka biblioteka nie nadaje się do obecnego zadania. Musiałem wypić wiele filiżanek herbaty i poszukać biblioteki, która pozwoli na uruchomienie asynchronicznego serwera UDP zdolnego do obsługi wielu połączeń jednocześnie. Taka biblioteka została znaleziona — AsyncUDP.h. W czym różni się serwer synchronizowany od asynchronizowanego? Rozważmy sześć epizodów ilustrujących możliwości pracy gniazd w rysunku 2.

Brama UDP między Wi-Fi a LoRa

Rysunek 2

W rolach głównych:

Człowiek w roli Gniazda;

Gołąb w roli Połączenia;

List w roli Danych.

Episod A. Synchronizowane gniazdo bez limitu czasu

Człowiek będzie stał, dopóki Gołąb nie przyniesie mu Listu.

Episod B. Synchronizowane gniazdo z limitem czasu

Człowiek czeka uzgodniony czas z Gołębiem, a jeśli ten nie przyleci na czas, Człowiek odejdzie.

Episod C. Synchronizowane gniazdo z wieloma wątkami

Człowiek bezczynnie ogląda, jak Gołębie same dostarczają Listy.

Episod D. Asynchroniczne gniazdo (gdy nie ma jeszcze nic do odebrania)

Człowiek zajmuje się swoimi ulubionymi zajęciami, ale nie zapomina o Gołębiach.

Episod E. Asynchroniczne gniazdo (gdy jest coś do odebrania)

Człowiek na chwilę oderwał się od swoich zajęć, aby odebrać list od Gołębia.

Episod F. Asynchroniczne gniazdo z wieloma wątkami

Człowiek zajmuje się swoimi sprawami i obserwuje, jak Gołębie same dostarczają Listy.

Jeśli byliście uważni, na pewno zauważyliście, że obroże na Gołębiach w każdym epizodzie mają określony kolor. I to nie jest przypadek. W epizodach A i B na serwerze działa tylko jedno gniazdo i to wszystko. W epizodzie C działają już dwa gniazda. W epizodach D, E i F działa już po trzy gniazda. "Dlaczego tam dwa, a tutaj trzy?" — zapytacie. To umownie 2 i 3, w rzeczywistości zamiast 2 może być 20, a zamiast trzech 200. Zadanie polega na pokazaniu, że asynchroniczne gniazda nie obciążają sprzętu tak mocno, jak synchronizowane.

Ile się zmieści?

Przyjrzyjmy się tabeli 1, w której przedstawiona jest struktura pakietu UDP i pomyślmy, co można z tym zrobić.

Tabela 1. Struktura pakietu UDP

Bity
0 — 15
16 — 31

0-31
Port źródłowy (Source port)
Port docelowy (Destination port)

32-63
Długość datagramu (Length)
Suma kontrolna (Checksum)

64-…
Dane (Data)

Dodajmy do początku tej tabeli jeszcze jedno pole Sesja (1 Bajt). To wystarczy dla tego projektu. Na podstawie sesji urządzenie będzie wiedziało, co zrobić z pakietem dalej. Teraz wymyślimy kody dla sesji i zapiszemy je w tabeli 2.

Tabela 2. Wyjaśnienie do sesji

Kod
Nazwa
Wyjaśnienie

0xA1
Bojler
Bramka nadaje nazwę sieci LoRa i zakres dozwolonych portów z określoną częstotliwością. Jest to konieczne, aby nowe urządzenia mogły zobaczyć dostępną sieć, a obecne urządzenia mogły określić poziom sygnału, gdy nie ma transmisji.

0xB1
Zgłoszenie
Kiedy klient wykrywa sieć, wysyła preferowany port.

0xA2
Zgoda lub odmowa
Jeśli żądany port jest wolny, serwer odpowiada zgodą, w przeciwnym razie odmową.

0xB2
Up-link
Kiedy klient przesyła pakiet UDP do bramki.

0xA3
Down-link
Kiedy bramka przesyła pakiet UDP do klienta.

0xC1
Kontynuacja Up-linka
Kiedy bramka wysyła pakiet UDP do lokalnej sieci.

Dobrze. Teraz porozmawiajmy o składzie sesji w tabeli 3.

Tabela 3. Sesje

Nazwa sesji
Skład

Bojler
Kod sesji (1 Bajt) + Nazwa sieci LoRa (4 Bajt) + Port początkowy (2 Bajt) + Port końcowy (2 Bajt)

Zgłoszenie
Kod transmisji (1 Bajt) + Nazwa sieci LoRa (4 Bajt) + Preferowany port (2 Bajt)

Zgoda lub odmowa
Kod transmisji (1 Bajt) + Nazwa sieci LoRa (4 Bajt) + Preferowany port (2 Bajt) + Wynik (1 Bajt)

Up-link
Kod transmisji (1 Bajt) + Nazwa sieci LoRa (4 Bajt) + Zdalny adres IP (4 Bajt) + Zdalny port (2 Bajt) + Lokalny adres IP (4 Bajt) + Lokalny port (2 Bajt) + Rozmiar danych (2 Bajt) + Dane

Down-link
Kod transmisji (1 Bajt) + Nazwa sieci LoRa (4 Bajt) + Zdalny adres IP (4 Bajt) + Zdalny port (2 Bajt) + Lokalny adres IP (4 Bajt) + Lokalny port (2 Bajt) + Rozmiar danych (2 Bajt) + Dane

Kontynuacja Up-linka
Zdalny adres IP (4 Bajt) + Zdalny port (2 Bajt) + Rozmiar danych (2 Bajt) + Dane

Napisałem dwóch klientów dla Arduino i M5Stack. Na wideo można zobaczyć, jak to działa. W obrębie mieszkania nie ma problemów, testy terenowe jeszcze nie były przeprowadzane.

Kod źródłowy jest dostępny na GitHubie na linkiem

Można poznać więcej informacji o podstawowym urządzeniu M5Stack i je kupić tutaj

Można wybrać bezprzewodowe moduły LoRa dla podstawowego urządzenia tutaj

Będę wdzięczny, jeśli ten projekt będzie dla Ciebie przydatny. Dziękuję za poświęcony czas!

Lista literatury i (lub) źródeł:

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster