Есть небольшая проблема с нахождением алгоритма подсчета CRC в протоколе от охранных панелей
Hunter Pro 832 от израильского производителя PIMA Alarms.
За чем мне это нужно? Есть идея сфарганить беспроводной индикатор состояния зон. Нужен он
для облегчения проведения регламентных проверок ОПС на крупных объектах. То есть, имея на руках
индикатор, можно проверять выдачу тревожного сигнала на ППКОП прямо на месте установки датчика без
звонков напарнику и криков через весь объект. Тем самым удостовериться, что конкретный датчик действительно обрывает шлейф.
Индикатор должен точно показывать то, что передает панель, потому обработка контрольной суммы важна.
Изучение протокола Huntera началось с ковыряния протокола его младшего собрата Captain-6
потому что тот был у меня под рукой. Вооружившись осциллографом и сев им на шину keybus (к которой подключается выносная клавиатура) я выяснил, что шина представляет собой обычный UART, только с напряжениями 0V-12V, работающий на скорости 2400 бод.
Спаяв переходник на трех транзисторах я приступил к сбору данных. После изучения состава пакетов, я нашел поле с контрольной суммой
и алгоритм подсчета благополучно разобрал. Там было все просто. CRC8 формируется методом сложения всех байтов пакета и числа 0x62.
Когда добрался до протокола Хантера, то сначала показалось, что и с его протоколом я разобрался. Выбрал два пакета из кучи,
посмотрел, какое поле реагирует на изменение любых данных и принял его за CRC. Посчитал, нашел init значение, посчитал второй пакет - все сходится. Выбрал из кучи еще пару пакетов и тут снова ступор. CRC не считается. Есть подозрение, что там вообще CRC16. Не знаю,
другие алгоритмы не пробовал, но заметил, что сложение всех байтов там всетаки используется. Достаточно обратить внимание на отличие контрольных сумм первых двух пакетов и самого содержимого этих двух пакетов. Разница между ними в том, что отличаются они только одним байтом. В одном этот байт равен нулю, во втором равен 0x03. И контрольные суммы этих двух пакетов отличаются на три. (CRC2 = CRC1 + 3)
Протокол мучаю в скрипте, написанном на Lua 5.3.3. Это последняя версия этого языка.
Поддерживает нативно битовые операции и сами операторы имеют Сишный синтаксис. Отличие только в операторе "^" В Lua он служит для возведения в степень.
Спойлер
Код: Выделить всё
-----------------------------------------------
--
DataArr =
{
device = "Hunter Pro 832",
{ -- 1
0xDB, -- Start
0xFF,
0xFE,
0x00, 0x01,
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0xFF, 0x2D, 0x2D, 0x4F, 0x4F, -- LCD string 1
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0xFF, 0xFF, -- LCD string 2
0x00, 0x61, 0x10, 0x00, 0x00, 0x10,
0xE4, -- CRC init 0x0B
0x46, -- CRC ?
0xDC, -- Stop
},
{
0xDB, -- Start
0xFF,
0xFE,
0x00, 0x01,
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0xFF, 0x2D, 0x2D, 0x4F, 0x4F, -- LCD string 1
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0xFF, 0xFF, -- LCD string 2
0x00, 0x61, 0x10, 0x00, 0x03, 0x10,
0xE7, -- CRC init 0x0B
0x46, -- CRC ?
0xDC, -- Stop
},
{ -- 2
0xDB, -- Start
0xFF,
0xFE,
0x00, 0x01,
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0xFF, 0x2D, 0xFF, 0x41, 0x41, -- LCD string 1
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0xFF, 0xFF, -- LCD string 2
0x00, 0xA1, 0x10, 0x00, 0x00, 0x10,
0x5B, -- CRC init 0x8C
0xCA, -- CRC ?
0xDC, -- Stop
},
{
0xDB, -- Start
0xFF,
0xFE,
0x00, 0x01,
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0xFF, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0xFF, 0x2D, 0x2D, 0x4F, 0x4F, -- LCD string 1
0x2D, 0x2D, 0xFF, 0xFF, 0x2D, 0x2D, 0x2D, 0xFF, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0xFF, 0xFF, -- LCD string 2
0x00, 0x61, 0x10, 0x31, 0x03, 0x10,
0xC6, -- CRC init
0xCA, -- CRC ?
0xDC, -- Stop
},
{ -- 3
0xDB, -- Start
0xFF,
0xFE,
0x00, 0x01,
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0xFF, 0x2D, 0xFF, 0x4F, 0x4F, -- LCD string 1
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0xFF, 0xFF, -- LCD string 2
0x00, 0xA1, 0x10, 0x00, 0x03, 0x10,
0x69, -- CRC init 0xA0
0x98, -- CRC ?
0xDC, -- Stop
},
{
0xDB, -- Start
0xFF,
0xFE,
0x00, 0x01,
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0xFF, 0x2D, 0x41, 0x2D, 0x2D, 0x2D, 0x2D, 0x41, 0x4F, 0x4F, -- LCD string 1
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0xFF, -- LCD string 2
0x00, 0x61, 0x10, 0x00, 0x01, 0x10,
0x3D, -- CRC init
0x98, -- CRC ?
0xDC, -- Stop
}
};
---------------------------------------------------------------
function ToBit(toBit, varSize)
if(varSize == nil) then
varSize = 8;
end
local toBitString = "";
for i = (varSize - 1), 0, -1 do
toBitString = toBitString..tostring((toBit & (2^i)) >> i);
end
return toBitString;
end
---------------------------------------------------------------
-- BEGIN EXECUTION CODE --
---------------------------------------------------------------
print("Control 130 = 10000010 : "..ToBit(130));
print("Control 130 xor 3 = 10000001 : "..ToBit((130 ~ 3)));
for ind = 1, #DataArr, 1 do
local CRC = 0x0B;
local lcdStr01 = "";
local lcdStr02 = "";
print("\n-----------------------------------------------");
---- Calculate CRC8
for i = 2, (#DataArr[ind] - 3), 1 do
CRC = CRC + DataArr[ind][i];
end
--CRC = CRC + DataArr[ind][(#DataArr[ind] - 1)] + DataArr[ind][#DataArr[ind]];
CRC = CRC & 0x000000FF;
print(string.format("Device: %s\nind = %d\nCRC real: 0x%02X\nCRC calculated: 0x%02X",
DataArr.device,
ind,
DataArr[ind][#DataArr[ind] - 2],
CRC));
---- Create LCD data
for i = 6, (32 + 5), 1 do
if(DataArr[ind][i] == 0xFF) then
DataArr[ind][i] = 0xDB;
end
if(i <= (16 + 5)) then
lcdStr01 = lcdStr01..string.char(DataArr[ind][i]);
else
lcdStr02 = lcdStr02..string.char(DataArr[ind][i]);
end
end
print("\n LCD indicator: ");
print(" \xDA\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xBF");
print(" \xB3"..lcdStr01.."\xB3");
print(" \xB3"..lcdStr02.."\xB3");
print(" \xC0\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xD9\n");
print("OTHER:");
for i = 4, 5, 1 do
print(string.format("%d = %s", i, ToBit(DataArr[ind][i])));
end
print(" ");
for i = 38, 43, 1 do
print(string.format("%d = %s", i, ToBit(DataArr[ind][i])));
end
end
print("-----------------------------------------------");
--os.execute("PAUSE NULL");
Спойлер
Код: Выделить всё
Control 130 = 10000010 : 10000010
Control 130 xor 3 = 10000001 : 10000001
-----------------------------------------------
Device: Hunter Pro 832
ind = 1
CRC real: 0xE4
CRC calculated: 0xE4
LCD indicator:
┌────────────────┐
│-----------█--OO│
│--------------██│
└────────────────┘
OTHER:
4 = 00000000
5 = 00000001
38 = 00000000
39 = 01100001
40 = 00010000
41 = 00000000
42 = 00000000
43 = 00010000
-----------------------------------------------
Device: Hunter Pro 832
ind = 2
CRC real: 0xE7
CRC calculated: 0xE7
LCD indicator:
┌────────────────┐
│-----------█--OO│
│--------------██│
└────────────────┘
OTHER:
4 = 00000000
5 = 00000001
38 = 00000000
39 = 01100001
40 = 00010000
41 = 00000000
42 = 00000011
43 = 00010000
-----------------------------------------------
Device: Hunter Pro 832
ind = 3
CRC real: 0x5B
CRC calculated: 0xDA
LCD indicator:
┌────────────────┐
│-----------█-█AA│
│--------------██│
└────────────────┘
OTHER:
4 = 00000000
5 = 00000001
38 = 00000000
39 = 10100001
40 = 00010000
41 = 00000000
42 = 00000000
43 = 00010000
-----------------------------------------------
Device: Hunter Pro 832
ind = 4
CRC real: 0xC6
CRC calculated: 0x60
LCD indicator:
┌────────────────┐
│-----█-----█--OO│
│--██---█------██│
└────────────────┘
OTHER:
4 = 00000000
5 = 00000001
38 = 00000000
39 = 01100001
40 = 00010000
41 = 00110001
42 = 00000011
43 = 00010000
-----------------------------------------------
Device: Hunter Pro 832
ind = 5
CRC real: 0x69
CRC calculated: 0xF9
LCD indicator:
┌────────────────┐
│-----------█-█OO│
│--------------██│
└────────────────┘
OTHER:
4 = 00000000
5 = 00000001
38 = 00000000
39 = 10100001
40 = 00010000
41 = 00000000
42 = 00000011
43 = 00010000
-----------------------------------------------
Device: Hunter Pro 832
ind = 6
CRC real: 0x3D
CRC calculated: 0x3B
LCD indicator:
┌────────────────┐
│------█-A----AOO│
│---------------█│
└────────────────┘
OTHER:
4 = 00000000
5 = 00000001
38 = 00000000
39 = 01100001
40 = 00010000
41 = 00000000
42 = 00000001
43 = 00010000
-----------------------------------------------
В аттаче лежит архив со скриптом, интерпретатором и батником для запуска.