rambo 6 ماه پیش
والد
کامیت
438ce1fb8d
4فایلهای تغییر یافته به همراه251 افزوده شده و 46 حذف شده
  1. 2 1
      python/mcu/McuDeviationSet.py
  2. 217 27
      python/mcu/capture/smart_shooter_class.py
  3. 29 18
      python/sockets/message_handler.py
  4. 3 0
      python/sockets/socket_server.py

+ 2 - 1
python/mcu/McuDeviationSet.py

@@ -236,7 +236,8 @@ class McuDeviationSet:
         self.mcu.to_init_device_origin_point(device_name="mcu", is_force=True)
         self.mcu.to_init_device_origin_point(device_name="mcu", is_force=True)
 
 
     async def get_mcu_deviation(self):
     async def get_mcu_deviation(self):
-        await self.mcu.getDeviationInfo()
+        await asyncio.sleep(0.01)
+        self.mcu.getDeviationInfo()
 
 
     def get_mcu_deviation_info(self, data):
     def get_mcu_deviation_info(self, data):
         if "_type" not in data:
         if "_type" not in data:

+ 217 - 27
python/mcu/capture/smart_shooter_class.py

@@ -1,51 +1,241 @@
 import json
 import json
 import datetime
 import datetime
+import random
 import zmq
 import zmq
 import asyncio
 import asyncio
 from PIL import Image
 from PIL import Image
 from io import BytesIO
 from io import BytesIO
 import base64
 import base64
 import zmq, sys
 import zmq, sys
+from utils.SingletonType import SingletonType
+from mcu.BaseClass import BaseClass
 
 
 
 
-class SmartShooter:
+# 定义为单例模式,避免被重复实例化
+class SmartShooter(BaseClass,metaclass=SingletonType):
     SET_REQ = "tcp://127.0.0.1:54544"
     SET_REQ = "tcp://127.0.0.1:54544"
     LISTEN_REQ = "tcp://127.0.0.1:54543"
     LISTEN_REQ = "tcp://127.0.0.1:54543"
 
 
-    def send_tcp_message(self, socket, code):
-        exit(1)
-        req = {}
-        req["msg_type"] = "Request"
-        req["msg_id"] = "ActivateLicense"
-        req["msg_seq_num"] = 0
-        req["ActivationCode"] = code
-        socket.send_string(json.dumps(req))
+    def __init__(self, websocket_manager):
+        super().__init__(websocket_manager)
+        self.msg_type = "smart_shooter"
+        self.websocket_manager = websocket_manager
+        # 是否停止监听
+        self.stop_listen = False
+        # 相机连接状态
+        self.connect_status = False
+        # 实时预览状态
+        self.perview_state = False
+        self.callback_listen = None
+        # loop = asyncio.get_event_loop()
+        # loop.create_task(
+        #         self.connect_listen(),
+        #         name="connect_listen",
+        #     )    
+
+    def __send_tcp_message(self, socket, msg):
+        # await asyncio.sleep(0.01)
+        socket.send_string(json.dumps(msg))
         rep = socket.recv()
         rep = socket.recv()
         str_msg = rep.decode("utf-8")
         str_msg = rep.decode("utf-8")
         json_msg = json.loads(str_msg)
         json_msg = json.loads(str_msg)
-        return json_msg["msg_result"]
+        return json_msg
 
 
-    def connect_send(self):
+    def __create_req(self) -> tuple[zmq.Socket, zmq.Context]:
         context = zmq.Context()
         context = zmq.Context()
         req_socket = context.socket(zmq.REQ)
         req_socket = context.socket(zmq.REQ)
+        # 设置发送超时为 5000 毫秒(5 秒)
+        req_socket.setsockopt(zmq.RCVTIMEO, 5000)
+        # 设置接收超时为 5000 毫秒(5 秒)
+        req_socket.setsockopt(zmq.SNDTIMEO, 5000)
+        req_socket.setsockopt(zmq.LINGER, 0)  # 设置为 0 表示不等待未完成的操作
         req_socket.connect(self.SET_REQ)
         req_socket.connect(self.SET_REQ)
+        return req_socket, context
 
 
-        if self.send_tcp_message(req_socket, True):
-            print("License activated")
-        else:
-            print("Failed to activate license", file=sys.stderr)
-    def connect_listen(self):
+    def __create_listen(self) -> tuple[zmq.Socket, zmq.Context]:
         context = zmq.Context()
         context = zmq.Context()
