Резервированные источники питания используются повсеместно. Они обеспечивают бесперебойным электропитанием приборы охранной и пожарной сигнализации, оборудование систем контроля доступа и другие системы. На нашем предприятии в качестве таких источников, как правило, используются приборы от ЗАО НВП Болид. У некоторых из них, как, например, у РИП-12-6/80M3-R-RS, имеется интерфейс RS485, что позволяет включать их в систему мониторинга.
Средства мониторинга
Мы используем Zabbix 5.2. Получать данные от РИП будем по протоколу Modbus RTU over TCP. Поддержка этого протокола реализована в Zabbix с помощью загружаемого модуля libzbxmodbus. Также в процессе мониторинга принимают участие преобразователь протокола C2000-ПП (вер. 1,32) в режиме «Master» и преобразователь последовательных интерфейсов (RS485 в Ethernet).

Объекты мониторинга
Для начала определимся, что конкретно мы сможем контролировать. Из документации к РИП-12-6/80M3-R-RS и С2000-ПП выяснилось, что рассчитывать мы можем на получение состояния семи зон (ШС) и числовых значений тока и напряжения. В ходе экспериментов мне удалось воспроизвести следующие состояния ШС:
ШС №0 Состояние прибора
149 | Взлом корпуса прибора | Корпус РИП открыт |
152 | Восстановление корпуса прибора | Корпус РИП закрыт |
250 | Потеряна связь с прибором | Потеряна связь с прибором |
ШС №1 Выходное напряжение
193 | Подключение выходного напряжения | РИП подключил выходное напряжение при появлении напряжения в сети |
192 | Отключение выходного напряжения | РИП отключил выходное напряжение при отсутствии напряжения в сети и разряде батареи |
199 | Восстановление питания | Напряжение питания прибора пришло в норму |
250 | Потеряна связь с прибором | Потеряна связь с прибором |
ШС №2 Ток нагрузки
194 | Перегрузка источника питания | Выходной ток РИП более 7,5 А |
195 | Перегрузка источника питания устранена | Выходной ток РИП менее 7,5 А |
250 | Потеряна связь с прибором | Потеряна связь с прибором |
ШС №3 и ШС №4 Напряжение на батарее №1 и №2 соответственно
200 | Восстановление батареи | Напряжение батареи выше 10 В, заряд батареи возможен |
202 | Неисправность батареи | Напряжение на батарее ниже 7 В или не подключена |
211 | Батарея разряжена | Напряжение на батарее ниже 11 В при отсутствии сетевого напряжения |
250 | Потеряна связь с прибором | Потеряна связь с прибором |
ШС №5 Степень заряда батарей
196 | Неисправность зарядного устройства | ЗУ не обеспечивает напряжение и ток для заряда батареи в заданных пределах |
197 | Восстановление зарядного устройства | ЗУ обеспечивает напряжение и ток для заряда батареи в заданных пределах |
250 | Потеряна связь с прибором | Потеряна связь с прибором |
ШС №6 Напряжение сети
1 | Восстановление сети 220 | Сетевое напряжение питания в пределах 150…250 В |
2 | Авария сети 220 В | Сетевое напряжение питания < 150 В или > 250 В |
250 | Потеряна связь с прибором | Потеряна связь с прибором |
Крайне вероятно, что мной была получена только часть из всех возможных состояний. Например, имеются догадки, что ШС №3 и №4 должны также иметь состояние [204] Необходимо обслуживание, а ШС №0 - состояние [203] Сброс прибора и другие. К сожалению, чтение документации ситуацию не прояснило. В связи с этим нам необходимо следить и реагировать на появление событий, которые мы не предусмотрели.
Конфигурирование устройств
Не будем долго останавливаться на процессе конфигурирования приборов, только коротко рассмотрим перечень необходимых действий. Настройка устройств Болид осуществляется при помощи утилиты UProg и имеет следующий порядок:
Назначение сетевых адресов всем устройствам (РИП и С2000-ПП),
Конфигурирование интерфейса интеграции С2000-ПП (Modbus RTU),
Добавление ШС, описанных выше, в таблицу зон С2000-ПП. Крайне важно, чтобы, во-первых, были добавлены все ШС, а во-вторых, ШС должны следовать друг за другом в порядке возрастания.

