Creiamo un gateway tra Wi-Fi e LoRa per UDP

Da bambino avevo un sogno: fornire a ogni dispositivo domestico "senza Wi-Fi" un biglietto per la rete, ossia un indirizzo IP e una porta. Dopo un po' ho capito che non dovevo rimandare. Dovevo semplicemente farlo.
Capitolato tecnico
Realizzare un gateway M5Stack con il modulo LoRa installato (Figura 1). Il gateway sarà connesso a una rete Wi-Fi, dalla quale riceverà un indirizzo IP locale tramite DHCP. Con una certa periodicità, il gateway trasmetterà nel "spectrum LoRa" il suo nome (corrispondente all'SSID per Wi-Fi) e l'intervallo di porte disponibili, affinché altri dispositivi sappiano che esiste una rete a cui possono connettersi e in quale intervallo possono scegliere una porta libera. Poiché questo sarà un prototipo, non ci sarà autenticazione in questa fase. I nuovi dispositivi client troveranno la rete LoRa disponibile e invieranno la porta scelta. Dopo che il gateway avrà ricevuto la porta dal nuovo client, verificherà se è libera; se sì, registrerà il nuovo client e inizierà ad ascoltare la porta selezionata sul proprio server UDP asincrono. Dopo la registrazione, il client riceverà un consenso o un rifiuto per l'uso della porta dichiarata. L'ordine di funzionamento è visualizzato nella Tabella 1.

Figura 1
Tabella 1
lato
direzione e dati
lato
sessione
[ client ]
<— segnale-faro —
[ gateway ]
0xA1
[ client ]
— porta selezionata —>
[ gateway ]
0xB1
[ client ]
<— consenso o rifiuto —
[ gateway ]
0xA2
[ client ]
— pacchetto UPD —>
[ gateway ]
0xB2
[ client ]
<— pacchetto UPD —
[ gateway ]
0xA3
[ rete ]
<— pacchetto UPD —
[ gateway ]
0xC1
Davanti a me sulla scrivania ci sono vari moduli per M5Stack che aspettano. Prendiamo la LoRa e divertiamoci con essa. La concezione dei moduli è fantastica! Cosa si può dire? Tuttavia, i moduli che ho sono della prima revisione, con un'orrenda antenna incorporata, realizzata su un circuito stampato flessibile e incollata alla parete laterale del case. Una volta ho effettuato dei test sul campo con tali moduli (puoi guardare il canale russo su YouTube):

Naturalmente, ho dovuto rimuovere questi rudimenti e saldare antenne standard a spirale, incluse con Ra-01. Dopo questa personalizzazione, la portata della comunicazione è significativamente migliorata, ma è emerso un aspetto collaterale: l'antenna ha un diametro maggiore della distanza consentita tra i moduli. Ho dovuto rinunciare al Modulo Finale per il tempo del progetto.
Le prime difficoltà della rigidità sincronizzata
Sembrerebbe semplice: prendi la libreria WiFiUdp.h, dove c'è tutto il necessario per un'esistenza comfortevole del server UDP, sì. La libreria è progettata per l'implementazione di un server sincrono, che, con grande rammarico, non può gestire più connessioni contemporaneamente in un singolo thread. Tale libreria non è adatta per il compito attuale. È stato necessario bere molte tazze di tè e cercare una libreria che consentisse di avviare un server UDP asincrono capace di supportare molte connessioni contemporaneamente. Una tale libreria è stata trovata — AsyncUDP.h. Qual è la differenza tra un server sincrono e uno asincrono? Analizziamo sei episodi nell'immagine 2, nei quali sono mostrati in modo triviale le varie opzioni di funzionamento dei socket.

Figura 2
Con i protagonisti:
Uomo nel ruolo di Socket;
Piccione nel ruolo di Connessione;
Lettera nel ruolo di Dati.
Episodio A. Socket sincrono senza timeout
L'Uomo rimarrà in attesa finché il Piccione non gli porterà la Lettera.
Episodio B. Socket sincrono con timeout
L'Uomo aspetta il tempo concordato con il Piccione, e, se quest'ultimo non arriva in tempo, l'Uomo se ne andrà.
Episodio C. Socket sincrono con multithreading
L'Uomo è inattivo e osserva mentre i Piccioni consegnano da soli le Lettere.
Episodio D. Socket asincrono (quando non c'è nulla da ricevere)
L'Uomo si dedica ai suoi passatempi preferiti, ma non dimentica i Piccioni.
Episodio E. Socket asincrono (quando c'è qualcosa da ricevere)
L'Uomo si distrae per un breve momento dalle sue attività per ricevere una lettera dal Piccione.
Episodio F. Socket asincrono con multithreading
L'Uomo si occupa delle sue faccende e osserva come i Piccioni consegnano da soli le Lettere.
Se avete prestato attenzione, avrete sicuramente notato che i collari sui Piccioni in ogni episodio hanno un colore specifico. E questo non è un caso. Negli episodi A e B c'è solo un socket attivo sul server. Nell'episodio C ci sono già due socket in funzione. Negli episodi D, E e F ci sono già tre socket. "Perché ci sono due lì e tre qui?" – chiederete. Questi sono convenzionalmente 2 e 3, in realtà al posto di 2 potrebbe essercene 20, e al posto di tre 200. L'obiettivo è mostrare che i socket asincroni non gravano sull'hardware come quelli sincroni.
Quanto e dove può essere contenuto?
Esaminiamo la tabella 1, che mostra la struttura di un pacchetto UDP e pensiamo a cosa possiamo fare con esso.
Tabella 1. Struttura del pacchetto UDP
Bit
0 — 15
16 — 31
0-31
Porta del mittente (Source port)
Porta del destinatario (Destination port)
32-63
Lunghezza del datagramma (Length)
Checksum
64-…
Dati (Data)
Aggiungiamo un ulteriore campo all'inizio di questa tabella Sessione (1 Byte). Questo è sufficiente per il progetto attuale. Sulla base della Sessione, il dispositivo saprà cosa fare con il pacchetto successivamente. Ora inventiamo dei codici per le sessioni e registriamoli nella tabella 2.
Tabella 2. Spiegazione delle sessioni
Codice
Nome
Spiegazione
0xA1
Beacon
Il gateway trasmette il nome della rete LoRa e l'intervallo di porte consentite a intervalli regolari. Questo è necessario affinché i nuovi clienti possano vedere la rete disponibile e i clienti attuali possano determinare il livello del segnale quando non ci sono trasmissioni.
0xB1
Richiesta
Quando il cliente rileva la rete, invia la porta preferita.
0xA2
Accettazione o rifiuto
Se la porta richiesta dal cliente è libera, il server risponde con un'accettazione, altrimenti con un rifiuto.
0xB2
Up-link
Quando il cliente invia un pacchetto UDP al gateway.
0xA3
Down-link
Quando il gateway invia un pacchetto UDP al cliente.
0xC1
Continuazione dell'Up-link
Quando il gateway invia un pacchetto UDP alla rete locale.
Bene. Ora discutiamo la composizione delle sessioni nella tabella 3.
Tabella 3. Sessioni
Nome della sessione
Composizione
Beacon
Codice della sessione (1 Byte) + Nome della rete LoRa (4 Byte) + Porta iniziale (2 Byte) + Porta finale (2 Byte)
Richiesta
Codice di trasmissione (1 Byte) + Nome della rete LoRa (4 Byte) + Porta preferita (2 Byte)
Accettazione o rifiuto
Codice di trasmissione (1 Byte) + Nome della rete LoRa (4 Byte) + Porta preferita (2 Byte) + Risultato (1 Byte)
Up-link
Codice di trasmissione (1 Byte) + Nome della rete LoRa (4 Byte) + Indirizzo IP remoto (4 Byte) + Porta remota (2 Byte) + Indirizzo IP locale (4 Byte) + Porta locale (2 Byte) + Dimensione dei dati (2 Byte) + Dati
Down-link
Codice di trasmissione (1 Byte) + Nome della rete LoRa (4 Byte) + Indirizzo IP remoto (4 Byte) + Porta remota (2 Byte) + Indirizzo IP locale (4 Byte) + Porta locale (2 Byte) + Dimensione dei dati (2 Byte) + Dati
Continuazione dell'Up-link
Indirizzo IP remoto (4 Byte) + Porta remota (2 Byte) + Dimensione dei dati (2 Byte) + Dati
Ho scritto due client per Arduino e per M5Stack. Puoi vedere come funziona. Non ci sono problemi all'interno dell'appartamento, ma non ho ancora eseguito test sul campo.
Il codice sorgente è disponibile su GitHub all'indirizzo
Per saperne di più sul dispositivo di base M5Stack e acquistarlo puoi
Scegliere moduli wireless LoRa per il dispositivo di base può essere fatto
Sarò felice se questo progetto ti sarà utile. Grazie mille per il tuo tempo!
Elenco delle risorse e/o fonti:
Fonte: habr.com