-        sub_socket = context.socket(zmq.SUB)
-        sub_socket.setsockopt(zmq.SUBSCRIBE, b"")
-        sub_socket.connect(self.LISTEN_REQ)
+        listen_socket = context.socket(zmq.SUB)
+        listen_socket.setsockopt(zmq.SUBSCRIBE, b"")
+        # 设置发送超时为 5000 毫秒(5 秒)
+        listen_socket.setsockopt(zmq.RCVTIMEO, 5000)
+        # 设置接收超时为 5000 毫秒(5 秒)
+        listen_socket.setsockopt(zmq.SNDTIMEO, 5000)
+        listen_socket.setsockopt(zmq.LINGER, 0)  # 设置为 0 表示不等待未完成的操作
+        listen_socket.connect(self.LISTEN_REQ)
+        return listen_socket, context
+
+    async def GetCameraInfo(self):
+        await asyncio.sleep(0.01)
+        '''
+        实时获取相机信息,是否连接、软件是否被打开
+        '''
+        try:
+            socket, context = self.__create_req()
+            req = {}
+            req["msg_type"] = "Request"
+            req["msg_id"] = "GetCamera"
+            req["msg_seq_num"] = 0
+            req["CameraSelection"] = "All"
+            json_msg = self.__send_tcp_message(socket, req)
+            msg_result = json_msg.get("msg_result")
+            if not msg_result:
+                self.connect_status = False
+                msg_send = "相机未连接或软件未打开"
+                # self.websocket_manager
+                self.sendSocketMessage(
+                    code=0,
+                    msg=msg_send,
+                    device_status=-1,
+                )
+                return False, msg_send
+            cameraInfo = json_msg.get("CameraInfo")
+            if cameraInfo == None or len(cameraInfo) == 0:
+                self.connect_status = False
+                msg_send = "相机未连接"
+                self.sendSocketMessage(
+                    code=0,
+                    msg=msg_send,
+                    device_status=-1,
+                )
+                return False, "相机未连接"
+            # 链接的相机
+            connect_camera = cameraInfo[0]
+            CameraStatus = connect_camera.get("CameraStatus")
+            if CameraStatus != "Ready":
+                self.connect_status = False
+                msg_send = "相机未连接"
+                self.sendSocketMessage(
+                    code=0,
+                    msg=msg_send,
+                    device_status=-1,
+                )
+                return False, msg_send
+            self.connect_status = True
+            msg_send = "相机已连接"
+            self.sendSocketMessage(
+                    code=0,
+                    msg=msg_send,
+                    device_status=2,
+                )
+            return True, "相机已连接"
+        except:
+            self.connect_status = False
+            socket.close()
+            context.term()
+            msg_send = "相机未连接或软件未打开"
+            self.sendSocketMessage(
+                    code=0,
+                    msg=msg_send,
+                    device_status=-1,
+                )
+            return False, msg_send
+
+    async def EnableCameraPreview(self,enable_status=True):
+        """
+        激活相机预览
+        """
+        camera_states,_ = await self.GetCameraInfo()
+        if not camera_states:
+            return False, "请先连接相机"
+        try:
+            socket, context = self.__create_req()
+            req = {}
+            req["msg_type"] = "Request"
+            req["msg_id"] = "EnableLiveview"
+            req["msg_seq_num"] = 0
+            req["CameraSelection"] = "All"
+            req["Enable"] = enable_status
+            json_msg = self.__send_tcp_message(socket, req)
+            msg_result = json_msg.get("msg_result")
+            if not msg_result:
+                self.perview_state = False
+                return False, "预览启用失败"
+            return True, "预览启用成功" if enable_status else "预览关闭成功"
+        except:
+            self.perview_state = False
+            socket.close()
+            context.term()
+            return False, "相机未连接或软件未打开"
+
+    async def CameraAutofocus(self):
+        """
+        相机自动对焦
+        """
+        camera_states, _ = await self.GetCameraInfo()
+        if not camera_states:
+            return False, "请先连接相机"
+        try:
+            socket, context = self.__create_req()
+            req = {}
+            req["msg_type"] = "Request"
+            req["msg_id"] = "Autofocus"
+            req["msg_seq_num"] = 0
+            req["CameraSelection"] = "All"
+            json_msg = self.__send_tcp_message(socket, req)
+            print("json_msg", json_msg)
+            msg_result = json_msg.get("msg_result")
+            if not msg_result:
+                return False, "对焦失败"
+            return True, "对焦成功"
+        except:
+            socket.close()
+            context.term()
+            return False, "相机未连接或软件未打开"
+
+    async def CameraShooter(self):
+        """
+        执行拍照
+        """
+        camera_states, _ = await self.GetCameraInfo()
+        if not camera_states:
+            return False, "请先连接相机"
+        try:
+            socket, context = self.__create_req()
+            req = {}
+            req["msg_type"] = "Request"
+            req["msg_id"] = "Shoot"
+            req["msg_seq_num"] = 0
+            req["CameraSelection"] = "All"
+            json_msg = self.__send_tcp_message(socket, req)
+            msg_result = json_msg.get("msg_result")
+            if not msg_result:
+                return False, "拍照失败"
+            return True, "拍照成功"
+        except:
+            socket.close()
+            context.term()
+            return False, "相机未连接或软件未打开"
 
 
+    async def connect_listen(self):
+        # 发起监听
+        sub_socket, context = self.__create_listen()
+        print("构建监听")
         while True:
         while True:
