Javascript中的纵向冗余检查
我正在使用集成销售点(POS)设备的系统,我使用chrome串口扫描端口并能够读取信用卡数据。
我面临的问题是我需要从这个格式的string连接LRC:
STX
='\ 002'(2 HEX)(文本开始)
LLL
=数据长度(不包括STX或ETX,但命令)。
Command C50
{C =从PC到POS的消息,50在POS上“打印”消息的实际代码}
ETX
='\ 003'(3 HEX)(文本结尾)
LRC
= 纵向冗余检查
消息示例如下:
'\002014C50HELLO WORLD\003'
这里我们可以看到002为STX,014是从C50到D的长度,003是ETX。
我在C#中find了这样一个或者这个 ,甚至是Java中的一些algorithm,我甚至在Google的caching中看到了从SO上移除的这个问题 , 这个问题其实和我一样问,但没有例子或答案。
我也做了这个Javaalgorithm:
private int calculateLRC(String str) { int result = 0; for (int i = 0; i < str.length(); i++) { String char1 = str.substring(i, i + 1); char[] char2 = char1.toCharArray(); int number = char2[0]; result = result ^ number; } return result; }
并尝试将其传递给Javascript(我知之甚less)
function calculateLRC2(str) { var result = 0; for (var i = 0; i < str.length; i++) { var char1 = str.substring(i, i + 1); //var char2[] = char1.join(''); var number = char1; result = result ^ number; } return result.toString(); }
并遵循维基百科的伪代码,我试着这样做:
function calculateLRC(str) { var buffer = convertStringToArrayBuffer(str); var lrc; for (var i = 0; i < str.length; i++) { lrc = (lrc + buffer[i]) & 0xFF; } lrc = ((lrc ^ 0xFF) + 1) & 0xFF; return lrc; }
这就是我所说的上述方法:
var finalMessage = '\002014C50HELLO WORLD\003' var lrc = calculateLRC(finalMessage); console.log('lrc: ' + lrc); finalMessage = finalMessage.concat(lrc); console.log('finalMessage: ' + finalMessage);
但是,尝试所有这些方法后,我仍然无法正确地向POS发送消息。 我现在有3天的时间试图解决这个问题,除非完成,否则不能做任何事情。
有没有人知道另一种方式来计算LRC或我在这里做错了什么? 我需要它与Javascritpt,因为POS通过NodeJS与PC沟通。
哦,顺便说一句, convertStringToArrayBuffer的代码是在这个铬的序列文档:
var writeSerial=function(str) { chrome.serial.send(connectionId, convertStringToArrayBuffer(str), onSend); } // Convert string to ArrayBuffer var convertStringToArrayBuffer=function(str) { var buf=new ArrayBuffer(str.length); var bufView=new Uint8Array(buf); for (var i=0; i<str.length; i++) { bufView[i]=str.charCodeAt(i); } return buf; }
编辑testing后,我来到这个algorithm返回一个'z'(小写)与下面的input: \002007C50HOLA\003
。
function calculateLRC (str) { var bytes = []; var lrc = 0; for (var i = 0; i < str.length; i++) { bytes.push(str.charCodeAt(i)); } for (var i = 0; i < str.length; i++) { lrc ^= bytes[i]; console.log('lrc: ' + lrc); //console.log('lrcString: ' + String.fromCharCode(lrc)); } console.log('bytes: ' + bytes); return String.fromCharCode(lrc); }
然而,在尝试读取卡片数据时,如果有一些较长的input和特殊字符 ,LRC有时会变成一个控制字符 ,在我的情况下,我在string中使用它们可能是一个问题。 有没有办法强制LRC避开这些angular色? 或者,也许我做错了,这就是为什么我把这些字符作为输出。
您的基于伪代码的algorithm正在使用加法。 对于XOR版本,试试这个:
function calculateLRC(str) { var buffer = convertStringToArrayBuffer(str); var lrc = 0; for (var i = 0; i < str.length; i++) { lrc = (lrc ^ buffer[i]) & 0xFF; } return lrc; }
我认为你在XOR版本上的初始尝试失败了,因为你需要获取字符代码。 number
variables仍然包含一个string,当你result = result ^ number
,所以结果可能不是你所期望的。
这是一个SWAG,因为我目前没有安装Node.JS,所以我无法validation它会工作。
另一件我会关心的是字符编码。 JavaScript对文本使用UTF-16,所以将任何非ASCII字符转换为8位字节可能会导致意外的结果。
在阅读@Jack A.的答案并将其修改为这个之后,我用下面的方法计算了LRC问题:
function calculateLRC (str) { var bytes = []; var lrc = 0; for (var i = 0; i < str.length; i++) { bytes.push(str.charCodeAt(i)); } for (var i = 0; i < str.length; i++) { lrc ^= bytes[i]; } return String.fromCharCode(lrc); }
它做什么的解释:
第一:它将接收到的string转换为ASCII码( charCodeAt()
)。
第二:通过在上次计算的LRC(第一次迭代中的0)和每个字符的stringASCII之间执行XOR运算来计算LRC。
第三:它从ASCII转换为它的等价聊天( fromCharCode()
),并将这个字符返回给main函数(或称为它的任何函数)。