Kiruxa писал(а): ↑Сб апр 20, 2019 2:44 pm
надеюсь связь с мажодомо по MQTT будет?
Пока пишу скетч для WiFi шлюза (WiFi gateway), задумался о связывании топиков MQTT и TopicID MQTT-SN.
(1) Изначально я полагал задавать все TopicID "намертво", т.е. задавать их в скетчах. Всю работу по связыванию и по устранению противоречий предполагалось делать вручную. Со временем можно было бы написать PC-шную программку для облегчения процесса, что-то наподобие сверхлегковесной СУБД. Такая программка могла бы заодно и соответствующие куски скетчей генерировать.
Для шлюза можно было сделать общую таблицу связывания, в виде файла, который можно загрузить в SPIFFS. Для начала - опять же вручную, впоследствии тоже генерировать программно.
Но это получается довольно громоздко, некрасиво как-то.
(2) Можно, конечно, возложить связывание на шлюз и использовать команды REGISTER и REGACK. Насколько я понимаю, MQTT-SN как раз и заточен на это: по запросу клиента REGISTER, шлюз в ответе REGACK назначает TopicID для запрошенного топика. Более того, в спецификации MQTT-SN даже сказано, что таблицы связывания желательно хранить для каждого клиента, а не в виде общего пула.
Однако это будет означать, что без шлюза система работать не сможет. Тогда как в варианте (1) все работает и без шлюза.
(3) Напрашивется вариант, когда узлы (клиенты) могут обмениваться командами REGISTER и REGACK даже при отсутствии шлюза. Наверное, достаточно было бы в узлах ввести задержку перед REGACK, тогда REGACK, выдаваемый шлюзом, получит приоритет. Ведь только шлюз может точно знать, какие TopicID уже использованы, чтобы избежать повторного назначения. А связывание, которое хранится в узле, тогда используется как "не очень надежное начальное связывание", на случай, если шлюза нет.
Но тогда возникает вопрос - как вновь подключенный шлюз узнает, какое связывание уже используется сейчас? В вариантах (1) и (2) этого вопроса не существует. Возможные решения такие:
- добавить новую широковещательную команду (как расширение списка команд MQTT-SN), по которой узел, в ответ на запрос, где представлен TopicID, публиковал бы полное имя связанного с ним топика
- добавить новую команду в режиме точка-точка (режим HBus), по которой узел выдает свою таблицу связывания; после подключения шлюз просто опрашивает все узлы и вытаскивает из них все что ему требуется, а затем, в случае конфликтов, широковещательными командами REGISTER назначает новые TopicID.
Пожалуй, последний вариант выглядит лучше.
(4) Можно пойти дальше и вообще не назначать TopicID вручную, а изначально задать TopicID=0 для всех топиков. При первом включении каждый модуль при помощи команды REGISTER будет спрашивать: "какой TopicID назначен для вот этого топика (TopicName)?" Если никто не ответил, то модуль сам себе назначает TopicID для данного TopicName. А чтобы разные модули не назначили себе один и тот же TopicID для разных топиков, достаточно генерировать TopicID из собственного ID модуля. Например, берем NodeID, сдвигаем его влево на 5 разрядов и приклеиваем индекс топика. Так каждый модуль сможет без коллизий назначить до 32 TopicID.
Единственно, что NodeID модулям надо ограничить диапазоном 1..0x7FF. Это некритично, все равно столько узлов в одном сегменте разместить не удастся.
А команду REGACK лучше не использовать. Достаточно одной REGISTER, с ней мороки меньше, она контекстно-независимая.