Выравнивание / Упаковка в Python Struct.Unpack - PullRequest
0 голосов
/ 11 октября 2019

У меня есть аппаратная часть, отправляющая данные с фиксированной длиной: 2 байта, 1 байт, 4 байта, 4 байта, 2 байта, 4 байта, всего 17 байтов. Если я изменяю свой формат на 18 байт, код работает, но значения неверны.

format = '<2s1s4s4s2s4s'
print(struct.calcsize(format))
print(len(hardware_data))
splitdata = struct.unpack(format,hardware_data)

Вывод 17, 18 и ошибка из-за несоответствия. Я думаю, что это вызвано выравниванием, но я не уверен, и ничто из того, что я пробовал, не исправило это. Ниже приведена пара типичных строк, если я print(hardware_data) заметил символы 'R' и 'n', но не уверен, как с ними обращаться.

b '\ x18 \ x06 \ x00R \ x1f \ x01\ x00 \ x00 \ x00 \ x00 \ x00 \ xd8 \ xff \ x00 \ x00 \ x00 \ x00 \ x80 '

b' \ x18 \ x06 \ x00R \ x1f \ x01 \ x00 \ x00 \ x00 \x00 \ x00 \ п \ x00 \ x00 \ x00 \ x00 \ x00 \ x80'

1 Ответ

0 голосов
/ 11 октября 2019

Шансы на то, что отправка данных заполняет их некоторым образом, которого вы не ожидаете.

Например, если первые четыре байта поля должны представлять int, правила структуры struct Cпотребовалось бы заполнить байт после одного байтового поля (чтобы выровнять следующие четыре байтовых поля с выравниванием в четыре байта). Так что просто добавьте байт заполнения явно, изменив строку формата на:

format = '<2s1sx4s4s2s4s'

x там говорит: «Я ожидаю, что байт здесь, но это заполнение, не распаковывайте его ни к чему». Возможно, байт пэда находится в другом месте (я понятия не имею, что делает ваше оборудование);Я заметил, что третий байт - это байт NUL (\0) в обоих примерах, но я предположил, что точка заполнения будет 'R', поэтому возможно, что вы захотите:

format = '<2sx1s4s4s2s4s'

. Или это может быть где-то еще (не зная, какое из полей является массивом char в аппаратной структуре, а какие являются более крупными типами с требованиями выравнивания, невозможно сказать). Дело в том, что ваше оборудование отправляет 18 байтов;выясните, какой из них является мусором, и поместите байт pad x в соответствующее место.

Примечание: объекты repr из bytes будут использовать ASCII или более простые экранированные символы ASCII, если они доступны. Вот почему вы видите R и \n в вашем выводе;b'R' и b'\x52' являются эквивалентными литералами, как и b'\n' и b'\x0a', и Python выбирает использовать "более читаемую" версию (когда bytes на самом деле является просто ASCII, это много более читабельно).

...