Шлюз за UDP между Wi-Fi и LoRa

Създаваме шлюз между Wi-Fi и LoRa за UDP.

Шлюз за UDP между Wi-Fi и LoRa

Детска мечта ми беше да дам на всяко обикновено "без Wi-Fi" устройство билет за мрежата, т.е. IP адрес и порт. След време осъзнах, че не трябва да отлагам. Трябва да взема и да го направя.

Техническо задание

Създайте шлюз с M5Stack, инсталиран с LoRa модул (фигура 1). Шлюзът ще бъде свързан с Wi-Fi мрежа, в която ще получи локален IP адрес чрез DHCP. На определени интервали, шлюзът ще излъчва в "LoRa ефира" името си (аналог на SSID за Wi-Fi) и диапазона на допустимите портове, за да могат другите устройства да знаят, че съществува такава мрежа, към която могат да се свържат и в какъв диапазон могат да изберат свободен порт. Понеже това ще бъде прототип, аутентификацията не е включена. Нови клиентски устройства ще намерят достъпната LoRa мрежа и ще предадат избрания порт. След като шлюзът получи от новия клиент порта, проверява дали е свободен, ако е, регистрира новия клиент и започва да слуша на посочения порт на собствения си асинхронен UDP сървър. След регистрацията клиентът ще получи одобрение или отказ за използването на обявения порт. Процесът на работа е показан в таблица 1.

Шлюз за UDP между Wi-Fi и LoRa
Рисунок 1

Таблица 1

страна
направление и данни
страна
сеанс

[ клиент ]
<— сигнал-маяк —
[ шлюз ]
0xA1

[ клиент ]
— избран порт —>
[ шлюз ]
0xB1

[ клиент ]
<— одобрение или отказ —
[ шлюз ]
0xA2

[ клиент ]
— UPD пакет —>
[ шлюз ]
0xB2

[ клиент ]
<— UPD пакет —
[ шлюз ]
0xA3

[ мрежа ]
<— UPD пакет —
[ шлюз ]
0xC1

На бюрото ми лежат различни модули за M5Stack и се отегчават. Хайде да вземем LoRa и да се позабавляваме с нея. Самата концепция за модулите е прекрасна! Какво повече да се каже? Но, модулите, които имам, са от първото ревизия и имат ужасна вградена антена, направена на гъвкава печатна платка и залепена за страничната стена на корпуса. Един път провеждах полеви тестове на такива модули (можете да ги видите на рускоезичния канал в YouTube):

Пуснете видеото

Разбира се, трябваше да премахна тези остатъци и да впоя стандартни спираловидни антени, които идват с Ra-01. След такава кастомизация обхватът на връзката значително се подобри, но се появи вторичен проблем — антената има по-голям диаметър от допустимото разстояние между модулите. Пришло се да се откажа от Завършващия модул за времето на проекта.

Първи трудности от синхронна затрудненост

На пръв поглед би трябвало да вземете библиотеката WiFiUdp.h, където всичко е налично за комфортното функциониране на UDP сървър, не е така. Библиотеката е проектирана да стартира синхронен сървър, който, за дълбоко съжаление, не може да обслужва множество връзки едновременно в един поток. Такава библиотека не е подходяща за текущата задача. Прихода ми наложи да изпия много чаши чай и да потърся библиотека, която да позволи стартирането на асинхронен UDP сървър, способен да поддържа много връзки едновременно. Такава библиотека беше намерена — AsyncUDP.h. Каква е разликата между синхронния и асинхронния сървър? Нека разгледаме шест епизода на рисунка 2, в които тривиално са показани вариантите на работа със сокети.

Шлюз за UDP между Wi-Fi и LoRa

Рисунка 2

В главните роли:

Човек в ролята на Сокета;

Гълъб в ролята на Връзките;

Писмо в ролята на Данни.

Епизод A. Синхронен сокет без таймаут

Човекът ще стои, докато Гълъбът не му донесе Писмо.

Епизод B. Синхронен сокет с таймаут

Човекът чака уговореното с Гълъба време и, ако той не пристигне навреме, Човекът ще си тръгне.

Епизод C. Синхронен сокет с многопоточност

Човекът бездейства и наблюдава как Гълъбите сами доставят Писма.

Епизод D. Асинхронен сокет (когато няма какво да се получи)

Човекът се занимава с любимите си занимания, но не забравя за Гълъбите.

