Как работать с динамической распаковкой и пониманием байт-структур
В ходе моего текущего проекта я получаю данные от набора датчиков дальнего действия, которые отправляют данные в виде серии байтов. Как правило, из-за наличия нескольких типов датчиков, структуры байтов и содержащиеся в них данные отличаются, поэтому необходимо сделать функциональность более динамичной, чтобы избежать необходимости жестко кодировать каждую отдельную настройку в будущем (что нецелесообразно).
На сервере будет использоваться Django, который, на мой взгляд, не имеет отношения к рассматриваемому вопросу, но я упомянул его на всякий случай, вдруг в нем есть что-то, что можно использовать.
Данные байтов, которые я получаю, выглядят следующим образом:
b'B\x10Vu\x87%\x00x\r\x0f\x04\x01\x00\x00\x00\x00\x1e\x00\x00\x00\x00ad;l'
А мой текущий процесс выглядит следующим образом:
- Возьмите первые байты для получения идентификатора устройства (
deviceID = val[0:6].hex()
) - Поищите формат, который будет использоваться в
struct.unpack()
(здесь:>BBHBBhBHhHL
после удаления первых байтов для идентификатора.
Теперь проблема заключается в следующем шаге. Многие из имеющихся у меня данных имеют различные формы предварительной обработки, которую необходимо выполнить. Например, некоторые значения нужно объединить с помощью оператора join (например, ".".join(str(values[2])
), в то время как другие требуют некоторых простых математических изменений (-113 + 2 * values[4]
) и, наконец, другие требуют простой логической проверки (values[7]==0x80
), чтобы вернуть булево значение.
Мой вопрос в том, как лучше всего закодировать эти методы? Я бы очень хотел избежать их жесткого кодирования, но это почти кажется лучшей идеей. Другая идея, которую я видел, это хранить функции в виде строки и выполнять их, как показано here, но я читал, что это очень плохая идея, и что это также замедляет выполнение. Последняя идея, которая у меня была - это жестко закодировать только некоторые общие функции и использовать что-то похожее на here, но это не решает проблему необходимости жестко кодировать каждый новый тип датчика, что нереально в живой установке. Есть ли более эффективные методы достижения того же самого?
Приложение: Минимальный код, который можно использовать для демонстрации и тестирования различных методов:
import struct
def decode(input):
val = bytearray(input)
deviceID = val[0:6].hex()
del(val[0:6])
print(deviceID)
values = list(struct.unpack('>BBHBBhBHhHL', val))
print(values)
# Now what?
decode(b'B\x10Vu\x87%\x00x\r\x0f\x04\x01\x00\x00\x00\x00\x1e\x00\x00\x00\x00ad;l')