Javascript

时间:2015-09-08 17:24:04

标签: javascript node.js algorithm google-chrome-app

我正在使用集成了销售点(POS)设备的系统,我使用chrome serial扫描端口并能够读取信用卡数据。

我面临的问题是我需要以这种格式从字符串中连接LRC:

STX ='\ 002'(2 HEX)(文字开头)

LLL =数据长度(不包括STX或ETX,但命令)。

Command C50 {C =从PC到POS的消息,50在POS上“打印”消息的实际代码}

ETX ='\ 003'(3 HEX)(文字结束)

LRC = Longitudinal Redundancy Check

消息示例如下:

'\002014C50HELLO WORLD\003'

这里我们可以看到002为STX,014是从C50到D的长度,003是ETX。

我在C#like this onethis one甚至this one in Java中找到了一些算法,我甚至看到this question已从Google的缓存中删除了SO,其实际上也是如此因为我没有例子或答案。

我也制作了这个Java算法:

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(我知之甚少)

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();
}

在关注Wikipedia's pseudocode之后,我尝试这样做:

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的代码在chrome序列文档中就是这个:

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;
}

编辑测试结束后,我带来了这个算法,它返回一个'z'(小写),输入如下:\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);
}

然而,在尝试读取卡片数据时有一些较长的输入和特定情况,LRC有时变成Control Character,在我的情况下,我在我的String上使用它们可能是个问题。有没有办法迫使LRC避开这些角色?或者也许我做错了,这就是我将这些角色作为输出的原因。

1 个答案:

答案 0 :(得分:1)

您的基于伪代码的算法正在使用添加。对于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变量在result = result ^ number时仍然包含字符串,因此结果可能与您的预期不符。

这是一个SWAG,因为我目前没有安装Node.JS所以我无法验证它是否可行。

我要关注的另一件事是字符编码。 JavaScript使用UTF-16作为文本,因此将任何非ASCII字符转换为8位字节可能会产生意外结果。