-            raw = sub_socket.recv()
-            str_msg = raw.decode("utf-8")
-            json_msg = json.loads(str_msg)
-            # if args.nopings and json_msg["msg_id"] == "NetworkPing":
-            #     continue
-            # print("{0}: {1}".format(datetime.datetime.now(), json_msg["msg_id"]))
-            # if not args.quiet:
-            #     print(str_msg)
+            await asyncio.sleep(0.01)
+            if self.callback_listen == None:
+                continue
+            camera_states, camera_msg = await self.GetCameraInfo()
+            if not camera_states:
+                print("相机未连接")
+                await asyncio.sleep(5)  # 等待相机连接
+                continue
+            if self.stop_listen:
+                break
+            try:
+                self.connect_status = True
+                raw = sub_socket.recv()
+                str_msg = raw.decode("utf-8")
+                json_msg = json.loads(str_msg)
+                if json_msg["msg_id"] == "NetworkPing":
+                    continue
+                self.callback_listen(json_msg)
+            except zmq.Again:
+                print("接收超时,继续监听...")
+                continue
+            except Exception as e:
+                self.connect_status = False
+                print(f"发生错误: {e}")
+                break
+        sub_socket.close()
+        context.term()
+        print("smart shooter连接断开")

+ 29 - 18
python/sockets/message_handler.py

@@ -5,7 +5,7 @@ from mcu.DeviceControl import DeviceControl, checkMcuConnection
 from mcu.BlueToothMode import BlueToothMode
 from mcu.BlueToothMode import BlueToothMode
 from databases import DeviceConfig, SqlQuery, CRUD, PhotoRecord, SysConfigs
 from databases import DeviceConfig, SqlQuery, CRUD, PhotoRecord, SysConfigs
 from mcu.capture.module_digicam import DigiCam
 from mcu.capture.module_digicam import DigiCam
