2013-05-29 40 views
1

我正在使用Python中的接口连接到家庭自动化系统(ElkM1)。我在下面的C#中有示例代码,它明显正确地计算向此系统发送消息时所需的校验和。我把下面的Python代码放在​​一起,但它似乎没有返回正确的值。在计算校验和时需要帮助

根据文档,消息的校验和需要是mod256中消息的ASCII值的总和,然后作为2s补码。从他们的手册中:“这是消息中除校验和本身和消息结尾的CR-LF终止符之外的消息中所有字符的模数256总和的十六进制2的补码。允许的字符是ASCII 0-9和大写AF,当所有字符被添加到校验和时,值应该等于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] 

他们的代码C#:

private string checksum(string s) 
{ 
    int sum = 0; 
    foreach (char c in s) 
     sum += (int)c; 

    sum = -(sum % 256); 

    return ((byte)sum).ToString("X2"); 
} 

回答

3

FWIW,这里的C#代码的字面翻译成Python:

def calc_checksum(s): 
    sum = 0 
    for c in s: 
     sum += ord(c) 
    sum = -(sum % 256) 
    return '%2X' % (sum & 0xFF) 

print calc_checksum('00300005000') 

它输出是对于显示的消息,您的和C#代码都不相同,请使用E8。鉴于手册中的描述和手工计算,我不明白他们的答案可能是74。你怎么知道这是正确的答案?

在看到Mark Ransom的评论C#代码确实返回E8之后,我花了一些时间来调试您的Python代码,并发现它为什么不会产生相同的结果。一个问题是,它不会在代码中注释#inverse的行上正确计算二进制补码。至少有几种方法可以正确执行此操作。

第二个问题是hex()函数处理负数不是你所期望的。在这种情况下使用-24二进制补码产生-0x18,而不是0xffe8或类似的东西。这意味着只是取大写结果的最后两个字符是不正确的。一个简单的方法就是使用%字符串插值运算符将值的低位字节转换为大写的十六进制数。这是你的函数的工作版本:

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^0xFF) + 1 # two's complement, hard way (one's complement + 1) 
    rem = -temp # two's complement, easier way 
    return '%2X' % (rem & 0xFF) 

一个更Python,速度更快的实现将是一个班轮这样使得使用内置sum()功能:

def calc_checksum(s): 
    """ 
    Calculates checksum for sending commands to the ELKM1. 
    Sums the ASCII character values mod256 and returns 
    the lower byte of the two's complement of that value. 
    """ 
    return '%2X' % (-(sum(ord(c) for c in s) % 256) & 0xFF) 
+1

使用sum()函数(并避免名为'sum'的变量):

 def calc_checksum(s): checksum = -(sum([ord(c) for c in s]) % 256) return '%2X' % (checksum & 0xFF) 
...但我得到了与@martineau相同的结果。 –

+1

这与C#输出匹配,请参阅http:// ideone。com/eIkJlh –

+0

谢谢@Mark,我们也很高兴能够学习[ideone.com](http://ideone.com/)。 – martineau