增加名字不为空,增加双重扫描
Showing
1 changed file
with
92 additions
and
28 deletions
| ... | @@ -131,20 +131,43 @@ class BLEClient: | ... | @@ -131,20 +131,43 @@ class BLEClient: |
| 131 | 131 | ||
| 132 | def on_disconnect(self, client): | 132 | def on_disconnect(self, client): |
| 133 | print("BLE连接断开,关闭WebSocket") | 133 | print("BLE连接断开,关闭WebSocket") |
| 134 | # 设置关闭标志 | ||
| 135 | self._shutdown = True | ||
| 136 | # 在事件循环中关闭WebSocket | ||
| 134 | if self.websocket and not self.websocket.closed: | 137 | if self.websocket and not self.websocket.closed: |
| 135 | asyncio.create_task(self.close_websocket()) | 138 | try: |
| 139 | # 尝试获取当前事件循环 | ||
| 140 | loop = asyncio.get_event_loop() | ||
| 141 | if loop.is_running(): | ||
| 142 | loop.create_task(self.close_websocket()) | ||
| 143 | except Exception: | ||
| 144 | # 如果没有事件循环,直接设置为None(延迟清理) | ||
| 145 | pass | ||
| 136 | 146 | ||
| 137 | async def close_websocket(self): | 147 | async def close_websocket(self): |
| 148 | """主动关闭WebSocket连接""" | ||
| 138 | if self.websocket: | 149 | if self.websocket: |
| 139 | try: | 150 | try: |
| 140 | await self.websocket.close() | 151 | if not self.websocket.closed: |
| 152 | # 使用1000状态码正常关闭 | ||
| 153 | await self.websocket.close(code=1000, reason="BLE connection closed") | ||
| 154 | print("WebSocket连接已关闭") | ||
| 141 | except Exception as e: | 155 | except Exception as e: |
| 142 | print(f"关闭WebSocket时出错: {e}") | 156 | print(f"关闭WebSocket时出错: {e}") |
| 143 | finally: | 157 | finally: |
| 144 | self.websocket = None | 158 | self.websocket = None |
| 159 | self._shutdown = True | ||
| 145 | 160 | ||
| 146 | def detection_callback(self, device, advertisement_data): | 161 | def detection_callback(self, device, advertisement_data): |
| 147 | if any(service_uuid in advertisement_data.service_uuids for service_uuid in self.services): | 162 | if any(service_uuid in advertisement_data.service_uuids for service_uuid in self.services): |
| 163 | # 优先使用广播包中的local_name | ||
| 164 | device_name = advertisement_data.local_name if advertisement_data.local_name else (device.name if device.name else "") | ||
| 165 | |||
| 166 | # 丢弃名字为空的设备 | ||
| 167 | if not device_name or device_name.strip() == "": | ||
| 168 | print(f"跳过名字为空的设备: {device.address}") | ||
| 169 | return None | ||
| 170 | |||
| 148 | self.target_device = (device, advertisement_data) | 171 | self.target_device = (device, advertisement_data) |
| 149 | if not self.target_device: | 172 | if not self.target_device: |
| 150 | print("未找到匹配设备") | 173 | print("未找到匹配设备") |
| ... | @@ -152,14 +175,15 @@ class BLEClient: | ... | @@ -152,14 +175,15 @@ class BLEClient: |
| 152 | else: | 175 | else: |
| 153 | device, adv_data = self.target_device | 176 | device, adv_data = self.target_device |
| 154 | print("\n找到目标设备:") | 177 | print("\n找到目标设备:") |
| 155 | print(f"设备名称: {device.name}") | 178 | print(f"设备名称(从广播包): {device_name}") |
| 156 | print(f"设备地址: {device.address}") | 179 | print(f"设备地址: {device.address}") |
| 157 | print(f"信号强度: {device.rssi} dBm") | 180 | print(f"信号强度: {device.rssi} dBm") |
| 158 | print("\n广播信息:") | 181 | print("\n广播信息:") |
| 159 | print(f"服务UUID列表: {adv_data.service_uuids}") | 182 | print(f"服务UUID列表: {adv_data.service_uuids}") |
| 160 | print(f"制造商数据: {adv_data.manufacturer_data}") | 183 | print(f"制造商数据: {adv_data.manufacturer_data}") |
| 161 | print(f"服务数据: {adv_data.service_data}") | 184 | print(f"服务数据: {adv_data.service_data}") |
| 162 | print(f"本地名称: {adv_data.local_name}") | 185 | print(f"本地名称(local_name): {adv_data.local_name}") |
| 186 | print(f"设备名称(device.name): {device.name if device.name else 'N/A'}") | ||
| 163 | # 发现设备后,尝试立即停止扫描 | 187 | # 发现设备后,尝试立即停止扫描 |
| 164 | try: | 188 | try: |
| 165 | if self._scanner is not None: | 189 | if self._scanner is not None: |
| ... | @@ -178,12 +202,18 @@ class BLEClient: | ... | @@ -178,12 +202,18 @@ class BLEClient: |
| 178 | 202 | ||
| 179 | async def handle_client(self, websocket, path): | 203 | async def handle_client(self, websocket, path): |
| 180 | self.websocket = websocket | 204 | self.websocket = websocket |
| 205 | self._shutdown = False # 重置关闭标志 | ||
| 181 | if path != "/scratch/ble": | 206 | if path != "/scratch/ble": |
| 182 | await websocket.close(code=1003, reason="Path not allowed") | 207 | await websocket.close(code=1003, reason="Path not allowed") |
| 183 | return | 208 | return |
| 184 | 209 | ||
| 185 | try: | 210 | try: |
| 186 | async for message in websocket: | 211 | async for message in websocket: |
| 212 | # 检查是否应该关闭连接 | ||
| 213 | if self._shutdown: | ||
| 214 | print("检测到关闭标志,终止消息接收") | ||
| 215 | break | ||
| 216 | |||
| 187 | try: | 217 | try: |
| 188 | await log_message("接收", message) | 218 | await log_message("接收", message) |
| 189 | request = json.loads(message) | 219 | request = json.loads(message) |
| ... | @@ -230,24 +260,28 @@ class BLEClient: | ... | @@ -230,24 +260,28 @@ class BLEClient: |
| 230 | 260 | ||
| 231 | if found: | 261 | if found: |
| 232 | device, adv_data = self.target_device | 262 | device, adv_data = self.target_device |
| 263 | # 优先使用广播包中的local_name,如果没有则使用device.name | ||
| 264 | device_name = adv_data.local_name if adv_data.local_name else (device.name if device.name else "") | ||
| 233 | discover_response = json.dumps({ | 265 | discover_response = json.dumps({ |
| 234 | "jsonrpc": "2.0", | 266 | "jsonrpc": "2.0", |
| 235 | "method": "didDiscoverPeripheral", | 267 | "method": "didDiscoverPeripheral", |
| 236 | "params": { | 268 | "params": { |
| 237 | "name": device.name, | 269 | "name": device_name, |
| 238 | "peripheralId": device.address, | 270 | "peripheralId": device.address, |
| 239 | "rssi": device.rssi | 271 | "rssi": device.rssi |
| 240 | } | 272 | } |
| 241 | }) | 273 | }) |
| 242 | await log_message("下发", discover_response) | 274 | await log_message("下发", discover_response) |
| 275 | if not websocket.closed: | ||
| 243 | await websocket.send(discover_response) | 276 | await websocket.send(discover_response) |
| 244 | 277 | ||
| 245 | result_response = json.dumps({ | 278 | result_response = json.dumps({ |
| 246 | "jsonrpc": "2.0", | 279 | "jsonrpc": "2.0", |
| 247 | "result": None, | 280 | "result": None, |
| 248 | "id": request_id | 281 | "id": request_id if request_id else 0 |
| 249 | }) | 282 | }) |
| 250 | await log_message("下发", result_response) | 283 | await log_message("下发", result_response) |
| 284 | if not websocket.closed: | ||
| 251 | await websocket.send(result_response) | 285 | await websocket.send(result_response) |
| 252 | 286 | ||
| 253 | elif method == "connect": | 287 | elif method == "connect": |
| ... | @@ -272,22 +306,25 @@ class BLEClient: | ... | @@ -272,22 +306,25 @@ class BLEClient: |
| 272 | "id": request_id | 306 | "id": request_id |
| 273 | }) | 307 | }) |
| 274 | await log_message("下发", response) | 308 | await log_message("下发", response) |
| 309 | if not websocket.closed: | ||
| 275 | await websocket.send(response) | 310 | await websocket.send(response) |
| 276 | else: | 311 | else: |
| 277 | error_response = json.dumps({ | 312 | error_response = json.dumps({ |
| 278 | "jsonrpc": "2.0", | 313 | "jsonrpc": "2.0", |
| 279 | "error": {"code": -1, "message": "连接失败"}, | 314 | "result": None, |
| 280 | "id": request_id | 315 | "id": request_id if request_id else 0 |
| 281 | }) | 316 | }) |
| 282 | await log_message("下发", error_response) | 317 | await log_message("下发", error_response) |
| 318 | if not websocket.closed: | ||
| 283 | await websocket.send(error_response) | 319 | await websocket.send(error_response) |
| 284 | except Exception as e: | 320 | except Exception as e: |
| 285 | error_response = json.dumps({ | 321 | error_response = json.dumps({ |
| 286 | "jsonrpc": "2.0", | 322 | "jsonrpc": "2.0", |
| 287 | "error": {"code": -1, "message": f"连接异常: {str(e)}"}, | 323 | "result": None, |
| 288 | "id": request_id | 324 | "id": request_id if request_id else 0 |
| 289 | }) | 325 | }) |
| 290 | await log_message("下发", error_response) | 326 | await log_message("下发", error_response) |
| 327 | if not websocket.closed: | ||
| 291 | await websocket.send(error_response) | 328 | await websocket.send(error_response) |
| 292 | if self.client: | 329 | if self.client: |
| 293 | self.client = None | 330 | self.client = None |
| ... | @@ -314,22 +351,25 @@ class BLEClient: | ... | @@ -314,22 +351,25 @@ class BLEClient: |
| 314 | "id": request_id | 351 | "id": request_id |
| 315 | }) | 352 | }) |
| 316 | await log_message("下发", response) | 353 | await log_message("下发", response) |
| 354 | if not websocket.closed: | ||
| 317 | await websocket.send(response) | 355 | await websocket.send(response) |
| 318 | except Exception as e: | 356 | except Exception as e: |
| 319 | error_response = json.dumps({ | 357 | error_response = json.dumps({ |
| 320 | "jsonrpc": "2.0", | 358 | "jsonrpc": "2.0", |
| 321 | "error": {"code": -1, "message": f"写入失败: {str(e)}"}, | 359 | "result": None, |
| 322 | "id": request_id | 360 | "id": request_id if request_id else 0 |
| 323 | }) | 361 | }) |
| 324 | await log_message("下发", error_response) | 362 | await log_message("下发", error_response) |
| 363 | if not websocket.closed: | ||
| 325 | await websocket.send(error_response) | 364 | await websocket.send(error_response) |
| 326 | else: | 365 | else: |
| 327 | error_response = json.dumps({ | 366 | error_response = json.dumps({ |
| 328 | "jsonrpc": "2.0", | 367 | "jsonrpc": "2.0", |
| 329 | "error": {"code": -1, "message": "未连接或参数不全"}, | 368 | "result": None, |
| 330 | "id": request_id | 369 | "id": request_id if request_id else 0 |
| 331 | }) | 370 | }) |
| 332 | await log_message("下发", error_response) | 371 | await log_message("下发", error_response) |
| 372 | if not websocket.closed: | ||
| 333 | await websocket.send(error_response) | 373 | await websocket.send(error_response) |
| 334 | 374 | ||
| 335 | elif method == "read": | 375 | elif method == "read": |
| ... | @@ -338,7 +378,11 @@ class BLEClient: | ... | @@ -338,7 +378,11 @@ class BLEClient: |
| 338 | 378 | ||
| 339 | if all([service_id, characteristic_id]) and self.client and self.client.is_connected: | 379 | if all([service_id, characteristic_id]) and self.client and self.client.is_connected: |
| 340 | try: | 380 | try: |
| 341 | data = await self.client.read_gatt_char(characteristic_id) | 381 | # 添加读取超时,避免长时间阻塞 |
| 382 | data = await asyncio.wait_for( | ||
| 383 | self.client.read_gatt_char(characteristic_id), | ||
| 384 | timeout=10.0 | ||
| 385 | ) | ||
| 342 | print('read-data',data) | 386 | print('read-data',data) |
| 343 | response = json.dumps({ | 387 | response = json.dumps({ |
| 344 | "jsonrpc": "2.0", | 388 | "jsonrpc": "2.0", |
| ... | @@ -350,22 +394,36 @@ class BLEClient: | ... | @@ -350,22 +394,36 @@ class BLEClient: |
| 350 | "id": request_id | 394 | "id": request_id |
| 351 | }) | 395 | }) |
| 352 | await log_message("下发", response) | 396 | await log_message("下发", response) |
| 397 | # 检查WebSocket状态后再发送 | ||
| 398 | if not websocket.closed: | ||
| 353 | await websocket.send(response) | 399 | await websocket.send(response) |
| 400 | except asyncio.TimeoutError: | ||
| 401 | error_response = json.dumps({ | ||
| 402 | "jsonrpc": "2.0", | ||
| 403 | "result": None, | ||
| 404 | "id": request_id if request_id else 0 | ||
| 405 | }) | ||
| 406 | await log_message("下发", error_response) | ||
| 407 | if not websocket.closed: | ||
| 408 | await websocket.send(error_response) | ||
| 354 | except Exception as e: | 409 | except Exception as e: |
| 355 | error_response = json.dumps({ | 410 | error_response = json.dumps({ |
| 356 | "jsonrpc": "2.0", | 411 | "jsonrpc": "2.0", |
| 357 | "error": {"code": -1, "message": f"读取失败: {str(e)}"}, | 412 | "result": None, |
| 358 | "id": request_id | 413 | "id": request_id if request_id else 0 |
| 359 | }) | 414 | }) |
| 360 | await log_message("下发", error_response) | 415 | await log_message("下发", error_response) |
| 416 | # 检查WebSocket状态后再发送 | ||
| 417 | if not websocket.closed: | ||
| 361 | await websocket.send(error_response) | 418 | await websocket.send(error_response) |
| 362 | else: | 419 | else: |
| 363 | error_response = json.dumps({ | 420 | error_response = json.dumps({ |
| 364 | "jsonrpc": "2.0", | 421 | "jsonrpc": "2.0", |
| 365 | "error": {"code": -1, "message": "未连接或参数不全"}, | 422 | "result": None, |
| 366 | "id": request_id | 423 | "id": request_id if request_id else 0 |
| 367 | }) | 424 | }) |
| 368 | await log_message("下发", error_response) | 425 | await log_message("下发", error_response) |
| 426 | if not websocket.closed: | ||
| 369 | await websocket.send(error_response) | 427 | await websocket.send(error_response) |
| 370 | 428 | ||
| 371 | elif method == "startNotifications": | 429 | elif method == "startNotifications": |
| ... | @@ -392,22 +450,25 @@ class BLEClient: | ... | @@ -392,22 +450,25 @@ class BLEClient: |
| 392 | "id": request_id | 450 | "id": request_id |
| 393 | }) | 451 | }) |
| 394 | await log_message("下发", response) | 452 | await log_message("下发", response) |
| 453 | if not websocket.closed: | ||
| 395 | await websocket.send(response) | 454 | await websocket.send(response) |
| 396 | except Exception as e: | 455 | except Exception as e: |
| 397 | error_response = json.dumps({ | 456 | error_response = json.dumps({ |
| 398 | "jsonrpc": "2.0", | 457 | "jsonrpc": "2.0", |
| 399 | "error": {"code": -1, "message": f"启动通知失败: {str(e)}"}, | 458 | "result": None, |
| 400 | "id": request_id | 459 | "id": request_id if request_id else 0 |
| 401 | }) | 460 | }) |
| 402 | await log_message("下发", error_response) | 461 | await log_message("下发", error_response) |
| 462 | if not websocket.closed: | ||
| 403 | await websocket.send(error_response) | 463 | await websocket.send(error_response) |
| 404 | else: | 464 | else: |
| 405 | error_response = json.dumps({ | 465 | error_response = json.dumps({ |
| 406 | "jsonrpc": "2.0", | 466 | "jsonrpc": "2.0", |
| 407 | "error": {"code": -1, "message": "未连接或参数不全"}, | 467 | "result": None, |
| 408 | "id": request_id | 468 | "id": request_id if request_id else 0 |
| 409 | }) | 469 | }) |
| 410 | await log_message("下发", error_response) | 470 | await log_message("下发", error_response) |
| 471 | if not websocket.closed: | ||
| 411 | await websocket.send(error_response) | 472 | await websocket.send(error_response) |
| 412 | 473 | ||
| 413 | elif method == "ping": | 474 | elif method == "ping": |
| ... | @@ -415,19 +476,21 @@ class BLEClient: | ... | @@ -415,19 +476,21 @@ class BLEClient: |
| 415 | response = json.dumps({ | 476 | response = json.dumps({ |
| 416 | "jsonrpc": "2.0", | 477 | "jsonrpc": "2.0", |
| 417 | "result": {"pong": True, "timestamp": int(time.time())}, | 478 | "result": {"pong": True, "timestamp": int(time.time())}, |
| 418 | "id": request_id | 479 | "id": request_id if request_id else 0 |
| 419 | }) | 480 | }) |
| 420 | await log_message("下发", response) | 481 | await log_message("下发", response) |
| 482 | if not websocket.closed: | ||
| 421 | await websocket.send(response) | 483 | await websocket.send(response) |
| 422 | 484 | ||
| 423 | except json.JSONDecodeError as e: | 485 | except json.JSONDecodeError as e: |
| 424 | error_msg = json.dumps({ | 486 | error_msg = json.dumps({ |
| 425 | "jsonrpc": "2.0", | 487 | "jsonrpc": "2.0", |
| 426 | "error": {"code": -32700, "message": "Parse error", "data": str(e)}, | 488 | "result": None, |
| 427 | "id": request.get("id") if request else None | 489 | "id": request.get("id") if request else 0 |
| 428 | }) | 490 | }) |
| 429 | await log_message("下发", error_msg) | 491 | await log_message("下发", error_msg) |
| 430 | try: | 492 | try: |
| 493 | if not websocket.closed: | ||
| 431 | await websocket.send(error_msg) | 494 | await websocket.send(error_msg) |
| 432 | except Exception: | 495 | except Exception: |
| 433 | pass | 496 | pass |
| ... | @@ -438,11 +501,12 @@ class BLEClient: | ... | @@ -438,11 +501,12 @@ class BLEClient: |
| 438 | 501 | ||
| 439 | error_msg = json.dumps({ | 502 | error_msg = json.dumps({ |
| 440 | "jsonrpc": "2.0", | 503 | "jsonrpc": "2.0", |
| 441 | "error": {"code": -32603, "message": "Internal error", "data": str(e)}, | 504 | "result": None, |
| 442 | "id": request.get("id") if request else None | 505 | "id": request.get("id") if request else 0 |
| 443 | }) | 506 | }) |
| 444 | await log_message("下发", error_msg) | 507 | await log_message("下发", error_msg) |
| 445 | try: | 508 | try: |
| 509 | if not websocket.closed: | ||
| 446 | await websocket.send(error_msg) | 510 | await websocket.send(error_msg) |
| 447 | except Exception: | 511 | except Exception: |
| 448 | pass | 512 | pass | ... | ... |
-
Please register or sign in to post a comment