-
+from mcu.capture.smart_shooter_class import SmartShooter
 # socket消息发送逻辑处理方法
 # socket消息发送逻辑处理方法
 async def handlerSend(
 async def handlerSend(
     manager: ConnectionManager, receiveData: str, websocket: WebSocket
     manager: ConnectionManager, receiveData: str, websocket: WebSocket
@@ -20,6 +20,18 @@ async def handlerSend(
     data = receiveData.get("data")
     data = receiveData.get("data")
     print("receiveData", receiveData)
     print("receiveData", receiveData)
     print("jsonType", jsonType)
     print("jsonType", jsonType)
+    def MsgCallback(msg):
+        msg_id = msg.get("msg_id")
+        match msg_id:
+            case "PhotoUpdated":
+                PhotoFilename = msg.get("PhotoFilename")
+                if PhotoFilename != "" and PhotoFilename != None:
+                    print("收到照片:", json.dumps(msg, ensure_ascii=False))
+                    print("PhotoFilename", PhotoFilename)
+            case "LiveviewUpdated":
+                CameraLiveviewImage = msg.get("CameraLiveviewImage", None)
+                # base64_to_image(CameraLiveviewImage, "liveview.jpg")
+                # print("收到直播画面:", json.dumps(msg, ensure_ascii=False))
     match jsonType:
     match jsonType:
         case "ping":
         case "ping":
             """发送心跳"""
             """发送心跳"""
@@ -131,23 +143,6 @@ async def handlerSend(
                 name="run_mcu_config",
                 name="run_mcu_config",
             )
             )
         case "re_take_picture":#重拍
         case "re_take_picture":#重拍
-            # try:
-            #     # 判断拍照软件是否初始化
-            #     digicam = DigiCam()
-            #     camera_is_connect = digicam.checkCameraConnect()
-            #     if camera_is_connect is not True:
-            #         data = manager.jsonMessage(
-            #             code=1, msg="相机未连接,请检查", msg_type=msg_type
-            #         )
-            #         await manager.send_personal_message(data, websocket)
-            #         return
-            #     digicam.getCaptureFolderPath()
-            # except:
-            #     data = manager.jsonMessage(
-            #         code=1, msg="digicam未初始化,请检查", msg_type=msg_type
-            #     )
-            #     await manager.send_personal_message(data, websocket)
-            #     return
             msg_type = "re_take_picture"
             msg_type = "re_take_picture"
             record_id = data.get("record_id")
             record_id = data.get("record_id")
             session = SqlQuery()
             session = SqlQuery()
@@ -224,6 +219,22 @@ async def handlerSend(
                 device_ctrl.sendCommand(data.get("command", None)),
                 device_ctrl.sendCommand(data.get("command", None)),
                 name="sendCommand",
                 name="sendCommand",
             )
             )
+        case "smart_shooter_getinfo":
+            '''
+            获取相机信息,是否连接
+            '''
+            smart_shooter = SmartShooter(
+                websocket_manager=manager
+            )
+            smart_shooter.callback_listen = MsgCallback
+            loop.create_task(
+                smart_shooter.GetCameraInfo(),
+                name="smart_shooter_getinfo",
+            )
+            loop.create_task(
+                smart_shooter.connect_listen(),
+                name="connect_listen",
+            )
         case _:
         case _:
             data = manager.jsonMessage(code=1, msg="未知消息")
             data = manager.jsonMessage(code=1, msg="未知消息")
             await manager.send_personal_message(data, websocket)
             await manager.send_personal_message(data, websocket)

+ 3 - 0
python/sockets/socket_server.py

@@ -5,12 +5,14 @@ from .connect_manager import ConnectionManager
 from .message_handler import *
 from .message_handler import *
 from mcu.DeviceControl import DeviceControl,checkMcuConnection
 from mcu.DeviceControl import DeviceControl,checkMcuConnection
 from mcu.BlueToothMode import BlueToothMode
 from mcu.BlueToothMode import BlueToothMode
+from mcu.capture.smart_shooter_class import SmartShooter
 import time
 import time
 from .socket_client import socket_manager
 from .socket_client import socket_manager
 conn_manager = ConnectionManager()
 conn_manager = ConnectionManager()
 active_connections = set()
 active_connections = set()
 device_ctrl = DeviceControl(websocket_manager=conn_manager)
 device_ctrl = DeviceControl(websocket_manager=conn_manager)
 blue_tooth = BlueToothMode(websocket_manager=conn_manager)
 blue_tooth = BlueToothMode(websocket_manager=conn_manager)
+smart_shooter = SmartShooter(websocket_manager=conn_manager)
 from utils.common import message_queue
 from utils.common import message_queue
 @app.websocket("/ws")
 @app.websocket("/ws")
 async def websocket_endpoint(websocket: WebSocket):
 async def websocket_endpoint(websocket: WebSocket):
@@ -25,6 +27,7 @@ async def websocket_endpoint(websocket: WebSocket):
                     byteDats = await websocket.receive()
                     byteDats = await websocket.receive()
                     socket_type = byteDats.get("type")
                     socket_type = byteDats.get("type")
                     if socket_type == "websocket.disconnect":
                     if socket_type == "websocket.disconnect":
+                        smart_shooter.stop_listen = True
                         device_ctrl.close_connect()
                         device_ctrl.close_connect()
                         device_ctrl.mcu_exit = True
                         device_ctrl.mcu_exit = True
                         device_ctrl.clearMyInstance()
                         device_ctrl.clearMyInstance()