2016-03-08 3 views
1

Я пытаюсь декодировать поток Novatel GPS в Python, и у меня есть все компоненты для сортировки по синхронизации, заголовку и полезной нагрузке, но я не могу реплицировать CRC32, используемый как часть сообщений. Алгоритм, используемый для генерации CRC добавляется на сообщении записывается в с следующим образом:Воспроизведение алгоритма C CRC32 в Python с 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-й бит должен быть одним, иначе вы получите исключение, указав, что степень должна быть 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 

Который является мало- конечное упорядоченное значение октетов 0x42, 0xdc, 0x4c, 0x48.

+0

Просто, чтобы подтвердить, что это работает с Python 2 и 3 сейчас. Благодарю. – Folau