Python Bleak库start_notify回调函数未触发问题求助
解决Bleak中BLE通知回调不触发及实现持续接收通知的问题
问题分析
你的代码能成功连接BLE设备,但回调未触发且无法持续接收通知,主要存在以下几个潜在问题:
- 仅通过
asyncio.sleep(5.0)固定等待5秒,可能设备还未推送通知就已停止监听 - 未验证目标特征是否真的支持通知属性
- 部分设备需要手动配置CCC描述符(尽管Bleak的
start_notify通常会自动处理,但少数场景需要手动干预)
解决方案及优化代码
以下是修复后的代码,同时实现持续接收通知的功能:
import asyncio import sys from bleak import BleakClient NOTIFY_CHAR_UUID = "2ea78970-7d44-44bb-b097-26183f402401" def notify_callback(handle: int, data: bytearray): print(f"收到通知 - 句柄: {handle}, 数据(十六进制): {data.hex()}") async def main(address): async with BleakClient(address) as client: print(f"已连接设备: {address}") # 检查目标特征是否存在且支持通知 target_char = client.services.get_characteristic(NOTIFY_CHAR_UUID) if not target_char: print(f"错误:未找到特征 {NOTIFY_CHAR_UUID}") return if "notify" not in target_char.properties: print(f"错误:特征 {NOTIFY_CHAR_UUID} 不支持通知属性") return # 启用通知监听 await client.start_notify(NOTIFY_CHAR_UUID, notify_callback) print("通知已启用,持续接收数据中...(按Ctrl+C停止)") # 用Event实现无限等待,直到用户手动中断 stop_signal = asyncio.Event() try: await stop_signal.wait() except KeyboardInterrupt: print("\n正在停止通知监听...") await client.stop_notify(NOTIFY_CHAR_UUID) print("已断开与设备的连接") if __name__ == "__main__": if len(sys.argv) != 2: print("使用方式:python ble_notify.py <BLE设备地址>") sys.exit(1) device_addr = sys.argv[1] asyncio.run(main(device_addr))
关键优化点
- 增加特征合法性检查:提前验证特征是否存在、是否支持通知,快速定位配置错误
- 替换固定休眠为无限等待:使用
asyncio.Event()实现持续运行,直到用户通过Ctrl+C主动终止 - 优化数据输出:将字节数组转为十六进制格式,更易读取BLE设备推送的原始数据
- 完善命令行参数处理:明确设备地址的传入方式,提升脚本可用性
额外排查技巧
- 验证设备端推送:用nRF Connect等BLE调试工具连接设备,订阅同一特征,确认设备是否真的在推送通知,排除设备端问题
- 启用调试日志:添加日志输出查看Bleak底层交互细节,定位通信问题:
import logging logging.basicConfig(level=logging.DEBUG) - 手动配置CCC描述符:若自动启用通知失败,可手动写入CCC描述符(UUID为
0x2902)开启通知:ccc_descriptor = target_char.get_descriptor("00002902-0000-1000-8000-00805f9b34fb") await client.write_gatt_descriptor(ccc_descriptor.handle, b"\x01\x00")
内容的提问来源于stack exchange,提问作者Geetha Maruthakutty
相关产品推荐
相关产品推荐

