Gateway para UDP entre Wi-Fi e LoRa

Criamos um gateway entre Wi-Fi e LoRa para UDP

Gateway para UDP entre Wi-Fi e LoRa

Eu tinha um sonho de infância — dar a cada dispositivo doméstico "sem Wi-Fi" um ingresso na rede, ou seja, um endereço IP e uma porta. Depois de algum tempo, percebi que não devia adiar. Precisava pegar e fazer.

Especificação técnica

Fazer um gateway com M5Stack equipado com o Módulo LoRa (Figura 1). O gateway será conectado a uma rede Wi-Fi, onde obterá um endereço IP local via DHCP. Com certa periodicidade, o gateway transmitirá em "LoRa-ether" seu nome (análogo ao SSID para Wi-Fi) e o intervalo de portas permitidas, para que outros dispositivos saibam que existe uma rede à qual podem se conectar e em qual intervalo podem escolher uma porta livre. Como este será um protótipo, a autenticação não será feita desta vez. Novos dispositivos-clientes encontrarão a rede LoRa disponível e enviarão a porta escolhida. Após o gateway receber a porta do novo cliente, ele verifica se está livre; se sim, registra o novo cliente e começa a ouvir essa porta em seu próprio servidor UDP assíncrono. Após o registro, o cliente receberá aprovação ou reprovação para o uso da porta solicitada. O funcionamento está descrito na Tabela 1.

Gateway para UDP entre Wi-Fi e LoRa
Figura 1

Tabela 1

lado
direção e dados
lado
sessão

[ cliente ]
<— sinal-bóia —
[ gateway ]
0xA1

[ cliente ]
— porta escolhida —>
[ gateway ]
0xB1

[ cliente ]
<— aprovação ou reprovação —
[ gateway ]
0xA2

[ cliente ]
— pacote UPD —>
[ gateway ]
0xB2

[ cliente ]
<— pacote UPD —
[ gateway ]
0xA3

[ rede ]
<— pacote UPD —
[ gateway ]
0xC1

Na minha mesa estão diversos módulos para M5Stack entediados. Vamos pegar a LoRa e nos divertir com ela. O conceito dos módulos é ótimo! O que mais posso dizer? Mas, os módulos que tenho são da primeira versão, com uma antena interna horrível, feita de uma placa de circuito flexível e colada na parede lateral do case. Uma vez fiz testes em campo com esses módulos (pode-se ver no canal em russo no YouTube):

Por que no hosting comum a administração do PrestaShop é lenta, e no seu não é?

Naturalmente, tive que remover esses resíduos e soldar antenas espirais padrão, que vêm com o Ra-01. Após essa customização, a distância de comunicação melhorou significativamente, mas surgiu um problema colateral — a antena tem um diâmetro maior que a distância permitida entre os módulos. Tive que desistir do Módulo Final por um tempo durante o projeto.

As primeiras dificuldades da rigidez síncrona

Aparentemente, basta pegar a biblioteca WiFiUdp.h, onde está tudo para a operação confortável de um servidor UDP, mas não. A biblioteca é projetada para levantar um servidor síncrono, que, para nosso grande desgosto, não pode atender várias conexões ao mesmo tempo em um único fluxo. Essa biblioteca não se adequa à tarefa atual. Foi preciso beber muitas xícaras de chá e procurar uma biblioteca que permita levantar um servidor UDP assíncrono capaz de suportar múltiplas conexões simultaneamente. Essa biblioteca foi encontrada — AsyncUDP.h. Qual é a diferença entre um servidor síncrono e um assíncrono? Vamos considerar seis episódios na Figura 2, que ilustram trivialmente as opções de operação dos sockets.

Gateway para UDP entre Wi-Fi e LoRa

Figura 2

Nos papéis principais:

Pessoa no papel de Socket;

Pombo no papel de Conexão;

Carta no papel de Dados.

Episódio A. Socket Síncrono sem Timeout

A pessoa ficará parada até que o pombo traga a carta.

Episódio B. Socket Síncrono com Timeout

A pessoa aguarda o tempo combinado com o pombo e, se ele não chegar a tempo, a pessoa irá embora.

Episódio C. Socket Síncrono com Multithreading

A pessoa está ociosa e observa como os pombos entregam as cartas por conta própria.

Episódio D. Socket Assíncrono (quando não há nada a receber)

