Хотел написать на эту тему подробную статью, но, очевидно, руки не доходят. Посему краткое сообщение. Я разработал и реализовал на нескольких языках в виде прототипного кода версию протокола MQTT под рабочим названием MQTT/UDP. Для нетерпеливых и тех, кому уже всё понятно и очевидно, код на Гитхабе

Зачем

Я живу в квартире, которая почти полностью управляется собственной системой умного дома несколько лет. Управление светом, климатом, датчики, лёгкая автоматизация, вот это всё.

За это время я выяснил (да, впрочем, и до того понимал), что главное свойство систем УД — надёжность.

Все системы с центральным узлом по определению ненадёжны. Отсюда — желание получить интерконнект компонент системы (а их в реальном умном доме много) без использования какого-либо центрального хаба.

При этом исходим из того, что в целом трафик систем УД невелик — датчики редко нуждаются в апдейте чаще раза в минуту, остальные данные имеют событийный характер (включили свет), и по трафику совершенно несущественны. Даже ежесекундное обновление всех данных в системе не является не только катастрофой, но и даже существенной проблемой.

Логичный вывод — UDP бродкаст является идеальным инструментом.

(Да, я предполагаю, что внутренняя сеть квартиры закрыта файрволлом.)

Что в плюсах:

Невероятно простая реализация. Минимальный микроконтроллер с крошечной памятью сумеет послать UDP-пакет. Для датчика даже приём UDP не нужен.

Предельно низкая латентность. Нет форварда в центральном хабе, время доставки UDP пакета -практически минимальный квант времени в современной системе.

Нет центральной точки отказа в хабе/брокере. Рассмотрим простую схему: два датчика температуры, контроллер тёплого пола, контроллер батарей отопления. С применением MQTT/UDP отказ любой части такой системы не приводит к отказу системы в целом.

Низкий трафик в сети. Ниже некуда. TCP и подтверждения только добавляют трафика, но не добавляют надёжности. Отказавший датчик не заработает от получения TCP ACK. А отказ мы и так выявляем по отсутствию обновлений.

Ненадёжность самого протокола UDP несущественна — датчики всё равно обновляют данные регулярно, и пропадание отсчёта совершенно незаметно, а пропадание команды с, например, выключателя визуально подтверждается несработкой целевой системы. Что делает человек? Щёлкает ещё раз. Тем не менее, это — главный ограничитель применимости протокола. Идеален для повторяющихся опросов.

Не нужна конфигурация системы. Никому не нужно прописывать адрес брокера, хаба и т.п. Впрочем, всё равно нужна конфигурация датчика — требуется прописать идентификатор датчика. Но при переносе других частей системы на другие сервера переконфигурация ответных компонент не потребуется.

Отдельно интересно, что эта модель обмена данными хорошо ложится на натурально бродкастные среды, такие как радиоканал или RS/485. Я с этим не экспериментировал, и протокол в таких средах нуждается в контроле. Логично здесь применить CRC16 от modbus, кстати.

Минусы также очевидны: надежность доставки определяется только хардвером и трафиком в сети, ну и если в сеть пробрался враг, то протокол повержен сразу. Правда, будем откровенны, взлом иных типичных протоколов умного дома — дело секунд, так что это — спорный недостаток MQTT/UDP. Ещё один неочевидный минус — максимум один приёмник на IP-адрес.

Что сделано и лежит в репозитории в исходниках:

  • Реализации клиента/сервера на нескольких языках. Есть Си, Питон и Ява. Я не осилил Lua (не смог поставить всё, что нужно, как вы в этом живёте?) и Codesys (не смог собрать пакет, кто придумал этот язык?).
  • Минимальный гейт в традиционный MQTT на Питоне
  • Примитивный инструмент для отображения трафика MQTT/UDP в сети

Что бы я сделал, будь у меня ещё время:

  • Написал бы модуль для openHUB.
  • Сделал бы вариант протокола на JSON на другом порту и конвертор в основной формат и порт. Или гейт в обе стороны.
  • Сделал бы болванки реализации для основных платформ. Для Arduino я сделал подход к весу и реально протестировал код, но не оформил всё как следует. Для Малины годятся тестовые примеры на Питоне.
  • Сделал бы цифровую подпись и шифрование, но неясно, как.
  • Мультикаст.

