Browse Source

设备连接流程

rambo 9 months ago
parent
commit
c1bca6dabc

+ 4 - 1
python/.gitignore

@@ -1,3 +1,6 @@
 .venv/
 venv/
-*.log
+*.log
+*.log.*
+resources/
+custom_plugins/

+ 1 - 1
python/config.ini

@@ -4,7 +4,7 @@ app_name=智慧拍-后端应用
 # 应用版本号
 version=1.0.0
 # 应用host地址
-host=127.0.0.1
+host=10.56.42.176
 # 应用服务启动名称
 app_run=api:app
 # 端口号

+ 2 - 3
python/mcu/BaseClass.py

@@ -9,9 +9,8 @@ class BaseClass:
 
     def sendSocketMessage(self, code=0, msg="", data=None, msg_type=""):
         data = {"code": code, "msg": msg, "data": data, "msg_type": msg_type}
-        # loop = asyncio.get_event_loop()
-        # loop.create_task(self.websocket_manager.broadcast(data))
-        message_queue.put(data)
+        loop = asyncio.get_event_loop()
+        loop.create_task(message_queue.put(data))
     def change_hex_to_int(self,_bytearray):
         return ' '.join([hex(x) for x in _bytearray])
 

+ 68 - 44
python/mcu/BlueToothMode.py

@@ -3,6 +3,8 @@ import time
 from bleak import BleakScanner, BleakClient
 import threading
 from collections import deque
+
+from networkx import is_connected
 from utils.SingletonType import SingletonType
 from .RemoteControlV2 import RemoteControlV2
 from .BaseClass import BaseClass
@@ -45,6 +47,8 @@ class BlueToothMode(BaseClass,metaclass=SingletonType):
 
     async def scan_for_esp32(self):
         """扫描附近的BLE设备,并寻找ESP32"""
+        if self.connect_state == True:
+            return
         print("Scanning for ESP32 devices...*****************")
         try:
             devices = await BleakScanner.discover()
@@ -84,6 +88,13 @@ class BlueToothMode(BaseClass,metaclass=SingletonType):
         if "remote" in name:
             self.print_error("71  关闭蓝牙连接{}-{}".format(address, name))
             self.remote_control_v2.close_bluetooth_connect()
+            self.connect_state = False
+            self.receive_data = b""
+            self.devices = {}
+            self.devices_name = {}
+            self.last_value = None
+            self.retry_num = 0
+            self.last_error = ""
 
     async def handle_disconnect(self, client):
         """处理断开连接事件"""
@@ -121,71 +132,76 @@ class BlueToothMode(BaseClass,metaclass=SingletonType):
         self.print_error("""连接到指定地址的ESP32设备并监听通知""")
         while True:
             # try:
-                async with BleakClient(address) as client:
-                    if not client.is_connected:
-                        self.print_error("Failed to connect to the device.")
-                        self.devices[address]["connect_state"] = False
-                        self.disconnect_device(
+            if len(self.devices) == 0:
+                break
+            async with BleakClient(address) as client:
+                if not client.is_connected:
+                    self.print_error("Failed to connect to the device.")
+                    self.devices[address]["connect_state"] = False
+                    self.disconnect_device(
                             address=address, name=self.devices[address]["name"]
                         )
-                        continue
-                    self.devices[address]["connect_state"] = True
-                    self.print_error(f"Connected to {address}")
-                    # 获取服务和特征(假设你已经知道要监听的特征UUID)
-                    services = await client.get_services()
-                    for service in services:
-                        for char in service.characteristics:
-                            if "notify" in char.properties:
-                                self.print_error(
+                    continue
+                if len(self.devices) == 0:
+                    break
+                self.devices[address]["connect_state"] = True
+                self.print_error(f"Connected to {address}")
+                # 获取服务和特征(假设你已经知道要监听的特征UUID)
+                services = await client.get_services()
+                for service in services:
+                    for char in service.characteristics:
+                        if "notify" in char.properties:
+                            self.print_error(
                                     f"Subscribing to characteristic: {char.uuid}"
                                 )
-                                await client.start_notify(
+                            await client.start_notify(
                                     char,
                                     lambda char, data: asyncio.create_task(
                                         self.notification_handler(address, char, data)
                                     ),
                                 )
 
-                    # 进入一个简单的循环,保持连接
-                    self.print_error(
+                # 进入一个简单的循环,保持连接
+                self.print_error(
                         "进入一个简单的循环  保持连接", self.devices[address]["name"]
                     )
-                    self.connect_device(
+                self.connect_device(
                         address=address, name=self.devices[address]["name"]
                     )
-                    self.retry_num += 1
-                    while True:
-                        if not client.is_connected:
-                            self.print_error(
+                self.retry_num += 1
+                while True:
+                    if not client.is_connected:
+                        self.print_error(
                                 f"Device {address} disconnected unexpectedly."
                             )
-                            with self._lock:
-                                self.disconnect_device(
+                        with self._lock:
+                            self.disconnect_device(
                                     address=address, name=self.devices[address]["name"]
                                 )
-                                self.devices[address]["connect_state"] = False
-                            break
-
-                        if self.devices[address]["send_queue"]:
-                            with self._lock:
-                                send_data = self.devices[address][
+                            self.devices[address]["connect_state"] = False
+                        break
+                    if len(self.devices) == 0:
+                        break
+                    if self.devices[address]["send_queue"]:
+                        with self._lock:
+                            send_data = self.devices[address][
                                     "send_queue"
                                 ].popleft()
-                                # print("-----------> send_data:", self.change_hex_to_10_int(send_data))
-                            await self.write_characteristic(
+                            # print("-----------> send_data:", self.change_hex_to_10_int(send_data))
+                        await self.write_characteristic(
                                 client, char.uuid, send_data
                             )
-                            await asyncio.sleep(0.01)
-
-                        await asyncio.sleep(0.02)
-            # except Exception as e:
-            #     with self._lock:
-            #         self.disconnect_device(
-            #             address=address, name=self.devices[address]["name"]
-            #         )
-            #         self.devices[address]["connect_state"] = False
-            #     print(f"Error during connection or listening: {e}")
-            #     await asyncio.sleep(2)  # 发生错误时等待一段时间再重试
+                        await asyncio.sleep(0.01)
+
+                    await asyncio.sleep(0.02)
+        # except Exception as e:
+        #     with self._lock:
+        #         self.disconnect_device(
+        #             address=address, name=self.devices[address]["name"]
+        #         )
+        #         self.devices[address]["connect_state"] = False
+        #     print(f"Error during connection or listening: {e}")
+        #     await asyncio.sleep(2)  # 发生错误时等待一段时间再重试
 
     async def main_func(self):
         """主函数"""
@@ -200,6 +216,15 @@ class BlueToothMode(BaseClass,metaclass=SingletonType):
         #                          }
         # self.devices_name[_name] = address
         # asyncio.create_task(self.connect_and_listen(address))
+        if self.connect_state == True:
+            print('蓝牙已连接,不可重新连接')
+            message = {
+                "_type": "show_info",
+                "plugins_mode": "remote_control",
+                "data": "遥控设备V2 打开蓝牙成功",
+            }
+            self.sendSocketMessage(code=0, msg="遥控设备V2 打开蓝牙成功", data=message)
+            return
         await self.scan_for_esp32()
         # 定期重新扫描以发现新设备
         while True:
@@ -208,7 +233,6 @@ class BlueToothMode(BaseClass,metaclass=SingletonType):
             else:
                 await asyncio.sleep(3)
             await self.scan_for_esp32()
-
     def run(self):
         self.print_error("开启蓝牙扫描")
         asyncio.run(self.main_func())

+ 18 - 8
python/mcu/DeviceControl.py

@@ -16,6 +16,7 @@ class DeviceControl(BaseClass,metaclass=SingletonType):
         self.p_list = []
         self.temp_ports_dict = {}
         self.is_running = False
+        self.connect_state = False
 
     def scan_serial_port(self) -> dict:
         # 获取所有可用串口列表
@@ -156,7 +157,6 @@ class DeviceControl(BaseClass,metaclass=SingletonType):
         # 不正常进行尝试连接
         # 连接不上,记录为其他列表
 
-
     def to_connect_com(self, port_name):
         # 关闭串口
         print("to_connect_com", port_name)
@@ -235,9 +235,7 @@ class DeviceControl(BaseClass,metaclass=SingletonType):
                     data=message_data,
                 )
                 self.connect_state = True
-                if not self.is_running:
-                    print("MCU start")
-                    self.is_running = True
+                self.is_running = True
                 print("MCU 已连接")
                 self.port_name = port_name
                 return
@@ -258,10 +256,23 @@ class DeviceControl(BaseClass,metaclass=SingletonType):
         self.port_name = ""
         if self.serial_ins:
             self.serial_ins.close_serial_port()
+            self.is_running = False
             self.connect_state = False
+            self.connected_ports_dict = {}  # 已连接的ports
+            self.p_list = []
+            self.temp_ports_dict = {}
+            print("关闭MCU")
 
 
 async def checkMcuConnection(device_ctrl: DeviceControl):
+    if device_ctrl.is_running == True:
+        message = {
+            "_type": "select_port_name",
+            "plugins_mode": "auto_select_com",
+            "data": device_ctrl.temp_ports_dict,
+        }
+        device_ctrl.sendSocketMessage(code=0, msg="MCU连接成功", data=message)
+        return
     """实时检测串口是否连接"""
     while True:
         await asyncio.sleep(0.5)
@@ -275,7 +286,6 @@ async def checkMcuConnection(device_ctrl: DeviceControl):
             print("串口未连接,请检查")
             device_ctrl.sendSocketMessage(code=1, msg="串口未连接,请检查")
             continue
-
         if ports_dict:
             for index, _i in enumerate(device_ctrl.p_list):
                 if _i not in ports_dict:
@@ -283,8 +293,8 @@ async def checkMcuConnection(device_ctrl: DeviceControl):
                     device_ctrl.remove_port(_p)
             for _port_name, _port_value in ports_dict.items():
                 if _port_name not in device_ctrl.p_list:
-                    # try:
+                    try:
                         device_ctrl.p_list.append(_port_name)
                         device_ctrl.add_port_by_linkage(_port_name)
-                    # except BaseException as e:
-                        # print("串口不存在{} {}".format(_port_name, e))
+                    except BaseException as e:
+                        print("串口不存在{} {}".format(_port_name, e))

+ 1 - 0
python/mcu/RemoteControlV2.py

@@ -125,6 +125,7 @@ class RemoteControlV2(BaseClass):
             print(message)
             self.sendSocketMessage(code=1, msg="遥控设备V2 蓝牙断开", data=message)
             self.close_connect()
+            print("关闭蓝牙")
 
     def set_voltage_value(self, voltage_value=None, voltage_text=None):
         if self.is_running:

BIN
python/requestments.txt


+ 6 - 2
python/sockets/connect_manager.py

@@ -1,8 +1,9 @@
 from models import WebSocket
 from logger import logger
 import json
-
+from starlette.websockets import WebSocketState
 class ConnectionManager:
+    is_connected = False
     def __init__(self):
         self.active_connections: list[WebSocket] = []
 
@@ -14,6 +15,7 @@ class ConnectionManager:
     async def connect(self, websocket: WebSocket):
         '''连接事件'''
         await websocket.accept()
+        self.is_connected = True
         self.active_connections.append(websocket)
         logger.info("socket 已连接")
 
@@ -31,5 +33,7 @@ class ConnectionManager:
     async def broadcast(self, message: str):
         """广播消息"""
         for connection in self.active_connections:
+            if connection.client_state == WebSocketState.DISCONNECTED:
+                continue
+            print("connection", connection.client_state)
             await connection.send_json(message)
-

+ 15 - 1
python/sockets/message_handler.py

@@ -1,6 +1,8 @@
 from .connect_manager import ConnectionManager
 from models import WebSocket
-import json
+import json, asyncio
+from mcu.DeviceControl import DeviceControl, checkMcuConnection
+from mcu.BlueToothMode import BlueToothMode
 
 # socket消息发送逻辑处理方法
 async def handlerSend(
@@ -26,3 +28,15 @@ async def handlerSend(
             data = receiveData.get("data")
             dictMsg = {"code":code,"msg":msg,"data":data}
             await manager.broadcast(dictMsg)
+        case "connect_mcu":
+            device_ctrl = DeviceControl(websocket_manager=manager)
+            # if device_ctrl.serial_ins.check_connect():
+            #     print("未连接")
+            loop = asyncio.get_event_loop()
+            loop.create_task(checkMcuConnection(device_ctrl), name="mcu")
+        case "connect_bluetooth":
+            blue_tooth = BlueToothMode(websocket_manager=manager)
+            # await  blue_tooth.main_func()
+            loop = asyncio.get_event_loop()
+            loop.create_task(blue_tooth.main_func(), name="blue_tooth")
+            # loop.close()

+ 18 - 8
python/sockets/socket_server.py

@@ -5,7 +5,6 @@ from .connect_manager import ConnectionManager
 from .message_handler import *
 from mcu.DeviceControl import DeviceControl,checkMcuConnection
 from mcu.BlueToothMode import BlueToothMode
-from mcu.RemoteControlV2 import RemoteControlV2
 import time
 from .socket_client import socket_manager
 conn_manager = ConnectionManager()
@@ -24,26 +23,37 @@ async def websocket_endpoint(websocket: WebSocket):
             while True:
                 try:
                     byteDats = await websocket.receive()
-                    byteDats.get("type")
+                    socket_type = byteDats.get("type")
+                    if socket_type == "websocket.disconnect":
+                        device_ctrl.close_connect()
+                        diviceList = blue_tooth.devices
+                        if len(diviceList) == 0:
+                            break
+                        diviceAddress = list(diviceList.keys())[0]
+                        if diviceAddress != "":
+                            print(diviceList.get(diviceAddress))
+                            diviceName = diviceList[diviceAddress]["name"]
+                            blue_tooth.disconnect_device(diviceAddress, diviceName)
+                        break
                     print("byteDats", byteDats)
                     await handlerSend(conn_manager, json.dumps(byteDats), websocket)
                 except Exception as e:
                     print(e)
                     break
-        async def checkConnMcu():
-            await checkMcuConnection(device_ctrl)
-        async def connectBlueTooth():
-            await blue_tooth.main_func()
+        # async def checkConnMcu():
+        #     await checkMcuConnection(device_ctrl)
+        # async def connectBlueTooth():
+        #     await blue_tooth.main_func()
         async def send_message():
             while True:
                 try:
                     message = await message_queue.get()
-                    await websocket.send_text(message)
+                    await websocket.send_json(message)
                 except Exception as e:
                     print(e)
                     break
 
-        await asyncio.gather(handler_messages(), checkConnMcu(), connectBlueTooth(), send_message())
+        await asyncio.gather(handler_messages(), send_message())
     except WebSocketDisconnect:
         # socket_manager.close()
         print("Client disconnected")