Kaynağa Gözat

封装socket

rambo 9 ay önce
ebeveyn
işleme
f8a2f48afd

+ 4 - 2
python/.env

@@ -14,5 +14,7 @@ port=7074
 works=1
 # 日志相关
 log_file_name="app.log" #日志名称
-max_bytes=102400 #最大字节数
-backup_counts=3 #备份数量
+#最大字节数
+max_bytes=102400 
+#备份数量
+backup_counts=3 

+ 2 - 1
python/.gitignore

@@ -1,2 +1,3 @@
 .venv/
-venv/
+venv/
+*.log

+ 44 - 2
python/app.log

@@ -1,2 +1,44 @@
-2025-03-11 13:06:36,268 - api - index - line:6 - INFO - Starting
-2025-03-11 13:06:50,590 - api - scanSerials - line:19 - INFO - Starting
+2025-03-12 14:03:39,841 - socket_server - connect - line:12 - INFO - socket 已连接
+2025-03-12 14:05:31,496 - socket_server - disconnect - line:16 - INFO - socket 连接断开
+2025-03-12 14:05:34,257 - socket_server - connect - line:12 - INFO - socket 已连接
+2025-03-12 14:06:54,447 - socket_server - disconnect - line:16 - INFO - socket 连接断开
+2025-03-12 14:21:23,734 - socket_server - connect - line:12 - INFO - socket 已连接
+2025-03-12 14:23:09,042 - socket_server - connect - line:20 - INFO - socket 已连接
+2025-03-12 14:24:32,744 - socket_server - connect - line:20 - INFO - socket 已连接
+2025-03-12 14:25:20,512 - socket_server - connect - line:20 - INFO - socket 已连接
+2025-03-12 14:25:22,337 - socket_server - websocket_endpoint - line:50 - INFO - received
+2025-03-12 14:25:54,458 - socket_server - connect - line:20 - INFO - socket 已连接
+2025-03-12 14:25:56,339 - socket_server - websocket_endpoint - line:50 - INFO - received
+2025-03-12 14:25:58,392 - socket_server - websocket_endpoint - line:50 - INFO - received
+2025-03-12 14:26:03,341 - socket_server - websocket_endpoint - line:50 - INFO - received
+2025-03-12 14:26:29,330 - socket_server - disconnect - line:24 - INFO - socket 连接断开
+2025-03-12 14:26:31,913 - socket_server - connect - line:20 - INFO - socket 已连接
+2025-03-12 14:26:33,224 - socket_server - websocket_endpoint - line:50 - INFO - received
+2025-03-12 14:27:11,415 - socket_server - disconnect - line:24 - INFO - socket 连接断开
+2025-03-12 14:27:14,591 - socket_server - connect - line:20 - INFO - socket 已连接
+2025-03-12 14:27:15,969 - socket_server - websocket_endpoint - line:50 - INFO - received
+2025-03-12 14:27:30,720 - socket_server - disconnect - line:24 - INFO - socket 连接断开
+2025-03-12 14:27:35,133 - socket_server - connect - line:20 - INFO - socket 已连接
+2025-03-12 14:27:36,077 - socket_server - websocket_endpoint - line:50 - INFO - received
+2025-03-12 14:28:58,922 - socket_server - connect - line:20 - INFO - socket 已连接
+2025-03-12 14:28:59,917 - socket_server - websocket_endpoint - line:50 - INFO - received
+2025-03-12 14:32:07,862 - socket_server - connect - line:20 - INFO - socket 已连接
+2025-03-12 14:32:31,556 - socket_server - connect - line:20 - INFO - socket 已连接
+2025-03-12 14:34:19,163 - socket_server - connect - line:20 - INFO - socket 已连接
+2025-03-12 14:34:19,244 - socket_server - disconnect - line:24 - INFO - socket 连接断开
+2025-03-12 14:34:22,248 - socket_server - connect - line:20 - INFO - socket 已连接
+2025-03-12 14:35:29,837 - socket_server - connect - line:20 - INFO - socket 已连接
+2025-03-12 14:36:01,118 - socket_server - connect - line:20 - INFO - socket 已连接
+2025-03-12 14:36:28,454 - socket_server - disconnect - line:24 - INFO - socket 连接断开
+2025-03-12 14:36:33,564 - socket_server - connect - line:20 - INFO - socket 已连接
+2025-03-12 14:36:45,141 - socket_server - disconnect - line:24 - INFO - socket 连接断开
+2025-03-12 14:36:50,811 - socket_server - connect - line:20 - INFO - socket 已连接
+2025-03-12 14:41:45,404 - socket_server - disconnect - line:24 - INFO - socket 连接断开
+2025-03-12 14:45:59,588 - socket_server - connect - line:20 - INFO - socket 已连接
+2025-03-12 14:46:39,681 - socket_server - connect - line:20 - INFO - socket 已连接
+2025-03-12 14:51:29,907 - socket_server - disconnect - line:24 - INFO - socket 连接断开
+2025-03-12 14:59:55,546 - connect_manager - connect - line:10 - INFO - socket 已连接
+2025-03-12 15:01:06,750 - connect_manager - connect - line:10 - INFO - socket 已连接
+2025-03-12 15:01:23,755 - connect_manager - connect - line:10 - INFO - socket 已连接
+2025-03-12 15:02:13,301 - connect_manager - connect - line:10 - INFO - socket 已连接
+2025-03-12 15:02:24,400 - connect_manager - connect - line:10 - INFO - socket 已连接

