Zabbix + Wirenboard: мониторинг производства
Введение
В этой статье я расскажу о том, как мы используем Zabbix и Wirenboard для мониторинга производственного оборудования, каким образом мы смогли получить данные с линий и источников основных ресурсов. Статья описывает концепцию и основные моменты организации мониторинга средствами свободно распространяемого ПО, но в ней не будут обсуждаться серьезные системы класса SCADA. Моя задача была быстро развернуть мониторинг без капитальных вложений и начать получать данные как можно скорее с того что уже есть.
Задача
У нас есть конвейерные линии с сырьем и готовой продукцией, есть печи, автоклавы и другие, полезные в производстве, штуки. Все это потребляет различные ресурсы (газ, вода, электричество) и требует контроля (работает или простаивает). Нужен мониторинг, который позволит нам выявить узкие места на производстве и сделать выводы об эффективности использования ресурсов и оборудования.
Сложности интеграции
К сожалению, все производственное оборудование управляется своими локальными контроллерами, сетевой интерфейс есть далеко не у всех, используемые протоколы у каждого свои, доступ к ОС закрыт, используются аналоговые датчики — делиться информацией с внешним миром мало кто хочет.
Все менять — долго, дорого и сложно, а данные нужно получить уже сейчас, вывод: нужно встраиваться.
Контроллер
В качестве контроллера мы выбрали Wirenboard. На его борту работает полностью открытый linux, можно устанавливать любые дополнительные пакеты, есть свой движок правил и web интерфейс. Производитель контроллера выпускает всю необходимую линейку датчиков и счетчиков, которые общаются между собой по открытому протоколу Modbus RTU. Все данные собираются в MQTT. На мой взгляд MQTT — самый подходящий способ сбора и доставки данных телеметрии, протокол открытый и максимально простой в работе.
Zabbix-mqtt-Wirenboard
Zabbix не работает напрямую c MQTT, но есть возможность использовать внешние модули, вот два варианта, которые я применял.
Первый и самый простой — установить Zabbix агента на контроллер, он будет опрашивать топики через MQTT клиент mosquitto_sub. В настройках агента потребуется указывается параметр:»UserParameter=mqtt.value[*], mosquitto_sub -t '$1' -C 1», а на стороне Zabbix сервера, в item key прописать mqtt.value[путь к топику].
Это заработало достаточно быстро, но у этого подхода есть проблема — MQTT хранит данные в топике без привязки ко времени. Если датчик умер, и не присылает новые данные, в топике все равно хранится последнее значение и на графике в Zabbix мы получим прямую линию. Можно использовать ключ «retain», который позволяет доставлять данные метрики только активным подписчикам на соответствующий топик, но тогда Zabbix данные не получит вообще, так как он опрашивает последнее значение, а не подписывается на топик. Еще одна неприятность — на каждый топик свой запрос, опрашивать нужно много и часто. Это приводит к расхождению реального состояния на производственной линии и полученных данных, потому что опрос производился в разное время и с интервалами.
Второй способ получения данных стал возможен благодаря переходу на Zabbix 4.2 и интеграции модуля zbx_mqtt. Скрипт опроса устанавливается на Zabbix сервер, с его помощью можно запросить всю ветку топиков устройств, получить данные в формате JSON и затем разобрать их по соответствующим метрикам. Так мы смогли забирать данные одновременно с нескольких датчиков и получить «снимок» состояния всей линии. Проблема с устареванием данных решается через обработку данных в Preprocessing: если данные не менялись — не записывать их.
Мониторинг
Счетчик импульсов
Импульсный выход — самый распространённый интерфейс для подсчета чего-либо. С его помощью можно:
посчитать потребление с расходомеров или сколько продукции прошло через оптические датчики
определять состояние дверей или положение подвижных элементов при помощи герконов
снимать данные с энкодеров двигателей и получить угол поворота или количество оборотов
определять статусы вкл/выкл через реле или аналоговые выводы.
Например, у нас есть счетчик WB-MCM8 c modbus адресом 32, мы его используем для подсчета банок оптическим датчиком на выходе конвейера, он передает данные в топики MQTT на Wirenboard.
/devices/wb-mcm8_32/controls/Input 1 counter
/devices/wb-mcm8_32/controls/Input 2 counter
…
/devices/wb-mcm8_32/controls/Input 8 counter
Для сбора данных мы создаем в Zabbix элемент MasterItem_WB-MCM8_32 с типом External check. Он будет забирать состояние всех счетчиков.
Пример Master item для MQTT метрик
В поле key мы указываем запрос: mqtt[»-t=/devices/wb-mcm8_32/#»,»--mqtt-host={HOST.CONN}»] где:
mqtt[] — вызов скрипта для опроса с параметрами
-t=/devices/wb-mcm8_32/# — запросить все данные внутри топика устройства wb-mcm832
--mqtt-host={HOST.CONN} — адрес контроллера Wirenboard. Адрес указан как переменная {HOST.CONN}
В результате такого запроса, в Zabbix возвращаются данные в формате JSON, вот пример фрагмента:
{…"/devices/wb-mcm8_32/controls/Input 7 counter": "3129705", "/devices/wb-mcm8_32/controls/Input 3 counter": "1885652", "/devices/wb-mcm8_32/controls/Input 1 counter/meta/type": "value", "/devices/wb-mcm8_32/controls/Input 5/meta/order": "13", "/devices/wb-mcm8_32/controls/Input 8/meta/order": "16"…}
Вторым шагом мы создаем dependent item, который будет забирать конкретную метрику из мастера.
Параметр key тут значения не играет, но в нем я указываю полный путь к топику mqtt для удобства поиска. Выборка данных указывается во вкладке Preprocessing.
JSONPath - указывает на нужный нам топик с метрикой
Check for error in JSON - у устройства wb-mcm8 есть специальный служебный топик с ошибками и можно сделать проверку: если он не пустой, значит проблема с устройством, значение не будет сохраняться и элемент данных в Zabbix перейдет в состояние ошибки.
Simple change - так как нам нужно не само значение счетчика, а его изменение (дельта) — мы используем функцию Simple change.
Использование пакетного сбора данных очень удобно, если нам нужно получить и счетчик и его дельту, то нам не требуется еще раз запрашивать данные с контроллера. Мы создаем еще один зависимый элемент и указываем другие настройки обработки, так он будет вычислен сразу, как только обновится мастер.
Счетчик электроэнергии
Мы использовали WB-MAP3H. Для его установки не требуется отключения линий и потребителей, устройство получает данные о расходе через внешние трансформаторы тока, которые крепятся на кабель без его демонтажа. Важно соблюсти соответствие подключаемых фаз (контролируется по фазовым углам) и указать коэффициенты трансформаторов (в новой версии они указаны на корпусе, в старой — делалась калибровка у производителя). Устройство не только измеряет основные характеристики (мощность, энергия, расход), но умеет измерять много дополнительных характеристик вплоть до определения доли гармоники и амплитуд всплесков (полный список измеряемых параметров можно посмотреть тут).
WB-MAP3H
Измеряя потребление можно не только определить кто и сколько расходует электричество, но и отслеживать какое оборудование работает. В теории, контролируя параметры потребления у двигателей и определяя аномалии, можно диагностировать физическое состояние и необходимость ремонта –, но это пока только задумка.
Получение данных от Delta по Modbus TCP и RTU
У нас часть промышленных линий управляется контроллерами Delta, на которых есть сетевой интерфейс и реализован протокол Modbus TCP. Переменные на контроллере сохраняются в регистры Modbus и их можно забрать в Zabbix при помощи модуля libzbxmodbus. Модуль оказался очень функциональным и удобным, он умеет работать не только по сети с TCP, но и через com порт с RTU реализацией Modbus. Подробное описание и параметры можно посмотреть на гите разработчика, а я покажу свой пример использования.
На Zabbix создан Master item, он забирает с контроллера 17 регистров по Modbus TCP, в которых хранятся данные от датчиков веса, температуры и уровня продукта в емкости.
modbus_read[{$MODBUS_ADDRESS},1,4110,3,17*s]
master item для опроса контроллера Delta
$MODBUS_ADDRESS — локальная переменная в Zabbix, в ней хранится ip адрес контроллера к которому обращаемся, у меня это «tcp://192.168.0.2»
1 — адрес устройства на шине Modbus. Как правило это »1», разные адреса могут быть при работе с RTU версией протокола, когда несколько устройств работают на одной шине
4110 — адрес начального регистра, который мы читаем первым
3 — функция протокола Modbus. В моем случае указана 3 — функция чтения регистра
17*s — модуль умеет читать несколько регистров подряд, в моем примере он берет 17 регистров и считает, что тип данных в них int16 (s=int16, f=float, b=bit это подробно описано в документации к модулю)
В 5й версии Zabbix появилась возможность сразу тестировать работу запроса и посмотреть возвращаемое значение — кнопка Test, нажав ее мы получим JSON объект со значениями 17 регистров (с 4110 по 4126).
{"4110":967,"4111":960,"4112":395,"4113":0,"4114":0,"4115":0,"4116":665,"4117":803,"4118":2500,"4119":2500,"4120":447,"4121":999,"4122":1224,"4123":2154,"4124":1493,"4125":1254,"4126":418}
Теперь мы можем создать зависимый элемент данных, указать в Preprocessing steps параметр JSONPath = $.4110 и получить в него значение метрики от 4110 регистра. Дополнительно можно указывать проверки полученного значения, например: параметр In range проверяет попадает ли значение в промежуток от 0 до 1500, если нет — значение отбрасывается. При помощи параметра Discard unchanged можно отбрасывать значения, если они не меняются.
Настройка метрики из регистра контроллера
Интеграция с Siemens
Контроллеры Siemens S7 используют свой протокол profinet / profibus, для работы с ним есть открытая библиотека Snap7. Для интеграции был создан скрипт zbx_s7_get на питоне, который умеет опрашивать контроллеры.
Пример запроса данных
Скрипту s7_get.py передаются параметры:
s7_get.py[{HOST.CONN},{$S7.RACK},{$S7.SLOT},{$S7.DB},6,bool,--json]
{HOST.CONN} — встроенная локальная переменная, которая содержит ip адрес узла сети (указан в host interface)
{$S7.RACK} — переменная, в которой указан rack id контроллера
{$S7.SLOT} — переменная, в которой указан слот
{$S7.DB} — переменная , в которой указан id базы
6 — offset
Bool — тип возвращаемых данных, в моем случае мне нужны именно true / false. Может быть int или float.
--json — формат данных. В моем случае выбран json, так как это master item и на его основе я создаю зависимые элементы с нужными метриками.
При тестировании этого элемента мы получим данные в JSON, которые можно будет разобрать по метрикам (в моем случае это статусы с датчиков на контроллере).
{"6": ["True", "False", "False", "True", "False", "True", "True", "False"]}
Получение данных с принтеров Linx 5900
Промышленный принтер Linx 5900 используется для маркировки продукции на конвейере (дата производства, номер партии). Маркировка очень важный процесс, за которым нужно следить, так как если принтер остановится или будет печатать некорректные данные — можно получить отзыв продукции со склада или претензию от клиентов.
Для подключения Zabbix к принтеру я использовал конвертер moxa NPORT 5150. Он позволяет прокинуть через tcp физический порт rs232 с принтера на виртуальный serial порт /dev/ttyr01 linux машины, где установлен Zabbix агент. Само общение с принтером происходит по Linx Remote Communications Interface (RSI). Протокол обмена основан на отправке команды в двоичном виде, вот пример заброса счетчика отпечатков (используется мной для подсчета продукции).
Запрос: 1b 02 08 1b 03
Ответ: 1b 06 00 00 08 da bc b9 01 1b 03
Протокол:
1b 06 - начало
00 00
08 – ответ на команду 8 (получить счетчик)
da bc b9 01 - полезные данные
1b 03 конец
Пример данных UINT32 - Little Endian (DCBA)
01 B9 BC 8F 28949647
01 B9 BC DA 28949722
01 B9 BD 25 28949797
Протокол обмена использует контрольные суммы в запросе и ответе, последовательность подробно описана в инструкции, но мне не удалось с ними разобраться и пришлось эту функцию отключить.
В Zabbix я использовал плагин serial.get. Item key для получения текущего состояния счетчика выглядит так:
serial.get[/dev/ttyr01,5,1b02081b03,uint32]
Заключение
Zabbix прекрасен своей гибкостью и функциональность, на его основе нам удалось быстро создать мониторинг основных параметров производственных линий без остановки и переоснащения.
С помощью мониторинга удалось:
выявить и устранить причины потери ресурсов и сократить расход (за счет устранения утечек и отключения лишних потребителей)
начать считать OEE и оперативно реагировать на снижение производительности отдельных участков
сравнивать производительность дневных и ночных смен в онлайн режиме
оптимизировать логику управления производственной линии и поднять ее производительность (за счет перенастройки таймингов насосов и приводов)
предоставить легкий доступ к актуальной информации во время проведения технических советов и совещаний (вместо бумажных отчетов)
При внедрении мониторинга важно понимать, что просто получить данные недостаточно, ими нужно активно пользоваться — анализировать и визуализировать, предоставлять легкий доступ всем заинтересованным. Про визуализацию в Grafana я написал другую статью, прочитать ее можно тут.
В планах:
Подключить к мониторингу удаленные площадки, куда не протянуть провода. Вероятно это будет через радо по lorawan
Разработать весовой контроль подаваемого сырья при помощи интеграции с весовыми терминалами CAS
Разработать мониторинг состояния двигателей за счет контроля потребления энергии и вибродиагностики
Расширить покрытие мониторинга по всему заводу
P.S.
Статья написана до выхода Zabbix 5.2. Новая версия ориентирована на работу с iot и в ней уже есть возможность получать данные из MQTT и Modbus без дополнительных модулей, за что огромное спасибо разработчикам Zabbix. Отдельное спасибо @wabbitза модули на git https://github.com/v-zhuravlev, именно они дали основной толчок к развитию мониторинга.