ef4d485a by huangyf2

优化rss,优化连接速度

1 parent c428ab60
Showing 1 changed file with 65 additions and 9 deletions
......@@ -274,15 +274,17 @@ class BLEClient:
async def _background_connect(self, peripheral_id, request_id):
"""
后台执行BLE连接任务
后台执行BLE连接任务 - 优化版本
策略:
1. 验证设备地址格式
2. 异步断开旧连接(不阻塞新连接)
3. 执行新连接(带超时)
4. 连接完成后发送状态通知
2. 检查连接历史,快速重连已连接过的设备
3. 异步断开旧连接(不阻塞新连接)
4. 执行新连接(带超时和重试机制)
5. 连接完成后发送状态通知并更新历史
"""
try:
self._connecting = True
current_time = time.time()
# 步骤0: 验证设备地址格式
if not peripheral_id or len(peripheral_id) < 12:
......@@ -304,6 +306,35 @@ class BLEClient:
self._connecting = False
return
# 优化策略1: 检查是否是最近连接过的设备,如果是且连接历史良好,使用更短的超时
connection_optimized = False
if peripheral_id in self._connection_history:
success_time, last_attempt, success_count = self._connection_history[peripheral_id]
# 如果最近30秒内成功连接过,且成功次数>=1,使用优化连接
if current_time - success_time < 30.0 and success_count >= 1:
connection_optimized = True
await log_message("连接", f"检测到快速重连设备: {peripheral_id} (历史成功: {success_count}次)")
# 优化策略2: 如果当前已连接的是同一设备,直接返回成功
if (self.client and self.client.is_connected and
self._last_connected_address == peripheral_id):
await log_message("连接", f"设备已连接: {peripheral_id}")
success_response = json.dumps({
"jsonrpc": "2.0",
"method": "connectionStatus",
"params": {
"connected": True,
"peripheralId": peripheral_id,
"cached": True
},
"id": request_id
})
await log_message("下发", success_response)
if self.websocket and not self.websocket.closed:
await self.websocket.send(success_response)
self._connecting = False
return
# 步骤1: 异步断开旧连接(最多等待1秒,超时后强制清理)
old_client = self.client
if old_client:
......@@ -337,15 +368,18 @@ class BLEClient:
# 注意:BLE连接包含多个阶段:
# 1. 建立物理连接(通常1-2秒)
# 2. 发现服务(get_services)(通常3-8秒,是主要瓶颈)
# 因此总超时设置为8秒,确保大多数设备能完成连接
# 优化:已连接过的设备使用更短的超时(6秒),新设备使用8秒
client = None
connect_timeout = 6.0 if connection_optimized else 8.0
try:
# BleakClient的超时只影响物理连接阶段
client = BleakClient(peripheral_id, timeout=10.0)
client.set_disconnected_callback(self.on_disconnect)
# 连接操作,总超时8秒(覆盖物理连接+服务发现)
await asyncio.wait_for(client.connect(), timeout=8.0)
# 连接操作,根据连接历史调整超时
await log_message("连接", f"开始连接设备: {peripheral_id} (超时: {connect_timeout}秒)")
await asyncio.wait_for(client.connect(), timeout=connect_timeout)
# 验证连接状态
if not client.is_connected:
......@@ -358,9 +392,17 @@ class BLEClient:
# 连接成功,保存客户端引用
self.client = client
self._last_connected_address = peripheral_id
self._connecting = False
client = None # 避免finally中重复清理
# 更新连接历史
if peripheral_id in self._connection_history:
success_time, _, success_count = self._connection_history[peripheral_id]
self._connection_history[peripheral_id] = (current_time, current_time, success_count + 1)
else:
self._connection_history[peripheral_id] = (current_time, current_time, 1)
await log_message("连接", f"成功连接到设备: {peripheral_id}")
# 发送连接成功通知
......@@ -379,12 +421,19 @@ class BLEClient:
except asyncio.TimeoutError:
self._connecting = False
error_msg = "连接BLE设备超时(8秒),可能是服务发现阶段耗时过长"
error_msg = f"连接BLE设备超时({connect_timeout}秒),可能是服务发现阶段耗时过长"
await log_exception_async(
asyncio.TimeoutError(error_msg),
"后台连接-连接超时"
)
# 更新连接历史(记录失败)
if peripheral_id in self._connection_history:
success_time, _, success_count = self._connection_history[peripheral_id]
self._connection_history[peripheral_id] = (success_time, current_time, success_count)
else:
self._connection_history[peripheral_id] = (0, current_time, 0)
# 清理超时的client资源
if client is not None:
try:
......@@ -510,6 +559,8 @@ class BLEClient:
current_time = time.time()
self._best_rssi_device = None
self._best_rssi_value = -999
found = False
scan_error = None
# 清理过期缓存
expired_addresses = [
......@@ -544,7 +595,6 @@ class BLEClient:
if not found:
# 双重扫描:快速扫描后若未发现,再进行扩展扫描;发现即停
phases = [("active", 3.0), ("passive", 6.0)]
scan_error = None
for phase_index, (scan_mode, duration) in enumerate(phases, start=1):
self.target_device = None
......@@ -592,10 +642,16 @@ class BLEClient:
# 检查是否找到设备
if self.target_device:
found = True
# 优先使用信号最强的设备
if self._best_rssi_device and self._best_rssi_value > -999:
self.target_device = self._best_rssi_device
break
else:
print(f"第{phase_index}阶段未找到设备")
# 更新扫描时间
self._last_scan_time = time.time()
# 处理扫描结果
if found:
device, adv_data = self.target_device
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!