You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Bleak库start_notify回调函数未触发问题求助

解决Bleak中BLE通知回调不触发及实现持续接收通知的问题

问题分析

你的代码能成功连接BLE设备,但回调未触发且无法持续接收通知,主要存在以下几个潜在问题:

  1. 仅通过asyncio.sleep(5.0)固定等待5秒,可能设备还未推送通知就已停止监听
  2. 未验证目标特征是否真的支持通知属性
  3. 部分设备需要手动配置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设备推送的原始数据
  • 完善命令行参数处理:明确设备地址的传入方式,提升脚本可用性

额外排查技巧

  1. 验证设备端推送:用nRF Connect等BLE调试工具连接设备,订阅同一特征,确认设备是否真的在推送通知,排除设备端问题
  2. 启用调试日志:添加日志输出查看Bleak底层交互细节,定位通信问题:
    import logging
    logging.basicConfig(level=logging.DEBUG)
    
  3. 手动配置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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 04:50:39