我如何 encode/decode 这个专有校验和(Athena 16C PID 控制器)?
How can I encode/decode this proprietary checksum (Athena 16C PID controller)?
我有一个通过 RS232 控制的 Athena 16C 控制器。它的消息传递协议需要专有校验和:
"CHKSUM:这是一个双字符消息代码编号系统,表示消息中所有字符(不包括 START、CHAR、END CHAR 和 CHKSM 本身)的所有 ASCII 值的总和。使用以下公式计算总和:
CHKSM = SUM(All Message Characters)%256 其中 % 表示取模运算符。"
示例消息(来自他们的文档)是这样的:
$Ø1Ø1RØ5C1<CR>
又可以分解为:
$ [START CHAR] 01 [ID] 01 [ZONE] R [TYPE] 05 [PARAM] C1 [CHKSM] <CR> [END CHAR]
我已将此消息发送到控制器,它按预期工作。
我正在用 JS 编写我的代码,并且有以下应该计算 CHKSM 的信息放在消息的末尾:
var sum = 'Ø1Ø1RØ5'
.split('')
.map(function(char) {
return char.charCodeAt(0);
})
.reduce(function(current, previous) {
return previous + current;
});
var chksm = (sum % 256);
console.log(chksm.toString(16));
根据消息格式,校验和应该是'C1'。但是计算出的总和是 377,这导致校验和为 121,等于十六进制的 79。
// 0 = 48, 1 = 49, R = 82, 5 = 53 (ASCII values)
// 48 + 49 + 48 + 49 + 82 + 48 + 53 = 377
// 377 % 256 = 121 (decimal) = 79 (hex)
Athena 的一位工程师向我发送了以下 VB 代码,但我无法理解其中的逻辑,尤其是语法。一般而言,这个问题是否缺少一些基本的东西?
' Covert the mod % 256 checksum to the 2 chars:
' Will set First and Second chars for encoded value. Pass in the value (Checksum mod 256)
' and where to return the 1st and 2nd chars to.
Public Sub EncodeIt(ByVal Value As Integer, ByRef FirstChar As Integer, ByRef SecondChar As Integer)
If Value > 359 Then 'Z9 = 359, absolute max possible
Value = 359
End If
'Note: backslash '\' means integer divide, not floating point!!
If Value > 99 Then
FirstChar = (Value \ 10) + 65 - 10 '65 = ascii "A"
Else
FirstChar = (Value \ 10) + 48 '48 = ascii "0"
End If
SecondChar = (Value Mod 10) + 48
End Sub
' Convert the two chars received in a message back to normal integer.
' Take the 2 chars and return a decoded integer value
Public Function DecodeIt(ByVal FirstChar As Integer, ByVal SecondChar As Integer) As Integer
'65 = ascii "A", 48 = ascii "0"
If FirstChar > 57 Then '57 = ascii "9"
Return ((FirstChar - 65 + 10) * 10) + (SecondChar - 48)
Else
Return ((FirstChar - 48) * 10) + (SecondChar - 48)
End If
End Function
十进制到字符串的编码是自定义的,不是base16。这就是 (121).toString(16)
不等于 C1
的原因。
从 post 的 VBA 中, encoding/decoding 函数应该是:
function compute_checksum(message) {
var sum = 0;
for(var i=0; i<message.length; i++)
sum += message.charCodeAt(i);
return sum % 256;
}
function encode_checksum(value) {
value = Math.min(value, 359);
var c1 = ((value / 10) | 0) + (value > 99 ? 55 : 48);
var c2 = (value % 10) + 48;
return String.fromCharCode(c1, c2);
}
function decode_checksum(text) {
var c1 = text.charCodeAt(0);
var c2 = text.charCodeAt(1);
return (c1 > 57 ? c1 - 55 : c1 - 48) * 10 + (c2 - 48)
}
这是一个用法示例:
var checksum = compute_checksum('0101R05');
console.log('checksum: ' + checksum);
var CHKSM = encode_checksum(checksum);
console.log('encoded checksum: ' + CHKSM);
console.log('decoded checksum: ' + decode_checksum(CHKSM));
我刚刚为 C# 完成了这个,并在上面的帮助下,想出了这个有效的代码(对我来说):
'reqtemp' 是包含控制器 ID#、区域、参数等的字符串,没有起始字符和校验和字符。
// generate checksum for Athena
int x = 0;
int sl = reqtemp.Length;
int FirstChar = 0; //checksum 1st character
int SecondChar = 0; //checksum 2nd char
string crcr; // crc for requests
for (int c = 0; c < sl; c++)
{
string sel = reqtemp.Substring(c, 1);
x = x + Convert.ToChar(sel);
}
x = x % 256; //modular 256
x = Math.Min(x, 359); // don't allow > 359
if (x > 99)
{ FirstChar = (x / 10) + 65 - 10; }
else
{ FirstChar = (x / 10) + 48; }
SecondChar = (x % 10) + 48;
crcr = Char.ConvertFromUtf32(FirstChar) + Char.ConvertFromUtf32(SecondChar);
// MessageBox.Show(crcr);
string reqtempfull = "$"+ reqtemp + crcr + (char)13;
crc.Text = reqtempfull; //display the full sp string
if (ComPort.IsOpen)
{
ComPort.Write(reqtempfull); // send it`enter code here`
}
我有一个通过 RS232 控制的 Athena 16C 控制器。它的消息传递协议需要专有校验和:
"CHKSUM:这是一个双字符消息代码编号系统,表示消息中所有字符(不包括 START、CHAR、END CHAR 和 CHKSM 本身)的所有 ASCII 值的总和。使用以下公式计算总和: CHKSM = SUM(All Message Characters)%256 其中 % 表示取模运算符。"
示例消息(来自他们的文档)是这样的:
$Ø1Ø1RØ5C1<CR>
又可以分解为:
$ [START CHAR] 01 [ID] 01 [ZONE] R [TYPE] 05 [PARAM] C1 [CHKSM] <CR> [END CHAR]
我已将此消息发送到控制器,它按预期工作。
我正在用 JS 编写我的代码,并且有以下应该计算 CHKSM 的信息放在消息的末尾:
var sum = 'Ø1Ø1RØ5'
.split('')
.map(function(char) {
return char.charCodeAt(0);
})
.reduce(function(current, previous) {
return previous + current;
});
var chksm = (sum % 256);
console.log(chksm.toString(16));
根据消息格式,校验和应该是'C1'。但是计算出的总和是 377,这导致校验和为 121,等于十六进制的 79。
// 0 = 48, 1 = 49, R = 82, 5 = 53 (ASCII values)
// 48 + 49 + 48 + 49 + 82 + 48 + 53 = 377
// 377 % 256 = 121 (decimal) = 79 (hex)
Athena 的一位工程师向我发送了以下 VB 代码,但我无法理解其中的逻辑,尤其是语法。一般而言,这个问题是否缺少一些基本的东西?
' Covert the mod % 256 checksum to the 2 chars:
' Will set First and Second chars for encoded value. Pass in the value (Checksum mod 256)
' and where to return the 1st and 2nd chars to.
Public Sub EncodeIt(ByVal Value As Integer, ByRef FirstChar As Integer, ByRef SecondChar As Integer)
If Value > 359 Then 'Z9 = 359, absolute max possible
Value = 359
End If
'Note: backslash '\' means integer divide, not floating point!!
If Value > 99 Then
FirstChar = (Value \ 10) + 65 - 10 '65 = ascii "A"
Else
FirstChar = (Value \ 10) + 48 '48 = ascii "0"
End If
SecondChar = (Value Mod 10) + 48
End Sub
' Convert the two chars received in a message back to normal integer.
' Take the 2 chars and return a decoded integer value
Public Function DecodeIt(ByVal FirstChar As Integer, ByVal SecondChar As Integer) As Integer
'65 = ascii "A", 48 = ascii "0"
If FirstChar > 57 Then '57 = ascii "9"
Return ((FirstChar - 65 + 10) * 10) + (SecondChar - 48)
Else
Return ((FirstChar - 48) * 10) + (SecondChar - 48)
End If
End Function
十进制到字符串的编码是自定义的,不是base16。这就是 (121).toString(16)
不等于 C1
的原因。
从 post 的 VBA 中, encoding/decoding 函数应该是:
function compute_checksum(message) {
var sum = 0;
for(var i=0; i<message.length; i++)
sum += message.charCodeAt(i);
return sum % 256;
}
function encode_checksum(value) {
value = Math.min(value, 359);
var c1 = ((value / 10) | 0) + (value > 99 ? 55 : 48);
var c2 = (value % 10) + 48;
return String.fromCharCode(c1, c2);
}
function decode_checksum(text) {
var c1 = text.charCodeAt(0);
var c2 = text.charCodeAt(1);
return (c1 > 57 ? c1 - 55 : c1 - 48) * 10 + (c2 - 48)
}
这是一个用法示例:
var checksum = compute_checksum('0101R05');
console.log('checksum: ' + checksum);
var CHKSM = encode_checksum(checksum);
console.log('encoded checksum: ' + CHKSM);
console.log('decoded checksum: ' + decode_checksum(CHKSM));
我刚刚为 C# 完成了这个,并在上面的帮助下,想出了这个有效的代码(对我来说): 'reqtemp' 是包含控制器 ID#、区域、参数等的字符串,没有起始字符和校验和字符。
// generate checksum for Athena
int x = 0;
int sl = reqtemp.Length;
int FirstChar = 0; //checksum 1st character
int SecondChar = 0; //checksum 2nd char
string crcr; // crc for requests
for (int c = 0; c < sl; c++)
{
string sel = reqtemp.Substring(c, 1);
x = x + Convert.ToChar(sel);
}
x = x % 256; //modular 256
x = Math.Min(x, 359); // don't allow > 359
if (x > 99)
{ FirstChar = (x / 10) + 65 - 10; }
else
{ FirstChar = (x / 10) + 48; }
SecondChar = (x % 10) + 48;
crcr = Char.ConvertFromUtf32(FirstChar) + Char.ConvertFromUtf32(SecondChar);
// MessageBox.Show(crcr);
string reqtempfull = "$"+ reqtemp + crcr + (char)13;
crc.Text = reqtempfull; //display the full sp string
if (ComPort.IsOpen)
{
ComPort.Write(reqtempfull); // send it`enter code here`
}