知道如何解码 python 中的这些小字节序字节吗?

Any idea how to decode these little endian bytes in python?

我正在从 BLE 设备中获取广告数据。我特别感兴趣的是这两个字节:

b'\x17d\x0e\x10\x0e\xd7\x02\x1d\x00G\x00U\x01\x00'
b'\x02\xad\x02\x8d\x00\x9b\x00\x0e\x01\xf6\x01\xad\x00\xcf\x00V\x01-\x01+\x00\x00\x00\x00\x00'

在设备手册中,可用 here。它们给出了广告数据的结构。我试着遵循它并使用 struct.unpack 如下所示:

import struct

bte = b'\x17d\x0e\x10\x0e\xd7\x02\x1d\x00G\x00U\x01\x00'
struct.unpack('<BBHHHH', bte)

但是,我收到此错误“解包需要 10 字节的缓冲区”。我认为这与第一个字节 \x17d\ 有关,因为 struct.unpack 总是 returns 当您有一个包含两个以上字符的字节时出现此错误。还有字节 \x00G\\x00U\ 因为我不确定 U 和 G 是什么意思。此字节也为 11 长,而格式 <BBHHHH 的字节应该只有 10 长。

如有任何帮助,我们将不胜感激。

在 Blue Maestro 设备上,我不认为他们将数据放入广告制造商数据中的小端格式。

查看您的数据,我希望它类似于以下内容:

import binascii
from pprint import pprint
from struct import unpack

pckt = binascii.unhexlify('17640e100ed7021d004700550100')
data = {}

data["version"] = unpack(">B", pckt[0:1])[0]
data["batt_lvl"] = unpack(">B", pckt[1:2])[0]
data["interval"] = unpack(">H", pckt[2:4])[0]
data["log_count"] = unpack(">H", pckt[4:6])[0]
data["humidity"] = unpack(">h", pckt[6:8])[0] / 10
data["dew_point"] = unpack(">h", pckt[8:10])[0] / 10
data["temperature"] = unpack(">h", pckt[10:12])[0] / 10
pprint(data)

输出为:

{'batt_lvl': 100,
 'dew_point': 7.1,
 'humidity': 54.1,
 'interval': 3600,
 'log_count': 3799,
 'temperature': 8.5,
 'version': 23}

您可以一次性解包,但您必须调整露点湿度和温度的值:

unpack('>BBHHhhh', pckt[:12])
# (23, 100, 3600, 3799, 541, 71, 85)

在挑选单个值时,使用 int.from_bytes 功能会更清晰。

import binascii
from pprint import pprint

pckt = binascii.unhexlify('17640e100ed7021d004700550100')
data = {}

data["version"] = int.from_bytes(pckt[0:1], byteorder='big')
data["batt_lvl"] = int.from_bytes(pckt[1:2], byteorder='big')
data["interval"] = int.from_bytes(pckt[2:4], byteorder='big')
data["log_count"] = int.from_bytes(pckt[4:6], byteorder='big')
data["humidity"] = int.from_bytes(pckt[6:8], byteorder='big', signed=True) / 10
data["dew_point"] = int.from_bytes(pckt[8:10], byteorder='big', signed=True) / 10
data["temperature"] = int.from_bytes(pckt[10:12], byteorder='big', signed=True) / 10
pprint(data)

给出相同的值:

{'batt_lvl': 100,
 'dew_point': 7.1,
 'humidity': 54.1,
 'interval': 3600,
 'log_count': 3799,
 'temperature': 8.5,
 'version': 23}

\x17d\x00G\x00U都是两个字节。然而,第二个字节恰好是 ASCII 值,因此 Python,在显示时,有助于显示字母而不是字节值。 为了证明这一点,我们可以输入字节值并在输出中查看 ASCII 值:

>>> b'\x64\x47\x55'
b'dGU'

您可以执行一些操作来显示实际字节值以帮助调试。

使用 hexlify:

>>> binascii.hexlify(bte)
b'17640e100ed7021d004700550100'

将字节转换为二进制值列表:

>>> list(bte)
[23, 100, 14, 16, 14, 215, 2, 29, 0, 71, 0, 85, 1, 0]

将其格式化为具有十六进制值的字符串:

>>> [f'{n:02X}' for n in bte]
['17', '64', '0E', '10', '0E', 'D7', '02', '1D', '00', '47', '00', '55', '01', '00']