Кроме наличия требуемых входов/выходов (в том числе 4-20 ма) и источника питания 5-30 в для датчиков, основным условием было минимизация потребления дабы иметь возможность питаться от батарей.После проработки схемотехники и печатной платы во весь рост встал вопрос о используемом протоколе. Хотелось чего-то простого и стандартного.
MQTT. Но MQTT это TCP со всеми достоинствами и недостатками. А у меня аккумулятор и срок работы от 3 месяцов. Для тестов был написан примитивный протокол поверх UDP. Но поскольку не отношу себя к пионэрам, свято уверенным, что вот сейчас за 2 дня напишут что-то удобоваримое — продолжил поиски чего-то общепринятого.
Уж не помню как — попалось мне упоминание о MQTT-SN. Протокол, наследующий семантику MQTT, но приспособленный для передачи по UDP и клиентам с батарейным питанием. Оказалось, есть такой, разработан в недрах IBM и в последующем открыт для сообщества. После прочтения описания стало понятно, что вот оно, счастье, рядом.
Но нужен брокер (так в MQTT называют сервер), привычный Mosquitto (по словам Яна Крагса от 2013) когда-нибудь сможет в MQTT-SN, но не сейчас. Зато есть RSMB, и даже в исходниках на Git-хабе.
Исходники это хорошо, надо собирать. Сборка производиться CygWin-ом в Visual Studio (которую я видел последний раз лет 5 назад). Ставим фришную версию, создаём проект и — никак. На 5-10 раз (вообще в моей жизни большую роль играет случай и упрямство) прописал правильно проект — и о, чудо, собрал таки брокера. Замечу что под Linux это действие прошло гораздо проще.
Торжественно запускаем. Обидно но не работает. Может всё-таки свой протокол это выход? Представив себе объём работы по написанию и отладке сервера и клиентов — решил нет, мой выбор — MQTT-SN. Оказалось всё просто — надо было конфигурацию прописать и указать брокеру.
Минимальная выглядит таким образом:
trace_output off # Диагностика, можно и включить
listener 1883 INADDR_ANY # Порт для обычного MQTT
listener 1883 INADDR_ANY mqtts # Порт для MQTT-SN протокола
И после этого брокер заработал. Вкратце отличия MQTT-SN от классического MQTT.
- Протокол MQTT-SN работает поверх UDP, а не TCP как обычный. Это перекладывает ответственность за контроль доставки сообщений на программиста. Зато позволяет устройству расходовать меньше энергии (а для меня это важно) на поддержание канала связи через GSM.
- Введён новый уровень QoS (Quality of Service, качество сервиса) -1. Означающий отсутствие контроля доставки. Устройство просыпается, делает нужную работу, отсылает результаты и тут-же засыпает не ожидая подтверждения.
- Появились шлюзы, позволяющие агрегировавать данные от множества устройств и пересылать их брокеру.
На git-е eclipsa лежат исходники клиента MQTT-SN с примерами. Собственно надо прописать функции работы с каналом transport_xx под свои нужды. В остальном больших проблем нет (нашёл пару ошибок, надо тестировать).
К сожалению не реализована поддержка спящих клиентов. Стоят заглушки. Кто сможет бросить в авторов протокола камень — исходники доступны, помощь приветствуется.
Что хотел сказать в итоге. Потратив некоторое (небольшое время) я получил готовую инфраструктуру для дальнейшего развития проекта. Протокол позволяет использовать STM32 на 4 МГц. Я могу использовать множество клиентов на разных платформах (что нереально было-бы сделать в одиночку при написании своего протокола). Более того, имея возможность собрать брокера под Linux я разместил его на инстансе Amazon-а и мой заказчик получил решение без необходимости держать и обслуживать сервер. Стандартные решения (не всегда, но в подавляющем количестве случаев) ускоряют исполнение задачи.
Ссылки:
MQTTSN client — Eclipse
RSMB — github
Комментарии (19)
ittakir
02.09.2016 05:43Что мешало просто просыпаться, передавать 1 UDP пакет и засыпать?
Протокол, например, такой:
struct
{
int device_id;
int value;
}Chulup
02.09.2016 06:11+1Вы, видимо, не очень хорошо себе представляете конкретно протокол UDP и протоколы общения прикладного уровня вообще.
Для первого необходимо реализовать подтверждение доставки как минимум.
Для второго поверх UDP вам нужны ещё и механизмы аутентификации, иначе к вам начнут прилетать пакеты непонятно откуда, но вы им будете верить. Я уже не говорю о том, что сообщения явно бывают разные, и тут начинаются все прелести самописных протоколов.ittakir
02.09.2016 17:11Я довольно хорошо представляю как устроен UDP. Если вы сомневаетесь в этом, прошу привести обоснованные аргументы.
Автор также использует UDP, и не ждет подтверждения доставки. Только вместо самописной структурки, что я привел как пример, он использует реализацию MQTT. Он вынужден использовать чужой брокер, вместо простейшего UDP сервера, который пишется за 10 минут.
Что касается аутентификации, то достаточно подписывать цифровой подписью данные в пакете. Если приватный ключ скрыт (а он будет скрыт в защищенной флеш-памяти STM), то никто не сможет подделать сообщения.elAlex
02.09.2016 17:37Простейший Udp сервер реально пишется быстро. Простейший. А затем приходит очередь писать клиентов, да под разные платформы. Да интегрировать это всё. И встаёт вопрос — что выгоднее — свой протокол и вся инфраструктура или готовый протокол и готовая инфраструктура? Даже с учётом того что пришлось собирать rsmb — для меня ответ очевиден, подняв брокера я получаю доступ к куче готового софта ( на самостоятельное написание которого потратил-бы не один месяц ).
Chulup
05.09.2016 14:33Согласен по поводу UDP, я пропустил пример его использования в статье.
Автор уже ответил по причинам выбора протокола MQTT, и я не могу его осуждать после того, как пришлось самому писать реализацию своего протокола. После анализа трудозатрат и выгоды я почти убедил менеджмент в отказе от него.
elAlex
02.09.2016 07:54Именно это я и сделал после сборки платы. Процесс написания своего тестового сервера и клиента доказал мне всю глупость ( по крайней мере в этом конкретном случае ) этой затеи.
elAlex
02.09.2016 07:58Собственно передача с QoS -1 и подразумевает описанное действие — проснулся, обработал, отправил и заснул. Просто данные обёрнуты в пакет позволяющий использовать готовую инфраструктуру MQTT-SN.
ColdPhoenix
02.09.2016 07:55Вы упомянули разницу UDP и TCP, и мне вот стало интересно, а насколько часты сейчас потери пакетов?
вроде бы все растет в сторону надежности.
Kealon
02.09.2016 07:55+1Для первого необходимо реализовать подтверждение доставки как минимум.
У автора как раз и используется UDP что бы не было заморочек с гарантированностью доставки, клиенты не ждут сервер — «дорого».
Аутентификация сигнала в таком контексте завершается на цифровой подписи, максимум.
Вопрос «обжимки» с непонятным устройством конечно более серьёзный
j_wayne
02.09.2016 09:11А CoAP рассматривали? http://coap.technology
Есть RFC: 7252. Нативно применяется UDP.elAlex
02.09.2016 16:16Теоретически — да. Но маловато информации, а поскольку была развёрнута инфраструктура MQTT — MQTT-SN оказался для меня находкой. Хотелось-бы почитать конечно по нему побольше.
zibn
02.09.2016 15:59+1Возник вопрос. Как по мне, то подъем GSM канала съедает столько энергии, что стоит ли уже, в этом случае, заморачиваться c передачей данных через UDP?
elAlex
02.09.2016 16:13Зависит от модели использования.
Если поднимать канал раз в 24 часа и сбрасывать расходомер — большой роли TCP | UDP не играет. Включил питание модуля — отправил ( получил подтверждение если TCP ) — выключил питание модуля.
Если-же раз в минуту поднимать датчик давления 4-20, оцифровывать и отсылать — время нахождения модуля в активном режиме играет большую роль. Тогда чем дольше будет спать GSM-модуль — тем дольше проживёт устройство. Естественно в этом случае модуль не рубиться по питанию но отправляется в сон.zibn
02.09.2016 17:28А не ставили ли натурный эксперимент, по сравнению экономности работы комплекса в целом, при работе через UDP и TCP? Я, конечно, до сравнений и сам доберусь… Просто это будет много позже. А результат, как в известной рекламе про зайцев и батарейки, интересен уже ;)
elAlex
02.09.2016 17:39Нет, поскольку для меня ответ очевиден. Может быть позже, когда соберу установочную партию.
Ivan_83
02.09.2016 22:35+1Для меня тоже очевиден ответ — заметной разницы не будет.
У вас гсм модуль в сети регается не мгновенно, а явно уходит пару секунд на это.
Далее приходит очередь передавать данные.
Даже если предположить что связь говно и слать их через всю страну то RTT вряд ли будет больше 200 мс.
В современных реализациях TCP есть варианты когда данные уходят сразу после ответного ACK от сервера, в итоге получается на 1 RTT дольше передача.
Модель собрать из готового барахла свой продукт имеет право на жизнь, но мне лично кажется далеко не оптимальным.
Особенно «порадовало» размещение не весть где сервера. Как применительно к предсказуемости его там жзни так и к увеличению RTT и соответственно времени работы гсм модуля, раз уж на то пошло.
2 ittakir
Ты себе хотя бы примерно представляешь сколько требуется вычислений для ЭЦП? (я про RSA/ECDSA)
Дак вот, этому несчастному контроллеру придётся не один десяток минут пахать чтобы что то подписать, хотя бы на уровне ECDSA с кривой уровня 128 бит секурности.
Единственный выход для таких применений это подписывать используя симметричную крипту и HMAC.
2 ColdPhoenix
В радио пакеты как терялись так и теряются, тем паче автор юзает гсм.elAlex
02.09.2016 22:55Т.е. сначала тезируется отсутствие разницы — затем выражается возмущение о расположении сервера и связанными с этим задержками TCP? Это как? Для того мне и нужен UDP что-бы не думать о задержках подтверждения.
Из готового барахла — а продемонстрируйте-ка свою работу. Как одиночки а не части команды. Моя вот
starius
Не могли бы вы предоставить ссылку?
elAlex
Прописал ссылки в подвале.