我们正在尝试使用Javascript编写GPS设备侦听器代码。
在执行此操作时,我们无法为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
请帮助我们在代码中找到错误。
非常感谢。
答案 0 :(得分:3)
原始代码中的~
仅起作用,因为它是16位类型。您应该使用crcX = crcX ^ 0xffff
代替crcX = ~crcX
。
您的buf.substring(i,i+4)
和i = i + 4
也是错误的。您需要一次处理一个字节,即两个十六进制数字。这些都应该是i+2
。
答案 1 :(得分: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
答案 2 :(得分:0)
这是我的代码
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;
}
答案 3 :(得分:0)
在CRC 16计算中找到很少的链接,但发现javascript中的current answer很有帮助。
如果有人正在使用python寻找相同的CRC 16计算,那么创建公共要点以及工作python小提琴示例:
https://gist.github.com/mrudang-vora/6a0767be085a275c0df3
希望它有所帮助。
答案 4 :(得分:0)
如果使用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++;
}