我正在创建一个简单的 python 脚本,通过蓝牙从 Polar 传感器读取心率数据。我已经阅读了很多其他帖子,但找不到我能够成功执行的简单内容。
我有 Polar 可穿戴设备的设备 MAC 地址。我知道我想要读取的值的服务 UUID(HR 为 0x180D)。我不太关心我使用哪个库或服务,但我似乎无法让它工作。
我能够让我的脚本成功识别 Polar 传感器,但是,我不知道如何从中读取值。我已经为我的手机下载了一个蓝牙扫描仪应用程序,它能够成功连接并读取值,所以我知道这应该很容易做到,但不知道如何编写它。
任何帮助将不胜感激。
如果您查看蓝牙分配的 16 位 UUID 编号,那么您正确地认为
0x180D
是心率服务
心率测量特征
0x2A37
将具有您正在寻找的值:
我没有设备来测试这个,我不知道你正在为哪个平台编写代码。
因此,我使用了 bleak 库,因为它是最跨平台的库。
该示例还订阅来自设备的通知而不是读取值。这是获取定期更新的值的更典型方法。
import asyncio
import bitstruct
import struct
from bleak import BleakClient
HR_MEAS = "00002A37-0000-1000-8000-00805F9B34FB"
async def run(address, debug=False):
async with BleakClient(address) as client:
connected = await client.is_connected()
print("Connected: {0}".format(connected))
def hr_val_handler(sender, data):
"""Simple notification handler for Heart Rate Measurement."""
print("HR Measurement raw = {0}: {1}".format(sender, data))
(hr_fmt,
snsr_detect,
snsr_cntct_spprtd,
nrg_expnd,
rr_int) = bitstruct.unpack("b1b1b1b1b1<", data)
if hr_fmt:
hr_val, = struct.unpack_from("<H", data, 1)
else:
hr_val, = struct.unpack_from("<B", data, 1)
print(f"HR Value: {hr_val}")
await client.start_notify(HR_MEAS, hr_val_handler)
while await client.is_connected():
await asyncio.sleep(1)
if __name__ == "__main__":
address = ("xx:xx:xx:xx:xx:xx") # Change to address of device
loop = asyncio.get_event_loop()
loop.run_until_complete(run(address))
您可以阅读有关心率测量值构造的更多信息:
https://www.bluetooth.com/specifications/specs/gatt-specification-supplement-6/
虽然@ukBaz 的代码示例很有用,并且在某些情况下会意外地显示正确的广播 HR,但解包 5 位标志的部分是完全错误的(位顺序错误并移位了 3 位)。当我还尝试解码其他数据(例如 R-R 间隔)并且其标志总是错误时,我发现了问题。
要更正标志,请按照我在下面所做的那样更改 bitstruct.unpack() 行。正确的代码是:
import asyncio
import bitstruct
import struct
from bleak import BleakClient
HR_MEAS = "00002A37-0000-1000-8000-00805F9B34FB"
async def run(address):
async with BleakClient(address) as client:
connected = await client.is_connected()
print("Connected: {0}".format(connected))
def hr_val_handler(sender, data):
"""Simple notification handler for Heart Rate Measurement."""
(unused, rr_int, nrg_expnd, snsr_cntct_spprtd, snsr_detect, hr_fmt) \
= bitstruct.unpack("b3b1b1b1b1b1", data)
if hr_fmt:
hr_val, = struct.unpack_from("<H", data, 1) # uint16
else:
hr_val, = struct.unpack_from("<B", data, 1) # uint8
print("HR: {0:3} bpm. Complete raw data: {1} ".format(hr_val, data.hex(sep=':')))
await client.start_notify(HR_MEAS, hr_val_handler)
while await client.is_connected():
await asyncio.sleep(1)
if __name__ == "__main__":
address = ("xx:xx:xx:xx:xx:xx") # Change to address of device
loop = asyncio.get_event_loop()
loop.run_until_complete(run(address))