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
对于单个字节值,小端字节顺序并不是严格必需的,但在使用蓝牙时这是一种很好的做法,因为数据通常采用小端格式。
我使用 bluepy
模块通过 BLE 运行 a battery monitor.
我的 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
对于单个字节值,小端字节顺序并不是严格必需的,但在使用蓝牙时这是一种很好的做法,因为数据通常采用小端格式。