日志异步处理,增加
Showing
1 changed file
with
292 additions
and
88 deletions
| 1 | # -*- coding: utf-8 -*- | 1 | # -*- coding: utf-8 -*- |
| 2 | """ | ||
| 3 | 高性能BLE客户端 - 优化版本 | ||
| 4 | 修复了以下问题: | ||
| 5 | 1. 内存泄漏 - 每次连接创建新实例导致资源无法释放 | ||
| 6 | 2. 日志阻塞 - 实现异步日志队列 | ||
| 7 | 3. 通知失效 - 完善连接状态检查和清理 | ||
| 8 | 4. WebSocket保活 - 添加ping/pong机制 | ||
| 9 | 5. 错误处理 - 全面增强异常捕获和处理 | ||
| 10 | """ | ||
| 2 | import sys | 11 | import sys |
| 3 | import asyncio | 12 | import asyncio |
| 4 | import websockets | 13 | import websockets |
| ... | @@ -9,6 +18,7 @@ import threading | ... | @@ -9,6 +18,7 @@ import threading |
| 9 | from collections import defaultdict | 18 | from collections import defaultdict |
| 10 | import socket | 19 | import socket |
| 11 | import time | 20 | import time |
| 21 | import traceback | ||
| 12 | 22 | ||
| 13 | import platform | 23 | import platform |
| 14 | 24 | ||
| ... | @@ -22,21 +32,58 @@ elif sys.platform.startswith('linux'): | ... | @@ -22,21 +32,58 @@ elif sys.platform.startswith('linux'): |
| 22 | print("当前运行在Linux系统") | 32 | print("当前运行在Linux系统") |
| 23 | elif sys.platform.startswith('darwin'): | 33 | elif sys.platform.startswith('darwin'): |
| 24 | print("当前运行在macOS系统") | 34 | print("当前运行在macOS系统") |
| 25 | # 添加线程锁以确保日志写入的原子性 | 35 | # 高性能日志系统 |
| 26 | write_lock = threading.Lock() | 36 | write_lock = threading.Lock() |
| 37 | _log_queue = None | ||
| 38 | _log_task = None | ||
| 39 | _log_dropped_count = 0 | ||
| 27 | 40 | ||
| 28 | def log_message_sync(direction, message): | 41 | def log_message_sync(direction, message): |
| 29 | """同步日志记录函数""" | 42 | """同步日志记录函数""" |
| 30 | log_entry = f"{direction}: {message}\n" | 43 | try: |
| 31 | print(log_entry, end='') # 控制台仍然输出 | 44 | log_entry = f"{direction}: {message}\n" |
| 32 | with write_lock: | 45 | print(log_entry, end='') # 控制台仍然输出 |
| 33 | with open('b.log', 'a', encoding='utf-8') as f: | 46 | |
| 34 | f.write(log_entry) | 47 | # 截断过长消息,避免写入过大的日志 |
| 48 | if len(log_entry) > 4000: | ||
| 49 | log_entry = log_entry[:4000] + "... [truncated]\n" | ||
| 50 | |||
| 51 | with write_lock: | ||
| 52 | with open('b.log', 'a', encoding='utf-8') as f: | ||
| 53 | f.write(log_entry) | ||
| 54 | except Exception: | ||
| 55 | pass # 日志失败不应影响主流程 | ||
| 56 | |||
| 57 | async def _log_writer_loop(): | ||
| 58 | """后台日志写入循环""" | ||
| 59 | global _log_queue | ||
| 60 | while True: | ||
| 61 | try: | ||
| 62 | item = await _log_queue.get() | ||
| 63 | if item is None: | ||
| 64 | break | ||
| 65 | direction, message = item | ||
| 66 | log_message_sync(direction, message) | ||
| 67 | except asyncio.CancelledError: | ||
| 68 | break | ||
| 69 | except Exception: | ||
| 70 | await asyncio.sleep(0.05) | ||
| 35 | 71 | ||
| 36 | async def log_message(direction, message): | 72 | async def log_message(direction, message): |
| 37 | """异步封装日志记录""" | 73 | """异步日志记录,非阻塞""" |
| 38 | loop = asyncio.get_event_loop() | 74 | global _log_queue, _log_task, _log_dropped_count |
| 39 | await loop.run_in_executor(None, log_message_sync, direction, message) | 75 | |
| 76 | # 首次调用时初始化 | ||
| 77 | if _log_queue is None: | ||
| 78 | _log_queue = asyncio.Queue(maxsize=1000) | ||
| 79 | _log_task = asyncio.create_task(_log_writer_loop()) | ||
| 80 | |||
| 81 | try: | ||
| 82 | _log_queue.put_nowait((direction, message)) | ||
| 83 | except asyncio.QueueFull: | ||
| 84 | _log_dropped_count += 1 | ||
| 85 | if _log_dropped_count % 100 == 1: | ||
| 86 | print(f"警告: 日志队列已满,已丢弃 {_log_dropped_count} 条日志") | ||
| 40 | 87 | ||
| 41 | def is_port_in_use(port, host='localhost'): | 88 | def is_port_in_use(port, host='localhost'): |
| 42 | """检查端口是否被占用""" | 89 | """检查端口是否被占用""" |
| ... | @@ -77,7 +124,9 @@ class BLEClient: | ... | @@ -77,7 +124,9 @@ class BLEClient: |
| 77 | self.services = [] | 124 | self.services = [] |
| 78 | self.optional_services = [] | 125 | self.optional_services = [] |
| 79 | self.websocket = None | 126 | self.websocket = None |
| 80 | self.notification_records = defaultdict(lambda: (None, 0)) # 特征ID: (最后消息, 时间戳) | 127 | self.notification_records = defaultdict(lambda: (None, 0.0)) # 特征ID: (最后消息, 时间戳) |
| 128 | self._notification_callbacks = {} # 存储通知回调,用于清理 | ||
| 129 | self._shutdown = False # 添加关闭标志 | ||
| 81 | 130 | ||
| 82 | def on_disconnect(self, client): | 131 | def on_disconnect(self, client): |
| 83 | print("BLE连接断开,关闭WebSocket") | 132 | print("BLE连接断开,关闭WebSocket") |
| ... | @@ -85,8 +134,13 @@ class BLEClient: | ... | @@ -85,8 +134,13 @@ class BLEClient: |
| 85 | asyncio.create_task(self.close_websocket()) | 134 | asyncio.create_task(self.close_websocket()) |
| 86 | 135 | ||
| 87 | async def close_websocket(self): | 136 | async def close_websocket(self): |
| 88 | await self.websocket.close() | 137 | if self.websocket: |
| 89 | self.websocket = None | 138 | try: |
| 139 | await self.websocket.close() | ||
| 140 | except Exception as e: | ||
| 141 | print(f"关闭WebSocket时出错: {e}") | ||
| 142 | finally: | ||
| 143 | self.websocket = None | ||
| 90 | 144 | ||
| 91 | def detection_callback(self, device, advertisement_data): | 145 | def detection_callback(self, device, advertisement_data): |
| 92 | if any(service_uuid in advertisement_data.service_uuids for service_uuid in self.services): | 146 | if any(service_uuid in advertisement_data.service_uuids for service_uuid in self.services): |
| ... | @@ -176,18 +230,44 @@ class BLEClient: | ... | @@ -176,18 +230,44 @@ class BLEClient: |
| 176 | elif method == "connect": | 230 | elif method == "connect": |
| 177 | peripheral_id = params.get("peripheralId") | 231 | peripheral_id = params.get("peripheralId") |
| 178 | if peripheral_id: | 232 | if peripheral_id: |
| 179 | self.client = BleakClient(peripheral_id) | 233 | # 如果已有连接,先断开 |
| 180 | self.client.set_disconnected_callback(self.on_disconnect) | 234 | if self.client and self.client.is_connected: |
| 181 | await self.client.connect() | 235 | try: |
| 236 | await self.client.disconnect() | ||
| 237 | except Exception: | ||
| 238 | pass | ||
| 182 | 239 | ||
| 183 | if self.client.is_connected: | 240 | try: |
| 184 | response = json.dumps({ | 241 | self.client = BleakClient(peripheral_id, timeout=10.0) # 添加超时 |
| 242 | self.client.set_disconnected_callback(self.on_disconnect) | ||
| 243 | await self.client.connect() | ||
| 244 | |||
| 245 | if self.client.is_connected: | ||
| 246 | response = json.dumps({ | ||
| 247 | "jsonrpc": "2.0", | ||
| 248 | "result": None, | ||
| 249 | "id": request_id | ||
| 250 | }) | ||
| 251 | await log_message("下发", response) | ||
| 252 | await websocket.send(response) | ||
| 253 | else: | ||
| 254 | error_response = json.dumps({ | ||
| 255 | "jsonrpc": "2.0", | ||
| 256 | "error": {"code": -1, "message": "连接失败"}, | ||
| 257 | "id": request_id | ||
| 258 | }) | ||
| 259 | await log_message("下发", error_response) | ||
| 260 | await websocket.send(error_response) | ||
| 261 | except Exception as e: | ||
| 262 | error_response = json.dumps({ | ||
| 185 | "jsonrpc": "2.0", | 263 | "jsonrpc": "2.0", |
| 186 | "result": None, | 264 | "error": {"code": -1, "message": f"连接异常: {str(e)}"}, |
| 187 | "id": request_id | 265 | "id": request_id |
| 188 | }) | 266 | }) |
| 189 | # await log_message("下发", response) | 267 | await log_message("下发", error_response) |
| 190 | await websocket.send(response) | 268 | await websocket.send(error_response) |
| 269 | if self.client: | ||
| 270 | self.client = None | ||
| 191 | 271 | ||
| 192 | elif method == "write": | 272 | elif method == "write": |
| 193 | service_id = params.get("serviceId") | 273 | service_id = params.get("serviceId") |
| ... | @@ -195,59 +275,117 @@ class BLEClient: | ... | @@ -195,59 +275,117 @@ class BLEClient: |
| 195 | message = params.get("message") | 275 | message = params.get("message") |
| 196 | encoding = params.get("encoding", "utf-8") | 276 | encoding = params.get("encoding", "utf-8") |
| 197 | 277 | ||
| 198 | if all([service_id, characteristic_id, message]): | 278 | if all([service_id, characteristic_id, message]) and self.client and self.client.is_connected: |
| 199 | if encoding == "base64": | 279 | try: |
| 200 | message_bytes = base64.b64decode(message) | 280 | if encoding == "base64": |
| 201 | print("write message_bytes",message_bytes) | 281 | message_bytes = base64.b64decode(message) |
| 202 | else: | 282 | print("write message_bytes",message_bytes) |
| 203 | print("write message",message) | 283 | else: |
| 204 | message_bytes = message.encode(encoding) | 284 | print("write message",message) |
| 205 | 285 | message_bytes = message.encode(encoding) | |
| 206 | 286 | ||
| 207 | await self.client.write_gatt_char(characteristic_id, message_bytes) | 287 | await self.client.write_gatt_char(characteristic_id, message_bytes) |
| 208 | response = json.dumps({ | 288 | response = json.dumps({ |
| 289 | "jsonrpc": "2.0", | ||
| 290 | "result": None, | ||
| 291 | "id": request_id | ||
| 292 | }) | ||
| 293 | await log_message("下发", response) | ||
| 294 | await websocket.send(response) | ||
| 295 | except Exception as e: | ||
| 296 | error_response = json.dumps({ | ||
| 297 | "jsonrpc": "2.0", | ||
| 298 | "error": {"code": -1, "message": f"写入失败: {str(e)}"}, | ||
| 299 | "id": request_id | ||
| 300 | }) | ||
| 301 | await log_message("下发", error_response) | ||
| 302 | await websocket.send(error_response) | ||
| 303 | else: | ||
| 304 | error_response = json.dumps({ | ||
| 209 | "jsonrpc": "2.0", | 305 | "jsonrpc": "2.0", |
| 210 | "result": None, | 306 | "error": {"code": -1, "message": "未连接或参数不全"}, |
| 211 | "id": request_id | 307 | "id": request_id |
| 212 | }) | 308 | }) |
| 213 | await log_message("下发", response) | 309 | await log_message("下发", error_response) |
| 214 | await websocket.send(response) | 310 | await websocket.send(error_response) |
| 215 | 311 | ||
| 216 | elif method == "read": | 312 | elif method == "read": |
| 217 | service_id = params.get("serviceId") | 313 | service_id = params.get("serviceId") |
| 218 | characteristic_id = params.get("characteristicId") | 314 | characteristic_id = params.get("characteristicId") |
| 219 | 315 | ||
| 220 | if all([service_id, characteristic_id]): | 316 | if all([service_id, characteristic_id]) and self.client and self.client.is_connected: |
| 221 | data = await self.client.read_gatt_char(characteristic_id) | 317 | try: |
| 222 | print('read-data',base64.decode(data)) | 318 | data = await self.client.read_gatt_char(characteristic_id) |
| 223 | response = json.dumps({ | 319 | print('read-data',data) |
| 320 | response = json.dumps({ | ||
| 321 | "jsonrpc": "2.0", | ||
| 322 | "result": { | ||
| 323 | "serviceId": service_id, | ||
| 324 | "characteristicId": characteristic_id, | ||
| 325 | "message": base64.b64encode(data).decode("utf-8") | ||
| 326 | }, | ||
| 327 | "id": request_id | ||
| 328 | }) | ||
| 329 | await log_message("下发", response) | ||
| 330 | await websocket.send(response) | ||
| 331 | except Exception as e: | ||
| 332 | error_response = json.dumps({ | ||
| 333 | "jsonrpc": "2.0", | ||
| 334 | "error": {"code": -1, "message": f"读取失败: {str(e)}"}, | ||
| 335 | "id": request_id | ||
| 336 | }) | ||
| 337 | await log_message("下发", error_response) | ||
| 338 | await websocket.send(error_response) | ||
| 339 | else: | ||
| 340 | error_response = json.dumps({ | ||
| 224 | "jsonrpc": "2.0", | 341 | "jsonrpc": "2.0", |
| 225 | "result": { | 342 | "error": {"code": -1, "message": "未连接或参数不全"}, |
| 226 | "serviceId": service_id, | ||
| 227 | "characteristicId": characteristic_id, | ||
| 228 | "message": base64.b64encode(data).decode("utf-8") | ||
| 229 | }, | ||
| 230 | "id": request_id | 343 | "id": request_id |
| 231 | }) | 344 | }) |
| 232 | await log_message("下发", response) | 345 | await log_message("下发", error_response) |
| 233 | await websocket.send(response) | 346 | await websocket.send(error_response) |
| 234 | 347 | ||
| 235 | elif method == "startNotifications": | 348 | elif method == "startNotifications": |
| 236 | service_id = params.get("serviceId") | 349 | service_id = params.get("serviceId") |
| 237 | characteristic_id = params.get("characteristicId") | 350 | characteristic_id = params.get("characteristicId") |
| 238 | 351 | ||
| 239 | if all([service_id, characteristic_id]): | 352 | if all([service_id, characteristic_id]) and self.client and self.client.is_connected: |
| 240 | await self.client.start_notify( | 353 | try: |
| 241 | characteristic_id, | 354 | # 如果已经监听,先停止旧的 |
| 242 | self.notification_handler(websocket, service_id, characteristic_id) | 355 | if characteristic_id in self._notification_callbacks: |
| 243 | ) | 356 | try: |
| 244 | response = json.dumps({ | 357 | await self.client.stop_notify(characteristic_id) |
| 358 | except Exception: | ||
| 359 | pass | ||
| 360 | |||
| 361 | # 创建新的通知处理器 | ||
| 362 | callback = self.notification_handler(websocket, service_id, characteristic_id) | ||
| 363 | await self.client.start_notify(characteristic_id, callback) | ||
| 364 | self._notification_callbacks[characteristic_id] = callback | ||
| 365 | |||
| 366 | response = json.dumps({ | ||
| 367 | "jsonrpc": "2.0", | ||
| 368 | "result": None, | ||
| 369 | "id": request_id | ||
| 370 | }) | ||
| 371 | await log_message("下发", response) | ||
| 372 | await websocket.send(response) | ||
| 373 | except Exception as e: | ||
| 374 | error_response = json.dumps({ | ||
| 375 | "jsonrpc": "2.0", | ||
| 376 | "error": {"code": -1, "message": f"启动通知失败: {str(e)}"}, | ||
| 377 | "id": request_id | ||
| 378 | }) | ||
| 379 | await log_message("下发", error_response) | ||
| 380 | await websocket.send(error_response) | ||
| 381 | else: | ||
| 382 | error_response = json.dumps({ | ||
| 245 | "jsonrpc": "2.0", | 383 | "jsonrpc": "2.0", |
| 246 | "result": None, | 384 | "error": {"code": -1, "message": "未连接或参数不全"}, |
| 247 | "id": request_id | 385 | "id": request_id |
| 248 | }) | 386 | }) |
| 249 | await log_message("下发", response) | 387 | await log_message("下发", error_response) |
| 250 | await websocket.send(response) | 388 | await websocket.send(error_response) |
| 251 | 389 | ||
| 252 | elif method == "ping": | 390 | elif method == "ping": |
| 253 | # 处理ping请求,返回pong响应 | 391 | # 处理ping请求,返回pong响应 |
| ... | @@ -259,56 +397,104 @@ class BLEClient: | ... | @@ -259,56 +397,104 @@ class BLEClient: |
| 259 | await log_message("下发", response) | 397 | await log_message("下发", response) |
| 260 | await websocket.send(response) | 398 | await websocket.send(response) |
| 261 | 399 | ||
| 262 | except json.JSONDecodeError: | 400 | except json.JSONDecodeError as e: |
| 263 | error_msg = json.dumps({ | 401 | error_msg = json.dumps({ |
| 264 | "jsonrpc": "2.0", | 402 | "jsonrpc": "2.0", |
| 265 | "result": {"message": "Parse error"}, | 403 | "error": {"code": -32700, "message": "Parse error", "data": str(e)}, |
| 266 | "id": None | 404 | "id": request.get("id") if request else None |
| 267 | }) | 405 | }) |
| 268 | await log_message("下发", error_msg) | 406 | await log_message("下发", error_msg) |
| 407 | try: | ||
| 408 | await websocket.send(error_msg) | ||
| 409 | except Exception: | ||
| 410 | pass | ||
| 269 | except Exception as e: | 411 | except Exception as e: |
| 412 | # 记录完整错误堆栈 | ||
| 413 | error_trace = traceback.format_exc() | ||
| 414 | print(f"处理请求时出错: {error_trace}") | ||
| 415 | |||
| 270 | error_msg = json.dumps({ | 416 | error_msg = json.dumps({ |
| 271 | "jsonrpc": "2.0", | 417 | "jsonrpc": "2.0", |
| 272 | "result": {"message": str(e)}, | 418 | "error": {"code": -32603, "message": "Internal error", "data": str(e)}, |
| 273 | "id": request.get("id") if request else None | 419 | "id": request.get("id") if request else None |
| 274 | }) | 420 | }) |
| 275 | await log_message("下发", error_msg) | 421 | await log_message("下发", error_msg) |
| 422 | try: | ||
| 423 | await websocket.send(error_msg) | ||
| 424 | except Exception: | ||
| 425 | pass | ||
| 276 | 426 | ||
| 277 | except websockets.exceptions.ConnectionClosed: | 427 | except websockets.exceptions.ConnectionClosed: |
| 278 | print("WebSocket连接关闭") | 428 | print("WebSocket连接关闭") |
| 279 | finally: | 429 | finally: |
| 430 | # 清理BLE连接和通知 | ||
| 431 | self._shutdown = True | ||
| 280 | if self.client and self.client.is_connected: | 432 | if self.client and self.client.is_connected: |
| 281 | await self.client.disconnect() | 433 | try: |
| 282 | self.client = None | 434 | # 停止所有通知 |
| 283 | self.target_device = None | 435 | for characteristic_id in list(self._notification_callbacks.keys()): |
| 436 | try: | ||
| 437 | await self.client.stop_notify(characteristic_id) | ||
| 438 | except Exception as e: | ||
| 439 | print(f"停止通知失败 {characteristic_id}: {e}") | ||
| 440 | |||
| 441 | # 断开连接 | ||
| 442 | await self.client.disconnect() | ||
| 443 | except Exception as e: | ||
| 444 | print(f"断开BLE连接失败: {e}") | ||
| 445 | finally: | ||
| 446 | self.client = None | ||
| 447 | self.target_device = None | ||
| 448 | self._notification_callbacks.clear() | ||
| 449 | self.notification_records.clear() | ||
| 284 | 450 | ||
| 285 | def notification_handler(self, websocket, service_id, characteristic_id): | 451 | def notification_handler(self, websocket, service_id, characteristic_id): |
| 286 | async def callback(sender, data): | 452 | async def callback(sender, data): |
| 287 | current_time = asyncio.get_event_loop().time() | 453 | try: |
| 288 | last_message, last_time = self.notification_records[characteristic_id] | 454 | # 检查websocket是否已关闭 |
| 289 | 455 | if self.websocket is None or self.websocket.closed or self._shutdown: | |
| 290 | # 解码当前数据用于比较 | 456 | return |
| 291 | current_message = base64.b64encode(data).decode('utf-8') | 457 | |
| 292 | print('notification_handler current_message',base64.b64decode(current_message)) | 458 | current_time = time.time() # 使用time.time()而不是event_loop.time() |
| 293 | 459 | last_message, last_time = self.notification_records[characteristic_id] | |
| 294 | # 过滤逻辑 | 460 | |
| 295 | if current_message == last_message and (current_time - last_time) < 0.5: | 461 | # 解码当前数据用于比较 |
| 296 | return | 462 | current_message = base64.b64encode(data).decode('utf-8') |
| 297 | 463 | print('notification_handler current_message',data) | |
| 298 | # 更新记录 | 464 | |
| 299 | self.notification_records[characteristic_id] = (current_message, current_time) | 465 | # 过滤逻辑 - 只在0.5秒内且消息完全相同时跳过 |
| 300 | 466 | if current_message == last_message and (current_time - last_time) < 0.5: | |
| 301 | response = json.dumps({ | 467 | return |
| 302 | "jsonrpc": "2.0", | 468 | |
| 303 | "method": "characteristicDidChange", | 469 | # 更新记录 |
| 304 | "params": { | 470 | self.notification_records[characteristic_id] = (current_message, current_time) |
| 305 | "serviceId": service_id, | 471 | |
| 306 | "characteristicId": characteristic_id, | 472 | response = json.dumps({ |
| 307 | "message": current_message | 473 | "jsonrpc": "2.0", |
| 308 | } | 474 | "method": "characteristicDidChange", |
| 309 | }) | 475 | "params": { |
| 310 | await log_message("下发", response) | 476 | "serviceId": service_id, |
| 311 | await websocket.send(response) | 477 | "characteristicId": characteristic_id, |
| 478 | "message": current_message | ||
| 479 | } | ||
| 480 | }) | ||
| 481 | |||
| 482 | # 使用非阻塞日志 | ||
| 483 | try: | ||
| 484 | await log_message("下发", response) | ||
| 485 | except Exception as e: | ||
| 486 | print(f"日志写入失败: {e}") | ||
| 487 | |||
| 488 | # 发送响应 | ||
| 489 | try: | ||
| 490 | await websocket.send(response) | ||
| 491 | except websockets.exceptions.ConnectionClosed: | ||
| 492 | print("WebSocket连接已关闭,停止发送通知") | ||
| 493 | self._shutdown = True | ||
| 494 | except Exception as e: | ||
| 495 | print(f"发送通知失败: {e}") | ||
| 496 | except Exception as e: | ||
| 497 | print(f"通知处理器出错: {e}") | ||
| 312 | return callback | 498 | return callback |
| 313 | 499 | ||
| 314 | async def check_port_and_start_server(port=20111, host='localhost'): | 500 | async def check_port_and_start_server(port=20111, host='localhost'): |
| ... | @@ -320,7 +506,11 @@ async def check_port_and_start_server(port=20111, host='localhost'): | ... | @@ -320,7 +506,11 @@ async def check_port_and_start_server(port=20111, host='localhost'): |
| 320 | print(f"端口 {port} 可用,正在启动服务...") | 506 | print(f"端口 {port} 可用,正在启动服务...") |
| 321 | server = await websockets.serve( | 507 | server = await websockets.serve( |
| 322 | lambda websocket, path: BLEClient().handle_client(websocket, path), | 508 | lambda websocket, path: BLEClient().handle_client(websocket, path), |
| 323 | host, port | 509 | host, port, |
| 510 | ping_interval=20, # 每20秒发送ping | ||
| 511 | ping_timeout=10, # 等待pong超时10秒 | ||
| 512 | max_size=2 * 1024 * 1024, # 最大消息大小2MB | ||
| 513 | close_timeout=5, # 关闭超时5秒 | ||
| 324 | ) | 514 | ) |
| 325 | 515 | ||
| 326 | print(f"WebSocket服务已启动: ws://{host}:{port}/scratch/ble") | 516 | print(f"WebSocket服务已启动: ws://{host}:{port}/scratch/ble") |
| ... | @@ -343,7 +533,21 @@ async def check_port_and_start_server(port=20111, host='localhost'): | ... | @@ -343,7 +533,21 @@ async def check_port_and_start_server(port=20111, host='localhost'): |
| 343 | async def main(): | 533 | async def main(): |
| 344 | server = await check_port_and_start_server() | 534 | server = await check_port_and_start_server() |
| 345 | if server: | 535 | if server: |
| 346 | await asyncio.Future() # 保持服务器运行 | 536 | try: |
| 537 | await asyncio.Future() # 保持服务器运行 | ||
| 538 | finally: | ||
| 539 | # 清理日志系统 | ||
| 540 | global _log_queue, _log_task | ||
| 541 | if _log_queue is not None: | ||
| 542 | try: | ||
| 543 | await _log_queue.put(None) | ||
| 544 | except Exception: | ||
| 545 | pass | ||
| 546 | if _log_task is not None: | ||
| 547 | try: | ||
| 548 | await _log_task | ||
| 549 | except Exception: | ||
| 550 | pass | ||
| 347 | 551 | ||
| 348 | if __name__ == "__main__": | 552 | if __name__ == "__main__": |
| 349 | asyncio.run(main()) | 553 | asyncio.run(main()) |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
-
Please register or sign in to post a comment