Нужна помощь в исправлении ошибок в методе проверки CRC-ITU, написанном на Javascript (node.js)

Мы пытаемся кодировать слушатель GPS устройства на Javascript.

При этом мы не можем разработать правильный сценарий для проверки ошибок CRC-ITU. Объяснение для генерации кода CRC из документа протокола приведено ниже

Контрольный код может использоваться терминалом или сервером, чтобы различать, является ли полученная информация ошибочной или нет. Для предотвращения возникновения ошибок во время передачи данных добавлена ​​проверка ошибок на предмет неправильной работы данных, чтобы повысить безопасность и эффективность системы. Контрольный код генерируется методом проверки CRC-ITU. Контрольные коды данных в структуре протокола, от длины пакета до серийного номера информации (включая "длину пакета" и "серийный номер информации"), являются значениями CRC-ITU. Ошибка CRC возникает при вычислении полученной информации, получатель игнорирует и отбрасывает пакет данных.

Мы ссылались на пример кода C, приведенный в документе протокола -

// calculate the 16-bit CRC of data with predetermined length. 

U16 GetCrc16(const U8* pData, int nLength) 
{ 
   U16 fcs = 0xffff; // initialization 
   while(nLength>0)
   { 
     fcs = (fcs >> 8) ^ crctab16[(fcs ^ *pData) & 0xff]; 
     nLength--; 
     pData++; 
   } 
   return ~fcs; // negated 
}

массив crctab16 - это тот же массив, который упоминается в нашем примере кода

    Incoming data string comes in following format

    Example of data packet sent by the terminal 78 78 0D 01 01 23 45 67 89 01 23 45 00 01 8C DD 0D 0A

    Explanation

    Start Bit - 0x78 0x78
    Length - 0x0D
    Protocol - 0x01
    Terminal ID - 0x01 0x23 0x45 0x67 0x89 0x01 0x23 0x45
    Serial No - 0x00 0x01
    Error - 0x8C 0xDD
    Stop Bit - 0x0D 0x0A

Наш код Javascript ниже

var net = require('net');

