We maken een gateway tussen Wi-Fi en LoRa voor UDP

Ik had als kind de droom om elk huishoudelijk 'zonder Wi-Fi' apparaat een toegang tot het netwerk te geven, dat wil zeggen, een IP-adres en poort. Na enige tijd realiseerde ik me dat ik het niet moest uitstellen. Ik moet het gewoon doen.
Technische specificatie
Maak een gateway met M5Stack met een geïnstalleerde LoRa-module (afbeelding 1). De gateway zal verbinding maken met het Wi-Fi-netwerk, waar hij via DHCP een lokaal IP-adres zal verkrijgen. De gateway zal op bepaalde tijdstippen zijn naam (de analogie van SSID voor Wi-Fi) en de reeks toegestane poorten uitzenden, zodat andere apparaten weten dat er een netwerk is waarmee ze verbinding kunnen maken en in welke reeks ze een vrije poort kunnen kiezen. Aangezien dit een prototype is, is authenticatie dit keer niet aan de orde. Nieuwe client-apparaten zullen het beschikbare LoRa-netwerk vinden en hun gekozen poort doorgeven. Nadat de gateway de poort van de nieuwe client heeft ontvangen, controleert hij of deze vrij is; als dat zo is, registreert hij de nieuwe client en begint te luisteren naar deze poort op zijn eigen asynchrone UDP-server. Na registratie ontvangt de client toestemming of weigering voor het gebruik van de opgegeven poort. De volgorde van werking is weergegeven in tabel 1.

Afbeelding 1
Tabel 1
zijde
richting en gegevens
zijde
sessie
[ client ]
<— signaal-baken —
[ gateway ]
0xA1
[ client ]
— gekozen poort —>
[ gateway ]
0xB1
[ client ]
<— toestemming of weigering —
[ gateway ]
0xA2
[ client ]
— UPD-pakket —>
[ gateway ]
0xB2
[ client ]
<— UPD-pakket —
[ gateway ]
0xA3
[ netwerk ]
<— UPD-pakket —
[ gateway ]
0xC1
Voor mij op de tafel liggen allerlei modules voor de M5Stack te wachten. Laten we de LoRa pakken en daarmee aan de slag gaan. Het concept van de modules is geweldig! Wat moet ik daarover zeggen? Maar, ik heb de modules van de eerste revisie, waarin de ingebouwde antenne vreselijk is, gemaakt van een flexibele printplaat en aan de zijkant van de behuizing geplakt. Een keer heb ik veldtests met zulke modules uitgevoerd (je kunt het bekijken op het Russischtalige YouTube-kanaal):

Natuurlijk moest ik deze restanten verwijderen en standaard spiraalantenne solderen, die bij de Ra-01 worden geleverd. Na deze aanpassing verbeterde het bereik aanzienlijk, maar er kwam een bijeffect — de antenne heeft een diameter die groter is dan de toegestane afstand tussen modules. Ik moest de afsluitmodule tijdelijk laten vallen voor het project.
De eerste moeilijkheden van synchronisatie-stijfheid
Het lijkt zo simpel, neem de bibliotheek WiFiUdp.h, waar alles is voor het comfortabele functioneren van een UDP-server, is er niet. De bibliotheek is ontworpen voor het opzetten van een synchrone server, die, tot diepere spijt, niet meerdere verbindingen in één thread tegelijkertijd kan bedienen. Zo'n bibliotheek is niet geschikt voor de huidige taak. We moesten veel kopjes thee drinken en zoeken naar een bibliotheek die het mogelijk maakt om een asynchrone UDP-server op te zetten die veel verbindingen tegelijkertijd kan ondersteunen. Zo'n bibliotheek is gevonden — AsyncUDP.h. Wat is het verschil tussen een synchrone server en een asynchrone? Laten we zes episodes bekijken in figuur 2, waarin de verschillende manieren van socket-werking triviaal worden weergegeven.

