树莓派Pico W基于aioble的BLE连接频繁中断问题求助
环境与问题
我正在使用MicroPython(v1.22.2)结合aioble库,为树莓派Pico W开发蓝牙低功耗(BLE)外设应用,中央设备为运行bluepy库的树莓派3 B+。目前遇到BLE连接在10-20秒后反复中断的问题,外设会发送传感器状态(开/关)通知,中央设备能正常接收这些通知。
具体现象简化如下:
- 中央设备连接到外设;
- 外设发送若干条通知;
- 连接突然中断。
外设端代码片段
# Bluetooth GATT setup _DOOR_SERVICE_UUID = bluetooth.UUID('12345678-1234-5678-1234-56789abcdef0') _DOOR_STATE_UUID = bluetooth.UUID('12345678-1234-5678-1234-56789abcdef1') _ADV_APPEARANCE_GENERIC_DOOR_SENSOR = const(768) _ADV_INTERVAL_MS = 250_000 door_service = aioble.Service(_DOOR_SERVICE_UUID) door_state_characteristic = aioble.Characteristic(door_service, _DOOR_STATE_UUID, read=True, notify=True) aioble.register_services(door_service) ... ... # Bluetooth advertising task async def peripheral_task(): global current_connection while True: if not current_connection: print("No Connection, attempting to advertise") try: async with await aioble.advertise( _ADV_INTERVAL_MS, name="DoorSensor", services=[_DOOR_SERVICE_UUID], appearance=_ADV_APPEARANCE_GENERIC_DOOR_SENSOR, ) as connection: current_connection = connection print("Connection from", connection.device) await connection.disconnected() except asyncio.CancelledError as e: print(f"Cancelled: {str(e)}") current_connection = None except Exception as e: print(f"Unhandled exception: {str(e)}") finally: current_connection = None else: if not current_connection.is_connected(): print("lost connection") print("connected") await asyncio.sleep(1) ... # loop which checks door state and notifies central ... if current_connection: door_state_characteristic.notify(current_connection, _encode_door_state(1)) await asyncio.sleep(1)
中央端代码
from bluepy.btle import Peripheral, DefaultDelegate class MyDelegate(DefaultDelegate): def __init__(self): DefaultDelegate.__init__(self) def handleNotification(self, cHandle, data): print("Notification from Handle: {}".format(cHandle)) state = int.from_bytes(data, byteorder='little') print("Door State Changed:", "Open" if state else "Closed") def connect_to_sensor(): peri = Peripheral("D8:3A:DD:9E:82:B1", "public") peri.setDelegate(MyDelegate()) print("Connected to device") # Get service and characteristic svc = peri.getServiceByUUID("12345678-1234-5678-1234-56789abcdef0") ch = svc.getCharacteristics("12345678-1234-5678-1234-56789abcdef1")[0] print("Service and characteristic found") # Correct CCCD UUID for enabling notifications cccd_uuid = "00002902-0000-1000-8000-00805f9b34fb" cccd = ch.getDescriptors(forUUID=cccd_uuid)[0] cccd.write(b"\x01\x00", True) # Enable notifications print("Subscribed to notifications") return peri p = None while True: if p: try: if p.waitForNotifications(1.0): continue print("Waiting for notifications...") except Exception as e: print(f"got some weird error\n{e}") p = None elif not p: p = connect_to_sensor() p.disconnect()
已尝试的解决措施
- 在外设脚本中实现重连策略,中断后立即重启广播;
- 在外设和中央脚本中添加异常处理,捕获并记录连接或通知处理过程中的错误。
预期结果
- 中断后立即重启广播,使中央设备能近乎持续地重连;
- 通过详细错误日志揭示中断原因,帮助定位并解决问题。
当前仍存在的问题
- 重连策略虽能快速恢复,但导致无规律的反复中断与重连循环,难以定位根因;
- 错误日志未显示具体异常,仅输出"Cancelled:"无额外详情。
外设端输出
No Connection, attempting to advertise Connection from Device(ADDR_PUBLIC, e4:aa:ea:fb:e0:32, CONNECTED) It's open # notification It's open # notification Cancelled: No Connection, attempting to advertise Connection from Device(ADDR_PUBLIC, e4:aa:ea:fb:e0:32, CONNECTED) It's open # notification Cancelled: No Connection, attempting to advertise Connection from Device(ADDR_PUBLIC, e4:aa:ea:fb:e0:32, CONNECTED) It's open # notification It's open # notification
使用bluetoothctl测试
在Ubuntu 22.04机器上用bluetoothctl测试显示,是外设主动断开连接而非中央设备。
内容的提问来源于stack exchange,提问作者green_rice
相关产品推荐
相关产品推荐