Епизод E. Асинхронен сокет (когато има какво да се получи)

Човекът се е отклонил за малко от своите дела, за да получи писмо от Гълъба.

Епизод F. Асинхронен сокет с многопоточност

Човекът се занимава със своите дела и наблюдава как Гълъбите сами доставят Писма.

Ако сте били внимателни, то със сигурност сте забелязали, че нашийниците на Гълъбите във всеки епизод имат определен цвят. И това не е случайно. В епизод A и B на сървъра работи само един сокет и толкова. В епизод C работят вече два сокета. В епизодите D, E и F вече има по три сокета. „Защо там има два, а тук три?“ — ще попитате Вие. Това условно са 2 и 3, всъщност вместо 2 може да има 20, а вместо три 200. Целта е да се покаже, че асинхронните сокети не натоварват толкова железата, колкото синхронните.

Колко какво се побира?

Нека разгледаме таблица 1, в която е представена структурата на UDP пакета и да помислим какво можем да направим с това.

Таблица 1. Структура на UDP пакета

Битовe
0 — 15
16 — 31

0-31
Порт на изпращача (Source port)
Порт на получателя (Destination port)

32-63
Дължина на датаграмата (Length)
Контролна сума (Checksum)

64-…
Данни (Data)

Добавим още едно поле в началото на тази таблица Сесия (1 байт). Това е достатъчно за този проект. Въз основа на сесията устройството ще знае как да обработи пакета по-нататък. Сега да измислим кодовете за сесиите и да ги запишем в таблица 2.

Таблица 2. Обяснение на сесиите

Код
Име
Пояснение

0xA1
Маяк
Шлюзът предава името на LoRa мрежата и диапазона на допустимите портове с определена периодичност. Това е необходимо, за да може новите клиенти да видят наличната мрежа, а настоящите клиенти, когато няма предавания, да могат да определят нивото на сигнала.

0xB1
Заявка
Когато клиентът открие мрежата, той изпраща предпочитания порт.

0xA2
Съгласие или отказ
Ако запитаният от клиента порт е свободен, сървърът отговаря със съгласие, а в противен случай с отказ.

0xB2
Up-линк
Когато клиентът изпраща UDP пакет до шлюза.

0xA3
Down-линк
Когато шлюзът предава UDP пакет на клиента.

0xC1
Продължение на Up-линка
Когато шлюзът изпраща UDP пакет в локалната мрежа.

Добре. Сега да обсъдим състава на сесиите в таблица 3.

Таблица 3. Сесии

Име на сесията
Състав

Маяк
Код на сесията (1 байт) + Име на LoRa мрежата (4 байта) + Начален порт (2 байта) + Краен порт (2 байта)

Заявка
Код на предаване (1 байт) + Име на LoRa мрежата (4 байта) + Предпочитан порт (2 байта)

Съгласие или отказ
Код на предаване (1 байт) + Име на LoRa мрежата (4 байта) + Предпочитан порт (2 байта) + Резултат (1 байт)

Up-линк
Код на предаване (1 байт) + Име на LoRa мрежата (4 байта) + Отдалечен IP адрес (4 байта) + Отдалечен порт (2 байта) + Локален IP адрес (4 байта) + Локален порт (2 байта) + Размер на данните (2 байта) + Данни

Down-link
Код на предаване (1 байт) + Име на LoRa мрежата (4 байта) + Отдалечен IP адрес (4 байта) + Отдалечен порт (2 байта) + Локален IP адрес (4 байта) + Локален порт (2 байта) + Размер на данните (2 байта) + Данни

Продължение на Up-линка
Отдалечен IP адрес (4 байта) + Отдалечен порт (2 байта) + Размер на данните (2 байта) + Данни

Написах два клиента за Ардуино и за M5Stack. Можете да видите как работи това. видео В рамките на апартамента няма проблеми, все още не съм правил полеви тестове.

Изходният код е наличен на GitHub на връзка

Можете да научите повече за Базовото устройство M5Stack и да го купите тук

Можете да изберете безжични модули LoRa за Базовото устройство тук

Бих се радвал, ако този проект ви бъде полезен. Благодаря ви много за отделеното време!

Списък с литературни източници и/или източници:

Източник: habr.com

Купете надежден хостинг за сайтове с защита от DDoS, VPS VDS сървъри 🔥 Купете надежден хостинг за сайтове с защита от DDoS, VPS VDS сървъри | ProHoster