Работа с ведущими нулями в функции упаковки/распаковки структуры?

Я использую библиотеку Python для беспроводной связи ANT+ с датчиками. Связь осуществляется путем сопряжения с идентификатором, который представляет собой число из 4-5 цифр. Все работало нормально, пока одно из протестированных мной устройств не получило идентификатор «00625».

Отслеживая код, источником проблемы является функция упаковки/распаковки структуры, используемая для кодирования и декодирования байтов сообщения протокола ANT+.

>>> from struct import *
>>> pack(b'<H', 11977)
'\xc9.'
>>> unpack(b'<H', '\xc9.')
(11977,)
>>> pack(b'<H', 625)
'q\x02'
>>> unpack(b'<H', 'q\x02')
(625,)
>>> pack(b'<H', 00625)
'\x95\x01'
>>> unpack(b'<H', '\x95\x01')
(405,)

Итак, когда я упаковываю ANT ID 11977 или 625, а затем распаковываю их, я получаю именно то, что упаковывал.

Однако, когда я упаковываю ANT ID 00625, а затем распаковываю его, я получаю обратно 405. Не знаю, как мне с этим справиться, чтобы правильно упаковать 00625.


person jftorre    schedule 13.03.2020    source источник
comment
Можно ли сначала упаковать 00625 как строку «00625», а затем распаковать результат?   -  person JYCH    schedule 13.03.2020
comment
@JYCH нет, выбрасывает struct.error: cannot convert argument to integer.   -  person jftorre    schedule 13.03.2020
comment
В Python начальные нули в десятичных целочисленных литералах не разрешены. Вам нужно будет их как-то раздеть. Каков источник кода с литералом 00625 в нем?   -  person martineau    schedule 13.03.2020
comment
Вы должны использовать Python 2. Целочисленные литералы с начальным нулем обрабатываются как восьмеричные. В Python 3 это было удалено, но префикс 0o все еще существует. В любом случае, как вы вообще вставили это целое число в свой код? В конечном счете проблема в этом, а не в struct.pack. Если он приходит в виде строки, вы должны использовать int(), а не eval(), и raw_input() вместо input().   -  person wjandrea    schedule 13.03.2020
comment
Связано: Что означают числа, начинающиеся с 0, в python?   -  person wjandrea    schedule 13.03.2020


Ответы (1)


Да, я использую Python 2, что означает, что начальный ноль заставит int интерпретироваться как восьмеричное. Углубившись в то, как отправляется сообщение, я понял, что вместо того, чтобы передавать начальные нули, я просто передаю «625» в качестве идентификатора и изменил аргументы функции упаковки, заполнив их двумя байтами заполнения. Это помогло, просто нужно было добавить условие, при котором любой int, переданный с менее чем 3 цифрами, дополняется, например:

>>> from struct import *
>>> pack(b'<H', 625)
'q\x02'
>>> pack(b'<xxH', 625)
'\x00\x00q\x02'

Поэтому я создал условие в модуле сообщений для использования того или иного в зависимости от размера идентификатора:

    def deviceNumber(self, device_number):
        if len(str(device_number)) > 3 :
            self._payload[1:3] = pack(b'<H', device_number)
        else :
            self._payload[1:3] = pack(b'<xxH', device_number)

Может быть, есть лучший способ, но он работает, этого пока достаточно!

person jftorre    schedule 14.03.2020