rambo 6 mēneši atpakaļ
vecāks
revīzija
438ce1fb8d

+ 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)
 
     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):
         if "_type" not in data:

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

@@ -1,51 +1,241 @@
 import json
 import datetime
+import random
 import zmq
 import asyncio
 from PIL import Image
 from io import BytesIO
 import base64
 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"
     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()
         str_msg = rep.decode("utf-8")
         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()
         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)
+        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()
-        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:
-            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 databases import DeviceConfig, SqlQuery, CRUD, PhotoRecord, SysConfigs
 from mcu.capture.module_digicam import DigiCam
-
+from mcu.capture.smart_shooter_class import SmartShooter
 # socket消息发送逻辑处理方法
 async def handlerSend(
     manager: ConnectionManager, receiveData: str, websocket: WebSocket
@@ -20,6 +20,18 @@ async def handlerSend(
     data = receiveData.get("data")
     print("receiveData", receiveData)
     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:
         case "ping":
             """发送心跳"""
@@ -131,23 +143,6 @@ async def handlerSend(
                 name="run_mcu_config",
             )
         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"
             record_id = data.get("record_id")
             session = SqlQuery()
@@ -224,6 +219,22 @@ async def handlerSend(
                 device_ctrl.sendCommand(data.get("command", None)),
                 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 _:
             data = manager.jsonMessage(code=1, msg="未知消息")
             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 mcu.DeviceControl import DeviceControl,checkMcuConnection
 from mcu.BlueToothMode import BlueToothMode
+from mcu.capture.smart_shooter_class import SmartShooter
 import time
 from .socket_client import socket_manager
 conn_manager = ConnectionManager()
 active_connections = set()
 device_ctrl = DeviceControl(websocket_manager=conn_manager)
 blue_tooth = BlueToothMode(websocket_manager=conn_manager)
+smart_shooter = SmartShooter(websocket_manager=conn_manager)
 from utils.common import message_queue
 @app.websocket("/ws")
 async def websocket_endpoint(websocket: WebSocket):
@@ -25,6 +27,7 @@ async def websocket_endpoint(websocket: WebSocket):
                     byteDats = await websocket.receive()
                     socket_type = byteDats.get("type")
                     if socket_type == "websocket.disconnect":
+                        smart_shooter.stop_listen = True
                         device_ctrl.close_connect()
                         device_ctrl.mcu_exit = True
                         device_ctrl.clearMyInstance()