При заполнении таблицы зон следует помнить следующее:
адрес прибора - сетевой адрес РИП, в нашем случае 126,
номер ШС - номер ШС от 0 до 6,
тип зоны - тип ШС, для ШС №0 назначаем тип зоны "3 - состояние прибора", для всех остальных - "8-РИП напряжение / ток".
Создаем шаблоны Zabbix
Напомню, что Zabbix с модулем libzbxmodbus выступает в роли Modbus-мастера. Из-за особенностей получения данных от C2000-ПП, о которых речь пойдет в процессе создания шаблонов, мы будем рассматривать два подхода к мониторингу.
мониторинг состояния ШС.
мониторинг как состояния, так и числовых параметров РИП.
Мониторинг состояния ШС
Итак, создадим шаблон RIP 12 mod 56 RIP 12 6 80 M3 R RS. Шаблон имеет один элемент данных с именем Request и типом "Простая проверка". Ключом элемента является функция: modbus_read[{$MODBUS_PORT},{$MODBUS_SLAVE},{$STATUS_REG},3,7*uint16] . В параметрах функции используются значения макросов, которые позволяют составить корректный modbus запрос к C2000-ПП.
{MODBUS_PORT} - тип используемого протокола (enc - Modbus RTU over TCP), адрес и порт преобразователя последовательных интерфейсов.
{MODBUS_SLAVE} - Modbus UID С2000-ПП (настраивается в UProg на вкладке прибор).
{STATUS_REG} - адрес регистра в котором расположен ШС №0 интересующего нас РИПа. Получить данный адрес можно следующим образом: "Номер зоны в таблице зон С2000-ПП" + 40000 - 1. В нашем примере это: 450+40000-1 = 40449.

Основная задача элемента Request - запросить у С2000-ПП значение всех семи ШС контролируемого РИП и предоставить их в формате JSON. Результирующий JSON содержит объекты, ключами которых являются адресы регистров С2000-ПП, а значениями - содержимое этих регистров:
{
"40449":39115,
"40450":51195,
"40451":50171,
"40452":51963,
"40453":51451,
"40454":50683,
"40455":763
}
Зависимые элементы данных
Элемент данных Request имеет 7 зависимых элементов. Основная задача этих элементов - распарсить JSON и получить состояние каждого ШС индивидуально. Вот эти элементы:
Status - состояние прибора (ШС №0),
Uout - выходное напряжение (ШС №1),
Iout - ток нагрузки (ШС №2),
Ubat1 - напряжение АКБ1 (ШС №3),
Ubat2 - напряжение АКБ2 (ШС №4),
Capacity - степень заряда АКБ (ШС №5),
Uin - напряжение сети (ШС №6).

Предобработка зависимых элементов данных
Чтобы получить состояние ШС №0 (Status), нам достаточно два шага предобработки. На первом шаге мы воспользуемся стандартным функционалом JSONPath, а затем разделим полученное значение на 256, тем самым получим код состояния.

К сожалению, мне не удалось использовать математические операции в параметрах JSONPath. Поэтому для оставшихся элементов данных пришлось использовать javascritpt-предобработку. Например, для элемента данных Iout (ШС №2) javascript-предобработка выглядит так:
function (value){
var reg = parseInt({$STATUS_REG})+2;
var data = JSON.parse(value);
return data[reg];
}

Триггеры
После добавления триггеров создание шаблона можно считать завершенным. Перечень созданных триггеров:
Взлом корпуса прибора,
Перегрузка источника питания,
Отключение выходного напряжения,
Неисправность батареи АКБ1,
Неисправность батареи АКБ2,
АКБ1 разряжен,
АКБ2 разряжен,
Авария сети 220 В,
Потеряна связь с прибором,
Неизвестное состояние Status,
Неизвестное состояние Iout,
Неизвестное состояние Uout,
Неизвестное состояние АКБ1,
Неизвестное состояние АКБ2,
Неизвестное состояние Capacity,
Неизвестное состояние Uin,
Превышено время отсутствия по MODBUS.
Демонстрация и импорт RIP 12 mod 56 RIP 12 6 80 M3 R RS


