Windows 10环境下基于BLED112与pygatt实现多ST外设蓝牙连接的问题咨询:断开事件捕获、批量通知订阅及持久连接
我来帮你搞定这些BLED112 + pygatt在Windows 10上的多BLE设备连接问题,这些都是多设备BLE部署里的典型痛点,咱们逐个拆解解决:
1. 捕获设备断开连接事件
pygatt的BGAPIBackend(适配BLED112)支持注册断开回调,能实时捕获设备离线事件,同时也可以在数据交互时捕获异常来辅助判断:
import pygatt def handle_disconnect(device): print(f"⚠️ 设备 {device.mac_address} 已断开连接") # 初始化后端 backend = pygatt.BGAPIBackend() backend.start() # 连接设备后注册回调 device = backend.connect("XX:XX:XX:XX:XX:XX") device.register_disconnect_callback(handle_disconnect)
另外,在读取/订阅操作时如果遇到pygatt.exceptions.NotConnectedError,也可以作为断开事件的补充判断,比如在心跳检查或数据处理逻辑里捕获这个异常。
2. 批量订阅5个外设的通知并同时接收数据
多设备订阅的核心是用线程隔离每个设备的订阅逻辑,避免单个设备的阻塞影响其他设备的数据接收。这里给你一个通用的批量订阅模板:
import threading import pygatt # 通用通知处理函数,接收来自所有设备的数据 def notification_handler(sender, data): print(f"📥 来自设备 {sender} 的数据: {data.hex()}") # 要连接的设备MAC列表 TARGET_DEVICES = ["MAC1", "MAC2", "MAC3", "MAC4", "MAC5"] # 替换成你的设备通知特征UUID(ST外设常用FFE1作为串口服务特征) NOTIFY_CHAR_UUID = "0000ffe1-0000-1000-8000-00805f9b34fb" backend = pygatt.BGAPIBackend() backend.start() connected_devices = [] def connect_and_subscribe(mac_addr): try: # 连接设备,可传入连接参数优化稳定性(后面会讲) device = backend.connect(mac_addr) # 订阅通知,indication=False表示用通知而非指示 device.subscribe(NOTIFY_CHAR_UUID, callback=notification_handler, indication=False) connected_devices.append(device) print(f"✅ 已连接并订阅设备 {mac_addr}") except Exception as e: print(f"❌ 处理设备 {mac_addr} 出错: {str(e)}") # 为每个设备启动独立线程 for mac in TARGET_DEVICES: thread = threading.Thread(target=connect_and_subscribe, args=(mac,)) thread.daemon = True # 设置为守护线程,随主程序退出 thread.start()
这样每个设备的通知回调都会在独立线程里运行,不会互相阻塞,能同时接收所有设备的流式数据。
3. 维持1小时以上的持久连接,避免莫名断开
设备莫名断开通常和BLE连接参数、Windows电源管理有关,咱们从两方面优化:
调整BLE连接参数
在连接设备时设置更紧凑的连接间隔和合理的超时,让设备保持活跃:
connection_params = { "min_connection_interval": 10, # 单位: 1.25ms → 12.5ms "max_connection_interval": 20, # 25ms "slave_latency": 0, # 从机不允许跳过连接事件 "supervision_timeout": 500 # 单位: 10ms → 5秒超时 } device = backend.connect(mac_addr, connection_parameters=connection_params)
更小的连接间隔会让设备更频繁地和BLED112通信,降低被判定为空闲的概率。
优化Windows系统设置
- 打开设备管理器 → 找到BLED112对应的蓝牙设备 → 右键属性 → 电源管理 → 取消勾选「允许计算机关闭此设备以节约电源」
- 确保蓝牙支持服务(Bluetooth Support Service)设置为自动启动,避免系统休眠时关闭蓝牙
定期发送心跳包
在代码里给每个设备加一个心跳线程,定期读取一个简单的特征(比如设备名称)来维持连接:
import time def keep_alive(device): # 设备名称特征UUID是通用的,几乎所有BLE设备都支持 NAME_CHAR_UUID = "00002a00-0000-1000-8000-00805f9b34fb" while True: try: device.read(NAME_CHAR_UUID) time.sleep(30) # 每30秒发一次心跳 except pygatt.exceptions.NotConnectedError: print(f"💔 设备 {device.mac_address} 心跳失败,已断开") break # 连接后为每个设备启动心跳线程 for dev in connected_devices: thread = threading.Thread(target=keep_alive, args=(dev,)) thread.daemon = True thread.start()
4. 设备断开后的自动重连机制
结合之前的断开回调,我们可以在设备断开时自动触发重连逻辑,确保服务不中断:
def handle_disconnect(device): print(f"🔄 设备 {device.mac_address} 已断开,尝试重连...") while True: try: # 用之前的连接参数重新连接 new_device = backend.connect(device.mac_address, connection_parameters=connection_params) # 重新订阅通知 new_device.subscribe(NOTIFY_CHAR_UUID, callback=notification_handler) # 更新已连接设备列表 for i, d in enumerate(connected_devices): if d.mac_address == device.mac_address: connected_devices[i] = new_device break print(f"✅ 设备 {device.mac_address} 重连成功") # 重新注册断开回调 new_device.register_disconnect_callback(handle_disconnect) break except Exception as e: print(f"❌ 重连失败,10秒后重试: {str(e)}") time.sleep(10) # 注意:连接设备时要注册这个回调 device.register_disconnect_callback(handle_disconnect)
另外,你也可以加一个全局监控线程,定期检查所有设备的连接状态,作为断开回调的补充:
def monitor_devices(): while True: # 遍历副本避免修改列表时出错 for dev in connected_devices.copy(): try: dev.read(NAME_CHAR_UUID) except pygatt.exceptions.NotConnectedError: print(f"🔍 检测到设备 {dev.mac_address} 连接失效,触发重连") handle_disconnect(dev) time.sleep(5) # 每5秒检查一次 # 启动监控线程 monitor_thread = threading.Thread(target=monitor_devices) monitor_thread.daemon = True monitor_thread.start()
把这些模块整合起来,就能实现稳定的多设备BLE连接、实时数据接收、断线重连,满足1小时以上的持久流式传输需求。
内容的提问来源于stack exchange,提问作者Shubham
相关产品推荐
相关产品推荐

