Русский
Русский
English
Статистика
Реклама

С2000-пп

Дешифрация протокола Орион Bolid

19.06.2021 06:09:13 | Автор: admin

Компания Bolid лидер в разработке интегрированных систем безопасности - то, что вы услышите, если позвоните им по телефону. Это своего рода российский Apple в сфере АСУТП, со своей закрытой экосистемой. Попробуем немного открыть экосистему.

Введение

Большая часть устройств Bolid обычно связывается между собой двумя проводами через RS-485 в большинстве случаев с параметрами 9600/8-N-1.

Для общения используются 2 шифрованных протокола: Орион или Орион Про. На момент написания статьи я пока не знаю в чём между ними разница, во всяком случае дальше будет речь о протоколе Орион (без Про).

Существует устройство С2000-ПП от компании Bolid для общения с bolid-устройствами через протокол Modbus-RTU. Но его функционал крайне ограничен.

Протокол Орион

Протокол Орион представляет из себя подобие Modbus-RTU, есть команда, количество передаваемых байт и CRC.

Мы общаемся со slave-устройствами как master, мы отправляем запросы, устройства нам отвечают.

Некоторые команды передаются в шифрованном виде, некоторые в открытом. Хорошим индикатором шифрованной команды является смещённый адрес в начале сообщения. У шифрованного сообщения смещение адреса идёт на 0x80 или 0d128. Как итог 127 возможных адресов + 128 число смещения = 255 (максимальное значение одного байта из 2^8 возможных).

Для того, чтобы устройства отвечали на шифрованные сообщения, необходимо задать глобальный ключ - GLOBAL_KEY для каждого устройства, хотя бы единожды (не проверял какой стоит по умолчанию).

При отправке шифрованных команд используется MESSAGE_KEY при каждом запросе.

Для общения с Bolid-устройствами нам нужно подключиться в любое место линии RS-485 (не забываем про терминаторы, иногда без них работа нестабильна).

Расчёт контрольной суммы

Для расчёта CRC используется CRC-8-Dallas, рассчитываемый табличным методом.

byte[] CrcTable = {            0x00,0x5E,0xBC,0xE2,0x61,0x3F,0xDD,0x83,0xC2,0x9C,0x7E,0x20,0xA3,0xFD,0x1F,0x41,            0x9D,0xC3,0x21,0x7F,0xFC,0xA2,0x40,0x1E,0x5F,0x01,0xE3,0xBD,0x3E,0x60,0x82,0xDC,            0x23,0x7D,0x9F,0xC1,0x42,0x1C,0xFE,0xA0,0xE1,0xBF,0x5D,0x03,0x80,0xDE,0x3C,0x62,            0xBE,0xE0,0x02,0x5C,0xDF,0x81,0x63,0x3D,0x7C,0x22,0xC0,0x9E,0x1D,0x43,0xA1,0xFF,            0x46,0x18,0xFA,0xA4,0x27,0x79,0x9B,0xC5,0x84,0xDA,0x38,0x66,0xE5,0xBB,0x59,0x07,            0xDB,0x85,0x67,0x39,0xBA,0xE4,0x06,0x58,0x19,0x47,0xA5,0xFB,0x78,0x26,0xC4,0x9A,            0x65,0x3B,0xD9,0x87,0x04,0x5A,0xB8,0xE6,0xA7,0xF9,0x1B,0x45,0xC6,0x98,0x7A,0x24,            0xF8,0xA6,0x44,0x1A,0x99,0xC7,0x25,0x7B,0x3A,0x64,0x86,0xD8,0x5B,0x05,0xE7,0xB9,            0x8C,0xD2,0x30,0x6E,0xED,0xB3,0x51,0x0F,0x4E,0x10,0xF2,0xAC,0x2F,0x71,0x93,0xCD,            0x11,0x4F,0xAD,0xF3,0x70,0x2E,0xCC,0x92,0xD3,0x8D,0x6F,0x31,0xB2,0xEC,0x0E,0x50,            0xAF,0xF1,0x13,0x4D,0xCE,0x90,0x72,0x2C,0x6D,0x33,0xD1,0x8F,0x0C,0x52,0xB0,0xEE,            0x32,0x6C,0x8E,0xD0,0x53,0x0D,0xEF,0xB1,0xF0,0xAE,0x4C,0x12,0x91,0xCF,0x2D,0x73,            0xCA,0x94,0x76,0x28,0xAB,0xF5,0x17,0x49,0x08,0x56,0xB4,0xEA,0x69,0x37,0xD5,0x8B,            0x57,0x09,0xEB,0xB5,0x36,0x68,0x8A,0xD4,0x95,0xCB,0x29,0x77,0xF4,0xAA,0x48,0x16,            0xE9,0xB7,0x55,0x0B,0x88,0xD6,0x34,0x6A,0x2B,0x75,0x97,0xC9,0x4A,0x14,0xF6,0xA8,            0x74,0x2A,0xC8,0x96,0x15,0x4B,0xA9,0xF7,0xB6,0xFC,0x0A,0x54,0xD7,0x89,0x6B,0x35        };