На сём благодарю, добро пожаловать в репозиторий

PS: Аналогичный подход, но уже с мультикастом, описан в этой статье.

Комментарии (30)


  1. lingvo
    13.11.2018 13:46

    Все системы с центральным узлом по определению ненадёжны.

    Как-то самолетчики и автопроизводители об этом не в курсе. Сделать два хаба в избыточной схеме и получить заветные девятки надежности ИМХО проще, чем делать свой протокол.


    1. dzavalishin Автор
      13.11.2018 18:17
      +1

      ТУ154: три гидросистемы, каждая со своим приводом, вся электрика троирована, причём каждый провод защищён автоматами с двух сторон. Ключевые приборы на панели дублированы, причём некоторые исполнены в вариантах с разными физическими принципами.

      Знают.

      Два хаба — это тоже новый протокол, причём сложный — кроме прочего, нужно избегать дублирования сообщений, что требует схемы гарантированной идентификации пакетов, плюс ответа на вопрос: что делать, если пакет 2 с хаба 1 пришёл раньше пакета 1 с хаба 2.

      Это всё решаемые проблемы, но, тупо, зачем? Предложенный метод проще.

      Я проектировал сложные протоколы и управлял сетью с избыточностью через топологию. Имею опыт. Хочется простого.


      1. lingvo
        13.11.2018 19:28

        ТУ154 был разработан в 1968 году. Вы действительно думаете, что современный Боинг и Аирбас все еще исповедуют его принципы построения надежных систем управления?


        Взгляните хотя-бы на Fly-by-Wire — там стоит по три-четыре вычислителя с кворумом, каждый со своими датчиками и исполнительными устройствами. И везде за главную функцию отвечает центральный узел — вычислитель


        Два хаба — это тоже новый протокол, причём сложный — кроме прочего, нужно избегать дублирования сообщений, что требует схемы гарантированной идентификации пакетов, плюс ответа на вопрос: что делать, если пакет 2 с хаба 1 пришёл раньше пакета 1 с хаба 2.

        Для домашней системы, где обход отказа может составлять десятки секунд, можно спокойно применить состему с холодным резервированием — т.е. дублирующий хаб при работающем основном просто все время выключен. Если основной хаб накрывается, реле — ватчдог тупо переключает питание на дублирующий. Дублирующий грузится и начинает выполнять ту же работу.


        Тупо и решает всю проблему с дублированием.


        1. dzavalishin Автор
          13.11.2018 20:20

          — Описанная Вами схема отличается от ТУ только названием компонент. Единственного центрального узла всё равно нет.

          — Можно сделать дома холодный резерв. Но ЗАЧЕМ? И — кто будет следить за тем, что он готов и работает? И кто будет управлять реле? По какому признаку?

          И, главное, цель-то в чём такого усложнения?


          1. lingvo
            13.11.2018 22:01

            — Описанная Вами схема отличается от ТУ только названием компонент. Единственного центрального узла всё равно нет.

            Как это нет? Там десятки, если не сотни датчиков, на основании данных от которых центральный вычислитель по сложному алгоритму определяет, что нужно делать исполнительным устройствам. Если этот вычислитель накрывается — весь канал (1 из четырех) считается неисправным. Если бы это была децентрализованная система, то датчики должны были бы непосредственно общаться с исполнительными устройствами, а такого в самолетах нет.


            Можно сделать дома холодный резерв. Но ЗАЧЕМ? И — кто будет следить за тем, что он готов и работает? И кто будет управлять реле? По какому признаку?

            Потому, что это просто! За резервным контролером следить не надо — он выключен до поры до времени и с ним вряд-ли что-то случится. За работой основного контроллера следит примитивная цепь, называемая в простонародье Ватчдог. В простейшем случае, это реле, которое удерживается в одном из состояний, если на вход периодически поступают импульсы. Импульсы пропали — реле переключилось и подало питание на резервный контроллер. Если эти импульсы будут поступать от основного контроллера — получите простейший ватчдог.


            Цель такого усложнения такая же, как и вашего — получить более надежную систему. И в моем предложении не надо придумывать никакие протоколы.


            1. dzavalishin Автор
              15.11.2018 00:18

              Реализуйте, посмотрим.


  1. yvm
    13.11.2018 13:54
    +1

    1. j_wayne
      13.11.2018 15:20

      И такой еще линк может быть полезен: coap.technology


    1. dzavalishin Автор
      13.11.2018 18:19

      Нет. Спасибо, интересно. Тематика та же и подход к реализации сходный.


  1. Alexeyslav
    13.11.2018 16:01
    +2

    Это всё хорошо когда датчики некритичные. И без обратного канала нет определения коллизий, могут наступать такие моменты синхронной работы датчиков что они будут очень долго находится в состоянии коллизий. С выключателем света очень наглядный пример. Сначала несрабатывание будет раздражать, потом просто начнёт бесить а с ростом количества датчиков и исполнителей всё будет становится хуже. Тут может помочь не центральный узел а какой-то простой арбитр, но для этого нужен хоть какой-то обратный канал. Например, выдавать в эфир сигнал синхронизации(передаёт номер секунды начиная с начала суток, например, день недели, дату, время дня день-ночь-сумерки и т.д.) каждую секунду, а датчики будут отсчитывать на какой секунде или даже миллисекунде внутри этой секунды им позволено отвечать(привязать это к IP-адресу, например). В итоге полная идиллия, всё работает четко и синхронно. Причем даже прослушивать эфир не нужно всё время — мы знаем что если получили синхронизирующий сигнал то следующий будет через секунду +-точность поддержания собственной частоты, приёмник включается за миллисекунду до предполагаемого времени и принимает синхронизирующий сигнал, корректируя собственный внутренний источник времени а первоначальный импульс можно и подождать секунду, или включаться с рандомной задержкой в надежде когда-нибудь поймать синхронизацию.


    1. dzavalishin Автор
      13.11.2018 18:22

      Можно ещё проще — каждый отправитель раз в N секунд отправляет апдейт своего состояния.

      Но, в принципе, меня больше всего волнуют именно датчики, а с ними всё и так хорошо. Выключатели я пока на этот протокол вешать не планирую. Правда, не из соображений надёжности, а просто потому, что они уже сделаны другим способом и реально бродкастить их на всю сеть нет потребности.

      А вот датчики температуры — есть потребность отдавать в несколько мест.


      1. Alexeyslav
        14.11.2018 01:51

        Это не решает проблемы. Будут коллизии, и чем больше датчиков и чем чаще опрос тем больше коллизий, поэтому нужна синхронизация или детектирование коллизий самим датчиком. А выключатели… их просто можно развести на другой частоте, датчики мешать не будут.


        1. dzavalishin Автор
          15.11.2018 00:17

          Нету коллизий в реальной сети. Не с чего им быть. Во-первых, потому что она давно не шина, а свитч, причём store/forward, во-вторых потому что для коллизий нужен довольно серьёзный трафик, которому в сегменте умного дома браться не откуда, и, наконец, потому что проведённые тесты вообще не показали пропаданий пакетов. На вполне живой сети в которой живут три десятка хостов, включая телевизоры, которые сигнал получают только через сеть, и никак иначе.


          1. Alexeyslav
            15.11.2018 12:45

            Что-то я уже запутался. У вас каждый датчик подключается по Ethernet используя для этого контроллеры с тактовой частотой ниже даже чем символьная скорость в линии?
            Я почему-то думал что речь идёт о радиолинии, с общей средой. Для небольшого УД это логичней чем использовать Ethernet в каждом датчике и тащить к ним провода. Так-то да, если использовать обычные свичи то все будет работать. Но стоимость… Кстати в дешёвых свичах коллизии есть, просто клиентские Ethernet умеют детектировать коллизии и есть механизм повторной передачи так чтобы избегать повторной коллизии(ведь этим двум девайсам всё ещё надо передать свои данные после обнаружения коллизии), поэтому при маленьком трафике кажется что их нет. А свич с функцией store/forward уже больше похож на роутер, с соответствующим ценником.


    1. Process0169
      13.11.2018 18:22

      Тогда уж проще CAN прикрутить. Там и арбитраж и подтверждение доставки и прочие плюшки.


      1. dzavalishin Автор
        13.11.2018 18:26

        Типовой масштаб сети — квартира. Для CAN это многовато. Да и локалка в квартире уже есть. И устройства с ethernet/wifi вполне массовые. И стоят уже.

        Арбитраж CAN мало чем отличается от арбитража ethernet, а с подтверждением доставки проблема логическая, а не техническая. Сделать его банально, но мы, строго говоря, не знаем количество получателей и не уверены в том, что они работают постоянно.

        Хранить на каждом передатчике карту получателей, собирать подтверждения, увеличить в разы трафик в сети, поднять требования к передатчику. Зачем? Датчик температуры всё равно отправит свою температуру через минуту снова.


        1. Process0169
          13.11.2018 18:41
          +1

          Больше 125 устройств в квартире? :) Тогда соглашусь что многовато. Топлогически CAN звездится довольно просто и в этом плане проложенная сеть может использоваться.
          Арбитраж CAN очень сильно отличается от Ethernet хотя бы тем, что в CAN аппаратное разрешение коллизий в отличие от Ethernet-овского обнаружения. Карта получателей — лишнее. В CAN нет адреса приемника/передатчика. Есть «адрес» пакета.
          Полудуплекс же. Один говорит — все слушают.


          1. dzavalishin Автор
            13.11.2018 20:22

            Ну да, поскольку там арбитраж на адресе, младший адрес побеждает и коллизии нет, это изящная схема. Но, опять, зачем?


            1. Process0169
              13.11.2018 20:48
              +1

              Хозяин, как говорится, — барин. Я просто предложил промышленную защищенную сеть. Всерьез рассуждать о надежности и использовать UDP — это очень и очень странно выглядит. Возможно ваша публикация первая в истории где упоминаются оба этих слова :)
              Так, для справки: 27000 пакетов в секунду на эзернете при 100Мбит — потолок.
              17500 пакетов в секунду потолок для CAN. При 1Мбит :)


              1. dzavalishin Автор
                15.11.2018 00:24

                Даже при невероятной тысяче датчиков в квартире и отправке данных раз в секунду этот потолок недостижим. Так что, в целом, надеюсь выжить.

                И ещё. При дроп рейте пакетов порядка нескольких процентов TCP встаёт колом и не работает. Для датчика температуры потеря каждого второго отсчёта (дроп рейт 50%) несущественна.

                Понятие надёжности ценно осознавать в прикладном аспекте, а не в абстрактном. В реальной свитчованной сети при отсутствии перегрузки по трафику вообще неясно, как UDP пакет может пропасть. Перегрузки по трафику для этой группы узлов быть не может (ок, всё может быть, но видимой причины нет).

                При перегрузке и потере пакетов любой TCP протокол ляжет, а UDP будет прорываться, хоть и с кровью.

                Внезапно, UDP… надёжнее для этого применения.


                1. lingvo
                  15.11.2018 10:38

                  Внезапно, UDP… надёжнее для этого применения.

                  Я чего-то не пойму ваше понятие надежности. Центральный узел априори не надежный, а потеря пакетов — фигня, жить можно?
                  Система связи в системах автоматизации должна быть надежна. Вашему датчику температуры, возможно и пофиг, а событийному выключателю далеко нет. Не дошло от него сообщение — свет не включился. Надежно?


                  При перегрузке и потере пакетов любой TCP протокол ляжет

                  И это правильное поведение. Вы должны получить понятное состояние системы, а не метание между "работает/не работает".


                  В реальной свитчованной сети при отсутствии перегрузки по трафику вообще неясно, как UDP пакет может пропасть. Перегрузки по трафику для этой группы узлов быть не может (ок, всё может быть, но видимой причины нет).

                  В реальной свитчованой сети нет приоритетов и ваш UDP трафик будет крутиться вместе с теми же более надежными TCP/IP пакетами. У вас домашняя сеть для УД изолирована от всего остального? Компьютеров, телевизоров, телефонов? Если нет — проведите тест — попробуйте перекинуть два больших файла по сети через один свитч и проверить надежность вашей MQTT/UDP. Странно, но TCP/IP не ложится при этом, правда?


        1. lolikandr
          13.11.2018 19:38
          +1

          Массовость и фактическое наличие — это сильный аргумент. А вот с масштабом — нет, адресов просто завались — 11 бит или 29 бит.
          И ещё, в CAN не арбитраж, а отсутствие коллизий — передатчик автоматически определяет, что он может помешать другому передатчику и перестаёт мешать. Исходное сообщение от первого передатчика — не портится.
          Карту получателей на каждом передатчике хранить не нужно, подтверждения тоже не нужно. Нужно только озаботиться, чтобы адреса у разных передатчиков не совпадали и всё.


  1. DeeZ
    14.11.2018 11:43

    А какой контроллер тёплого пола используете? (интересуюсь тк выбираю сейчас как раз)


    1. dzavalishin Автор
      15.11.2018 00:27
      +1

      Овен ПЛК 110-30. датчики температуры pt1000 через овеновский же аналоговый модуль (3 шт), управление полом и частью радиаторов.

      PID-регуляторы в итоге писал сам, это оказалось проще, чем постичь штатные, да и легче было сделать связанный алгоритм руления полом и радиаторами.


  1. LeshiyUrban
    14.11.2018 11:49

    Идея отличная.
    Можете еще глянуть на эту статью https://habr.com/post/240053/ — там я описывал сходную идею на UDP multicast (не broadcast)


    1. dzavalishin Автор
      15.11.2018 00:27

      Спасибо, прочитаю.


    1. dzavalishin Автор
      15.11.2018 00:31

      Мы с Вами рассуждали совершенно идентично и пришли к почти идентичной модели. :) Мультикаст я тоже рассматривал, но пока отложил просто потому, что хотелось обеспечить реализацию для популярных в смарт хоум языков, а что там с мультикастом — навскидку неочевидно. Я вон в lua до обычного UDP-то не достучался. :)


  1. Alex_ME
    14.11.2018 15:25
    +1

    1) У Вас в любом случае есть центральный узел — роутер или иное устойство, которое проводную и/или беспроводную сеть поддерживает, разве нет? Упадёт он и никуда никакие UDP пакеты не дойдут.


    1. Насколько вероятен отказ центрального хаба? Те же роутеры работают месяцами-годами. Допустим, что будет программный отказ (повиснет). Тогда достаточно вочдога, который его перезагрузит. А какая вероятность аппаратного отказа?


    1. dzavalishin Автор
      15.11.2018 00:32

      Вы правы. То есть, конечно, можно и сеть резервировать, но никто этого дома делать не будет. Тут плюсом является тот факт, что отказ локалки пользователь так и так заметит по другим признакам и ситуацию будет исправлять. А отказ брокера или компа под ним, поверьте, можно не видеть месяцами. Из практики.


      1. lingvo
        15.11.2018 10:27

        То есть, конечно, можно и сеть резервировать, но никто этого дома делать не будет.

        Сразу скажу, что проводную сеть резервировать очень дорого. С STP/RSTP в одноранговой домашней сети особо много не сделаешь, а полное дублирование по типу PRP/HSR требует соответствующего железа.


        С этой точки зрения безпроводка — отличная штука. И мой подход выше тоже. На ту же переключаемую розетку вешаем еще и беспроводной роутер с теми же настройками и получаем резервную сеть.


        У меня, правда, почти все датчики и устройства не на Wi-Fi, а на Z-wave, поэтому протоколами вообще не заморачиваюсь и резервирование центрального контроллера Z-wave вообще плевое дело.