如何实现BTLE设备(Sensirion SHT41x)的可靠蓝牙连接?
Windows笔记本连接Sensirion SHT41x BTLE设备连接可靠性提升方案
问题背景
Windows笔记本与Sensirion SHT41x BTLE设备(距离半米)连接时,仅约1/10的成功率,连接失败时抛出错误:
raise BleakDeviceNotFoundError( bleak.exc.BleakDeviceNotFoundError: Device with address ... was not found.
已尝试的操作:
- 重新运行脚本
- 开关笔记本蓝牙
- 移除设备电池重启设备
初始测试脚本:
import asyncio from bleak import BleakClient address = "..." async def connect_device(): async with BleakClient(address) as client: connected = await client.is_connected() print(f"Connected: {connected}") disconnected = await client.disconnect() print(f"Disonnected: {disconnected}") asyncio.run(connect_device())
添加重试逻辑后的脚本仍多数失败:
import time import asyncio from bleak import BleakClient from loguru import logger async def just_connect(mac): async with BleakClient(mac) as client: pass await asyncio.sleep(2) mac = "C5:5A:42:A4:3C:80" tries = 10 results = {} start = time.time() timeout = 12 for try_ in range(tries): try: await asyncio.wait_for(just_connect(mac), timeout) logger.info(f"try {try_} succeeded") except Exception as e: logger.info(f"try {try_} failed due to {type(e).__name__}: {e}")
典型失败日志:
2024-06-02 15:25:25.346 | INFO | __main__:<module>:24 - try 0 failed due to BleakDeviceNotFoundError: Device with address C5:5A:42:A4:3C:80 was not found. 2024-06-02 15:25:35.366 | INFO | __main__:<module>:24 - try 1 failed due to BleakDeviceNotFoundError: Device with address C5:5A:42:A4:3C:80 was not found. 2024-06-02 15:25:45.377 | INFO | __main__:<module>:24 - try 2 failed due to BleakDeviceNotFoundError: Device with address C5:5A:42:A4:3C:80 was not found. 2024-06-02 15:25:55.907 | INFO | __main__:<module>:24 - try 3 failed due to TimeoutError: 2024-06-02 15:26:05.941 | INFO | __main__:<module>:24 - try 4 failed due to BleakDeviceNotFoundError: Device with address C5:5A:42:A4:3C:80 was not found. 2024-06-02 15:26:17.953 | INFO | __main__:<module>:24 - try 5 failed due to TimeoutError: 2024-06-02 15:26:27.951 | INFO | __main__:<module>:24 - try 6 failed due to BleakDeviceNotFoundError: Device with address C5:5A:42:A4:3C:80 was not found. 2024-06-02 15:26:39.963 | INFO | __main__:<module>:24 - try 7 failed due to TimeoutError: 2024-06-02 15:26:51.971 | INFO | __main__:<module>:24 - try 8 failed due to TimeoutError: 2024-06-02 15:27:01.978 | INFO | __main__:<module>:24 - try 9 failed due to BleakDeviceNotFoundError: Device with address C5:5A:42:A4:3C:80 was not found.
提升连接可靠性的具体方案
1. 明确BLE设备地址类型
Windows下SHT41x可能使用随机BLE地址,默认Bleak按公共地址查找会导致设备找不到。先扫描确认地址类型:
from bleak import BleakScanner import asyncio async def scan_devices(): devices = await BleakScanner.discover(timeout=5) for d in devices: print(f"设备名称: {d.name}, 地址: {d.address}, 地址类型: {d.address_type}") asyncio.run(scan_devices())
然后在连接时指定地址类型:
async def just_connect(mac): # 按扫描到的地址类型填写,通常为"random" async with BleakClient(mac, address_type="random") as client: if client.is_connected: logger.info("连接成功") await asyncio.sleep(1)
2. 先扫描再连接,避免直接用MAC硬连
直接通过MAC连接容易因设备未被扫描到失败,改为先扫描确认设备存在再发起连接:
import asyncio from bleak import BleakClient, BleakScanner from loguru import logger TARGET_MAC = "C5:5A:42:A4:3C:80" async def scan_and_connect(): # 延长扫描时间确保捕获设备信号 scanner = BleakScanner() await scanner.start() await asyncio.sleep(3) devices = scanner.discovered_devices await scanner.stop() target_device = next((d for d in devices if d.address == TARGET_MAC), None) if not target_device: logger.error("扫描未找到目标设备") return False # 使用扫描到的设备对象连接,而非仅MAC try: async with BleakClient(target_device, timeout=15) as client: if client.is_connected: logger.info("连接成功") return True except Exception as e: logger.error(f"连接失败: {type(e).__name__}: {e}") return False async def retry_connection(max_tries=5): for try_num in range(max_tries): success = await scan_and_connect() if success: return True logger.info(f"第{try_num+1}次尝试失败,等待2秒后重试") await asyncio.sleep(2) return False asyncio.run(retry_connection())
3. 调整Windows蓝牙栈设置
- 更新蓝牙驱动:前往笔记本厂商官网下载最新蓝牙适配器驱动,旧驱动常存在BLE兼容性问题。
- 禁用蓝牙节能:打开设备管理器 → 蓝牙适配器 → 属性 → 电源管理,取消勾选"允许计算机关闭此设备以节约电源",避免系统休眠蓝牙适配器。
- 减少干扰:暂时关闭笔记本附近其他BLE设备(如耳机、蓝牙鼠标),减少信道冲突。
4. 优化Bleak连接参数
- 延长连接超时:Windows下BLE协商耗时更长,设置
timeout=15避免过早触发超时。 - 禁用缓存:添加
cached=False参数,强制每次重新扫描设备,避免使用过期的设备缓存:
async with BleakClient(target_device, timeout=15, cached=False) as client: # ...
5. 检查SHT41x设备配置
- 确认设备持续广播:部分BLE传感器会进入低功耗休眠模式停止广播,查看SHT41x文档调整广播间隔,确保设备处于持续可发现状态。
- 重置设备蓝牙:若设备支持,通过官方工具重置蓝牙配置,恢复默认广播参数。
内容的提问来源于stack exchange,提问作者Dr-Nuke
相关产品推荐
相关产品推荐

