blupy 从特征中读取值作为整数而不是 ascii

blupy read value from chacteristics as integer and not as ascii

我使用 bluepy 模块通过 BLE 运行 a battery monitor.

连接到 Arduino 开发板

我的 Python 脚本运行良好。我得到了我期望的值。但我不喜欢这个解决方案,因为在获取该 ASCII 字符的十进制表示之前,从特征读取的二进制值被解释为 ASCII 字符。

我尝试使用 binascii 模块

val = binascii.b2a_hex(ch.read())
val = binascii.unhexlify(val)
val = struct.unpack('f', val)[0]

但这只适用于偶数字符串长度。我还有其他问题我现在不记得了。

我当前的“双重铸造”解决方案在这里。

from bluepy.btle import Peripheral, BTLEException, UUID
import sys
import time
try:
    print("Trying to Connect to Device")
    p = Peripheral() # 3rd param = 0 means /dev/hci0, 1 means /dev/hci1
    p.connect("7C:9E:BD:3A:D0:A2")
    uuid = UUID(0x180F)
except BTLEException as e:
    sys.exit(e)
else:
    print("Connection established")
finally:
char = p.getServiceByUUID(uuid).getCharacteristics()[0]
    i = 0
    while i < 10:
        # TODO react to the notification instead of looping
        val = char.read()
        # Yes this works but is definitly not the way to do it right
        # reading the characteristics interpreted it as ascii and than
        # converting this ascii too it coresponding integer value
        print(ord(val.decode()))
        time.sleep(0.2)
        i+=1
    p.disconnect()

但我真的不喜欢倒数第四行。虽然它得到了我的预期值,但我觉得它只是糟糕的代码。

print(ord(val.decode()))

看起来在这种情况下 python 自动假定该值应被解释为 ASCII,因为它会打印相应的 ASCII 值,即使我没有对其进行解码。例如,当我不解码时打印出 b'/',解码时打印出 /,所以电池电量为 47%,这是正确的。

直接将 val 从基数 2 表示转换为整数不起作用:

print(int(val,2))

Python 假定 val 被读取为 ASCII 字符,因此转换失败。

TLDR: 我正在寻找替代

的解决方案
print(ord(val.decode()))

更奇特的是,我不将从特征中读取的二进制值转换为 ASCII 字符,然后为该字符获取相应的十进制值。

只是将二进制值立即读取为十进制的东西。它也可以是另一个模块。

提前致谢。

特征读取正在返回字节,例如 b'/'。如果您想将其转换为整数,那么 int.from_bytes() 功能很有用。例如:

>>> val = b'/'
>>> batt = int.from_bytes(val, byteorder='little', signed=True)
>>> print(f'Battery level is: {batt}%')

给出输出: Battery level is: 47%

正在打印的 / 只是 Python 的产物,它试图在您打印字节时提供帮助。如果将字节包装在列表中,您将看到真实值。例如:

>>> print(b'\x2f\x2a\x26\x20')
b'/*& '
>>> list(b'/*& ')
[47, 42, 38, 32]
>>> [f'{_:2x}' for _ in b'/*& ']
['2f', '2a', '26', '20']

在您的问题中,您试图在 Python 中使用 struct 模块。转换也可以用它来完成:

>>> batt = struct.unpack('<b', b'/')[0]
>>> print(batt)
47

对于单个字节值,小端字节顺序并不是严格必需的,但在使用蓝牙时这是一种很好的做法,因为数据通常采用小端格式。