В данной статье рассматривается пример общения шифрованными сообщениями через протокол Орион Болид. Маленький шажок для самодельного IOT популярной системы безопасности.

Введение

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

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

Существует устройство С2000-ПП для общения с 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