知道如何解码 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']
我正在从 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']