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

使用Bleak模块连接BLE设备时遭遇连接超时问题求助

BLE设备连接失败(AsyncTimeoutError)排查与修复方案

问题背景

使用Bleak官方示例代码连接BLE设备,昨日可成功连接两次,但之后无法建立连接。根据设备文档,其广播时长为10.248秒,已将扫描超时设为10秒、连接超时设为22秒,仍触发AsyncTimeoutError;调整多种超时参数后问题依旧。

可能原因

  • 设备广播异常:设备进入低功耗/休眠模式,广播间隔变大或停止广播
  • 扫描阶段漏检:find_device_by_address的扫描窗口未覆盖设备广播周期
  • 连接握手超时:设备响应慢,或本地系统BLE栈资源不足
  • 绑定状态冲突:设备记录了旧的绑定信息,拒绝新连接请求

排查步骤

  1. 验证设备广播状态:用BLE调试工具(如nRF Connect)扫描设备,确认设备是否在正常广播,记录广播间隔和时长
  2. 重置设备:重启BLE设备,排除低功耗模式导致的广播异常
  3. 清理本地BLE缓存:
    • Windows:设备管理器中删除对应BLE设备,重新扫描
    • macOS:蓝牙偏好设置中移除设备,重启蓝牙
    • Linux:通过bluetoothctl执行remove <设备地址>清理缓存
  4. 延长扫描超时:设置扫描超时为设备广播时长的3-5倍,确保覆盖多个广播周期

优化后的代码

针对扫描和连接阶段的问题,优化代码如下:

import asyncio
import platform
import sys
from bleak import BleakClient, BleakScanner
from bleak.exc import BleakError, AsyncTimeoutError

ADDRESS = (
    "F5:8B:A2:4C:AD:9C"
    if platform.system() != "Darwin"
    else "B9EA5233-37EF-4DD6-87A8-2A875E821C46"
)

async def scan_device(ble_address: str, scan_timeout: int = 30):
    """带回调的设备扫描,确保捕获到设备广播"""
    found_device = None
    def detection_callback(device, advertisement_data):
        nonlocal found_device
        if device.address == ble_address:
            print(f"扫描到目标设备: {device.name or '未命名设备'}")
            found_device = device

    scanner = BleakScanner(detection_callback=detection_callback)
    await scanner.start()
    await asyncio.sleep(scan_timeout)
    await scanner.stop()
    return found_device

async def main(ble_address: str):
    max_retries = 3
    for retry in range(max_retries):
        try:
            print(f"第 {retry+1} 次尝试连接...")
            # 延长扫描超时至30秒,覆盖多个广播周期
            device = await scan_device(ble_address, scan_timeout=30)
            if not device:
                raise BleakError(f"未找到地址为 {ble_address} 的设备")
            
            # 连接超时设为30秒,适配设备可能的慢响应
            async with BleakClient(device, timeout=30.0) as client:
                print("连接成功!")
                print("设备服务列表:")
                for service in client.services:
                    print(f"- {service.uuid}: {service.description}")
                return
        except AsyncTimeoutError:
            print("连接超时,准备重试...")
        except BleakError as e:
            print(f"错误信息: {e}")
    print(f"已尝试 {max_retries} 次,均未成功连接")

if __name__ == "__main__":
    target_address = sys.argv[1] if len(sys.argv) == 2 else ADDRESS
    asyncio.run(main(target_address))

验证建议

  • 运行优化后的代码,查看是否能扫描到目标设备
  • 如果扫描到但连接超时,检查设备是否需要配对,或设备的连接响应逻辑
  • 用BLE调试工具手动连接设备,确认设备本身是否能正常响应连接请求

内容的提问来源于stack exchange,提问作者Nguyễn Thuận Hải

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 06:55:19