优化rss,优化连接速度
Showing
1 changed file
with
65 additions
and
9 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,7 +595,6 @@ class BLEClient: | ... | @@ -544,7 +595,6 @@ 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 | 598 | ||
| 549 | for phase_index, (scan_mode, duration) in enumerate(phases, start=1): | 599 | for phase_index, (scan_mode, duration) in enumerate(phases, start=1): |
| 550 | self.target_device = None | 600 | self.target_device = None |
| ... | @@ -592,10 +642,16 @@ class BLEClient: | ... | @@ -592,10 +642,16 @@ class BLEClient: |
| 592 | # 检查是否找到设备 | 642 | # 检查是否找到设备 |
| 593 | if self.target_device: | 643 | if self.target_device: |
| 594 | found = True | 644 | found = True |
| 645 | # 优先使用信号最强的设备 | ||
| 646 | if self._best_rssi_device and self._best_rssi_value > -999: | ||
| 647 | self.target_device = self._best_rssi_device | ||
| 595 | break | 648 | break |
| 596 | else: | 649 | else: |
| 597 | print(f"第{phase_index}阶段未找到设备") | 650 | print(f"第{phase_index}阶段未找到设备") |
| 598 | 651 | ||
| 652 | # 更新扫描时间 | ||
| 653 | self._last_scan_time = time.time() | ||
| 654 | |||
| 599 | # 处理扫描结果 | 655 | # 处理扫描结果 |
| 600 | if found: | 656 | if found: |
| 601 | device, adv_data = self.target_device | 657 | device, adv_data = self.target_device | ... | ... |
-
Please register or sign in to post a comment