Figuur 2
In de hoofdrol:
De Mens in de rol van Socket;
De Duif in de rol van Verbinding;
De Brief in de rol van Gegevens.
Episode A. Synchrone socket zonder timeout
De Mens staat te wachten totdat de Duif hem de Brief brengt.
Episode B. Synchrone socket met timeout
De Mens wacht de afgesproken tijd af met de Duif, en als deze niet op tijd komt, zal de Mens vertrekken.
Episode C. Synchrone socket met multi-threading
De Mens doet niets en kijkt hoe de Duiven zelf de Brieven bezorgen.
Episode D. Asynchrone socket (wanneer er nog niets te ontvangen is)
De Mens houdt zich bezig met zijn favoriete bezigheden, maar vergeet de Duiven niet.
Episode E. Asynchrone socket (wanneer er iets te ontvangen is)
De Mens heeft zich even afgeleid van zijn bezigheden om een brief van de Duif te ontvangen.
Episode F. Asynchrone socket met multi-threading
De Mens is bezig met zijn zaken en kijkt hoe de Duiven zelf de Brieven bezorgen.
Als je goed hebt opgelet, heb je ongetwijfeld opgemerkt dat de kraag op de Duiven in elke episode een bepaalde kleur heeft. En dat is niet voor niets. In episode A en B werkt er slechts één socket op de server, en dat is alles. In episode C werken er al twee sockets. In de episodes D, E en F zijn het er al drie. 'Waarom daar twee en hier drie?' - vraag je je af. Dit zijn bij benadering 2 en 3; in werkelijkheid kan het in plaats van 2 ook 20 zijn, en in plaats van drie zelfs 200. Het idee is om te laten zien dat asynchrone sockets niet zo veel belasting op de hardware leggen als synchrone.
Hoeveel ruimte is er?
Laten we kijken naar tabel 1, die de structuur van een UDP-pakket laat zien en nadenken over wat we ermee kunnen doen.
Tabel 1. Structuur van een UDP-pakket
Bits
0 — 15
16 — 31
0-31
Afzendpoort (Source port)
Bestemmingspoort (Destination port)
32-63
Lengte van de datagram (Length)
Checksum
64-…
Gegevens (Data)
Laten we nog een veld aan het begin van deze tabel toevoegen Sessie (1 Byte). Dat is voldoende voor dit project. Op basis van de Sessie weet het apparaat wat ermee verder moet. Laten we nu codes voor de sessies bedenken en deze in tabel 2 noteren.
Tabel 2. Uitleg over sessies
Code
Naam
Uitleg
0xA1
Boeg
De gateway zendt de naam van het LoRa-netwerk en het bereik van toegestane poorten periodiek uit. Dit is nodig zodat nieuwe klanten het beschikbare netwerk kunnen zien en lopende klanten, wanneer er geen transmissions zijn, het signaalniveau kunnen bepalen.
0xB1
Aanvraag
Wanneer de klant het netwerk heeft ontdekt, stuurt hij de gewenste poort.
0xA2
Toestemming of weigering
Als de door de klant aangevraagde poort vrij is, antwoordt de server met toestemming, anders met een weigering.
0xB2
Up-link
Wanneer de klant een UDP-pakket naar de gateway verzendt.
0xA3
Down-link
Wanneer de gateway een UDP-pakket naar de klant verzendt.
0xC1
Voortzetting van de Up-link
Wanneer de gateway een UDP-pakket naar het lokale netwerk verzendt.
Goed. Laten we nu de samenstelling van de sessies in tabel 3 bespreken.
Tabel 3. Sessies
Naam van de sessie
Samenstelling
Boeg
Sessencode (1 Byte) + Naam LoRa-netwerk (4 Byte) + Beginpoort (2 Byte) + Eindpoort (2 Byte)
Aanvraag
Verzendcode (1 Byte) + Naam LoRa-netwerk (4 Byte) + Gewenste poort (2 Byte)
Toestemming of weigering
Verzendcode (1 Byte) + Naam LoRa-netwerk (4 Byte) + Gewenste poort (2 Byte) + Resultaat (1 Byte)
Up-link
Verzendcode (1 Byte) + Naam LoRa-netwerk (4 Byte) + Extern IP-adres (4 Byte) + Externe poort (2 Byte) + Lokaal IP-adres (4 Byte) + Lokale poort (2 Byte) + Grootte van de gegevens (2 Byte) + Gegevens
Down-link
Verzendcode (1 Byte) + Naam LoRa-netwerk (4 Byte) + Extern IP-adres (4 Byte) + Externe poort (2 Byte) + Lokaal IP-adres (4 Byte) + Lokale poort (2 Byte) + Grootte van de gegevens (2 Byte) + Gegevens
Voortzetting van de Up-link
Extern IP-adres (4 Byte) + Externe poort (2 Byte) + Grootte van de gegevens (2 Byte) + Gegevens
Ik heb twee clients gemaakt voor Arduino en voor M5Stack. Op kun je zien hoe dit werkt. Binnen het appartement zijn er geen problemen, veldtests heb ik tot nu toe nog niet uitgevoerd.
De broncode is beschikbaar op GitHub op
Meer informatie over het Basisapparaat M5Stack en de aankoop kan via
Draadloze LoRa-modules voor het Basisapparaat kunnen via
Ik ben blij als dit project nuttig voor je is. Hartelijk dank voor je tijd!
Literatuurlijst en (of) bronnen:
Bron: habr.com
