2013-05-29 4 views
1

저는 Python의 홈 자동화 시스템 (ElkM1)에 대한 인터페이스 작업을하고 있습니다. 이 시스템에 메시지를 보낼 때 필요한 체크섬을 올바르게 계산하는 C# 아래 샘플 코드가 있습니다. 아래의 파이썬 코드를 조합했지만 정확한 값을 반환하지 않는 것 같습니다.체크섬 계산에 도움이 필요합니다

설명서에 따르면 메시지의 체크섬은 mod256의 메시지 ASCII 값의 합계가 2의 보수로 취해 져야합니다. 설명서에서 "이것은 체크섬 자체와 메시지 끝의 CR-LF 종결자를 제외한 메시지의 모든 문자의 ASCII 값을 모듈로 256 합계로 16 진수로 2를 더한 것입니다. 허용되는 문자는 ASCII 0-9 및 대문자 AF 모든 문자가 체크섬에 추가되면 값은 0이어야합니다. "

벤더에는 올바른 체크섬을 계산하는 도구가 있습니다. 테스트 데이터로 내가 사용하는 74

내 코드의 체크섬을 반환해야 '00300005000'은 사전에 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# 코드의 직역이다 :

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

print calc_checksum('00300005000') 

그것은 출력이 E8은 사용자의 C# 코드와 다른 메시지를 표시합니다. 설명서의 설명과 손으로 계산을 할 때, 나는 그들의 대답이 74 일 수있는 방법을 모르겠다. 그것이 정답인지 어떻게 알 수 있습니까?

C# 코드가 실제로 E8을 반환한다는 Mark Ransom의 의견을 본 후 나는 파이썬 코드를 디버깅하는 데 약간의 시간을 할애하여 동일한 결과를 얻지 못하는 이유를 발견했습니다. 한 가지 문제는 코드에 주석 #inverse이있는 행에서 2의 보수를 올바르게 계산하지 않는다는 것입니다. 이 작업을 올바르게 수행하는 데는 최소한 두 가지 방법이 있습니다.

두 번째 문제는 음수를 처리하는 hex() 함수가 예상 한 것과 다릅니다. 이 경우 -24의 2의 보수로 0xffe8 또는 이와 유사한 것이 아닌 -0x18을 생성합니다. 즉, 대문자로 된 결과의 마지막 두 문자를 가져 오면 올바르지 않습니다. 정말 쉬운 방법은 % 문자열 보간 연산자를 사용하여 값의 하위 바이트를 대문자 16 진수로 변환하는 것입니다. 다음은 함수의 작업 버전입니다 : 구현을 사용합니다 이런 한 줄 것 (빠르고)

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) 

보다 파이썬은 내장 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

은 Using sum() 함수를 사용하면 ('sum'이라는 변수를 사용하지 않아도됩니다.)

 def calc_checksum(s): checksum = -(sum([ord(c) for c in s]) % 256) return '%2X' % (checksum & 0xFF) 
... 그러나 @martineau와 같은 결과를 얻습니다. –

+1

이것은 http : // ideone을 참조하여 C# 출력과 일치합니다.com/eIkJlh –

+0

감사합니다. @Mark, [ideone.com] (http://ideone.com/)과 같은 것이 있다는 것을 배우는 것도 좋았습니다. – martineau

관련 문제