+ 3 - 4
python/index.py

@@ -2,8 +2,7 @@ import sys
 import uvicorn
 import signal
 from api import *
-from sockets import *
-
+from sockets.socket_server import *
 def handle_shutdown(signum, frame):
     """关闭系统应用服务"""
     sys.exit(0)
@@ -12,6 +11,8 @@ def handle_shutdown(signum, frame):
 if __name__ == "__main__":
     signal.signal(signal.SIGINT, handle_shutdown)
     signal.signal(signal.SIGTERM, handle_shutdown)
+    # 控制台默认关闭输出信息,如果想要查看控制台输出,请单独启动服务 npm run dev-python
+    print("python server is running at port:", PORT)
     # uvicorn会多创建一个进程,并且stdio独立于控制台,如果(开发时)出现进程没有关闭,可尝试关闭终端
     uvicorn.run(
         APP_RUN,
@@ -20,5 +21,3 @@ if __name__ == "__main__":
         reload=IS_DEBUG,
         workers=int(APP_WORKS),
     )
-    # 控制台默认关闭输出信息,如果想要查看控制台输出,请单独启动服务 npm run dev-python
-    print("python server is running at port:", PORT)

+ 3 - 0
python/logger.py

@@ -1,5 +1,6 @@
 import logging.handlers
 import logging
+import sys
 # 导入设置
 from settings import LOG_FILE_NAME, MAX_BYTES, BACKUP_COUNTS
 
@@ -7,9 +8,11 @@ from settings import LOG_FILE_NAME, MAX_BYTES, BACKUP_COUNTS
 logger = logging.getLogger()
 logger.setLevel(logging.INFO)
 ch = logging.StreamHandler()
+# ch.setLevel(logging.DEBUG) 
 fh = logging.handlers.RotatingFileHandler(
     str(LOG_FILE_NAME),
     mode="a",
+    encoding="utf-8",
     maxBytes=int(MAX_BYTES),
     backupCount=int(BACKUP_COUNTS),
 )

+ 145 - 0
python/mcu/DeviceControl.py

@@ -0,0 +1,145 @@
+import serial.tools.list_ports
+import time
+# mcu命令
+class DeviceControl:
+
+    def scan_serial_port(self) -> dict:
+        # 获取所有可用串口列表
+        ports_dict = {}
+        ports = serial.tools.list_ports.comports()
+        # 遍历所有端口并打印信息
+        for port in ports:
+            if "CH340" in port.description:
+                ports_dict[port.name] = {
+                    "name": port.name,
+                    "device": port.device,
+                    "description": port.description,
+                    "hwid": port.hwid,
+                    "manufacturer": port.manufacturer,
+                    "product": port.product,
+                    "serial_number": port.serial_number,
+                }
+        if len(ports_dict) <= 0:
+            return {}
+        return ports_dict
+
+    def add_port(self, port_name, port_value=None):
+        # port_value :串口基础信息
+        # todo 根据prot_value 信息自动进行连接
+        print("add", port_name)
+        # 对没有连接的设备进行尝试连接
+        self.sign_data.emit(
+            {
+                "_type": "show_info",
+                "plugins_mode": "auto_select_com",
+                "data": {"text": "开始识别接口:{}".format(port_name)},
+            }
+        )
+        time.sleep(1)
+        """
+        步骤:
+        1、进行临时连接,并发送命令,成功后,自动连接对应设备
+        """
+        try:
+            # 尝试使用115200波特率链接
+            serial_handle = serial.Serial(port=port_name, baudrate=115200, timeout=0.5)
+        except:
+            self.sign_data.emit(
+                {
+                    "_type": "show_info",
+                    "plugins_mode": "auto_select_com",
+                    "data": {"text": "串口:{} 被占用,或无法识别".format(port_name)},
+                }
+            )
+            print("串口:{} 被占用".format(port_name))
+            return
+
+        time.sleep(2)
+        print("开始发送命令")
+        data = [90, 1]
+        try:
+            serial_handle.flushInput()  # 尝试重置输入缓冲区
+        except serial.SerialTimeoutException:
+            print("超时错误:无法在规定时间内重置输入缓冲区。")
+            serial_handle.close()
+            return
+        print("尝试写入数据")
+
+        buf = bytearray(b"")
+        buf.extend([0x55, 0x55, (0xFF & len(data))])
+        buf.extend(data)
+        buf.extend([0xFF & ~sum(data)])
+        try:
+            self.receive_data = b""
+            serial_handle.write(buf)
+        except serial.SerialTimeoutException:
+            print("写入数据错误")
+            serial_handle.close()
+            return
+
+        time.sleep(0.3)
+        print("尝试接收命令")
+        receive_data = self.read_cmd(serial_handle)
+        device_id = 0
+
+        if receive_data:
+            print("receive_data", receive_data)
+            if receive_data[0] == 90:
+                connect_flag = receive_data[1]
+                device_id = receive_data[2]
+
+        print("关闭串口:{}".format(port_name))
+        serial_handle.close()
+
+        if device_id > 0:
+            if device_id == 1:
+                self.windows.mcu.to_connect_com(port_name, is_test=False)
+                self.sign_data.emit(
+                    {
+                        "_type": "show_info",
+                        "plugins_mode": "auto_select_com",
+                        "data": {"text": "MCU开始连接"},
+                    }
+                )
+                self.connected_ports_dict[port_name] = "MCU"
+            if device_id == 2:
+                self.windows.remote_control.to_connect_com(port_name, is_test=False)
+                self.sign_data.emit(
+                    {
+                        "_type": "show_info",
+                        "plugins_mode": "auto_select_com",
+                        "data": {"text": "开始连接遥控器"},
+                    }
+                )
+                self.connected_ports_dict[port_name] = "有线遥控器"
+
+            # RemoteControlV2 新版遥控器 2024-12-02
+            if device_id == 4:
+                self.windows.remote_control_v2.to_connect_com(port_name, is_test=False)
+                self.sign_data.emit(
+                    {
+                        "_type": "show_info",
+                        "plugins_mode": "auto_select_com",
+                        "data": {"text": "开始连接遥控器V2"},
+                    }
+                )
+                self.connected_ports_dict[port_name] = "无线遥控器V2"
+
+            self.sign_data.emit(
+                {
+                    "_type": "select_port_name",
+                    "plugins_mode": "auto_select_com",
+                    "data": {
+                        "device_name": "mcu" if device_id == 1 else "remote_control",
+                        "port_name": port_name,
+                    },
+                }
+            )
+        else:
+            print("串口无法识别")
+            # 走其他途径处理
+
+        # 检查当前MCU链接是否正常
+        # 正常跳过;记录为其他列表
+        # 不正常进行尝试连接
+        # 连接不上,记录为其他列表