net.createServer(function(socket) 
{

    socket.setEncoding('hex');

    // New client connection event
    socket.on('connect', function(data)

    // Incoming data event
    socket.on('data', function(data) 
    {
        console.log("Client said: " + data); // server log
        data_p = data.substring(4,28);
        err_code = crc16(data_p);
        console.log("error: " + err_code);
    });


    // Disconnect event
    socket.on('end', function()
    {
        //Log it to the server output
        console.log("someone left us." + socket.remoteAddress);
    });

}).listen(3006);

console.log("TCP ECHO SERVER STARTED ON 3006");





function crc16(buf)
{

    var crcTable = 
    [
        0X0000, 0X1189, 0X2312, 0X329B, 0X4624, 0X57AD, 0X6536, 0X74BF, 0X8C48, 0X9DC1, 0XAF5A, 
        0XBED3, 0XCA6C, 0XDBE5, 0XE97E, 0XF8F7, 0X1081, 0X0108, 0X3393, 0X221A, 0X56A5, 0X472C, 
        0X75B7, 0X643E, 0X9CC9, 0X8D40, 0XBFDB, 0XAE52, 0XDAED, 0XCB64, 0XF9FF, 0XE876, 0X2102, 
        0X308B, 0X0210, 0X1399, 0X6726, 0X76AF, 0X4434, 0X55BD, 0XAD4A, 0XBCC3, 0X8E58, 0X9FD1, 
        0XEB6E, 0XFAE7, 0XC87C, 0XD9F5, 0X3183, 0X200A, 0X1291, 0X0318, 0X77A7, 0X662E, 0X54B5, 
        0X453C, 0XBDCB, 0XAC42, 0X9ED9, 0X8F50, 0XFBEF, 0XEA66, 0XD8FD, 0XC974, 0X4204, 0X538D, 
        0X6116, 0X709F, 0X0420, 0X15A9, 0X2732, 0X36BB, 0XCE4C, 0XDFC5, 0XED5E, 0XFCD7, 0X8868, 
        0X99E1, 0XAB7A, 0XBAF3, 0X5285, 0X430C, 0X7197, 0X601E, 0X14A1, 0X0528, 0X37B3, 0X263A, 
        0XDECD, 0XCF44, 0XFDDF, 0XEC56, 0X98E9, 0X8960, 0XBBFB, 0XAA72, 0X6306, 0X728F, 0X4014, 
        0X519D, 0X2522, 0X34AB, 0X0630, 0X17B9, 0XEF4E, 0XFEC7, 0XCC5C, 0XDDD5, 0XA96A, 0XB8E3, 
        0X8A78, 0X9BF1, 0X7387, 0X620E, 0X5095, 0X411C, 0X35A3, 0X242A, 0X16B1, 0X0738, 0XFFCF, 
        0XEE46, 0XDCDD, 0XCD54, 0XB9EB, 0XA862, 0X9AF9, 0X8B70, 0X8408, 0X9581, 0XA71A, 0XB693, 
        0XC22C, 0XD3A5, 0XE13E, 0XF0B7, 0X0840, 0X19C9, 0X2B52, 0X3ADB, 0X4E64, 0X5FED, 0X6D76, 
        0X7CFF, 0X9489, 0X8500, 0XB79B, 0XA612, 0XD2AD, 0XC324, 0XF1BF, 0XE036, 0X18C1, 0X0948, 
        0X3BD3, 0X2A5A, 0X5EE5, 0X4F6C, 0X7DF7, 0X6C7E, 0XA50A, 0XB483, 0X8618, 0X9791, 0XE32E, 
        0XF2A7, 0XC03C, 0XD1B5, 0X2942, 0X38CB, 0X0A50, 0X1BD9, 0X6F66, 0X7EEF, 0X4C74, 0X5DFD, 
        0XB58B, 0XA402, 0X9699, 0X8710, 0XF3AF, 0XE226, 0XD0BD, 0XC134, 0X39C3, 0X284A, 0X1AD1, 
        0X0B58, 0X7FE7, 0X6E6E, 0X5CF5, 0X4D7C, 0XC60C, 0XD785, 0XE51E, 0XF497, 0X8028, 0X91A1, 
        0XA33A, 0XB2B3, 0X4A44, 0X5BCD, 0X6956, 0X78DF, 0X0C60, 0X1DE9, 0X2F72, 0X3EFB, 0XD68D, 
        0XC704, 0XF59F, 0XE416, 0X90A9, 0X8120, 0XB3BB, 0XA232, 0X5AC5, 0X4B4C, 0X79D7, 0X685E, 
        0X1CE1, 0X0D68, 0X3FF3, 0X2E7A, 0XE70E, 0XF687, 0XC41C, 0XD595, 0XA12A, 0XB0A3, 0X8238, 
        0X93B1, 0X6B46, 0X7ACF, 0X4854, 0X59DD, 0X2D62, 0X3CEB, 0X0E70, 0X1FF9, 0XF78F, 0XE606, 
        0XD49D, 0XC514, 0XB1AB, 0XA022, 0X92B9, 0X8330, 0X7BC7, 0X6A4E, 0X58D5, 0X495C, 0X3DE3, 
        0X2C6A, 0X1EF1, 0X0F78
    ];


    crcX = parseInt("FFFF",16);
    cr1 = parseInt("FF",16);
    cr2 = parseInt("FFFF",16);
    i = 0;

    while(i < buf.length)
    {
        str = buf.substring(i,i+4);
        console.log("str "+str);
        str_hex = parseInt(str,16);

        j = (crcX ^ str_hex) & cr1;
        crcX = (crcX >> 8) ^ crcTable[j] ;

        i = i + 4;
    }

    crcX = ~crcX;

    console.log("crcX - " + crcX.toString(16));
    return crcX;
}

Ниже приведены пары входных строк и соответствующий код, который должен быть сгенерирован функцией crc16.

    78780d01035889905017664600267bf90d0a - 7bf9
    78780d010358899050176646002ab1950d0a - b195
    78780d010358899050176646002ba01c0d0a - a01c

Пожалуйста, помогите нам найти ошибки в нашем коде.

Большое спасибо.

4 ответа

Решение

~ в оригинальном коде работал только потому, что это был 16-битный тип. Вы должны использовать crcX = crcX ^ 0xffff вместо crcX = ~crcX,

Также ваш buf.substring(i,i+4) а также i = i + 4 неправильно. Вам нужно обрабатывать один байт за раз, то есть две шестнадцатеричные цифры. Те, и другие должны быть i+2,

Есть некоторые crc пакеты на npm, но они могут не работать для вас, я создаю новый, который является просто копией c код из вашей ссылки на документ.

устанавливать crc-itu от терминала:

npm install crc-itu

app.js

var crc16 = require('crc-itu').crc16;

var crcInHex = crc16('0d0103588990501766460026', 'hex').toString(16);
console.log(crcInHex); // will print 7bf9

Вы также можете попробовать с этими значениями, обратите внимание: crc16(data).toString(16) => crc

start          data              crc   end
-------------------------------------------
7878   0d0103588990501766460026  7bf9  0d0a
7878   0d010358899050176646002a  b195  0d0a
7878   0d010358899050176646002b  a01c  0d0a

Нашел очень мало ссылок на вычисления CRC 16, но нашел текущий ответ в javascript полезным.

В случае, если кто-то ищет тот же расчет CRC 16 с использованием Python, создайте публичный гист вместе с примером рабочего скрипта Python:

https://gist.github.com/mrudang-vora/6a0767be085a275c0df3

Надеюсь, это поможет кому-то.

Это мой код

var net = require('net');

var HOST = '192.168.1.151';
var PORT = 5023;


function protocall_decorder(data,sbit,plength,protono,ebit){

// Login data   
if(plength.toString('hex') == '0d') {
    var ret = crc16Ccitt(data.slice(2,14));
    var err_code = ret;
    console.log(err_code.toString(16));
    plength = new Buffer('05','hex');
    var res = sbit + plength + protono + data.slice(12,14) + err_code.toString(16) + ebit;

    data = "device_imei: " + parseInt(data.slice(4,12).toString('hex'));
    console.log(data);


    res = new Buffer(res)
    var dataArr = {response:res, type:"login", data:data};
}
/*
// Location data
else if(plength == '1F') {
    var res = '787805' + ***** +  data.slice(60,64) + data.slice(24,28) +'D9DC' + '0D0A';
    dataArr = data.substring(2);
}

// Alarm data
else if(plength == '25') {
    dataArr = data.substring(2);
}
// Heart Beat
else if(plength == '08') {
    dataArr = data.substring(2);
}
// Undefined data length
*/
else {
    var dataArr = {response:"error", data:plength};
}


return dataArr;

}

// The sock object the callback function receives UNIQUE for each connection
net.createServer(function(sock) {

// We have a connection - a socket object is assigned to the connection automatically
console.log('CONNECTED: ' + sock.remoteAddress +':'+ sock.remotePort);

// Add a 'data' event handler to this instance of socket
sock.on('data', function(data) {

    console.log('DATA ' + sock.remoteAddress + ': ' + data);
    // Write the data back to the socket, the client will receive it as data from the server


//////////////// MySQL | Begin ////////////////////
var mysql      = require('mysql');
var con = mysql.createConnection({
    host     : 'localhost',
    user     : 'root',
    password : 'lahirutm',
    database : 'gt06n'
});
con.connect();


var sbit = data.slice(0,2);
var plength = data.slice(2,3);
var protono = data.slice(3,4);
var ebit = data.slice(-2)

if(sbit.toString('hex') == '7878') {
    var res = protocall_decorder(data,sbit,plength,protono,ebit);
    if(res['response'] != 'error') {
        sock.write(res['response']);
        var response = res['response'];
    }
}
else {
    console.log('Undefined protocol data');
}

console.log(response); // Write data to socket

var message  = {start_bit: sbit, packet_length: plength, proto_no: protono, serial:'*', end_bit: ebit};
var query = con.query('INSERT INTO incoming_data SET ?', message,
//var message = {data: data} 
//var query = con.query('INSERT INTO row_data SET ?', message,
function(err, result) {
        // Neat!
});
console.log(query.sql);

var message = {data: data} 
var query = con.query('INSERT INTO row_data SET ?', message,
function(err, result) {
        // Neat!
});
console.log(query.sql);
con.end();
///////////////  MySQL | Begin ////////////////

});

// Add a 'close' event handler to this instance of socket
sock.on('close', function(data) {
    console.log('CLOSED: ' + sock.remoteAddress +' '+ sock.remotePort);
});

}).listen(PORT, HOST);

console.log('Server listening on ' + HOST +':'+ PORT);



/**
* CRC functions
*/

var crc16CcittTableReverse = [
    0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
    0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
    0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
    0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
    0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
    0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
    0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
    0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
    0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
    0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
    0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
    0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
    0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
    0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
    0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
    0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
    0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
    0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
    0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
    0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
    0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
    0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
    0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
    0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
    0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
    0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
    0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
    0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
    0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
    0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
    0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
    0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78
];


var crc16CcittStart = 0xFFFF;
var crc16CcittXorout = 0xFFFF;

function crc16Reflected(buf, crc_in, table) {
    var crc16 = crc_in;

    for (i = 0; i < buf.length; i++) {
        crc16 = table[(crc16 ^ buf[i]) & 0xff] ^ (crc16 >> 8);
    }

    return crc16 & 0xFFFF;
}

function crc16Ccitt(buf) {
    return crc16Reflected(buf, crc16CcittStart, crc16CcittTableReverse) ^ crc16CcittXorout;
}

В случае использования java

  public static void main(String[] args) {
  String sample_string ="78 78 0D 01 01 23 45 67 89 01 23 45 00 01 8C DD 0D 
  0A";
  String[] data_packet = packet.split(" ");
  String[] pdata = Arrays.copyOfRange(data_packet, 2, data_packet.length - 4);
  //pdata will be from "packet-length" to "Information Serial Nummber"
  //discarding "start-bit" from start and "Error-check" and "Stop Bit" from end
  //actual pdata[]={0D,01,01,23,45,67,89,01,23,45,00,01};
  String error_code = crc16(pdata);
  System.out.println("================>Error_code:" + error_code);

  }
  public String crc16(String[] pdata) {

    int[] crcTable
            = {
                0X0000, 0X1189, 0X2312, 0X329B, 0X4624, 0X57AD, 0X6536, 0X74BF, 0X8C48, 0X9DC1, 0XAF5A,
                0XBED3, 0XCA6C, 0XDBE5, 0XE97E, 0XF8F7, 0X1081, 0X0108, 0X3393, 0X221A, 0X56A5, 0X472C,
                0X75B7, 0X643E, 0X9CC9, 0X8D40, 0XBFDB, 0XAE52, 0XDAED, 0XCB64, 0XF9FF, 0XE876, 0X2102,
                0X308B, 0X0210, 0X1399, 0X6726, 0X76AF, 0X4434, 0X55BD, 0XAD4A, 0XBCC3, 0X8E58, 0X9FD1,
                0XEB6E, 0XFAE7, 0XC87C, 0XD9F5, 0X3183, 0X200A, 0X1291, 0X0318, 0X77A7, 0X662E, 0X54B5,
                0X453C, 0XBDCB, 0XAC42, 0X9ED9, 0X8F50, 0XFBEF, 0XEA66, 0XD8FD, 0XC974, 0X4204, 0X538D,
                0X6116, 0X709F, 0X0420, 0X15A9, 0X2732, 0X36BB, 0XCE4C, 0XDFC5, 0XED5E, 0XFCD7, 0X8868,
                0X99E1, 0XAB7A, 0XBAF3, 0X5285, 0X430C, 0X7197, 0X601E, 0X14A1, 0X0528, 0X37B3, 0X263A,
                0XDECD, 0XCF44, 0XFDDF, 0XEC56, 0X98E9, 0X8960, 0XBBFB, 0XAA72, 0X6306, 0X728F, 0X4014,
                0X519D, 0X2522, 0X34AB, 0X0630, 0X17B9, 0XEF4E, 0XFEC7, 0XCC5C, 0XDDD5, 0XA96A, 0XB8E3,
                0X8A78, 0X9BF1, 0X7387, 0X620E, 0X5095, 0X411C, 0X35A3, 0X242A, 0X16B1, 0X0738, 0XFFCF,
                0XEE46, 0XDCDD, 0XCD54, 0XB9EB, 0XA862, 0X9AF9, 0X8B70, 0X8408, 0X9581, 0XA71A, 0XB693,
                0XC22C, 0XD3A5, 0XE13E, 0XF0B7, 0X0840, 0X19C9, 0X2B52, 0X3ADB, 0X4E64, 0X5FED, 0X6D76,
                0X7CFF, 0X9489, 0X8500, 0XB79B, 0XA612, 0XD2AD, 0XC324, 0XF1BF, 0XE036, 0X18C1, 0X0948,
                0X3BD3, 0X2A5A, 0X5EE5, 0X4F6C, 0X7DF7, 0X6C7E, 0XA50A, 0XB483, 0X8618, 0X9791, 0XE32E,
                0XF2A7, 0XC03C, 0XD1B5, 0X2942, 0X38CB, 0X0A50, 0X1BD9, 0X6F66, 0X7EEF, 0X4C74, 0X5DFD,
                0XB58B, 0XA402, 0X9699, 0X8710, 0XF3AF, 0XE226, 0XD0BD, 0XC134, 0X39C3, 0X284A, 0X1AD1,
                0X0B58, 0X7FE7, 0X6E6E, 0X5CF5, 0X4D7C, 0XC60C, 0XD785, 0XE51E, 0XF497, 0X8028, 0X91A1,
                0XA33A, 0XB2B3, 0X4A44, 0X5BCD, 0X6956, 0X78DF, 0X0C60, 0X1DE9, 0X2F72, 0X3EFB, 0XD68D,
                0XC704, 0XF59F, 0XE416, 0X90A9, 0X8120, 0XB3BB, 0XA232, 0X5AC5, 0X4B4C, 0X79D7, 0X685E,
                0X1CE1, 0X0D68, 0X3FF3, 0X2E7A, 0XE70E, 0XF687, 0XC41C, 0XD595, 0XA12A, 0XB0A3, 0X8238,
                0X93B1, 0X6B46, 0X7ACF, 0X4854, 0X59DD, 0X2D62, 0X3CEB, 0X0E70, 0X1FF9, 0XF78F, 0XE606,
                0XD49D, 0XC514, 0XB1AB, 0XA022, 0X92B9, 0X8330, 0X7BC7, 0X6A4E, 0X58D5, 0X495C, 0X3DE3,
                0X2C6A, 0X1EF1, 0X0F78
            };

    int crcX = 0xFFFF;
    int cr1 = 0xFF;
    int cr2 = 0xFFFF;
    int i = 0;
    int j;

    while (i < pdata.length) {
        String str = pdata[i];

        int str_hex = Integer.parseInt(str, 16);

        j = (crcX ^ str_hex) & cr1;
        crcX = (crcX >> 8) ^ crcTable[j];

        i++;
    }
Другие вопросы по тегам