Wb-mqtt-serial templates: различия между версиями
(Перенаправление на Wb-mqtt-serial driver) Метка: новое перенаправление |
PeteK (обсуждение | вклад) (Добавил информацию про пользовательские шаблоны в /etc/wb-mqtt-serial.conf.d/templates) |
||
(не показано 50 промежуточных версий 4 участников) | |||
Строка 1: | Строка 1: | ||
<languages/> | |||
<translate> | |||
=== Опрос устройства Modbus вручную перед написанием шаблона === | |||
Перед тем как писать шаблон, нужно вручную проверить, что устройство правильно подключено, и с него удаётся получить данные. Для этого потребуется документация на устройство, включающая его параметры последовательного порта (скорость, чётность, количество стоп-бит) и список его Modbus-регистров с описанием их возможных значений. После этого нужно подключить устройство и, используя эту информацию, попробовать вручную получить из него данные с помощью утилиты [[Modbus-client | modbus_client]]. | |||
=== Общая структура шаблона устройства === <!--T:1--> | |||
<!--T:2--> | |||
Файл шаблона устройств представляет собой структуру [https://ru.wikipedia.org/wiki/JSON JSON], описывающую параметры устройства. Шаблон допускает наличие комментариев. | |||
JSON-структура записывается внутри пространства между открывающей и закрывающей фигурной скобкой: <code>{ ... }</code>. | |||
<!--T:3--> | |||
Общая структура шаблона устройства выглядит следующим образом: | |||
<syntaxhighlight lang="JSON"> | |||
//Шаблон устройства | |||
{ | |||
"device": { | |||
"Параметр 1 устройства":"значение", | |||
"Параметр 2 устройства":"значение", | |||
... | |||
"channels": [ {Параметры канала 1}, {Параметры канала 2}, ...] | |||
} | |||
}</syntaxhighlight> | |||
<!--T:4--> | |||
Здесь '''device''' — устройство, подключаемое к контроллеру, '''канал''' — источник данных: обычно Modbus-регистр с описанием типа данных, частоты опроса, преобразования значений и проч. | |||
Подробное описание смотрите в следующих разделах. Файлы шаблонов, поставляемые в составе пакета, хранятся на контроллере в директории <pre>/usr/share/wb-mqtt-serial/templates</pre> | |||
Для версий '''wb-mqtt-serial''', начиная с '''2.6.3''', шаблоны, созданные вами для нового устройства, следует сохранять в директорию <pre>/etc/wb-mqtt-serial.conf.d/templates</pre> | |||
Для более старых версий - в <code>/usr/share/wb-mqtt-serial/templates</code>. | |||
В наших шаблонах мы используем отступы по 4 пробела на уровень, что обеспечивает удобочитаемость кода шаблона, и рекомендуем писать новые шаблоны с такими же отступами. | |||
=== Параметры устройства (device) === <!--T:5--> | |||
[[File:Device_properties_mqtt_serial.png|650px|thumb|right|Параметры устройства описываются в wb-mqtt-serial.schema.json (подготовлено в [http://www.bodurov.com/JsonFormatter/ Collapsible JSON Formatter])]] | |||
<!--T:6--> | |||
В начале шаблона задаются параметры устройства в виде набора пар ''ключ:значение''. | |||
Обязательными параметрами являются ключи "device_type" и "device". | |||
<!--T:7--> | |||
Ключ '''device_type''' задает уникальное название типа устройства в виде строки, например: | |||
<syntaxhighlight lang="JSON">"device_type":"WB-MAP12H", </syntaxhighlight>. | |||
<!--T:8--> | |||
Значение ключа '''device''' — составная структура, описывающее конкретные параметры устройства: | |||
<!--T:9--> | |||
<syntaxhighlight lang="JSON"> | |||
"device": { | |||
"name": "WB-MAP12H", | |||
"id": "wb-map12h", | |||
"channels": [...] | |||
}</syntaxhighlight> | |||
<!--T:10--> | |||
* '''name''' — отображаемое имя устройства. Публикуется как <code> .../meta/name в mqtt</code>. Имя устройства используется при отображении web-интерфейсе, хранится в топике <code>"id" + " " + "slave_id"</code>. Пример для устройства с modbus-адресом 5 (slave_id) и значением <code>"name":"WB-MAP12H (basic)"</code> <code>/devices/wb-map12h_5/meta/name WB-MAP12H (basic)</code>. | |||
<!--T:11--> | |||
* '''id''' — уникальный идентификатор устройства в MQTT. Каждый элемент в devices должен иметь уникальный id. mqtt-topic'и, относящиеся в MQTT к данному устройству, имеют общий префикс /devices/<идентификатор топика>/... Также по умолчанию берется из шаблона с добавлением slave_id: <code>"id" + "_" + slave_id</code> | |||
<!--* '''slave_id''' — Modbus-адрес устройства. Задается в виде <code>"slave_id" : slaveID,</code>. Необязательный параметр для шаблона, slave_id задается при конкурировании устройства и уже с этим параметром включается в конфигурационный файл <cоde>/etc/wb-mqtt-serial.conf</cоde>.--> | |||
<!--T:12--> | |||
* '''channels''' — список каналов устройств, задается в виде массива <code>[...]</code>, каждый из элементов которого представляет описание отдельного канала. | |||
<!--T:13--> | |||
Остальные параметры устройства либо добавляются в раздел при включении шаблона в общую конфигурацию wb-mqtt-serial, либо используются значения по умолчанию. Полный список можно найти в файле [https://github.com/contactless/wb-mqtt-serial/blob/master/wb-mqtt-serial.schema.json wb-mqtt-serial.schema.json] (его копия также хранится на контроллере: <code>/usr/share/wb-mqtt-confed/schemas/wb-mqtt-serial.schema.json</code>). Смотрите свойства объекта <code>"device" -> "properties"</code>. | |||
=== Каналы устройства === <!--T:14--> | |||
[[File:Channel_properties_mqtt_serial.png|450px|thumb|right|Параметры канала описываются в wb-mqtt-serial.schema.json (подготовлено в [http://www.bodurov.com/JsonFormatter/ Collapsible JSON Formatter])]] | |||
Описание канала представляет собой структуру | |||
<!--T:15--> | |||
<syntaxhighlight lang="JSON"> | |||
"channels": [ | |||
{ | |||
"name": "Имя канала 1", | |||
... | |||
}, | |||
{ | |||
"name": "Имя канала 2", | |||
... | |||
}, | |||
... | |||
] | |||
</syntaxhighlight> | |||
<!--T:16--> | |||
Структура содержит следующий набор полей. | |||
<!--T:17--> | |||
[[File:Vartype_properties_mqtt_serial.png|450px|thumb|right|формат представления данных в Modbus-регистрах, описывается в wb-mqtt-serial.schema.json (подготовлено в [http://www.bodurov.com/JsonFormatter/ Collapsible JSON Formatter])]] | |||
<!--T:18--> | |||
* '''name''' — имя канала, уникальное для устройство имя канала | |||
* '''reg_type''' — тип Modbus-регистра, одно из "coil", "discrete", "holding", "holding_single", "holding_multi", "input", "direct" | |||
* '''address''' — адрес Modbus-регистра, связанного с каналом. | |||
* '''type''' — тип контрола -- виртуального элемента для представления данных в Web-интерфейсе контроллера: "switch", "pushbutton", "range", "rgb" и другие; полностью перечислены в схеме wb-mqtt-serial.schema.json. | |||
* '''readonly''' — "true", если значения можно только считывать. | |||
* '''format''' — тип переменной, описывающей значение, см. рис. | |||
<!--T:19--> | |||
В простейшем случае достаточно полей "name", "reg_type", "address" и "type". Описания остальных типов параметров полностью перечислены в схеме wb-mqtt-serial.schema.json. | |||
=== Примеры шаблонов устройств === <!--T:20--> | |||
<!--T:21--> | |||
Ниже приведены примеры файлов шаблонов для некоторых устройств Wiren Board, охватывающие основной список используемых параметров при создании шаблонов. | |||
<!--T:22--> | |||
---- | |||
==== WB-MS-THLS v.2 ==== <!--T:23--> | |||
<!--T:24--> | |||
Устройство [[WB-MS_Modbus_Sensor|WB-MS-THLS]] — универсальный комбинированный Modbus-датчик температуры, влажности, освещённости и звукового давления. Устройство предоставляет доступ к данным через input-регистры Modbus. Первоначальные настройки устройства записаны в holding-регистры, но не используются для получения данных и управления устройством, поэтому в шаблон не входят. | |||
По ссылке "Expand" можно увидеть полный код шаблона. | |||
<!--T:25--> | |||
<div class="mw-collapsible mw-collapsed" style="width:500px; overflow: hidden;" > | |||
<syntaxhighlight lang="JSON" highlight="6,13-15"> | |||
{ | |||
"device_type": "WB-MS-THLS v.2", | |||
"device": { | |||
"name": "WB-MS / WB-MSW", | |||
"id": "wb-ms-thls-v2", | |||
"max_read_registers": 0, | |||
"channels": [ | |||
{ | |||
"name": "Temperature", | |||
"reg_type": "input", | |||
"address": 0, | |||
"type": "temperature", | |||
"format": "s16", | |||
"scale": 0.1, | |||
"error_value": "0x7FFF" | |||
}, | |||
{ | |||
"name": "Humidity", | |||
"reg_type": "input", | |||
"address": 1, | |||
"type": "rel_humidity", | |||
"scale": 0.1, | |||
"error_value": "0xFFFF" | |||
}, | |||
{ | |||
"name": "Illuminance", | |||
"reg_type": "input", | |||
"address": 2, | |||
"type": "lux" | |||
}, | |||
{ | |||
"name": "Sound Level", | |||
"reg_type": "input", | |||
"address": 3, | |||
"scale": 0.01, | |||
"type": "sound_level" | |||
}, | |||
{ | |||
"name": "Input Voltage", | |||
"reg_type": "input", | |||
"address": 121, | |||
"scale": 0.001, | |||
"type": "voltage" | |||
}, | |||
{ | |||
"name": "External Sensor 1", | |||
"type": "temperature", | |||
"reg_type": "input", | |||
"address": "6", | |||
"format": "s16", | |||
"scale": 0.0625, | |||
"error_value": "0x7FFF" | |||
}, | |||
{ | |||
"name": "External Sensor 2", | |||
"type": "temperature", | |||
"reg_type": "input", | |||
"address": "7", | |||
"format": "s16", | |||
"scale": 0.0625, | |||
"error_value": "0x7FFF" | |||
} | |||
] | |||
} | |||
} | |||
</syntaxhighlight> | |||
</div> | |||
<!--T:26--> | |||
В настройках устройства интересен параметр <syntaxhighlight lang="JSON"> "max_read_registers": 0,</syntaxhighlight> Этот параметр описывает максимальное количество регистров, считываемых с устройства при запросе. Значение по умолчанию — 1, в нашем случае мы указываем считывать все регистры за один проход (bulk read). | |||
В настройках канала "Temperature" имеются три параметра, на которые стоит обратить внимание: | |||
<syntaxhighlight lang="JSON"> | |||
"format": "s16", | |||
"scale": 0.1, | |||
"error_value": "0x7FFF" | |||
</syntaxhighlight> | |||
Параметр '''"format": "s16"''' указывает на то, что число в регистрах представлено в виде знакового 16-битного целого, '''"scale": 0.1''' — говорит о том, что полученное из регистров значение следует домножить на коэффициент масштабирования 0,1 для получения значения температуры, а параметр '''"error_value": "0x7FFF"''' задает значение, получаемое из регистра, указывающее на то, что при опросе датчика произошла ошибка. Такой параметр будет выделен красным цветом в Web-интерфейсе контроллера. Применять такой параметр следует, если вы знаете, какое значение выдает ваше устройство в случае ошибки. | |||
<!--T:27--> | |||
---- | |||
==== WB-MRGBW-D ==== <!--T:28--> | |||
Устройство [[WB-MRGBW-D|WB-MRGBW-D]] — четырехканальный диммер для управления светодиодными лентами. Может управлять лентой RGB+W либо независимо четырьмя одноцветными лентами. | |||
Настройки яркости хранятся в holding-регистрах; шаблон описывает, какие регистры можно менять для получения нужной яркости каналов, отслеживать нажатия на кнопки диммера и получать значения количества нажатий.По ссылке "Expand" можно увидеть полный код шаблона. | |||
<!--T:29--> | |||
<div class="mw-collapsible mw-collapsed" style="width:500px; overflow: hidden;" > | |||
<syntaxhighlight lang="JSON" highlight="8-25"> | |||
{ | |||
"device_type": "WB-MRGBW-D", | |||
"device": { | |||
"name": "WB-MRGBW-D", | |||
"id": "wb-mrgbw-d", | |||
"max_read_registers": 0, | |||
"channels": [ | |||
{ | |||
"name": "RGB", | |||
"type": "rgb", | |||
"consists_of": [ | |||
{ | |||
"reg_type": "holding", | |||
"address": 1 | |||
}, | |||
{ | |||
"reg_type": "holding", | |||
"address": 0 | |||
}, | |||
{ | |||
"reg_type": "holding", | |||
"address": 2 | |||
} | |||
] | |||
}, | |||
{ | |||
"name": "White", | |||
"reg_type": "holding", | |||
"address": 3, | |||
"type": "range", | |||
"max": 255 | |||
}, | |||
{ | |||
"name": "Button 1", | |||
"reg_type": "holding", | |||
"readonly": true, | |||
"address": 6, | |||
"type": "switch" | |||
}, | |||
{ | |||
"name": "Button 2", | |||
"reg_type": "holding", | |||
"readonly": true, | |||
"address": 7, | |||
"type": "switch" | |||
}, | |||
{ | |||
"name": "Button 3", | |||
"reg_type": "holding", | |||
"readonly": true, | |||
"address": 8, | |||
"type": "switch" | |||
}, | |||
{ | |||
"name": "Button 1 counter", | |||
"reg_type": "holding", | |||
"readonly": true, | |||
"address": 32, | |||
"type": "value" | |||
}, | |||
{ | |||
"name": "Button 2 counter", | |||
"reg_type": "holding", | |||
"readonly": true, | |||
"address": 33, | |||
"type": "value" | |||
}, | |||
{ | |||
"name": "Button 3 counter", | |||
"reg_type": "holding", | |||
"readonly": true, | |||
"address": 34, | |||
"type": "value" | |||
}, | |||
{ | |||
"name": "Serial NO", | |||
"type": "text", | |||
"reg_type": "holding", | |||
"address": 270, | |||
"format": "u32" | |||
} | |||
] | |||
} | |||
} | |||
</syntaxhighlight> | |||
</div> | |||
В этом шаблоне составной канал RGB задает одновременно яркости трех цветовых компонентов ленты, хранящихся в трех holding-регистрах и описывается следующим образом: | |||
<syntaxhighlight lang="JSON"> | |||
{ | |||
"name": "RGB", | |||
"type": "rgb", | |||
"consists_of": [ | |||
{ | |||
"reg_type": "holding", | |||
"address": 1 | |||
}, | |||
{ | |||
"reg_type": "holding", | |||
"address": 0 | |||
}, | |||
{ | |||
"reg_type": "holding", | |||
"address": 2 | |||
} | |||
] | |||
}, | |||
</syntaxhighlight> | |||
<!--T:30--> | |||
Канал белого цвета управляется отдельно, | |||
<syntaxhighlight lang="JSON"> | |||
{ | |||
"name": "White", | |||
"reg_type": "holding", | |||
"address": 3, | |||
"type": "range", | |||
"max": 255 | |||
}, | |||
</syntaxhighlight> | |||
Здесь указано максимальное значение, которое можно установить для ползунка яркости белого — 255:<syntaxhighlight lang="JSON">"max": 255</syntaxhighlight> | |||
<!--T:31--> | |||
Серийный номер устройства (канал "Serial NO") считывается как беззнаковое 32-битное целое: <syntaxhighlight lang="JSON">"format": "u32"</syntaxhighlight> | |||
<!--T:32--> | |||
---- | |||
==== WBIO-DO-R10A-8 ==== <!--T:33--> | |||
Устройство [[WBIO-DO-R10A-8_Relay_Module|WBIO-DO-R10A-8]] — релейный боковой модуль, который подключается непосредственно к WBIO-разъему контроллера, и не управляется по Modbus. Но при подключении его через устройство расширения WB-MIO или WB-MIO-E становится полноценным Modbus-устройством, для которого имеется соответствующий шаблон. | |||
По ссылке "Expand" можно увидеть полный код шаблона. | |||
<!--T:34--> | |||
<div class="mw-collapsible mw-collapsed" style="width:500px; overflow: hidden;" > | |||
<syntaxhighlight lang="JSON" highlight="6-15"> | |||
{ | |||
"device_type": "WBIO-DO-R10A-8", | |||
"device": { | |||
"name": "WBIO-DO-R10A-8", | |||
"id": "wb-mio-gpio", | |||
"protocol": "modbus_io", | |||
"stride": 1000, | |||
"shift": 500, | |||
"max_read_registers": 0, | |||
"setup": [ | |||
{ | |||
"title": "IODIR", | |||
"address": 10000, | |||
"value": "0x0000" | |||
}, | |||
{ | |||
"title": "IPOL", | |||
"address": 10001, | |||
"value": "0x0000" | |||
}, | |||
{ | |||
"title": "GPINTEN", | |||
"address": 10002, | |||
"value": "0xffff" | |||
}, | |||
{ | |||
"title": "DEFVAL", | |||
"address": 10003, | |||
"value": "0x0000" | |||
}, | |||
{ | |||
"title": "INTCON", | |||
"address": 10004, | |||
"value": "0x0000" | |||
}, | |||
{ | |||
"title": "IOCON", | |||
"address": 10005, | |||
"value": "0x4444" | |||
}, | |||
{ | |||
"title": "FLAG", | |||
"address": 9999, | |||
"value": 1 | |||
} | |||
], | |||
"channels": [ | |||
{ | |||
"name": "K1", | |||
"reg_type": "coil", | |||
"address": 0, | |||
"type": "switch" | |||
}, | |||
{ | |||
"name": "K2", | |||
"reg_type": "coil", | |||
"address": 1, | |||
"type": "switch" | |||
}, | |||
{ | |||
"name": "K3", | |||
"reg_type": "coil", | |||
"address": 2, | |||
"type": "switch" | |||
}, | |||
{ | |||
"name": "K4", | |||
"reg_type": "coil", | |||
"address": 3, | |||
"type": "switch" | |||
}, | |||
{ | |||
"name": "K5", | |||
"reg_type": "coil", | |||
"address": 4, | |||
"type": "switch" | |||
}, | |||
{ | |||
"name": "K6", | |||
"reg_type": "coil", | |||
"address": 5, | |||
"type": "switch" | |||
}, | |||
{ | |||
"name": "K7", | |||
"reg_type": "coil", | |||
"address": 6, | |||
"type": "switch" | |||
}, | |||
{ | |||
"name": "K8", | |||
"reg_type": "coil", | |||
"address": 7, | |||
"type": "switch" | |||
} | |||
] | |||
} | |||
} | |||
</syntaxhighlight> | |||
</div> | |||
<!--T:35--> | |||
В этом шаблоне следует обратить внимание на следующие параметры устройства. | |||
<syntaxhighlight lang="JSON"> | |||
"protocol": "modbus_io", | |||
"stride": 1000, | |||
"shift": 500, | |||
"max_read_registers": 0, | |||
"setup": [ | |||
</syntaxhighlight> | |||
<!--T:36--> | |||
Параметр '''"protocol": "modbus_io"''' указывает, что устройство подключается оп специальному протоколу к модулю расширения. Параметры '''"stride": 1000''' и '''"shift": 500''' задают сдвиг регистров в зависимости от того, в каком порядке подключены модули к модулю расширения. | |||
<!--T:37--> | |||
Сдвиг регистров (число, которое нужно добавить к базовому номеру регистра) вычисляется по формуле: <syntaxhighlight lang="C++">Shift = (((SlaveId.Secondary - 1) % 4) + 1) * DeviceConfig()->Stride + DeviceConfig()->Shift;</syntaxhighlight> Здесь stride — ''DeviceConfig()->Stride'', a shift — ''DeviceConfig()->Shift''. Каждое подключенное устройство имеет порядковый номер (''SlaveId.Secondary''), начинающийся с 1 для первого устройства. (Здесь знаком "%" обозначается деление по модулю.) | |||
<!--T:38--> | |||
Например, подставляя значения shift и stride в формулу, получаем: <syntaxhighlight lang="C++">Shift = ((( 1 - 1) % 4) + 1) * 500 + 1000 = (0 + 1) * 500 + 1000 = 1500</syntaxhighlight> То есть ко всем регистрам, указанным в шаблоне, надо добавить 1500. | |||
<!--T:39--> | |||
Еще один важный параметр — setup-секция, массив | |||
<syntaxhighlight lang="JSON"> | |||
"setup": [ { | |||
"title": "IODIR", | |||
"address": 10000, | |||
"value": "0x0000" | |||
}, | |||
{}, | |||
...] | |||
</syntaxhighlight> | |||
Он описывает регистры и значения, которые однократно заносятся в эти регистры при инициализации устройства (при запуске или перезапуске wb-mqtt-serial). Его можно использовать для конфигурирования устройств для работы в каком-то определенном режиме, задавать изначальные значения яркости, положения сервоприводов, состояния реле, режима работы с входами релейных модулей и т. п. | |||
<!--T:40--> | |||
---- | |||
==== WB-MAP3H ==== <!--T:41--> | |||
<!--T:42--> | |||
Устройство [[WB-MAP3H_Power_Meter|WB-MAP3H]] — трехканальный счетчик электроэнергии. Он измеряет большое количество параметров электрической сети. Поскольку опрос всех регистров такого устройства может занять достаточно много времени, имеется несколько шаблонов, содержащих оптимальный набор параметров для решения текущей задачи. Мы рассмотрим базовый шаблон. По ссылке "Expand" можно увидеть полный код шаблона. | |||
<!--T:43--> | |||
<div class="mw-collapsible mw-collapsed" style="width:500px; overflow: hidden;" > | |||
<syntaxhighlight lang="JSON" highlight="6,162-171"> | |||
{ | |||
"device_type": "WB-MAP3H (basic)", | |||
"device": { | |||
"name": "WB-MAP3H (basic)", | |||
"id": "wb-map3h", | |||
"max_read_registers": 60, | |||
"channels": [ | |||
{ | |||
"name": "Urms L1", | |||
"reg_type": "input", | |||
"address": "0x10d9", | |||
"type": "voltage", | |||
"format": "u16", | |||
"scale": 0.01, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "THDN U L1", | |||
"reg_type": "input", | |||
"address": "0x10f1", | |||
"type": "value", | |||
"format": "u16", | |||
"scale": 0.01, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "Urms L2", | |||
"reg_type": "input", | |||
"address": "0x10da", | |||
"type": "voltage", | |||
"format": "u16", | |||
"scale": 0.01, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "THDN U L2", | |||
"reg_type": "input", | |||
"address": "0x10f2", | |||
"type": "value", | |||
"format": "u16", | |||
"scale": 0.01, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "Urms L3", | |||
"reg_type": "input", | |||
"address": "0x10db", | |||
"type": "voltage", | |||
"format": "u16", | |||
"scale": 0.01, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "THDN U L3", | |||
"reg_type": "input", | |||
"address": "0x10f3", | |||
"type": "value", | |||
"format": "u16", | |||
"scale": 0.01, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "Frequency", | |||
"reg_type": "input", | |||
"address": "0x10f8", | |||
"type": "value", | |||
"format": "u16", | |||
"scale": 0.01, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "Voltage angle L1", | |||
"reg_type": "input", | |||
"address": "0x10fd", | |||
"type": "value", | |||
"format": "s16", | |||
"scale": 0.1, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "Voltage angle L2", | |||
"reg_type": "input", | |||
"address": "0x10fe", | |||
"type": "value", | |||
"format": "s16", | |||
"scale": 0.1, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "Voltage angle L3", | |||
"reg_type": "input", | |||
"address": "0x10ff", | |||
"type": "value", | |||
"format": "s16", | |||
"scale": 0.1, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "Irms L1", | |||
"reg_type": "input", | |||
"address": "0x10dd", | |||
"type": "value", | |||
"format": "u16", | |||
"scale": 0.001, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "THDN I L1", | |||
"reg_type": "input", | |||
"address": "0x10f5", | |||
"type": "value", | |||
"format": "u16", | |||
"scale": 0.01, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "P L1", | |||
"reg_type": "input", | |||
"address": "0x1302", | |||
"type": "power", | |||
"format": "s32", | |||
"scale": 1.52588e-05, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "Q L1", | |||
"reg_type": "input", | |||
"address": "0x130a", | |||
"type": "value", | |||
"format": "s32", | |||
"scale": 1.52588e-05, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "S L1", | |||
"reg_type": "input", | |||
"address": "0x1312", | |||
"type": "value", | |||
"format": "s32", | |||
"scale": 1.52588e-05, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "PF L1", | |||
"reg_type": "input", | |||
"address": "0x10bd", | |||
"type": "value", | |||
"format": "s16", | |||
"scale": 0.001, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "AP energy L1", | |||
"reg_type": "input", | |||
"address": "0x1204", | |||
"type": "power_consumption", | |||
"format": "u64", | |||
"scale": 3.125e-05, | |||
"round_to": 0.0001, | |||
"word_order": "little_endian" | |||
}, | |||
{ | |||
"name": "RP energy L1", | |||
"reg_type": "input", | |||
"address": "0x1224", | |||
"type": "value", | |||
"format": "u64", | |||
"scale": 3.125e-05, | |||
"round_to": 0.0001, | |||
"word_order": "little_endian" | |||
}, | |||
{ | |||
"name": "Irms L2", | |||
"reg_type": "input", | |||
"address": "0x10de", | |||
"type": "value", | |||
"format": "u16", | |||
"scale": 0.001, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "THDN I L2", | |||
"reg_type": "input", | |||
"address": "0x10f6", | |||
"type": "value", | |||
"format": "u16", | |||
"scale": 0.01, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "P L2", | |||
"reg_type": "input", | |||
"address": "0x1304", | |||
"type": "power", | |||
"format": "s32", | |||
"scale": 1.52588e-05, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "Q L2", | |||
"reg_type": "input", | |||
"address": "0x130c", | |||
"type": "value", | |||
"format": "s32", | |||
"scale": 1.52588e-05, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "S L2", | |||
"reg_type": "input", | |||
"address": "0x1314", | |||
"type": "value", | |||
"format": "s32", | |||
"scale": 1.52588e-05, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "PF L2", | |||
"reg_type": "input", | |||
"address": "0x10be", | |||
"type": "value", | |||
"format": "s16", | |||
"scale": 0.001, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "AP energy L2", | |||
"reg_type": "input", | |||
"address": "0x1208", | |||
"type": "power_consumption", | |||
"format": "u64", | |||
"scale": 3.125e-05, | |||
"round_to": 0.0001, | |||
"word_order": "little_endian" | |||
}, | |||
{ | |||
"name": "RP energy L2", | |||
"reg_type": "input", | |||
"address": "0x1228", | |||
"type": "value", | |||
"format": "u64", | |||
"scale": 3.125e-05, | |||
"round_to": 0.0001, | |||
"word_order": "little_endian" | |||
}, | |||
{ | |||
"name": "Irms L3", | |||
"reg_type": "input", | |||
"address": "0x10df", | |||
"type": "value", | |||
"format": "u16", | |||
"scale": 0.001, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "THDN I L3", | |||
"reg_type": "input", | |||
"address": "0x10f7", | |||
"type": "value", | |||
"format": "u16", | |||
"scale": 0.01, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "P L3", | |||
"reg_type": "input", | |||
"address": "0x1306", | |||
"type": "power", | |||
"format": "s32", | |||
"scale": 1.52588e-05, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "Q L3", | |||
"reg_type": "input", | |||
"address": "0x130e", | |||
"type": "value", | |||
"format": "s32", | |||
"scale": 1.52588e-05, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "S L3", | |||
"reg_type": "input", | |||
"address": "0x1316", | |||
"type": "value", | |||
"format": "s32", | |||
"scale": 1.52588e-05, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "PF L3", | |||
"reg_type": "input", | |||
"address": "0x10bf", | |||
"type": "value", | |||
"format": "s16", | |||
"scale": 0.001, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "AP energy L3", | |||
"reg_type": "input", | |||
"address": "0x120c", | |||
"type": "power_consumption", | |||
"format": "u64", | |||
"scale": 3.125e-05, | |||
"round_to": 0.0001, | |||
"word_order": "little_endian" | |||
}, | |||
{ | |||
"name": "RP energy L3", | |||
"reg_type": "input", | |||
"address": "0x122c", | |||
"type": "value", | |||
"format": "u64", | |||
"scale": 3.125e-05, | |||
"round_to": 0.0001, | |||
"word_order": "little_endian" | |||
}, | |||
{ | |||
"name": "Total P", | |||
"reg_type": "input", | |||
"address": "0x1300", | |||
"type": "power", | |||
"format": "s32", | |||
"scale": 6.10352e-05, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "Total Q", | |||
"reg_type": "input", | |||
"address": "0x1308", | |||
"type": "value", | |||
"format": "s32", | |||
"scale": 6.10352e-05, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "Total S", | |||
"reg_type": "input", | |||
"address": "0x1310", | |||
"type": "value", | |||
"format": "s32", | |||
"scale": 6.10352e-05, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "Total PF", | |||
"reg_type": "input", | |||
"address": "0x10bc", | |||
"type": "value", | |||
"format": "s16", | |||
"scale": 0.001, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "Total AP energy", | |||
"reg_type": "input", | |||
"address": "0x1200", | |||
"type": "power_consumption", | |||
"format": "u64", | |||
"scale": 3.125e-05, | |||
"round_to": 0.0001, | |||
"word_order": "little_endian" | |||
}, | |||
{ | |||
"name": "Total RP energy", | |||
"reg_type": "input", | |||
"address": "0x1220", | |||
"type": "value", | |||
"format": "u64", | |||
"scale": 3.125e-05, | |||
"round_to": 0.0001, | |||
"word_order": "little_endian" | |||
}, | |||
{ | |||
"name": "Phase angle L1", | |||
"reg_type": "input", | |||
"address": "0x10f9", | |||
"type": "value", | |||
"format": "s16", | |||
"scale": 0.1, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "Phase angle L2", | |||
"reg_type": "input", | |||
"address": "0x10fa", | |||
"type": "value", | |||
"format": "s16", | |||
"scale": 0.1, | |||
"round_to": 0.01 | |||
}, | |||
{ | |||
"name": "Phase angle L3", | |||
"reg_type": "input", | |||
"address": "0x10fb", | |||
"type": "value", | |||
"format": "s16", | |||
"scale": 0.1, | |||
"round_to": 0.01 | |||
} | |||
] | |||
} | |||
} | |||
</syntaxhighlight> | |||
</div> | |||
<!--T:44--> | |||
На что следует обратить внимание в этом шаблоне? В первую очередь в параметрах устройства мы указываем, что одновременно следует считывать не более 60 регистров, чтобы не останавливать надолго опрос остальных устройств: '''"max_read_registers": 60'''. | |||
Также показательным является параметр, описывающий накопленную реактивную энергию по фазе L1: | |||
<syntaxhighlight lang="JSON"> | |||
{ | |||
"name": "RP energy L1", | |||
"reg_type": "input", | |||
"address": "0x1224", | |||
"type": "value", | |||
"format": "u64", | |||
"scale": 3.125e-05, | |||
"round_to": 0.0001, | |||
"word_order": "little_endian" | |||
}, | |||
</syntaxhighlight> | |||
<!--T:45--> | |||
Здесь стоит обратить внимание на то, что адрес регистра может задаваться и в шестнадцатеричном виде: '''"address": "0x1224"''', вещественный коэффициент масштабирования можно задавать в экспоненциальной записи: '''"scale": 3.125e-05''', при считывании значения округлять его до нужного порядка: '''"round_to": 0.0001''', а также учитывать, что число в Modbus-регистрах хранится в порядке от младшего к старшему: '''"word_order": "little_endian"'''. | |||
Форматы хранения для 16-битных Modbus регистров описываются следующим образом: | |||
<pre> | |||
big-endian : ( [0xAA 0xBB] [0xCC 0xDD] => 0xAABBCCDD ) | |||
little-endian : ( [0xAA 0xBB] [0xCC 0xDD] => 0xCCDDAABB ) | |||
</pre> | |||
По умолчанию предполагается формат big-endian. | |||
<!--T:46--> | |||
Типы переменных, используемых в шаблонах, перечислены в следующей таблице: | |||
{| class="wikitable" | |||
! Обозначение !! Тип | |||
|- | |||
| s16 || Signed 16-bit integer | |||
|- | |||
| u16 || Unsigned 16-bit integer | |||
|- | |||
| s8 || Signed 8-bit integer | |||
|- | |||
| u8 || Unsigned 8-bit integer | |||
|- | |||
| s24 || Signed 24-bit integer | |||
|- | |||
| u24 || Unsigned 24-bit integer | |||
|- | |||
| s32 || Signed 32-bit integer | |||
|- | |||
| u32 || Unsigned 32-bit integer | |||
|- | |||
| s64 || Signed 64-bit integer | |||
|- | |||
| u64 || Unsigned 64-bit integer | |||
|- | |||
| bcd8 || 8-bit BCD | |||
|- | |||
| bcd16 || 16-bit BCD | |||
|- | |||
| bcd24 || 24-bit BCD | |||
|- | |||
| bcd32 || 32-bit BCD | |||
|- | |||
| float || IEEE754 32-bit float | |||
|- | |||
| double || IEEE754 64-bit float (double) | |||
|- | |||
| char8 || 8-bit ASCII char | |||
|} | |||
=== Источники информации === <!--T:47--> | |||
В этой статье описаны основные правила создания шаблонов устройств для контроллеров Wiren Board. Информация изменяется и дополняется по мере обновления ПО и выходу новых продуктов. Самая полная и актуальная информация может быть найдена в следующих источниках: | |||
* в описании сервиса [https://github.com/contactless/wb-mqtt-serial/ wb-mqtt-serial] на GitHub; | |||
* в файлах самих шаблонов. | |||
* в файле [https://github.com/contactless/wb-mqtt-serial/blob/master/wb-mqtt-serial.schema.json wb-mqtt-serial.schema.json] на GitHub. | |||
</translate> |
Версия 07:43, 26 января 2021
Опрос устройства Modbus вручную перед написанием шаблона
Перед тем как писать шаблон, нужно вручную проверить, что устройство правильно подключено, и с него удаётся получить данные. Для этого потребуется документация на устройство, включающая его параметры последовательного порта (скорость, чётность, количество стоп-бит) и список его Modbus-регистров с описанием их возможных значений. После этого нужно подключить устройство и, используя эту информацию, попробовать вручную получить из него данные с помощью утилиты modbus_client.
Общая структура шаблона устройства
Файл шаблона устройств представляет собой структуру JSON, описывающую параметры устройства. Шаблон допускает наличие комментариев.
JSON-структура записывается внутри пространства между открывающей и закрывающей фигурной скобкой: { ... }
.
Общая структура шаблона устройства выглядит следующим образом:
//Шаблон устройства
{
"device": {
"Параметр 1 устройства":"значение",
"Параметр 2 устройства":"значение",
...
"channels": [ {Параметры канала 1}, {Параметры канала 2}, ...]
}
}
Здесь device — устройство, подключаемое к контроллеру, канал — источник данных: обычно Modbus-регистр с описанием типа данных, частоты опроса, преобразования значений и проч.
Подробное описание смотрите в следующих разделах. Файлы шаблонов, поставляемые в составе пакета, хранятся на контроллере в директории
/usr/share/wb-mqtt-serial/templates
Для версий wb-mqtt-serial, начиная с 2.6.3, шаблоны, созданные вами для нового устройства, следует сохранять в директорию
/etc/wb-mqtt-serial.conf.d/templates
Для более старых версий - в /usr/share/wb-mqtt-serial/templates
.
В наших шаблонах мы используем отступы по 4 пробела на уровень, что обеспечивает удобочитаемость кода шаблона, и рекомендуем писать новые шаблоны с такими же отступами.
Параметры устройства (device)
![](/wiki/images/thumb/6/68/Device_properties_mqtt_serial.png/650px-Device_properties_mqtt_serial.png)
В начале шаблона задаются параметры устройства в виде набора пар ключ:значение. Обязательными параметрами являются ключи "device_type" и "device".
Ключ device_type задает уникальное название типа устройства в виде строки, например:
"device_type":"WB-MAP12H",
.
Значение ключа device — составная структура, описывающее конкретные параметры устройства:
"device": {
"name": "WB-MAP12H",
"id": "wb-map12h",
"channels": [...]
}
- name — отображаемое имя устройства. Публикуется как
.../meta/name в mqtt
. Имя устройства используется при отображении web-интерфейсе, хранится в топике"id" + " " + "slave_id"
. Пример для устройства с modbus-адресом 5 (slave_id) и значением"name":"WB-MAP12H (basic)"
/devices/wb-map12h_5/meta/name WB-MAP12H (basic)
.
- id — уникальный идентификатор устройства в MQTT. Каждый элемент в devices должен иметь уникальный id. mqtt-topic'и, относящиеся в MQTT к данному устройству, имеют общий префикс /devices/<идентификатор топика>/... Также по умолчанию берется из шаблона с добавлением slave_id:
"id" + "_" + slave_id
- channels — список каналов устройств, задается в виде массива
[...]
, каждый из элементов которого представляет описание отдельного канала.
Остальные параметры устройства либо добавляются в раздел при включении шаблона в общую конфигурацию wb-mqtt-serial, либо используются значения по умолчанию. Полный список можно найти в файле wb-mqtt-serial.schema.json (его копия также хранится на контроллере: /usr/share/wb-mqtt-confed/schemas/wb-mqtt-serial.schema.json
). Смотрите свойства объекта "device" -> "properties"
.
Каналы устройства
![](/wiki/images/thumb/d/d5/Channel_properties_mqtt_serial.png/450px-Channel_properties_mqtt_serial.png)
Описание канала представляет собой структуру
"channels": [
{
"name": "Имя канала 1",
...
},
{
"name": "Имя канала 2",
...
},
...
]
Структура содержит следующий набор полей.
![](/wiki/images/thumb/c/c4/Vartype_properties_mqtt_serial.png/450px-Vartype_properties_mqtt_serial.png)
- name — имя канала, уникальное для устройство имя канала
- reg_type — тип Modbus-регистра, одно из "coil", "discrete", "holding", "holding_single", "holding_multi", "input", "direct"
- address — адрес Modbus-регистра, связанного с каналом.
- type — тип контрола -- виртуального элемента для представления данных в Web-интерфейсе контроллера: "switch", "pushbutton", "range", "rgb" и другие; полностью перечислены в схеме wb-mqtt-serial.schema.json.
- readonly — "true", если значения можно только считывать.
- format — тип переменной, описывающей значение, см. рис.
В простейшем случае достаточно полей "name", "reg_type", "address" и "type". Описания остальных типов параметров полностью перечислены в схеме wb-mqtt-serial.schema.json.
Примеры шаблонов устройств
Ниже приведены примеры файлов шаблонов для некоторых устройств Wiren Board, охватывающие основной список используемых параметров при создании шаблонов.
WB-MS-THLS v.2
Устройство WB-MS-THLS — универсальный комбинированный Modbus-датчик температуры, влажности, освещённости и звукового давления. Устройство предоставляет доступ к данным через input-регистры Modbus. Первоначальные настройки устройства записаны в holding-регистры, но не используются для получения данных и управления устройством, поэтому в шаблон не входят. По ссылке "Expand" можно увидеть полный код шаблона.
В настройках устройства интересен параметр
"max_read_registers": 0,
Этот параметр описывает максимальное количество регистров, считываемых с устройства при запросе. Значение по умолчанию — 1, в нашем случае мы указываем считывать все регистры за один проход (bulk read).
В настройках канала "Temperature" имеются три параметра, на которые стоит обратить внимание:
"format": "s16",
"scale": 0.1,
"error_value": "0x7FFF"
Параметр "format": "s16" указывает на то, что число в регистрах представлено в виде знакового 16-битного целого, "scale": 0.1 — говорит о том, что полученное из регистров значение следует домножить на коэффициент масштабирования 0,1 для получения значения температуры, а параметр "error_value": "0x7FFF" задает значение, получаемое из регистра, указывающее на то, что при опросе датчика произошла ошибка. Такой параметр будет выделен красным цветом в Web-интерфейсе контроллера. Применять такой параметр следует, если вы знаете, какое значение выдает ваше устройство в случае ошибки.
WB-MRGBW-D
Устройство WB-MRGBW-D — четырехканальный диммер для управления светодиодными лентами. Может управлять лентой RGB+W либо независимо четырьмя одноцветными лентами. Настройки яркости хранятся в holding-регистрах; шаблон описывает, какие регистры можно менять для получения нужной яркости каналов, отслеживать нажатия на кнопки диммера и получать значения количества нажатий.По ссылке "Expand" можно увидеть полный код шаблона.
В этом шаблоне составной канал RGB задает одновременно яркости трех цветовых компонентов ленты, хранящихся в трех holding-регистрах и описывается следующим образом:
{
"name": "RGB",
"type": "rgb",
"consists_of": [
{
"reg_type": "holding",
"address": 1
},
{
"reg_type": "holding",
"address": 0
},
{
"reg_type": "holding",
"address": 2
}
]
},
Канал белого цвета управляется отдельно,
{
"name": "White",
"reg_type": "holding",
"address": 3,
"type": "range",
"max": 255
},
Здесь указано максимальное значение, которое можно установить для ползунка яркости белого — 255:
"max": 255
Серийный номер устройства (канал "Serial NO") считывается как беззнаковое 32-битное целое:
"format": "u32"
WBIO-DO-R10A-8
Устройство WBIO-DO-R10A-8 — релейный боковой модуль, который подключается непосредственно к WBIO-разъему контроллера, и не управляется по Modbus. Но при подключении его через устройство расширения WB-MIO или WB-MIO-E становится полноценным Modbus-устройством, для которого имеется соответствующий шаблон. По ссылке "Expand" можно увидеть полный код шаблона.
В этом шаблоне следует обратить внимание на следующие параметры устройства.
"protocol": "modbus_io",
"stride": 1000,
"shift": 500,
"max_read_registers": 0,
"setup": [
Параметр "protocol": "modbus_io" указывает, что устройство подключается оп специальному протоколу к модулю расширения. Параметры "stride": 1000 и "shift": 500 задают сдвиг регистров в зависимости от того, в каком порядке подключены модули к модулю расширения.
Сдвиг регистров (число, которое нужно добавить к базовому номеру регистра) вычисляется по формуле:
Shift = (((SlaveId.Secondary - 1) % 4) + 1) * DeviceConfig()->Stride + DeviceConfig()->Shift;
Здесь stride — DeviceConfig()->Stride, a shift — DeviceConfig()->Shift. Каждое подключенное устройство имеет порядковый номер (SlaveId.Secondary), начинающийся с 1 для первого устройства. (Здесь знаком "%" обозначается деление по модулю.) Например, подставляя значения shift и stride в формулу, получаем:
Shift = ((( 1 - 1) % 4) + 1) * 500 + 1000 = (0 + 1) * 500 + 1000 = 1500
То есть ко всем регистрам, указанным в шаблоне, надо добавить 1500.
Еще один важный параметр — setup-секция, массив
"setup": [ {
"title": "IODIR",
"address": 10000,
"value": "0x0000"
},
{},
...]
Он описывает регистры и значения, которые однократно заносятся в эти регистры при инициализации устройства (при запуске или перезапуске wb-mqtt-serial). Его можно использовать для конфигурирования устройств для работы в каком-то определенном режиме, задавать изначальные значения яркости, положения сервоприводов, состояния реле, режима работы с входами релейных модулей и т. п.
WB-MAP3H
Устройство WB-MAP3H — трехканальный счетчик электроэнергии. Он измеряет большое количество параметров электрической сети. Поскольку опрос всех регистров такого устройства может занять достаточно много времени, имеется несколько шаблонов, содержащих оптимальный набор параметров для решения текущей задачи. Мы рассмотрим базовый шаблон. По ссылке "Expand" можно увидеть полный код шаблона.
На что следует обратить внимание в этом шаблоне? В первую очередь в параметрах устройства мы указываем, что одновременно следует считывать не более 60 регистров, чтобы не останавливать надолго опрос остальных устройств: "max_read_registers": 60. Также показательным является параметр, описывающий накопленную реактивную энергию по фазе L1:
{
"name": "RP energy L1",
"reg_type": "input",
"address": "0x1224",
"type": "value",
"format": "u64",
"scale": 3.125e-05,
"round_to": 0.0001,
"word_order": "little_endian"
},
Здесь стоит обратить внимание на то, что адрес регистра может задаваться и в шестнадцатеричном виде: "address": "0x1224", вещественный коэффициент масштабирования можно задавать в экспоненциальной записи: "scale": 3.125e-05, при считывании значения округлять его до нужного порядка: "round_to": 0.0001, а также учитывать, что число в Modbus-регистрах хранится в порядке от младшего к старшему: "word_order": "little_endian". Форматы хранения для 16-битных Modbus регистров описываются следующим образом:
big-endian : ( [0xAA 0xBB] [0xCC 0xDD] => 0xAABBCCDD ) little-endian : ( [0xAA 0xBB] [0xCC 0xDD] => 0xCCDDAABB )
По умолчанию предполагается формат big-endian.
Типы переменных, используемых в шаблонах, перечислены в следующей таблице:
Обозначение | Тип |
---|---|
s16 | Signed 16-bit integer |
u16 | Unsigned 16-bit integer |
s8 | Signed 8-bit integer |
u8 | Unsigned 8-bit integer |
s24 | Signed 24-bit integer |
u24 | Unsigned 24-bit integer |
s32 | Signed 32-bit integer |
u32 | Unsigned 32-bit integer |
s64 | Signed 64-bit integer |
u64 | Unsigned 64-bit integer |
bcd8 | 8-bit BCD |
bcd16 | 16-bit BCD |
bcd24 | 24-bit BCD |
bcd32 | 32-bit BCD |
float | IEEE754 32-bit float |
double | IEEE754 64-bit float (double) |
char8 | 8-bit ASCII char |
Источники информации
В этой статье описаны основные правила создания шаблонов устройств для контроллеров Wiren Board. Информация изменяется и дополняется по мере обновления ПО и выходу новых продуктов. Самая полная и актуальная информация может быть найдена в следующих источниках:
- в описании сервиса wb-mqtt-serial на GitHub;
- в файлах самих шаблонов.
- в файле wb-mqtt-serial.schema.json на GitHub.