+ 0 - 0
python/mcu/__init__.py


+ 1 - 1
python/middleware.py

@@ -1,6 +1,6 @@
 from typing import Union, Optional
 from fastapi import FastAPI, Request, Body, Form, Query
-from fastapi.websockets import WebSocket
+from fastapi.websockets import WebSocket, WebSocketDisconnect
 from fastapi.exceptions import RequestValidationError
 from fastapi.responses import JSONResponse
 from fastapi.staticfiles import StaticFiles

+ 0 - 7
python/sockets.py

@@ -1,7 +0,0 @@
-from models import *
-@app.websocket("/ws")
-async def websocket_endpoint(websocket: WebSocket):
-    await websocket.accept()
-    while True:
-        data = await websocket.receive_text()
-        await websocket.send_text(f"Message text was: {data}")

+ 0 - 0
python/sockets/__init__.py


+ 21 - 0
python/sockets/connect_manager.py

@@ -0,0 +1,21 @@
+from models import WebSocket
+from logger import logger
+class ConnectionManager:
+    def __init__(self):
+        self.active_connections: list[WebSocket] = []
+
+    async def connect(self, websocket: WebSocket):
+        await websocket.accept()
+        self.active_connections.append(websocket)
+        logger.info("socket 已连接")
+
+    def disconnect(self, websocket: WebSocket):
+        self.active_connections.remove(websocket)
+        logger.info("socket 连接断开")
+
+    async def send_personal_message(self, message: str, websocket: WebSocket):
+        await websocket.send_json(message)
+
+    async def broadcast(self, message: str):
+        for connection in self.active_connections:
+            await connection.send_json(message)

+ 42 - 0
python/sockets/socket_server.py

@@ -0,0 +1,42 @@
+import json
+import asyncio
+from models import *
+from .connect_manager import ConnectionManager
+
+def jsonMessage(code=0, msg="", data: object = None):
+    """json字符串数据"""
+    jsonData = {"code": code, "msg": msg, "data": data}
+    return json.dumps(jsonData)
+manager = ConnectionManager()
+
+
+
+
+@app.websocket("/ws")
+async def websocket_endpoint(websocket: WebSocket):
+    await manager.connect(websocket)
+    try:
+        while True:
+            '''接收json数据'''
+            data = await websocket.receive_json()
+            # 处理发送消息逻辑
+            await handlerSend(data,websocket)
+            # await manager.broadcast(f"Client # says: {data}")
+    except WebSocketDisconnect:
+        data = jsonMessage(code=1,data=None,msg="socket 内部错误")
+        await manager.broadcast(data,websocket)
+        manager.disconnect(websocket)
+
+async def handlerSend(receiveData,websocket):
+    # 处理消息发送逻辑
+    jsonType = receiveData.get("type")
+    match jsonType:
+        case 'ping':
+            '''发送心跳'''
+            data = jsonMessage("pong")
+            await manager.send_personal_message(data,websocket)
+        case 'pong':
+            '''发送心跳'''
+            pass
+
+