ef4d485a by huangyf2

优化rss,优化连接速度

1 parent c428ab60
Showing 1 changed file with 107 additions and 51 deletions
...@@ -274,15 +274,17 @@ class BLEClient: ...@@ -274,15 +274,17 @@ class BLEClient:
274 274
275 async def _background_connect(self, peripheral_id, request_id): 275 async def _background_connect(self, peripheral_id, request_id):
276 """ 276 """
277 后台执行BLE连接任务 277 后台执行BLE连接任务 - 优化版本
278 策略: 278 策略:
279 1. 验证设备地址格式 279 1. 验证设备地址格式
280 2. 异步断开旧连接(不阻塞新连接) 280 2. 检查连接历史,快速重连已连接过的设备
281 3. 执行新连接(带超时) 281 3. 异步断开旧连接(不阻塞新连接)
282 4. 连接完成后发送状态通知 282 4. 执行新连接(带超时和重试机制)
283 5. 连接完成后发送状态通知并更新历史
283 """ 284 """
284 try: 285 try:
285 self._connecting = True 286 self._connecting = True
287 current_time = time.time()
286 288
287 # 步骤0: 验证设备地址格式 289 # 步骤0: 验证设备地址格式
288 if not peripheral_id or len(peripheral_id) < 12: 290 if not peripheral_id or len(peripheral_id) < 12:
...@@ -304,6 +306,35 @@ class BLEClient: ...@@ -304,6 +306,35 @@ class BLEClient:
304 self._connecting = False 306 self._connecting = False
305 return 307 return
306 308
309 # 优化策略1: 检查是否是最近连接过的设备,如果是且连接历史良好,使用更短的超时
310 connection_optimized = False
311 if peripheral_id in self._connection_history:
312 success_time, last_attempt, success_count = self._connection_history[peripheral_id]
313 # 如果最近30秒内成功连接过,且成功次数>=1,使用优化连接
314 if current_time - success_time < 30.0 and success_count >= 1:
315 connection_optimized = True
316 await log_message("连接", f"检测到快速重连设备: {peripheral_id} (历史成功: {success_count}次)")
317
318 # 优化策略2: 如果当前已连接的是同一设备,直接返回成功
319 if (self.client and self.client.is_connected and
320 self._last_connected_address == peripheral_id):
321 await log_message("连接", f"设备已连接: {peripheral_id}")
322 success_response = json.dumps({
323 "jsonrpc": "2.0",
324 "method": "connectionStatus",
325 "params": {
326 "connected": True,
327 "peripheralId": peripheral_id,
328 "cached": True
329 },
330 "id": request_id
331 })
332 await log_message("下发", success_response)
333 if self.websocket and not self.websocket.closed:
334 await self.websocket.send(success_response)
335 self._connecting = False
336 return
337
307 # 步骤1: 异步断开旧连接(最多等待1秒,超时后强制清理) 338 # 步骤1: 异步断开旧连接(最多等待1秒,超时后强制清理)
308 old_client = self.client 339 old_client = self.client
309 if old_client: 340 if old_client:
...@@ -337,15 +368,18 @@ class BLEClient: ...@@ -337,15 +368,18 @@ class BLEClient:
337 # 注意:BLE连接包含多个阶段: 368 # 注意:BLE连接包含多个阶段:
338 # 1. 建立物理连接(通常1-2秒) 369 # 1. 建立物理连接(通常1-2秒)
339 # 2. 发现服务(get_services)(通常3-8秒,是主要瓶颈) 370 # 2. 发现服务(get_services)(通常3-8秒,是主要瓶颈)
340 # 因此总超时设置为8秒,确保大多数设备能完成连接 371 # 优化:已连接过的设备使用更短的超时(6秒),新设备使用8秒
341 client = None 372 client = None
373 connect_timeout = 6.0 if connection_optimized else 8.0
374
342 try: 375 try:
343 # BleakClient的超时只影响物理连接阶段 376 # BleakClient的超时只影响物理连接阶段
344 client = BleakClient(peripheral_id, timeout=10.0) 377 client = BleakClient(peripheral_id, timeout=10.0)
345 client.set_disconnected_callback(self.on_disconnect) 378 client.set_disconnected_callback(self.on_disconnect)
346 379
347 # 连接操作,总超时8秒(覆盖物理连接+服务发现) 380 # 连接操作,根据连接历史调整超时
348 await asyncio.wait_for(client.connect(), timeout=8.0) 381 await log_message("连接", f"开始连接设备: {peripheral_id} (超时: {connect_timeout}秒)")
382 await asyncio.wait_for(client.connect(), timeout=connect_timeout)
349 383
350 # 验证连接状态 384 # 验证连接状态
351 if not client.is_connected: 385 if not client.is_connected:
...@@ -358,9 +392,17 @@ class BLEClient: ...@@ -358,9 +392,17 @@ class BLEClient:
358 392
359 # 连接成功,保存客户端引用 393 # 连接成功,保存客户端引用
360 self.client = client 394 self.client = client
395 self._last_connected_address = peripheral_id
361 self._connecting = False 396 self._connecting = False
362 client = None # 避免finally中重复清理 397 client = None # 避免finally中重复清理
363 398
399 # 更新连接历史
400 if peripheral_id in self._connection_history:
401 success_time, _, success_count = self._connection_history[peripheral_id]
402 self._connection_history[peripheral_id] = (current_time, current_time, success_count + 1)
403 else:
404 self._connection_history[peripheral_id] = (current_time, current_time, 1)
405
364 await log_message("连接", f"成功连接到设备: {peripheral_id}") 406 await log_message("连接", f"成功连接到设备: {peripheral_id}")
365 407
366 # 发送连接成功通知 408 # 发送连接成功通知
...@@ -379,12 +421,19 @@ class BLEClient: ...@@ -379,12 +421,19 @@ class BLEClient:
379 421
380 except asyncio.TimeoutError: 422 except asyncio.TimeoutError:
381 self._connecting = False 423 self._connecting = False
382 error_msg = "连接BLE设备超时(8秒),可能是服务发现阶段耗时过长" 424 error_msg = f"连接BLE设备超时({connect_timeout}秒),可能是服务发现阶段耗时过长"
383 await log_exception_async( 425 await log_exception_async(
384 asyncio.TimeoutError(error_msg), 426 asyncio.TimeoutError(error_msg),
385 "后台连接-连接超时" 427 "后台连接-连接超时"
386 ) 428 )
387 429
430 # 更新连接历史(记录失败)
431 if peripheral_id in self._connection_history:
432 success_time, _, success_count = self._connection_history[peripheral_id]
433 self._connection_history[peripheral_id] = (success_time, current_time, success_count)
434 else:
435 self._connection_history[peripheral_id] = (0, current_time, 0)
436
388 # 清理超时的client资源 437 # 清理超时的client资源
389 if client is not None: 438 if client is not None:
390 try: 439 try:
...@@ -510,6 +559,8 @@ class BLEClient: ...@@ -510,6 +559,8 @@ class BLEClient:
510 current_time = time.time() 559 current_time = time.time()
511 self._best_rssi_device = None 560 self._best_rssi_device = None
512 self._best_rssi_value = -999 561 self._best_rssi_value = -999
562 found = False
563 scan_error = None
513 564
514 # 清理过期缓存 565 # 清理过期缓存
515 expired_addresses = [ 566 expired_addresses = [
...@@ -544,57 +595,62 @@ class BLEClient: ...@@ -544,57 +595,62 @@ class BLEClient:
544 if not found: 595 if not found:
545 # 双重扫描:快速扫描后若未发现,再进行扩展扫描;发现即停 596 # 双重扫描:快速扫描后若未发现,再进行扩展扫描;发现即停
546 phases = [("active", 3.0), ("passive", 6.0)] 597 phases = [("active", 3.0), ("passive", 6.0)]
547 scan_error = None
548
549 for phase_index, (scan_mode, duration) in enumerate(phases, start=1):
550 self.target_device = None
551 self._scanner = None
552 598
553 try: 599 for phase_index, (scan_mode, duration) in enumerate(phases, start=1):
554 # 创建扫描器 600 self.target_device = None
555 self._scanner = BleakScanner(scanning_mode=scan_mode) 601 self._scanner = None
556 self._scanner.register_detection_callback(self.detection_callback)
557 print(f"开始第{phase_index}阶段扫描(模式: {scan_mode}, 时长: {duration}s)...")
558 602
559 # 启动扫描
560 try: 603 try:
561 await self._scanner.start() 604 # 创建扫描器
562 except Exception as e: 605 self._scanner = BleakScanner(scanning_mode=scan_mode)
563 await log_exception_async(e, f"扫描启动失败-阶段{phase_index}") 606 self._scanner.register_detection_callback(self.detection_callback)
564 scan_error = str(e) 607 print(f"开始第{phase_index}阶段扫描(模式: {scan_mode}, 时长: {duration}s)...")
565 continue
566
567 # 轮询检查是否已找到,找到则提前停止
568 start_ts = time.time()
569 while time.time() - start_ts < duration and not self.target_device:
570 await asyncio.sleep(0.1)
571 608
572 # 检查是否应该关闭 609 # 启动扫描
573 if self._shutdown:
574 break
575
576 except Exception as e:
577 await log_exception_async(e, f"扫描过程异常-阶段{phase_index}")
578 scan_error = str(e)
579 finally:
580 # 确保扫描器被停止和清理
581 if self._scanner is not None:
582 try: 610 try:
583 await self._scanner.stop() 611 await self._scanner.start()
584 except Exception as e: 612 except Exception as e:
585 await log_exception_async(e, f"扫描停止失败-阶段{phase_index}") 613 await log_exception_async(e, f"扫描启动失败-阶段{phase_index}")
586 pass 614 scan_error = str(e)
587 self._scanner = None 615 continue
616
617 # 轮询检查是否已找到,找到则提前停止
618 start_ts = time.time()
619 while time.time() - start_ts < duration and not self.target_device:
620 await asyncio.sleep(0.1)
621
622 # 检查是否应该关闭
623 if self._shutdown:
624 break
625
626 except Exception as e:
627 await log_exception_async(e, f"扫描过程异常-阶段{phase_index}")
628 scan_error = str(e)
629 finally:
630 # 确保扫描器被停止和清理
631 if self._scanner is not None:
632 try:
633 await self._scanner.stop()
634 except Exception as e:
635 await log_exception_async(e, f"扫描停止失败-阶段{phase_index}")
636 pass
637 self._scanner = None
638
639 # 等待一小段时间确保扫描完全停止
640 await asyncio.sleep(0.1)
588 641
589 # 等待一小段时间确保扫描完全停止 642 # 检查是否找到设备
590 await asyncio.sleep(0.1) 643 if self.target_device:
644 found = True
645 # 优先使用信号最强的设备
646 if self._best_rssi_device and self._best_rssi_value > -999:
647 self.target_device = self._best_rssi_device
648 break
649 else:
650 print(f"第{phase_index}阶段未找到设备")
591 651
592 # 检查是否找到设备 652 # 更新扫描时间
593 if self.target_device: 653 self._last_scan_time = time.time()
594 found = True
595 break
596 else:
597 print(f"第{phase_index}阶段未找到设备")
598 654
599 # 处理扫描结果 655 # 处理扫描结果
600 if found: 656 if found:
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!