Вариант расчёта CRC:

byte сalculate_сrc(byte[] inputMessage){            byte crc = 0;            if (inputMessage.Count == 0)            {                return 0;            }            var length = inputMessage.Count;            for (int i = 0; i < length; ++i)            {                crc = CrcTable[crc ^ inputMessage[i]];            }            return crc;}

Вариант расчёта CRC:

byte CalculateCrc(IList<byte> inputMessage){            return inputMessage.Aggregate((byte)0, (prev, next) => CrcTable[prev ^ next]);}

Установка глобального ключа

Для того, чтобы общаться с каким-то устройством, ему нужно задать глобальный ключ (для забавы и наглядности выбран ключ 0xBA, получается BABA).

Далее по тексту операция исключающего или (XOR) будет обозначаться символом ^.

Зададим Bolid-устройству с адресом 3 глобальный ключ следующей командой:

0x03 0x06 0x00 0x11 0xBA 0xBA 0x8D
  • 0x03 - адрес Bolid-устройства, в данном случае устройство имеет адрес 3 (из возможных 1..127);

  • 0x06 - количество передаваемых байт (итоговая длина сообщения минус один);

  • 0x00 - GLOBAL_KEY ^ MESSAGE_KEY (в данном случае GLOBAL_KEY = MESSAGE_KEY, поэтому GLOBAL_KEY ^ MESSAGE_KEY == 0);

  • 0x11 - команда на запись нового ключа устройства;

  • 0xBA - новый GLOBAL_KEY;

  • 0xBA - новый GLOBAL_KEY (повтор байта, видимо на всякий случай);

  • 0x8D - контрольная сумма CRC-8.

Считаем статус устройства

Для того, чтобы получить текущий статус устройства, отправим следующую команду:

0x83 0x08 0x00 0xED 0xB8 0xBA 0xBA 0xBA 0x62
  • 0x83 - ADDRESS + 0x80(смещение адреса при шифровании) (ADDRESS == 3);

  • 0x08 - количество передаваемых байт (итоговая длина сообщения минус один);

  • 0x00 - GLOBAL_KEY ^ MESSAGE_KEY (они одинаковые, поэтому ноль);

  • 0xED - 0x57 ^ MESSAGE_KEY команда на чтение статуса;

  • 0xB8 - 0x02 ^ MESSAGE_KEY команда на чтение статуса;

  • 0xBA - MESSAGE_KEY;

  • 0xBA - MESSAGE_KEY;

  • 0xBA - MESSAGE_KEY;

  • 0x62 - контрольная сумма CRC-8.

На данную команду мы можем получить ответ навроде:

