Продольная проверка избыточности в Javascript
Я работаю с системой, которая включает в себя устройство Point of Sell (POS), я использую chrome serial для сканирования портов и возможности чтения данных кредитных карт.
Проблема, с которой я сталкиваюсь, заключается в том, что мне нужно объединить LRC из строки в следующем формате:
STX
= '\ 002' (2 HEX) (начало текста)
LLL
= Длина данных (не включает STX или ETX, но команда).
Command C50
{C = сообщение от ПК к POS, 50 фактический код, который "печатает" сообщение на POS}
ETX
= '\ 003' (3 HEX) (конец текста)
LRC
= Продольная проверка избыточности
Пример сообщения будет следующим:
'\002014C50HELLO WORLD\003'
Здесь мы можем видеть 002 как STX, 014 - длину от C50 до D и 003 как ETX.
Я нашел некоторые алгоритмы в C#, такие как этот или этот, и даже этот в Java, я даже видел этот вопрос, который был удален из SO в кеше Google, который фактически спрашивает то же, что и я, но у меня не было примеров или ответов.
Я также сделал этот алгоритм 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();
}
и после псевдокода Википедии я попытался сделать это:
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.
О, кстати, код от 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 иногда становится управляющим символом, что в моем случае, если я использую их в своей строке, может быть проблемой. Есть ли способ заставить LRC избегать этих персонажей? Или, возможно, я делаю это неправильно, и именно поэтому у меня есть эти символы в качестве вывода.
2 ответа
Я решил проблему LRC, рассчитав ее следующим методом, прочитав ответ @Jack A. и изменив его на этот:
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);
}
Объяснение того, что он делает:
1-е: преобразует полученную строку в эквивалент ASCII (charCodeAt()
).
2-й: он вычисляет LRC, выполняя операцию XOR между последним вычисленным LRC (0 на 1-й итерации) и ASCII строки для каждого символа.
3-е: он конвертирует из ASCII в эквивалентный чат (fromCharCode()
) и возвращает этот символ в основную функцию (или любую функцию, которая ее назвала).
Ваш алгоритм на основе псевдокода использует сложение. Для версии 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-битные байты может дать неожиданные результаты.