Ссылки для импорта: Шаблон RIP 12 mod 56 RIP 12 6 80 M3 R RS, Преобразование значений RIP 12 mod 56 RIP 12 6 80 M3 R RS.
Мониторинг состояния и числовых параметров
Мониторинг числовых параметров имеет свои особенности. Все дело в том, что для получения числового значения нам необходимо сделать два modbus-запроса к С2000-ПП. Первый запрос устанавливает зону для запроса тока или напряжения, второй - непосредственное получение значения. В таком случае мы не имеем возможности использовать функционал libzbxmodbus, т.к. попросту не cможем гарантировать правильную очередность запросов.
Первое и самое простое, что приходит на ум, - это создать скрипт, который сделает получение числового параметра атомарной операцией и воспользоваться возможностями внешних проверок Zabbix. Но такой скрипт тоже не позволит использовать загружаемый модуль libzbxmodbus по причине невозможности организации монопольного доступа к разделяемому ресурсу, в нашем случае к преобразователю последовательных интерфейсов.
В связи с вышесказанным, для этих целей было решено отказаться от использования libzbxmodbus и написать скрипт, который сможет предоставлять и числовые параметры РИП и состояния его ШС.
Пишем shell скрипт для внешней проверки
Для того, чтобы синхронизировать доступ к преобразователю последовательных интерфейсов, воспользуемся утилитой flock. Работу с Modbus будем осуществлять при помощи modpoll. В /usr/lib/zabbix/externalscripts создадим скрипт rip_12_mod_56.sh
#!/bin/bash
# rip_12_mod_56.sh
# $1 - protocol://host:port
# $2 - Modbus UID
# $3 - Status register
# $4 - Offset (0 - 6)
# Example of requesting statuses: ./rip_12_mod_56.sh enc://127.0.0.1:4001 1 40000
# Example value request: ./rip_12_mod_56.sh enc://127.0.0.1:4001 1 40000 3
(($# < 3)) && { printf '%s\n' "You have given little data. Command exited with non-zero"; exit 1; }
lockfile=$(echo "$1" | awk -F "://" '{print $2}')
setzone()
{
modpoll -m $1 -a $4 -r 46181 -0 -1 -c 1 -p $3 $2 $5> /dev/null 2>&1
(($? != 0)) && { printf '%s\n' "Command exited with non-zero"; exit 1; }
sleep 0.15
}
getvalue ()
{
value=$(modpoll -m $1 -a $4 -r 46328 -0 -1 -c 1 -t 4:hex -p $3 $2 |grep ]: |awk '{print $2}')
printf "%d" $value
}
getstatus ()
{
status=$(modpoll -m $1 -a $4 -r $5 -1 -c 7 -t 4:hex -p $3 $2 | grep ]: | awk -F "0x" 'BEGIN { printf"["} NR!=7{printf "\""$2"\","} NR==7 {printf "\""$2"\""} END { printf "]"}')
echo "{ \"status\": $status }"
}
(
flock -e 200
protocol=$(echo $1 | awk -F "://" '{print $1}');
host=$(echo $1 | awk -F "://" '{print $2}' | awk -F ":" '{print $1}')
port=$(echo $1 | awk -F "://" '{print $2}' | awk -F ":" '{print $2}')
register=$(($3+1))
if (($# >= 4)); then
zone=$(($register+$4-40000))
setzone $protocol $host $port $2 $zone
echo $(getvalue $protocol $host $port $2)
sleep 0.15
exit 0
fi
echo $(getstatus $protocol $host $port $2 $register)
sleep 0.15;
) 200> /tmp/$lockfile
Подробности настройки внешних проверок в Zabbix уточняйте в документации.
Создаем RIP 12 mod 56 RIP 12 6 80 M3 R RS EXTENDED
Для получения информации о состоянии ШС шаблон содержит элемент данных Request с типом "Внешняя проверка". Ключом элемента является скрипт: rip_12_mod_56.sh[{$MODBUS_PORT}, {$MODBUS_SLAVE}, {$STATUS_REG}]. Как и в шаблоне RIP 12 mod 56 RIP 12 6 80 M3 R RS, задача элемента Request - сформировать JSON с состояниями всех ШС.

Возвращаемый JSON оптимизирован для использования функционала JSONPath. Для упрощения скрипта значения возвращаются в шестнадцатеричной форме:
{
"status": ["98CB","C7FB","C3FB","CAFB","C8FB","C5FB","02FB"]
}
Состояния ШС. Снова зависимые элементы данных.
Как и в предыдущем шаблоне, элемент данных Request имеет 7 зависимых элементов. Задача этих элементов тоже неизменна - распарсить JSON и получить состояние каждого ШС.

Получаем числовые значения
Для получения числовых значений создадим 5 элементов данных с типом "Внешняя проверка".
Uout_value - значение выходного напряжения, В.
Iout_value - значение выходного тока, А.
Ubat1_value - значение напряжения на батарее №1, В.
Ubat2_value - значение напряжения на батарее №2, В.
Uin_value -значение напряжения сети, В.
Ключом этих элементов является скрипт: rip_12_mod_56.sh[{$MODBUS_PORT}, {$MODBUS_SLAVE}, {$STATUS_REG}, <НОМЕР ШС>].

Триггеры
Перечень триггеров не отличается от триггеров, созданных в шаблоне RIP 12 mod 56 RIP 12 6 80 M3 R RS.
Демонстрация и импорт RIP 12 mod 56 RIP 12 6 80 M3 R RS EXTENDED


Ссылки для импорта: Шаблон RIP 12 mod 56 RIP 12 6 80 M3 R RS EXTENDED, rip_12_mod_56.sh.
Вместо заключения
В своем мониторинге мы используем шаблон RIP 12 mod 56 RIP 12 6 80 M3 R RS. По-большому счету причина такого решения одна - расширяемость системы. Использование загружаемого модуля позволяет включать в одну линию приборы разных типов и модификаций, организовать их мониторинг стандартными средствами. Кроме этого, большой потребности в получении числовых значений у нас пока не возникало.
Однако, несмотря на все вышесказанное, возможность получения числовых значений тоже может оказаться востребованной. В этом случае можно задуматься об использовании в триггерах функций прогнозирования.
Спасибо за внимание!