A pessoa se dedica às suas atividades favoritas, mas não se esquece dos pombos.

Episódio E. Socket Assíncrono (quando há algo a receber)

A pessoa se distrai brevemente de suas atividades para receber uma carta do pombo.

Episódio F. Socket Assíncrono com Multithreading

A pessoa continua em suas tarefas e observa como os pombos entregam as cartas sozinhos.

Se você prestou atenção, deve ter notado que as coleiras nos pombos em cada episódio têm uma cor específica. E isso não é à toa. Nos episódios A e B, apenas um socket está ativo no servidor. No episódio C, já são dois sockets. Nos episódios D, E e F, já são três sockets. 'Por que são dois ali, e três aqui?' — você deve estar se perguntando. Isso é condicionalmente 2 e 3; na verdade, em vez de 2 pode ser 20, e em vez de três, 200. O objetivo é mostrar que os sockets assíncronos não sobrecarregam tanto o hardware quanto os síncronos.

Quanto cabe onde?

Vamos considerar a Tabela 1, que apresenta a estrutura de um pacote UDP e pensar no que pode ser feito com isso.

Tabela 1. Estrutura do Pacote UDP

Bits
0 — 15
16 — 31

0-31
Porta do remetente (Source port)
Porta do destinatário (Destination port)

32-63
Tamanho do datagrama (Length)
Checksum

64-…
Dados (Data)

Vamos adicionar um campo no início desta tabela Sessão (1 Byte). Isso é suficiente para este projeto. Com base na Sessão, o dispositivo saberá como lidar com o pacote a seguir. Agora vamos criar códigos para as sessões e registrá-los na tabela 2.

Tabela 2. Explicação das sessões

Código
Nome
Explicação

0xA1
Farol
O gateway transmite o nome da rede LoRa e a faixa de portas permitidas com uma certa periodicidade. Isso é necessário para que novos clientes vejam a rede disponível e para que clientes atuais possam determinar o nível de sinal quando não há transmissões.

0xB1
Solicitação
Quando o cliente detecta a rede, ele envia a porta preferida.

0xA2
Consentimento ou recusa
Se a porta solicitada pelo cliente estiver livre, o servidor responde com consentimento; caso contrário, com recusa.

0xB2
Up-link
Quando o cliente envia um pacote UDP para o gateway.

0xA3
Down-link
Quando o gateway envia um pacote UDP para o cliente.

0xC1
Continuação do Up-link
Quando o gateway envia um pacote UDP para a rede local.

Ótimo. Agora vamos discutir a composição das sessões na tabela 3.

Tabela 3. Sessões

Nome da sessão
Composição

Farol
Código da sessão (1 Byte) + Nome da rede LoRa (4 Bytes) + Porta inicial (2 Bytes) + Porta final (2 Bytes)

Solicitação
Código de transmissão (1 Byte) + Nome da rede LoRa (4 Bytes) + Porta preferida (2 Bytes)

Consentimento ou recusa
Código de transmissão (1 Byte) + Nome da rede LoRa (4 Bytes) + Porta preferida (2 Bytes) + Resultado (1 Byte)

Up-link
Código de transmissão (1 Byte) + Nome da rede LoRa (4 Bytes) + Endereço IP remoto (4 Bytes) + Porta remota (2 Bytes) + Endereço IP local (4 Bytes) + Porta local (2 Bytes) + Tamanho dos dados (2 Bytes) + Dados

Down-link
Código de transmissão (1 Byte) + Nome da rede LoRa (4 Bytes) + Endereço IP remoto (4 Bytes) + Porta remota (2 Bytes) + Endereço IP local (4 Bytes) + Porta local (2 Bytes) + Tamanho dos dados (2 Bytes) + Dados

Continuação do Up-link
Endereço IP remoto (4 Bytes) + Porta remota (2 Bytes) + Tamanho dos dados (2 Bytes) + Dados

Escrevi dois clientes para Arduino e para M5Stack. Você vídeo pode ver como isso funciona. Dentro do apartamento não há problemas, ainda não fiz testes de campo.

O código-fonte está disponível no GitHub em link

Saiba mais sobre o dispositivo básico M5Stack e compre aqui

Escolher módulos sem fio LoRa para o dispositivo básico pode ser feito aqui

Ficarei feliz se este projeto for útil para você. Muito obrigado pelo seu tempo!

Lista de referências e/ou fontes:

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster