我正在用Python开发一个家庭自动化系统(ElkM1)的接口。我有C#中的示例代码,下面的代码显然正确地计算了向此系统发送消息时所需的校验和。我将下面的python代码组合在一起,但它似乎没有返回正确的值。
根据文档,消息的校验和需要是mod256中消息的ASCII值之和,然后作为2s补码。在他们的手册中:“这是对消息中所有字符(不包括校验和本身和消息末尾的CR-LF终止符)的ASCII值的256模和的十六进制2补码。允许的字符是ASCII 0-9和大写A-F。当所有字符添加到校验和时,该值应等于0。”
供应商有一个工具可以计算正确的校验和。作为测试数据,我一直在使用'00300005000',它应该返回74的校验和
我的代码返回18
提前谢谢。
def calc_checksum (string):
'''
Calculates checksum for sending commands to the ELKM1.
Sums the ASCII character values mod256 and takes
the Twos complement
'''
sum= 0
for i in range(len(string)) :
sum = sum + ord(string[i])
temp = sum % 256 #mod256
rem = temp ^ 256 #inverse
cc1 = hex(rem)
cc = cc1.upper()
p=len(cc)
return cc[p-2:p]
private string checksum(string s)
{
int sum = 0;
foreach (char c in s)
sum += (int)c;
sum = -(sum % 256);
return ((byte)sum).ToString("X2");
}
FWIW,这里是C代码到Python的直译:
对于显示的消息,它的输出是
E8
,这与您的代码和C代码都不同。根据手册中的描述和手工计算,我看不出他们的答案是74
。你怎么知道这是正确的答案?在看到Mark Ransom关于C代码确实返回
E8
的评论之后,我花了一些时间调试了您的Python代码,并发现为什么它不会产生相同的结果。一个问题是,它在代码中带有注释#inverse
的行上无法正确计算两个补码。至少有几种方法可以做到这一点。第二个问题是
hex()
函数处理负数的方式不是您所期望的。在本例中,使用-24
two的补码,它产生-0x18
,而不是0xffe8
或类似的东西。这意味着只取大写结果的最后两个字符是不正确的。一个非常简单的方法是使用%
字符串插值运算符将值的低位字节转换为大写十六进制。下面是您的函数的工作版本:一个更加Pythonic(和更快)的实现是这样的一行程序,它使用内置的
sum()
函数:相关问题 更多 >
编程相关推荐