2016-03-08 54 views
1

我試圖在Python中解碼Novatel GPS流,並且我已經將所有組件同步,頭文件和有效載荷排序,但是我無法複製用作部分消息。用於生成附加在所述消息的CRC算法是用C如下:在Python中重新創建C CRC32算法與crcmod

#include <iostream> 
#include <string> 

using namespace std; 

#define CRC32_POLYNOMIAL 0xEDB88320L 
//#define CRC32_POLYNOMIAL 0x04C11DB7L 

unsigned long CRC32Value(int i) 
{ 
    int j; 
    unsigned long ulCRC; 
    ulCRC = i; 
    for (j = 8; j > 0; j--) 
    { 
     if (ulCRC & 1) 
      ulCRC = (ulCRC >> 1)^CRC32_POLYNOMIAL; 
     else 
      ulCRC >>= 1; 
    } 
    return ulCRC; 
} 
unsigned long CalculateBlockCRC32(
    unsigned long ulCount, 
    unsigned char *ucBuffer) 
{ 
    unsigned long ulTemp1; 
    unsigned long ulTemp2; 
    unsigned long ulCRC = 0; 
    while (ulCount-- != 0) 
    { 
     ulTemp1 = (ulCRC >> 8) & 0x00FFFFFFL; 
     ulTemp2 = CRC32Value(((int)ulCRC^*ucBuffer++) & 0xff); 
     ulCRC = ulTemp1^ulTemp2; 
    } 
    return(ulCRC); 
} 

int main() 
{ 
    unsigned char buffer[] = {0xaa, 0x44, 0x12, 0x1c, 0x2a, 0x00, 0x02, 0x20, 0x48, 0x00, 0x00, 0x00, 0x90, 0xb4, 0x93, 0x05, 0xb0, 0xab, 0xb9, 0x12, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xbc, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1b, 0x04, 0x50, 0xb3, 0xf2, 0x8e, 0x49, 0x40, 0x16, 0xfa, 0x6b, 0xbe, 0x7c, 0x82, 0x5c, 0xc0, 0x00, 0x60, 0x76, 0x9f, 0x44, 0x9f, 0x90, 0x40, 0xa6, 0x2a, 0x82, 0xc1, 0x3d, 0x00, 0x00, 0x00, 0x12, 0x5a, 0xcb, 0x3f, 0xcd, 0x9e, 0x98, 0x3f, 0xdb, 0x66, 0x40, 0x40, 0x00, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x0b, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03}; 

    unsigned long crc = CalculateBlockCRC32(sizeof(buffer), buffer); 
    cout << hex << crc << endl; 
} 

這樣做的結果是的0x42,的0xDC,0x4c,0x48 - 其相匹配的手冊中給出的例子中,所以這是一個好的開始。

雖然我可以在代碼中使用這種算法,但我希望儘可能保留在Python中,所以在這一點上,我覺得我有兩個選擇。我可以自己把它翻譯成Python,也可以希望有一個內置的Python函數或模塊能夠爲我做這件事,這正是我一直在研究的。到目前爲止,我已經發現了三個功能/模塊:

  • binascii.crc32
  • zlib.crc32
  • crcmod模塊

這些前兩名給出相同的不正確的結果,我不能告訴任何改變設置的方式或者指定可能會對此產生積極影響的參數。

另一方面,crcmod有很多設置和預定義的函數,我認爲應該能夠做我想要的。創造了CRC函數的格式如下:

crcmod.mkCrcFun(poly[, initCrc, rev, xorOut]) 

的關鍵事情,我發現有預定義的CRC功能,並在此CRC32版本從binascii和zlib的結果匹配:

Name Polynomial Reversed? Init-value XOR-out Check 
crc-32 0x104C11DB7 True 0x00000000 0xFFFFFFFF 0xCBF43926 

因此,至少可以幫助我理解zlib和binascii變體來自哪個多項式。

我確信我應該能夠使用此函數生成與C算法相同的結果,但是不能熟練使用C我不確定我是如何做到這一點的。 C算法中使用的多項式是多項式的反轉表示,所以這意味着上面的設置應該可以工作,但是它們不會根據C代碼生成上面的答案。

我在尋找什麼來確定這些設置,是否有一個模塊/函數會這樣做,我還沒有看到,或者這是行不通的,我應該只是開始將該C轉換成Python自己?

回答

3

對於crcmod,您需要在多項式的前面添加1,因爲第33位需要爲1,否則會得到一個異常,說明度必須是8,16,24或32。這似乎產生的預期輸出:

import crcmod 
crc = crcmod.mkCrcFun(0x104C11DB7, 0, True, 0) 

然後下面的例子中應在兩個Python 2和3正常工作:

value = bytes(bytearray(
    [0xaa, 0x44, 0x12, 0x1c, 0x2a, 0x00, 0x02, 0x20, 
    0x48, 0x00, 0x00, 0x00, 0x90, 0xb4, 0x93, 0x05, 
    0xb0, 0xab, 0xb9, 0x12, 0x00, 0x00, 0x00, 0x00, 
    0x45, 0x61, 0xbc, 0x0a, 0x00, 0x00, 0x00, 0x00, 
    0x10, 0x00, 0x00, 0x00, 0x1b, 0x04, 0x50, 0xb3, 
    0xf2, 0x8e, 0x49, 0x40, 0x16, 0xfa, 0x6b, 0xbe, 
    0x7c, 0x82, 0x5c, 0xc0, 0x00, 0x60, 0x76, 0x9f, 
    0x44, 0x9f, 0x90, 0x40, 0xa6, 0x2a, 0x82, 0xc1, 
    0x3d, 0x00, 0x00, 0x00, 0x12, 0x5a, 0xcb, 0x3f, 
    0xcd, 0x9e, 0x98, 0x3f, 0xdb, 0x66, 0x40, 0x40, 
    0x00, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x0b, 0x0b, 0x00, 0x00, 
    0x00, 0x06, 0x00, 0x03])) 

print(hex(crc(value)))) 

打印

0x484cdc42 

哪個是little- endian八位字節的有序值0x42, 0xdc, 0x4c, 0x48

+0

只是爲了確認這與Python 2和3現在一起工作。謝謝。 – Folau