0x83 0x0A 0xE2 0xB8 0xBA 0xBE 0xB9 0x7D 0x2F 0x72 0xD7
  • 0x83 - ADDRESS + 0x80 (ADDRESS == 3);

  • 0x0A - количество передаваемых байт (итоговая длина сообщения минус один);

  • 0xE2 - 0x88 ^ MESSAGE_KEY - назначение байта мне не известно;

  • 0xB8 - 0x02 ^ MESSAGE_KEY - назначение байта мне не известно;

  • 0xBA - MESSAGE_KEY;

  • 0xBE - 0x04 ^ MESSAGE_KEY - назначение байта мне не известно;

  • 0xB9 - 0x03 ^ MESSAGE_KEY - назначение байта мне не известно;

  • 0x7D - STATUS_1(0xC7) ^ MESSAGE_KEY;

  • 0x2F - STATUS_2(0x95) ^ MESSAGE_KEY;

  • 0x72 - 0xC8 ^ MESSAGE_KEY - назначение байта мне не известно;

  • 0xD7- контрольная сумма CRC-8.

Мы получили 2 статуса STATUS_1 и STATUS_2:

0xC7 и 0x95

199 и 149, соответственно.

Статус 199 - это Восстановление источника питания;

Статус 149 - это Взлом корпуса прибора.

Полный перечень статусов можно взять из документации на С2000-ПП.

Ссылка на одноимённую тему форума cxem.net

Подробнее..

Как я мониторил РИП-12 от Bolid

28.04.2021 02:24:00 | Автор: admin

Резервированные источники питания используются повсеместно. Они обеспечивают бесперебойным электропитанием приборы охранной и пожарной сигнализации, оборудование систем контроля доступа и другие системы. На нашем предприятии в качестве таких источников, как правило, используются приборы от ЗАО НВП Болид. У некоторых из них, как, например, у РИП-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 В

Сетевое напряжение питания в пределах 150250 В

250

Потеряна связь с прибором

Потеряна связь с прибором

Крайне вероятно, что мной была получена только часть из всех возможных состояний. Например, имеются догадки, что ШС 3 и 4 должны также иметь состояние [204] Необходимо обслуживание, а ШС 0 - состояние [203] Сброс прибора и другие. К сожалению, чтение документации ситуацию не прояснило. В связи с этим нам необходимо следить и реагировать на появление событий, которые мы не предусмотрели.

Конфигурирование устройств

Не будем долго останавливаться на процессе конфигурирования приборов, только коротко рассмотрим перечень необходимых действий. Настройка устройств Болид осуществляется при помощи утилиты UProg и имеет следующий порядок:

  1. Назначение сетевых адресов всем устройствам (РИП и С2000-ПП),

  2. Конфигурирование интерфейса интеграции С2000-ПП (Modbus RTU),

  3. Добавление ШС, описанных выше, в таблицу зон С2000-ПП. Крайне важно, чтобы, во-первых, были добавлены все ШС, а во-вторых, ШС должны следовать друг за другом в порядке возрастания.

UProg. Конфигурация С2000-ППUProg. Конфигурация С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. Перегрузка источника питания,

  3. Отключение выходного напряжения,

  4. Неисправность батареи АКБ1,

  5. Неисправность батареи АКБ2,

  6. АКБ1 разряжен,

  7. АКБ2 разряжен,

  8. Авария сети 220 В,

  9. Потеряна связь с прибором,

  10. Неизвестное состояние Status,

  11. Неизвестное состояние Iout,

  12. Неизвестное состояние Uout,

  13. Неизвестное состояние АКБ1,

  14. Неизвестное состояние АКБ2,

  15. Неизвестное состояние Capacity,

  16. Неизвестное состояние Uin,

  17. Превышено время отсутствия по 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 в картинкахПример создания узла сетиПример создания узла сети

Ссылки для импорта: Шаблон 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 RIP 12 6 80 M3 R RS EXTENDED в картинкахПоследние значения 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 RIP 12 6 80 M3 R RS EXTENDED, rip_12_mod_56.sh.

Вместо заключения

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

Однако, несмотря на все вышесказанное, возможность получения числовых значений тоже может оказаться востребованной. В этом случае можно задуматься об использовании в триггерах функций прогнозирования.

Спасибо за внимание!

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru