С новым годом, с новым MQTT/UDP
Привет.
Как я уже писал недавно (Первая краткая статья о MQTT/UDP), MQTT/UDP — протокол на базе MQTT, но:
- Ходит поверх UDP broadcast (не нужен брокер, почти не нужна конфигурация)
- До неприличия простой в реализации (10 строк на си + UDP/IP стек — и вы отправляете данные с сенсора)
- Все слышат всех
В некотором смысле это CAN, но поверх Ethernet-а.
Зачем.
Моя квартира реально несколько лет живёт под управлением системы типа «дом не совсем олигофрен». Умом это назвать было бы избыточно, но — свет и климат автоматизированы. Чтобы представить себе масштаб бедствия — система занимает полную битком набитую стойку о 19 дюймах ширины и двух метрах высоты. Две стенки стойки заняты почти до пола.
Когда я всё это проектировал, вопрос отказоустойчивости стоял на первом месте. Несколько лет эксплуатации показали: оно и верно. Отказывает всё. Рано или поздно. Вот только электромеханические реле ещё пока не отказывали, а именно на них последний эшелон защиты от отказа.
Следующая после отказоустойчивости проблема — зоопарк. В силу естественного течения жизни, моего любопытства и насущных потребностей, в системе живут обычный Юникс на обычном PC, ПЛК Овен, Raspberr+Orange PI, модули на Atmega, модули на базе NodeMCU (ESP8266), и всё это ходит друг к другу через modbus 485, modbus TCP, http, и сбоку висит неприкаянный MQTT брокер, как наследие неудачной попытки перейти на него всем табором.
Почему попытка перейти на MQTT неудачна. Во-первых, для части железа он тяжеловат или сложноват. На том обломке Паскаля, который прячется в CodeSys ПЛК написать MQTT может только мазохист. А ведь потом надо и отладить. Аналогично на atmega: запихать можно, но тесно. Но и это не вся беда.
MQTT как он есть (а заимплеменчен везде 3.1.1) настаивает на том, чтобы посылать PUBLISH пакет (то есть наше сообщение в сторону брокера) всем получателям, в том числе и отправителю. Эффект от этого маразма фееричен — тот же OpenHAB не может отправлять и получать данные в MQTT под одним и тем же именем. Это означает, что организовать на базе MQTT шину (несколько модулей, которые обновляют значение одного и того же объекта и пользуются им же) нельзя. А именно так должна быть организована связь ПЛК, в котором живёт основное управление светом, ОпенХАБа, который управляет светом с веб-интерфейса и мобильного приложения, и смарт-выключателей, которые я хотел бы иметь возможность добавлять там и тут. То есть, конечно, и эту проблему можно обойти, но фактически это означает построить свой протокол ПОВЕРХ MQTT, а это уже кажется перебором.
В то же время, что мне нужно? Отправить апдейт значения параметра и получить его на всех заинтересованных точках. Для чего, собственно, деды и сделали UDP на бродкастный адрес.
После прошлого поста на Хабре один из читателей долго упрекал меня ненадёжностью протокола UDP. Я же умозрительно отвечал ему, что для IoT оный UDP БОЛЕЕ надёжен, чем TCP: при 50% потерь пакетов в сети TCP не просто ляжет, а ляжет ВООБЩЕ, а температурный датчик, посылающий измерения по UDP, просто потеряет половину отсчётов, что скажется на работе системы примерно никак. Вообще.
Но это было умозрительно. Однако, новогодние каникулы и даны человеку для того, чтобы допив шампанское спросить себя:, а положим сегодня домашнюю локалку на лопатки? А что бы и нет.
Я взял MQTT/UDP и написал примитивный тест. Одна сторона шлёт последовательные пакеты без паузы между пакетами, сколько может. Вторая считает скорость и потери пакетов. Эксперимент был прост: запускаем это издевательство, а параллельно два HD телевизора показывают кино из интернета, а настольный комп пишет на NAS огромный файл.
Оцените итог. Я ждал всего, но… максимум потерь на UDP достиг целого полупроцента, а оба телевизора остановили показ. Так что я ещё был пессимистом. В реальной домашней сети надёжность доставки UDP близка к абсолюту. Тем не менее, версию с подтверждениями и перепосылками пакетов я, видимо, сделаю. Сложности немного, а вопрос снимает совсем.
Второй вопрос — секьюрити, но, право, если мне взломают домашнюю сеть, потеря данных с датчиков температуры — последнее, о чём я буду горевать. Впрочем, опять же, задача цифровой подписи пакетов в issue tracker’е присутствует, и я уже понимаю, как расширить MQTT-шные пакеты под её реализацию.
В общем, я планирую по первой паре устройств в домашней сети перейти на MQTT/UDP буквально на днях.
И вам предлагаю его попробовать в своих программах и устройствах: Репозиторий и документация на английском.
Что есть в наличии:
Довольно полные реализации на Яве, Питоне и Си. Базовая реализация на Lua. Пока только отправка для Arduino и CodeSys ПЛК (тестировалось и работает на Овене, но должно пойти на чём угодно).
GUI инструмент для того, чтобы глядеть на происходящее и вмешиваться:
Программы для отправки и приёма данных на Питоне, Луа и Яве.
Коннекторы на Питоне для интеграции с обычным MQTT и напрямую с OpenHAB. Они отрабатывают защиту от циклов, запрещая обратную трансляцию сообщения в течение 5 сек после прохода в прямом направлении. Кроме того есть библиотека для ограничения потока повторных данных. Она проверяет, был ли уже апдейт данного топика в течение указанного времени, и если был, то пропускает новый апдейт только если данные изменились.
Я планирую постепенно переехать на этот протокол полностью, и вот один из примеров того, что я хочу получить с датчиками:
Здесь три датчика в одной комнате (ну, или на улице, не принципиально). Они отправляют отсчёты через MQTT/UDP. Получают эти отсчёты одновременно основная система умного дома (OpenHAB), база исторических данных и настенный монитор, который показывает температуру жителям.
Вся прелесть MQTT/UDP в том, что в такой схеме отказ любого блока не создаёт никаких проблем всем остальным. И это при феерической простоте протокола.
Более того, в этой же схеме легко реализуются и избыточные схемы управления с дублированием. Сервер БД можно сдублировать вообще без проблем. Хитрее будет сдублировать модули, которые занимаются управлением. Например, слушая температуру выдают управляющее воздействие на батареи отопления. Но, наверное, это уже следующая история. На сегодня я планирую остановиться на сборе сигналов с датчиков и обмене между модулями умного дома.