16 343
правки
м (→Настройка своего брокера MQTT: Поправил) |
м (Обновил оформление статьи — теперь выглядит лучше) |
||
Строка 10: | Строка 10: | ||
К [[Wiren Board]] подключён датчик температуры по шине [[1-Wire]]. Проследим, как данные с него через MQTT попадают в веб-интерфейс: | К [[Wiren Board]] подключён датчик температуры по шине [[1-Wire]]. Проследим, как данные с него через MQTT попадают в веб-интерфейс: | ||
#Драйвер, отвечающий за данную аппаратную функцию ([https://github.com/contactless/wb-homa-drivers/tree/master/wb-homa-w1 wb-homa-w1]) опрашивает подключённые к контролеру датчики 1-Wire. | #Драйвер, отвечающий за данную аппаратную функцию ([https://github.com/contactless/wb-homa-drivers/tree/master/wb-homa-w1 wb-homa-w1]) опрашивает подключённые к контролеру датчики 1-Wire. | ||
#При получении значения драйвер публикует по MQTT сообщение вида: <pre>/devices/wb-w1/controls/28-0115a48fcfff 23.25</pre>Оно значит, что | #При получении значения драйвер публикует по MQTT сообщение вида: <pre>/devices/wb-w1/controls/28-0115a48fcfff 23.25</pre>Оно значит, что от устройства 1-Wire с идентификатором ''28-0115a48fcfff'' получено значение 23.25 °C. | ||
#Веб-интерфейс, который подписан на все сообщения из MQTT, получает это сообщение и выводит значение датчика на страницу. | #Веб-интерфейс, который подписан на все сообщения из MQTT, получает это сообщение и выводит значение датчика на страницу. | ||
===Нажатие кнопки в веб-интерфейсе и переключение реле на внешнем модуле=== | ===Нажатие кнопки в веб-интерфейсе и переключение реле на внешнем модуле=== | ||
[[File:Web-devices-serial.png|400px|thumb|Веб-интерфейс после нажатия кнопки включения Реле 1 на подключённом по RS-485 релейном модуле [[WB-MRM2]]]] | [[File:Web-devices-serial.png|400px|thumb|Веб-интерфейс после нажатия кнопки включения Реле 1 на подключённом по RS-485 релейном модуле [[WB-MRM2]]]] | ||
К контроллеру по шине [[RS-485]] подключён релейный модуль [[WB-MRM2]]. Пользователь в веб-интерфейсе нажимает кнопку включения реле. Проследим, как команда из веб-интерфейса попадает на внешний модуль: | К контроллеру по шине [[RS-485]] подключён релейный модуль [[WB-MRM2]]. Пользователь в веб-интерфейсе нажимает кнопку включения реле. Проследим, как команда из веб-интерфейса попадает на внешний модуль: | ||
#После нажатия кнопки веб-интерфейс публикует по MQTT сообщение вида: <pre>/devices/wb-mrm2_130/controls/Relay 1/on 1</pre>Оно значит, что устройство WB-MRM2 с адресом ''130'' должно перевести ''Реле 1'' в состояние логической единицы | #После нажатия кнопки веб-интерфейс публикует по MQTT сообщение вида: <pre>/devices/wb-mrm2_130/controls/Relay 1/on 1</pre>Оно значит, что устройство WB-MRM2 с адресом ''130'' должно перевести ''Реле 1'' в состояние логической единицы — «включено». | ||
#[[Драйвер wb-mqtt-serial]], отвечающий за данную аппаратную функцию, получает это сообщение (он ''подписан'' на все сообщения, относящиеся к подключённым по RS-485 устройствам) и посылает по шине RS-485 релейному модулю команду на включение первого реле. | #[[Драйвер wb-mqtt-serial]], отвечающий за данную аппаратную функцию, получает это сообщение (он ''подписан'' на все сообщения, относящиеся к подключённым по RS-485 устройствам) и посылает по шине RS-485 релейному модулю команду на включение первого реле. | ||
#Релейный модуль WB-MRM2 получает команду от контроллера, переключает реле и посылает обратно уведомление «Реле 1 включено». | #Релейный модуль WB-MRM2 получает команду от контроллера, переключает реле и посылает обратно уведомление «Реле 1 включено». | ||
Строка 42: | Строка 42: | ||
=== Структура сообщения о состоянии устройства === | === Структура сообщения о состоянии устройства === | ||
Вот | Вот сообщение от драйвера температурного датчика 1-Wire из примера выше: | ||
<pre> | <pre> | ||
/devices/wb-w1/controls/28-0115a48fcfff 23.25 | /devices/wb-w1/controls/28-0115a48fcfff 23.25 | ||
Строка 49: | Строка 49: | ||
Название топика состоит из вложенных друг в друга «подтопиков»: | Название топика состоит из вложенных друг в друга «подтопиков»: | ||
* | * <code>/devices</code> — коренной топик для всех «устройств» — как встроенных функций Wiren Board (цифровые, АЦП, ...), так и подключённых внешних (например, модулей реле). | ||
* | * <code>/wb-w1</code> — подтопик, который наполняется драйвером 1-Wire. | ||
* | * <code>/controls</code> — подтопик, который есть у всех устройств — именно в него записываются все их параметры, которые меняются («включено-выключено», значение датчика, ...). | ||
* | * <code>/28-0115a48fcfff</code> — непосредственно сам «канал» («контрол») — топик, куда записывается значение с датчика. Его название совпадает с адресом 1-Wire датчика на шине. | ||
Содержание сообщения: | Содержание сообщения: | ||
* | * <code>23.25</code> — значение температуры | ||
Если вы хотите самостоятельно написать драйвер устройства, и хотите, что оно отображалось на вкладке Devices и его можно было использовать в правилах, вам необходимо придерживаться такой же структуры топиков. | Если вы хотите самостоятельно написать драйвер устройства, и хотите, что оно отображалось на вкладке '''Devices''' и его можно было использовать в правилах, вам необходимо придерживаться такой же структуры топиков. | ||
=== Структура сообщения об ошибке опроса устройства === | === Структура сообщения об ошибке опроса устройства === | ||
Строка 76: | Строка 76: | ||
Клиенты, которые хотят следить за значением температуры, «подписываются» на этот топик, и им приходят все новые сообщения — меняющиеся значения температуры. Один из таких клиентов — веб-интерфейс. | Клиенты, которые хотят следить за значением температуры, «подписываются» на этот топик, и им приходят все новые сообщения — меняющиеся значения температуры. Один из таких клиентов — веб-интерфейс. | ||
Подписаться на сообщения можно и из консоли Linux при помощи утилиты | Подписаться на сообщения можно и из консоли Linux при помощи утилиты <code>mosquitto_sub</code>: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
root@wirenboard:~# mosquitto_sub -t '/devices/wb-w1/controls/28-0115a48fcfff' -v //получить сообщения из топика устройства 1-Wire с идентификатором 28-0115a48fcfff | root@wirenboard:~# mosquitto_sub -t '/devices/wb-w1/controls/28-0115a48fcfff' -v //получить сообщения из топика устройства 1-Wire с идентификатором 28-0115a48fcfff | ||
Строка 83: | Строка 83: | ||
/devices/wb-w1/controls/28-0115a48fcfff 22.75 | /devices/wb-w1/controls/28-0115a48fcfff 22.75 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Полное описание работы с MQTT из командной строки смотрите ниже. | |||
=== Структура сообщения — команды на изменение состояния === | === Структура сообщения — команды на изменение состояния === | ||
Строка 139: | Строка 141: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
В результате мы получили не только значения с «контрола» устройства, но и топики с метаданными — название драйвера устройства и тип «контрола» - ''temperature''. | В результате мы получили не только значения с «контрола» устройства, но и топики с метаданными — название драйвера устройства и тип «контрола» - ''temperature''. | ||
Существует так же метасимвол ''+'', который обозначает один уровень, а не произвольное количество,как ''#'': | Существует так же метасимвол '''+''', который обозначает один уровень, а не произвольное количество,как '''#''': | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
mosquitto_sub -v -t "/config/widgets/+/name" | mosquitto_sub -v -t "/config/widgets/+/name" | ||
Строка 146: | Строка 148: | ||
[http://mosquitto.org/man/mqtt-7.html Полное описание системы топиков и подписок]. | |||
==== Очистка очереди сообщений ==== | ==== Очистка очереди сообщений ==== | ||
Строка 153: | Строка 155: | ||
Это приводит к тому, что несуществующие больше устройства могут отображаться в разделе ''Devices'' веб-интерфейса. | Это приводит к тому, что несуществующие больше устройства могут отображаться в разделе ''Devices'' веб-интерфейса. | ||
Для удаления топиков можно воспользоваться командой | Для удаления топиков можно воспользоваться командой <code>mqtt-delete-retained</code>. | ||
Например, удалим все топики, начинающиеся на <code>/devices/noolite_tx_1234/</code> | |||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
root@wirenboard:~# mqtt-delete-retained '/devices/noolite_tx_1234/#' | root@wirenboard:~# mqtt-delete-retained '/devices/noolite_tx_1234/#' | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Для удаления топиков «по маске», можно циклично вызывать runShellCommand из правил. Таким образом, задача сводится к задаче работы со строками в js. | Для удаления топиков «по маске», можно циклично вызывать <code>runShellCommand</code> из правил. Таким образом, задача сводится к задаче работы со строками в js. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
var deviceName = ['name1',.., 'nameN']; | var deviceName = ['name1',.., 'nameN']; | ||
Строка 171: | Строка 174: | ||
=== Работа с MQTT из внешних программ === | === Работа с MQTT из внешних программ === | ||
Если вы разрабатываете собственное ПО для Wiren Board, взаимодействовать с его аппаратными ресурсами лучше всего через протокол MQTT — ваша программа передаёт сообщение по MQTT, драйвер управляет устройством | Если вы разрабатываете собственное ПО для Wiren Board, взаимодействовать с его аппаратными ресурсами лучше всего через протокол MQTT — ваша программа передаёт сообщение по MQTT, драйвер управляет устройством и вашей программе не нужно напрямую взаимодействовать с устройством на низком уровне. | ||
Для того, чтобы отправлять сообщения MQTT, для многих языков программирования есть библиотеки | Для того, чтобы отправлять сообщения MQTT, для многих языков программирования есть библиотеки: | ||
* Python - [https://github.com/contactless/mqtt-tools] | * Python - [https://github.com/contactless/mqtt-tools] | ||
* C - [http://mosquitto.org/man/libmosquitto-3.html] | * C - [http://mosquitto.org/man/libmosquitto-3.html] | ||
Строка 179: | Строка 182: | ||
=== Просмотр MQTT-каналов в web-интерфейсе === | === Просмотр MQTT-каналов в web-интерфейсе === | ||
MQTT-названия устройств, их элементов управления и последние значения можно найти в разделе Settings web-интерфейса: | MQTT-названия устройств, их элементов управления и последние значения можно найти в разделе '''Settings''' web-интерфейса: | ||
[[Файл:Wb_settings.png|900px|thumb|center|Информация об MQTT-названиях устройств]] | [[Файл:Wb_settings.png|900px|thumb|center|Информация об MQTT-названиях устройств]] | ||
Строка 204: | Строка 207: | ||
#: (последняя строка говорит, что нужно пересылать все сообщения (метасимвол '''#''', смотрите описание выше) в обе ('''both''') стороны (с брокера контроллера на облачный брокер и обратно) | #: (последняя строка говорит, что нужно пересылать все сообщения (метасимвол '''#''', смотрите описание выше) в обе ('''both''') стороны (с брокера контроллера на облачный брокер и обратно) | ||
#: Более подробное описание всех опций смотрите на https://mosquitto.org/man/mosquitto-conf-5.html. | #: Более подробное описание всех опций смотрите на https://mosquitto.org/man/mosquitto-conf-5.html. | ||
# Перезапустите mosquitto, выполнив в консоли | # Перезапустите <code>mosquitto</code>, выполнив в консоли: | ||
#: <syntaxhighlight lang="bash"> | #: <syntaxhighlight lang="bash"> | ||
service mosquitto restart | service mosquitto restart | ||
Строка 213: | Строка 216: | ||
Список облачных брокеров, в том числе бесплатных: [https://github.com/mqtt/mqtt.github.io/wiki/public_brokers https://github.com/mqtt/mqtt.github.io/wiki/public_brokers] | Список облачных брокеров, в том числе бесплатных: [https://github.com/mqtt/mqtt.github.io/wiki/public_brokers https://github.com/mqtt/mqtt.github.io/wiki/public_brokers] | ||
'''Задача:''' настроить пересылку топика MQTT на другой контроллер. | |||
Есть два контроллера в одной сети^ | |||
# ''DestinationController'' с адресом <code>10.0.0.40</code>, на этот контроллер получать топик. | |||
# ''SourceController'' с адресом <code>10.0.0.70</code>, с этого контроллера будем забирать топик. | |||
''' | На ''SourceController'' есть <code>/client/temp1</code>, но его нужно видеть на ''DestinationController'' в <code>/devices/temp1</code>. | ||
Решается двумя способами, можно с ''SourceController'' публиковать на ''DestinationController'' или с ''DestinationController'' подписаться на топик ''SourceController'' и забирать изменения. От выбора стратегии зависит на каком контроллере будем проводить настройки. | |||
Мы будем настраивать ''DestinationController''. | |||
'''Решение:''' | '''Решение:''' На контроллере ''DestinationController'' добавьте в конфиг: | ||
На контроллере | |||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
mcedit /etc/mosquitto/conf.d/bridge.conf | mcedit /etc/mosquitto/conf.d/bridge.conf | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Строки: | |||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
connection wb_40 | connection wb_40 | ||
Строка 242: | Строка 241: | ||
topic /temp1/# in 2 /devices /client | topic /temp1/# in 2 /devices /client | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Перезапустите <code>mosquitto</code> на ''DestinationController'': | |||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
systemctl restart mosquitto; systemctl status mosquitto | systemctl restart mosquitto; systemctl status mosquitto | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''ВАЖНО''' перед перезапуском желательно [[watchdog |остановить watchdog]]. В случае ошибки в | '''ВАЖНО:''' перед перезапуском желательно [[watchdog |остановить watchdog]]. В случае ошибки в конфигурационных файлах брокер не запустится и watchdog вызовет перезапуск контроллера. | ||
Рассмотрим подробнее строчку <code>topic /temp1/# in 2 /devices /client</code> | |||
< | |||
topic /temp1/# in 2 /devices /client | |||
</ | |||
где: | где: | ||
* <code>/temp1/#</code> это топик от «корня». На брокере-источнике /client/'''temp1'''. | |||
* <code>in</code> — только забираем, изменения на контроллере не передадутся на сервер. | |||
* <code>/devices</code> — «корень» '''куда''' располагаем локально. На контроллере ''DestinationController'' это <code>/devices</code> и полный путь будет выгляджеть как '''/devices'''/temp1. | |||
* <code>/client</code> — «корень» откуда забираем на удаленном. На контроллере ''SourceController'' это <code>/client</code> и полный путь будет выгляджеть как '''/client'''/temp1. | |||
'''Проверка:''' | '''Проверка:''' | ||
Дожидаемся статуса бриджа «1» в топике <code>/client/wb_40/bridge_status</code> на контроллере '' | Дожидаемся статуса бриджа «1» в топике <code>/client/wb_40/bridge_status</code> на контроллере ''SourceController''. | ||
На нем же публикуем: | На нем же публикуем: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
Строка 275: | Строка 266: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Подписавшись на контроллере ''DestinationController'' на целевой топик можно видеть: | |||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
mosquitto_sub -v -t /devices/temp1/# | mosquitto_sub -v -t /devices/temp1/# |