Browse Source

Merge branch 'dev-smartshooter5' into smart-shooter-master

rambo 4 months ago
parent
commit
a08035ff6f

+ 15 - 20
python/api.py

@@ -150,18 +150,16 @@ def fromExcelHandler(params: HandlerDetail):
                 "\\", "/"
             )
             check_path(image_dir)
-            for itemImg in images:
+            for idx, itemImg in enumerate(images):
                 if itemImg.image_path == "" or itemImg.image_path == None:
                     raise UnicornException(
                         f"货号【{goods_art_no}】存在没有拍摄完成的图片,请重拍或删除后重试"
                     )
-                new_file_name = (
-                    str(itemImg.goods_art_no) + "_" + str(itemImg.id) + ".jpg"
-                )
+                new_file_name = str(itemImg.goods_art_no) + "_" + str(idx) + ".jpg"
                 if not os.path.exists(
                     image_dir + "/" + os.path.basename(new_file_name)
                 ):
-                    shutil.copy(itemImg.image_path, image_dir + "/" + new_file_name)
+                    shutil.copy(itemImg.image_path, image_dir + new_file_name)
             dealImage = DealImage(image_dir)
             resFlag, path = dealImage.dealMoveImage(
                 image_dir=image_dir,
@@ -321,18 +319,16 @@ async def handle_detail(request: Request, params: HandlerDetail):
         if move_folder_array.get(goods_art_no) == None:
             image_dir = "{}/data/".format(os.getcwd()).replace("\\", "/")
             check_path(image_dir)
-            for itemImg in images:
+            for idx, itemImg in enumerate(images):
                 if itemImg.image_path == "" or itemImg.image_path == None:
                     raise UnicornException(
                         f"货号【{goods_art_no}】存在没有拍摄完成的图片,请重拍或删除后重试"
                     )
-                new_file_name = (
-                    str(itemImg.goods_art_no) + "_" + str(itemImg.id) + ".jpg"
-                )
+                new_file_name = str(itemImg.goods_art_no) + "_" + str(idx) + ".jpg"
                 if not os.path.exists(
                     image_dir + "/" + os.path.basename(new_file_name)
                 ):
-                    shutil.copy(itemImg.image_path, image_dir + "/" + new_file_name)
+                    shutil.copy(itemImg.image_path, image_dir + new_file_name)
             dealImage = DealImage(image_dir)
             resFlag, path = dealImage.dealMoveImage(
                 image_dir=image_dir, callback_func=None, goods_art_no=goods_art_no
@@ -517,7 +513,7 @@ def get_device_configs(params: ModelGetDeviceConfig):
 
 
 @app.post("/device_config_detail", description="获取可执行程序详情")
-def get_device_configs(params: ModelGetDeviceConfigDetail):
+def device_config_detail(params: ModelGetDeviceConfigDetail):
     action_id = params.id
     session = SqlQuery()
     configModel = CRUD(DeviceConfig)
@@ -599,14 +595,14 @@ def reset_config(params: ModelGetDeviceConfig):
         device_config = DeviceConfig(**data)
         session.add(device_config)
     session.commit()
-    session.close()
+    # session.close()
     return {"code": 0, "msg": "操作成功", "data": None}
 
 
 @app.get("/get_photo_records", description="获取拍照记录")
 def get_photo_records(page: int = 1, size: int = 5):
     session = SqlQuery()
-    photos = CRUD(PhotoRecord)
+    # photos = CRUD(PhotoRecord)
     print("准备查询拍摄记录", datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
     statement = (
         select(PhotoRecord)
@@ -632,7 +628,6 @@ def get_photo_records(page: int = 1, size: int = 5):
             .join(DeviceConfig, PhotoRecord.action_id == DeviceConfig.id)
         )
         list_item = session.exec(query).mappings().all()
-        session.close()
         list.append(
             {
                 "goods_art_no": item.goods_art_no,
@@ -640,7 +635,7 @@ def get_photo_records(page: int = 1, size: int = 5):
                 "items": list_item,
             }
         )
-    session.close()
+    # session.close()
     print("循环查询 完成 ", datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
     return {
         "code": 0,
@@ -658,7 +653,7 @@ def get_last_photo_record():
         .order_by(desc("photo_create_time"))
     )
     result = session.exec(statement).first()
-    session.close()
+    # session.close()
     return {
         "code": 0,
         "msg": "",
@@ -667,13 +662,13 @@ def get_last_photo_record():
 
 
 @app.get("/get_photo_record_detail", description="通过货号获取拍照记录详情")
-def get_photo_records(goods_art_no: str = None):
+def get_photo_record_detail(goods_art_no: str = None):
     if goods_art_no == None:
         return {"code": 1, "msg": "参数错误", "data": None}
     session = SqlQuery()
     photos = CRUD(PhotoRecord)
     items = photos.read_all(session, conditions={"goods_art_no": goods_art_no})
-    session.close()
+    # session.close()
     return {
         "code": 0,
         "msg": "",
@@ -687,7 +682,7 @@ def delect_goods_arts(params: PhotoRecordDelete):
     photos = CRUD(PhotoRecord)
     for item in params.goods_art_nos:
         photos.deleteConditions(session, conditions={"goods_art_no": item})
-    session.close()
+    # session.close()
     return {
         "code": 0,
         "msg": "操作成功",
@@ -702,7 +697,7 @@ def get_sys_config(key: str = None):
     session = SqlQuery()
     photos = CRUD(SysConfigs)
     item = photos.read(session, conditions={"key": key})
-    session.close()
+    # session.close()
     return {
         "code": 0,
         "msg": "",

+ 1 - 1
python/config.ini

@@ -12,7 +12,7 @@ port=7074
 debug=false
 env=prod
 # 线程数
-works=3
+works=5
 project=惠利玛
 is_upload=true
 [log]

+ 77 - 80
python/databases.py

@@ -8,6 +8,7 @@ from sqlalchemy import and_, desc, asc
 from utils.utils_func import check_path
 from sqlalchemy.dialects import sqlite
 from model import DeviceConfig, PhotoRecord, SysConfigs, DeviceConfigTabs
+
 check_path("C:/Zhihuiyin")
 # 创建SQLite数据库引擎
 sqlite_file_name = "C:/Zhihuiyin/database.db"
@@ -15,6 +16,7 @@ sqlite_url = f"sqlite:///{sqlite_file_name}"
 engine = create_engine(
     sqlite_url,
     echo=False,
+    connect_args={"check_same_thread": False},  # 允许多线程访问
     pool_size=10,
     max_overflow=20,
     pool_timeout=30,
@@ -36,54 +38,6 @@ def __get_session():
             session.close()
 
 
-def batch_insert_device_configs(session: Session, action_tabs: list, data_list: list):
-    """批量插入数据到设备配置表"""
-    for idx, tab in enumerate(action_tabs):
-        crud = CRUD(DeviceConfigTabs)
-        device_tab = DeviceConfigTabs(
-            mode_type=tab.get("mode_type"),
-            mode_name=tab.get("mode_name"),
-        )
-        create_obj = crud.create(session, obj_in=device_tab)
-        for data in data_list:
-            data["tab_id"] = create_obj.id
-            data["is_system"] = False
-            if idx  in [0, 6]:
-                data["is_system"] = True
-            device_config = DeviceConfig(**data)
-            session.add(device_config)
-    session.commit()
-    session.close()
-
-
-def batch_insert_sys_configs(session: Session, data_list: list):
-    """批量插入数据到设备配置表"""
-    for data in data_list:
-        config = SysConfigs(**data)
-        session.add(config)
-    session.commit()
-    session.close()
-
-
-def insert_photo_records(
-    image_deal_mode: int, goods_art_no: str, image_index: int, action_id: int
-):
-    session = SqlQuery()
-    """批量插入数据到照片记录"""
-    data = {
-        "image_deal_mode": image_deal_mode,
-        "goods_art_no": goods_art_no,
-        "image_index": image_index,
-        "action_id": action_id,
-    }
-    device_config = PhotoRecord(**data)
-    session.add(device_config)
-    session.commit()
-    record_id = device_config.id
-    session.close()
-    return True, record_id
-
-
 # 创建一个通用的 CRUD 类
 class CRUD:
     def __init__(self, model):
@@ -94,8 +48,7 @@ class CRUD:
         db_obj = self.model(**obj_in_data)
         session.add(db_obj)
         session.commit()
-        # session.refresh(db_obj)
-        # session.close()
+        session.refresh(db_obj)
         return db_obj
 
     def read(
@@ -121,7 +74,6 @@ class CRUD:
             else:
                 query = query.order_by(desc(getattr(self.model, order_by)))
         data = session.exec(query).first()
-        session.close()
         return data
 
     def read_all(
@@ -162,43 +114,16 @@ class CRUD:
             else:
                 query = query.order_by(desc(getattr(self.model, order_by)))
         data = session.exec(query).all()
-        session.close()
         return data
 
     def update(self, session: Session, obj_id: int, **kwargs):
         db_obj = session.get(self.model, obj_id)
         for key, value in kwargs.items():
-            # if value == None or value == "":
-            #     continue
             setattr(db_obj, key, value)
         session.commit()
         session.refresh(db_obj)
-        session.close()
         return db_obj
 
-    def updateConditions(
-        self, session: Session, conditions: Optional[Dict] = None, **kwargs
-    ):
-        query = select(self.model)
-        if conditions:
-            query = query.where(
-                and_(
-                    *(
-                        getattr(self.model, key) == value
-                        for key, value in conditions.items()
-                    )
-                )
-            )
-        data = session.exec(query).first()
-        for key, value in kwargs.items():
-            if value == None or value == "":
-                continue
-            setattr(data, key, value)
-        session.commit()
-        session.refresh(data)
-        session.close()
-        return data
-
     def deleteConditions(
         self,
         session: Session,
@@ -219,14 +144,86 @@ class CRUD:
         for obj in objects_to_delete:
             session.delete(obj)
         session.commit()
-        session.close()
+        # session.refresh()
         return True
 
     def delete(self, session: Session, obj_id: int):
         db_obj = session.get(self.model, obj_id)
         session.delete(db_obj)
         session.commit()
-        session.close()
+        # session.refresh()
+
+    # 恢复 updateConditions 方法
+    def updateConditions(self, session: Session, conditions: Dict, **kwargs):
+        """
+        根据条件更新记录
+        :param session: 数据库会话
+        :param conditions: 更新条件字典
+        :param kwargs: 需要更新的字段和值
+        :return: 更新后的对象
+        """
+        query = select(self.model).where(
+            and_(
+                *(
+                    getattr(self.model, key) == value
+                    for key, value in conditions.items()
+                )
+            )
+        )
+        result = session.exec(query).first()
+        if result:
+            for key, value in kwargs.items():
+                setattr(result, key, value)
+            session.commit()  # 提交事务以保存更改
+            return result
+        return None
+
+
+# 批量插入数据到设备配置表
+def batch_insert_device_configs(session: Session, action_tabs: list, data_list: list):
+    """批量插入数据到设备配置表"""
+    for idx, tab in enumerate(action_tabs):
+        crud = CRUD(DeviceConfigTabs)
+        device_tab = DeviceConfigTabs(
+            mode_type=tab.get("mode_type"),
+            mode_name=tab.get("mode_name"),
+        )
+        create_obj = crud.create(session, obj_in=device_tab)
+        for data in data_list:
+            data["tab_id"] = create_obj.id
+            data["is_system"] = False
+            if idx in [0, 6]:
+                data["is_system"] = True
+            device_config = DeviceConfig(**data)
+            session.add(device_config)
+    session.commit()  # 合并事务提交
+
+# 批量插入系统配置
+def batch_insert_sys_configs(session: Session, data_list: list):
+    """批量插入数据到设备配置表"""
+    for data in data_list:
+        config = SysConfigs(**data)
+        session.add(config)
+    session.commit()  # 合并事务提交
+
+# 插入照片记录
+async def insert_photo_records(
+    image_deal_mode: int, goods_art_no: str, image_index: int, action_id: int
+):
+    with SqlQuery() as session:  # 使用上下文管理器复用会话
+        """批量插入数据到照片记录"""
+        data = {
+            "image_deal_mode": image_deal_mode,
+            "goods_art_no": goods_art_no,
+            "image_index": image_index,
+            "action_id": action_id,
+        }
+        device_config = PhotoRecord(**data)
+        session.add(device_config)
+        session.commit()
+        session.refresh(device_config)
+        record_id = device_config.id
+        return True, record_id
 
 
 def SqlQuery():

+ 10 - 2
python/index.py

@@ -10,7 +10,6 @@ import uvicorn.protocols.websockets.auto
 import uvicorn.lifespan.on
 from multiprocessing import Process, freeze_support
 from service.init_load_source import init_load_source
-
 def handle_shutdown(signum, frame):
     """关闭系统应用服务"""
      # 终止事件循环
@@ -27,6 +26,7 @@ async def run_server():
         port=int(PORT),
         reload=isDebug,
         workers=int(APP_WORKS),
+        loop="auto",
     )
     server = uvicorn.Server(config)
     await server.serve()
@@ -38,11 +38,19 @@ async def main():
 
 
 if __name__ == "__main__":
+    if sys.platform == "win32":
+        asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
+
     signal.signal(signal.SIGINT, handle_shutdown)
     signal.signal(signal.SIGTERM, handle_shutdown)
     print("python server is running at port:", PORT)
     print("python server is running at port:", APP_RUN)
-    asyncio.run(main())
+
+    loop = asyncio.new_event_loop()
+    try:
+        loop.run_until_complete(main())
+    finally:
+        loop.close()
     # isDebug = True if IS_DEBUG == "true" else False
     # uvicorn.run(
     #     app=APP_RUN,

+ 152 - 31
python/mcu/DeviceControl.py

@@ -15,6 +15,7 @@ from databases import insert_photo_records
 from .McuDeviationSet import McuDeviationSet
 from .OtherSet import OtherSet
 from .DebugUart import DebugUart
+from .LineControl import LineControl
 import copy
 from mcu.capture.smart_shooter_class import SmartShooter
 # mcu命令
@@ -29,6 +30,7 @@ class DeviceControl(BaseClass, metaclass=SingletonType):
         self.mcu_deviation_set = McuDeviationSet(self)
         self.mcu_other_set = OtherSet(self)
         self.debug_uart = DebugUart(self)
+        self.line_control = LineControl(websocket_manager)
         self.m_t = 1
         # 0未开始  1进行中 2已结束  99异常
         self.action_state = 2
@@ -201,6 +203,44 @@ class DeviceControl(BaseClass, metaclass=SingletonType):
         self.sendSocketMessage(code=1, msg="MCU 连接失败", data=message,device_status=-1)
         self.close_connect()
 
+    async def initControlLine(self,serial_handle):
+        '''实例化有线控制设备'''
+        self.line_control.connect_state = True
+        self.line_control.serial_ins = serial_handle
+        await self.line_control.run()
+        # if self.init_state == True:
+        #     print("已经初始化过,请勿重复初始化")
+        #     self.sendSocketMessage(msg="设备初始化完成", device_status=2)
+        #     return False
+        # self.serial_ins.clearn_flush()
+        # self.to_init_device_origin_point(device_name="mcu", is_force=is_force)
+        # print("MCU 开始循环~")
+        # while 1:
+        #     await asyncio.sleep(0.01)
+        #     if not self.serial_ins or not self.connect_state:
+        #         break
+        #     try:
+        #         # print("mcu   send_cmd")
+        #         self.send_cmd()
+        #         # time.sleep(0.01)
+        #         self.get_basic_info_mcu()
+        #         # self.close_other_window()
+        #     except BaseException as e:
+        #         print("121231298908", e)
+        #         break
+
+        # self.is_running = False
+        # self.connect_state = False
+        # print("MCU 循环退出~")
+        # # self.sign_data.emit(
+        # #     {"_type": "show_info", "plugins_mode": "mcu", "data": "MCU 连接失败"}
+        # # )
+        # message = {"_type": "show_info", "plugins_mode": "mcu", "data": "MCU 连接失败"}
+        # self.sendSocketMessage(
+        #     code=1, msg="MCU 连接失败", data=message, device_status=-1
+        # )
+        # self.close_connect()
+
     def stop_mcu(self):
         buf = [self.command["stop_mcu"]]
         buf.extend(self.encapsulation_data(data=1, len_data=1))
@@ -856,7 +896,7 @@ class DeviceControl(BaseClass, metaclass=SingletonType):
         }
         self.sendSocketMessage(1, "串口被移除", data)
 
-    def add_port_by_linkage(self, port_name):
+    async def add_port_by_linkage(self, port_name):
         # port_value :串口基础信息
         # todo 根据prot_value 信息自动进行连接
         print("add", port_name)
@@ -869,7 +909,7 @@ class DeviceControl(BaseClass, metaclass=SingletonType):
         self.sendSocketMessage(
             msg="开始识别接口:{}".format(port_name), data=message_data, device_status=1
         )
-        time.sleep(1)
+        await asyncio.sleep(1)
         """
         步骤:
         1、进行临时连接,并发送命令,成功后,自动连接对应设备
@@ -890,9 +930,9 @@ class DeviceControl(BaseClass, metaclass=SingletonType):
                 device_status=-1,
             )
             print("串口:{} 被占用".format(port_name))
-            return
+            return False
 
-        time.sleep(2)
+        await asyncio.sleep(2)
         print("开始发送命令")
         data = [90, 1]
         try:
@@ -905,7 +945,7 @@ class DeviceControl(BaseClass, metaclass=SingletonType):
                 data=None,
             )
             serial_handle.close()
-            return
+            return False
         print("尝试写入数据")
 
         buf = bytearray(b"")
@@ -918,9 +958,9 @@ class DeviceControl(BaseClass, metaclass=SingletonType):
         except serial.SerialTimeoutException:
             print("写入数据错误")
             serial_handle.close()
-            return
+            return False
 
-        time.sleep(0.3)
+        await asyncio.sleep(0.3)
         print("尝试接收命令")
         receive_data = self.read_cmd(serial_handle)
         device_id = 0
@@ -933,10 +973,11 @@ class DeviceControl(BaseClass, metaclass=SingletonType):
 
         print("关闭串口:{}".format(port_name))
         serial_handle.close()
-
+        loop = asyncio.get_event_loop()
+        print("device_id============>>>", device_id)
         if device_id > 0:
             if device_id == 1:
-                self.to_connect_com(port_name)
+                await self.to_connect_com(port_name)
                 message_data = {
                     "_type": "show_info",
                     "plugins_mode": "auto_select_com",
@@ -946,32 +987,66 @@ class DeviceControl(BaseClass, metaclass=SingletonType):
                     msg="MCU开始连接", data=message_data, device_status=1
                 )
                 self.connected_ports_dict[port_name] = "MCU"
-            message_data = {
-                "_type": "select_port_name",
-                "plugins_mode": "auto_select_com",
-                "data": {
-                    "device_name": "mcu" if device_id == 1 else "remote_control",
-                    "port_name": port_name,
-                },
-            }
-            self.sendSocketMessage(
-                msg="MCU连接成功", data=message_data, device_status=2
-            )
-            time.sleep(2)
-            loop = asyncio.get_event_loop()
-            loop.create_task(self.initDevice(), name="init_mcu")
+                message_data = {
+                    "_type": "select_port_name",
+                    "plugins_mode": "auto_select_com",
+                    "data": {
+                        "device_name": "mcu" if device_id == 1 else "remote_control",
+                        "port_name": port_name,
+                    },
+                }
+                self.sendSocketMessage(
+                    msg="MCU连接成功", data=message_data, device_status=2
+                )
+                await asyncio.sleep(2)
+                # await self.initDevice()
+                loop.create_task(
+                    self.initDevice(port_name),
+                    name="initDevice",
+                )
+            elif device_id == 2:
+                # 有线接收器
+                print("device_id", device_id)
+                loop.create_task(
+                    self.line_control.to_connect_com(port_name),
+                    name="line_control_to_connect_com",
+                )
+                # message_data = {
+                #     "_type": "show_info",
+                #     "plugins_mode": "auto_select_com",
+                #     "data": {"text": "有线控制器开始连接"},
+                # }
+                # self.sendSocketMessage(
+                #     msg="有线控制器开始连接", data=message_data, device_status=1
+                # )
+                # self.connected_ports_dict[port_name] = "MCU"
+                # message_data = {
+                #     "_type": "select_port_name",
+                #     "plugins_mode": "auto_select_com",
+                #     "data": {
+                #         "device_name": "mcu" if device_id == 1 else "remote_control",
+                #         "port_name": port_name,
+                #     },
+                # }
+                # self.sendSocketMessage(
+                #     msg="有线控制器开始连接", data=message_data, device_status=2
+                # )
+                # await asyncio.sleep(2)
+                # await self.initControlLine(serial_handle)
             # async def getBaseInfo():
             #     while True:
             #         await asyncio.sleep(1)
             #         # 异步循环获取设备信息
             #         self.to_get_mcu_base_info()
             # asyncio.gather(getBaseInfo())
+            return True
         else:
             print("串口无法识别")
             self.sendSocketMessage(
                 code=1,
                 msg="串口无法识别,请重新插拔拍照机USB", data=message_data, device_status=-1
             )
+            return False
             # 走其他途径处理
 
         # 检查当前MCU链接是否正常
@@ -980,11 +1055,11 @@ class DeviceControl(BaseClass, metaclass=SingletonType):
         # 连接不上,记录为其他列表
     def clearMyInstance(self):
         SingletonType.clear_instance()
-    def to_connect_com(self, port_name):
+    async def to_connect_com(self, port_name):
         # 关闭串口
         print("to_connect_com", port_name)
         self.close_connect()
-        time.sleep(0.3)
+        await asyncio.sleep(0.3)
         self.connect_state = False
         try:
             self.serial_ins = SerialIns(port_name=port_name, baud=115200, timeout=0.1)
@@ -999,7 +1074,7 @@ class DeviceControl(BaseClass, metaclass=SingletonType):
                 )
                 self.serial_ins = None
                 self.connect_state = False
-                return False
+                return False,None
 
         except:
             message_data = {
@@ -1012,7 +1087,7 @@ class DeviceControl(BaseClass, metaclass=SingletonType):
             )
             self.serial_ins = None
             self.connect_state = False
-            return False
+            return False, None
 
         message_data = {
             "_type": "show_info",
@@ -1029,7 +1104,7 @@ class DeviceControl(BaseClass, metaclass=SingletonType):
         self.serial_ins.write_cmd(data)
 
         # 延迟接收数据
-        time.sleep(0.3)
+        await asyncio.sleep(0.3)
         receive_data = self.serial_ins.read_cmd(out_time=1)
         if receive_data:
             print(
@@ -1153,6 +1228,9 @@ class DeviceControl(BaseClass, metaclass=SingletonType):
 
         cmd = 1
         device_id = self.device_name_dict[device_name]
+        # if device_id != 1:
+        #     print("F非MCU设备,禁止处理")
+        #     return
         print("正在执行",device_name)
         match device_name:
             case "camera_high_motor":
@@ -1405,7 +1483,7 @@ class DeviceControl(BaseClass, metaclass=SingletonType):
                     image_counts += 1
                     # 批量插入
                     image_deal_mode = 0 if action_info == "执行左脚程序" else 1
-                    state,record_id = insert_photo_records(
+                    state,record_id = await insert_photo_records(
                         image_deal_mode=image_deal_mode,
                         goods_art_no=goods_art_no,
                         image_index=idx,
@@ -1434,7 +1512,7 @@ class DeviceControl(BaseClass, metaclass=SingletonType):
             for index, action in enumerate(config_list):
                 # await asyncio.sleep(0.01)
                 if self.is_stop_action == True:
-                    self.is_stop_action = False
+                    print("停止命令接收,立即终止")
                     break
                 # action_is_take_picture = action["take_picture"]
                 record_id = action["record_id"]
@@ -1478,6 +1556,27 @@ class DeviceControl(BaseClass, metaclass=SingletonType):
                     )
                 self.msg_type = "mcu"
                 # 在第三张图时检查是否有对应图片生成
+                # if index == 3:
+                #     # if not self.image_process_data.check_photo_is_get():
+                #     self.sendSocketMessage(
+                #             code=1,
+                #             msg="未获取到图片数据",
+                #             device_status=0,
+                #         )
+                #     self.action_state = 2
+                #     return
+                if index == total_len - 1:
+                    #  最后一个初始化处理
+                    pass
+                # self.action_state = 2
+            if self.is_stop_action==True:
+                self.msg_type = "run_mcu_stop"
+                self.sendSocketMessage(
+                    code=0,
+                    msg=f"货号:{goods_art_no},执行终止",
+                    device_status=2,
+                )
+                self.is_stop_action = False
             self.action_state = 2
             self.is_runn_action = False
             self.msg_type = "photo_take_finish"
@@ -1534,6 +1633,26 @@ class DeviceControl(BaseClass, metaclass=SingletonType):
                 code=1, msg="未查询到重拍记录得配置信息,请确认", device_status=0
             )
 
+    async def only_take_photo(self, goods_art_no, image_index, record_id):
+        await asyncio.sleep(0.1)
+        print("only_take_photo=====>",goods_art_no, image_index, record_id)
+        if goods_art_no == "":
+            print("only_take_photo 数据查询异常")
+            return
+        # 关闭led
+        self.controlDevice("laser_position", 0)
+        program_item = ProgramItem(
+            websocket_manager=self.websocket_manager,
+            action_data={},
+            mcu=self,
+            goods_art_no=goods_art_no,
+            image_index=image_index,
+            record_id=record_id,
+        )
+        program_item.digicam_take_picture()
+        # 打开led
+        self.controlDevice("laser_position", 1)
+
 
 async def checkMcuConnection(device_ctrl: DeviceControl):
     if device_ctrl.is_running == True:
@@ -1568,8 +1687,10 @@ async def checkMcuConnection(device_ctrl: DeviceControl):
             for _port_name, _port_value in ports_dict.items():
                 if _port_name not in device_ctrl.p_list:
                     try:
+                        flag = await device_ctrl.add_port_by_linkage(_port_name)
+                        if flag == False:
+                            continue
                         device_ctrl.p_list.append(_port_name)
-                        device_ctrl.add_port_by_linkage(_port_name)
                     except BaseException as e:
                         print("串口不存在{} {}".format(_port_name, e))
     print("MCU断开连接,已释放")

+ 245 - 0
python/mcu/LineControl.py

@@ -0,0 +1,245 @@
+import time
+
+# from import_qt_mode import *
+import asyncio
+from .SerialIns import SerialIns
+from .BaseClass import BaseClass
+from utils.SingletonType import SingletonType
+from databases import SqlQuery, PhotoRecord, DeviceConfig, CRUD, insert_photo_records
+from .capture.module_digicam import DigiCam
+from .capture.module_watch_dog import FileEventHandler
+from sockets.connect_manager import ConnectionManager
+
+class LineControl(BaseClass):
+    # sign_data = Signal(dict)
+
+    def __init__(self, websocket_manager: ConnectionManager):
+        super().__init__(websocket_manager)
+        self.serial_ins = None
+        self.connect_state = False
+        self.is_running = False
+        self.msg_type = "blue_tooth"
+        self.goods_art_no = None
+        # 0 闲置;1进行中;2已完成;
+        self.photo_take_state = 0
+
+    async def to_connect_com(self, port_name):
+        self.close_connect()
+        await asyncio.sleep(0.5)
+        try:
+            # 原值为9600
+            self.serial_ins = SerialIns(port_name=port_name, baud=115200)
+            if self.serial_ins.serial_handle:
+                self.connect_state = True
+                message = {
+                    "_type": "show_info",
+                    "plugins_mode": "remote_control",
+                    "data": {"msg": "有线遥控器 打开串口成功", "port_name": port_name},
+                }
+                self.sendSocketMessage(
+                    code=0,
+                    msg="有线遥控器 打开串口成功",
+                    data=message,
+                    device_status=2,
+                )
+                # 循环监听消息
+                await self.run()
+                return True
+            else:
+                message = {
+                    "_type": "show_info",
+                    "plugins_mode": "remote_control",
+                    "data": {"msg": "有线遥控器 打开串口失败"},
+                }
+                self.sendSocketMessage(
+                    code=1,
+                    msg="有线遥控器 打开串口失败",
+                    data=message,
+                    device_status=-1,
+                )
+                self.serial_ins = None
+                self.connect_state = False
+        except:
+            message = {
+                "_type": "show_info",
+                "plugins_mode": "remote_control",
+                "data": {"msg": "有线遥控器 打开串口失败"},
+            }
+            self.sendSocketMessage(
+                code=1,
+                msg="有线遥控器 打开串口失败",
+                data=message,
+                device_status=-1,
+            )
+            self.serial_ins = None
+            self.connect_state = False
+            return False
+
+    def close_connect(self):
+        if self.connect_state:
+            self.serial_ins.close_serial_port()
+            self.connect_state = False
+
+    def __del__(self):
+        self.close_connect()
+
+    async def to_connect_linecontrol(self):
+        """连接有线控制器"""
+        print("to_connect_linecontrol 连接有线控制器,连接状态", self.connect_state)
+        if self.connect_state:
+            return
+        message = {
+            "_type": "show_info",
+            "plugins_mode": "remote_control",
+            "data": "有线遥控器 打开成功",
+        }
+        self.close_connect()
+        print(message)
+        self.sendSocketMessage(
+            code=0, msg="有线遥控器 打开蓝牙成功", data=message, device_status=2
+        )
+        self.connect_state = True
+        self.is_running = True
+        await self.run()
+
+    def handlerAction(self, button_value):
+        """处理拍照动作按键[左 右]"""
+        control_program = "执行左脚程序" if button_value == 1 else "执行右脚程序"
+        match button_value:
+            case 1:
+                control_program = "执行左脚程序"
+            case 2:
+                control_program = "执行右脚程序"
+        if self.goods_art_no == None or self.goods_art_no == "":
+            input_data = {
+                "data": {
+                    "action": control_program,
+                    "goods_art_no": "",
+                },
+                "type": "run_mcu",
+            }
+            self.msg_type = "blue_tooth_scan"
+            self.sendSocketMessage(
+                code=0,
+                msg=f"准备执行[{control_program}]",
+                data=input_data,
+                device_status=2,
+            )
+            self.msg_type = "blue_tooth"
+            return
+        self.photo_take_state = 1
+        input_data = {
+            "data": {
+                "action": control_program,
+                "goods_art_no": self.goods_art_no,
+            },
+            "type": "run_mcu",
+        }
+        self.msg_type = "blue_tooth_scan"
+        self.sendSocketMessage(
+            code=0,
+            msg=f"准备执行[{control_program}]",
+            data=input_data,
+            device_status=2,
+        )
+        self.goods_art_no = None
+        self.msg_type = "blue_tooth"
+        self.photo_take_state = 2
+
+    async def analysis_received_data(self,):
+        await asyncio.sleep(0.01)
+        if not self.connect_state:
+            return
+        receive_data = self.serial_ins.read_cmd(out_time=1, check=0x6B)
+        if receive_data is False:
+            self.connect_state = False
+            return False
+
+        if not receive_data:
+            return
+        else:
+            print("有线控制器receive_data", receive_data)
+            # print(
+            #     "有线控制器 read receive_data {}".format(
+            #         self.serial_ins.change_hex_to_int(receive_data)
+            #     )
+            # )
+            pass
+        # 数据 结构 command,按命令解析
+        if receive_data[0] == 1:
+            # 扫码数据
+            bar_code = receive_data[1:].decode()
+            bar_code = bar_code.replace("\r", "")
+            bar_code = bar_code.replace("\n", "")
+            # self.sign_data.emit(
+            #     {"_type": 0, "plugins_mode": "remote_control", "data": bar_code}
+            # )
+            message = {"_type": 0, "plugins_mode": "remote_control", "data": bar_code}
+            print("有线控制器 扫码数据1", message)
+            self.goods_art_no = bar_code
+            self.sendSocketMessage(code=0, msg="", data=message, device_status=2)
+            return
+        if receive_data[0] == 9:
+            button_value = receive_data[1]
+            data = {"button_value": button_value}
+            message = {"_type": 9, "plugins_mode": "remote_control", "data": data}
+            if button_value in [1, 2]:
+                # 扫描货号
+                if self.photo_take_state != 0:
+                    self.sendSocketMessage(1, "前置拍照未完成,请稍后", device_status=-1)
+                    return
+                print("收到货号信息", self.goods_art_no)
+                self.handlerAction(button_value)
+                self.photo_take_state = 0
+            if button_value in [3]:
+                # 处理遥控器单拍
+                self.msg_type = "handler_take_picture"
+                # 0 闲置;1进行中;2已完成;
+                _data = {"type": self.msg_type, "data": None}
+                self.sendSocketMessage(0, "处理单拍消息", data=_data, device_status=-1)
+                self.msg_type = "blue_tooth"
+            if button_value in [9]:
+                # 处理停止
+                self.msg_type = "stop_action"
+                # 0 闲置;1进行中;2已完成;
+                _data = {"type": self.msg_type, "data": None}
+                self.sendSocketMessage(
+                    0, "停止执行组合动作", data=_data, device_status=-1
+                )
+                self.msg_type = "blue_tooth"
+            self.sendSocketMessage(code=0, msg="", data=message, device_status=2)
+            return
+        pass
+
+    async def run(self):
+        self.is_running = True
+        while True:
+            await asyncio.sleep(0.06)
+            if not self.connect_state:
+                message = {
+                    "_type": "show_info",
+                    "plugins_mode": "remote_control",
+                    "data": {"msg": "有线遥控器 未连接"},
+                }
+                self.sendSocketMessage(
+                    code=1,
+                    msg="有线遥控器 未连接",
+                    data=message,
+                    device_status=-1,
+                )
+                break
+            await self.analysis_received_data()
+
+        self.is_running = False
+        if not self.connect_state:
+            message = {
+                "_type": "show_info",
+                "plugins_mode": "remote_control",
+                "data": {"msg": "有线遥控器 未连接"},
+            }
+            self.sendSocketMessage(
+                code=1,
+                msg="有线遥控器 未连接",
+                data=message,
+                device_status=-1,
+            )

+ 0 - 5
python/mcu/McuDeviationSet.py

@@ -236,12 +236,7 @@ class McuDeviationSet:
         self.mcu.to_init_device_origin_point(device_name="mcu", is_force=True)
 
     def get_mcu_deviation(self):
-        # await asyncio.sleep(0.01)
-        # await self.mcu.getDeviationInfo()
-        # loop = asyncio.get_event_loop()
-        # loop.create_task(self.mcu.getDeviationInfo(), name="get_mcu_deviation")
         asyncio.run(self.mcu.getDeviationInfo())
-
     def get_mcu_deviation_info(self, data):
         if "_type" not in data:
             return

+ 7 - 0
python/mcu/ProgramItem.py

@@ -323,6 +323,13 @@ class ProgramItem(BaseClass):
                 id=record_id,
             ),
         )
+    def digicam_take_picture(self):
+        self.mcu.to_deal_device(device_name="buzzer", times=1)
+        # 用于临时拍照计数
+        is_af = True
+        self.capture_one.photograph(is_af=is_af)
+        self.last_photograph_time = time.time()  # 记录最近一次拍照时间
+        print("仅拍照执行完成")
 
     def rephotograph_one_pic(self, *args):
         """

+ 3 - 4
python/mcu/RemoteControlV2.py

@@ -3,12 +3,11 @@
 
 import json
 import time, asyncio
-from model import DeviceConfig
 import settings
 from .SerialIns import SerialIns
 from .BaseClass import BaseClass
 from sockets.connect_manager import ConnectionManager
-from databases import SqlQuery, PhotoRecord,DeviceConfig, CRUD, insert_photo_records
+from databases import SqlQuery, PhotoRecord, DeviceConfig, CRUD, insert_photo_records
 from .capture.module_digicam import DigiCam
 from .capture.module_watch_dog import FileEventHandler
 
@@ -289,7 +288,7 @@ class RemoteControlV2(BaseClass):
                 action_id = AllTabConfig[len(AllTabConfig) - 1].id
             image_index = record.image_index + 1
             self.photo_take_state = 1
-            state, record_id = insert_photo_records(
+            state, record_id = await insert_photo_records(
                 record.image_deal_mode,
                 record.goods_art_no,
                 image_index,
@@ -318,7 +317,7 @@ class RemoteControlV2(BaseClass):
                         ),
                         name="CameraShooter",
                     )
-                time.sleep(1)
+                await asyncio.sleep(1)
                 self.msg_type = "photo_take"
                 self.sendSocketMessage(
                     code=0,

+ 44 - 10
python/mcu/capture/smart_shooter_class.py

@@ -6,7 +6,7 @@ import asyncio
 from PIL import Image
 from io import BytesIO
 import base64
-import zmq, sys
+import zmq, sys, time
 from utils.SingletonType import SingletonType
 
 
@@ -22,6 +22,7 @@ class SmartShooter(metaclass=SingletonType):
         self.stop_listen = False
         # 相机连接状态
         self.connect_status = False
+        # self.preview_queue = asyncio.Queue()
         # 实时预览状态
         self.perview_state = False
         self.callback_listen = None
@@ -112,6 +113,8 @@ class SmartShooter(metaclass=SingletonType):
                 return False, "相机未连接"
             # 链接的相机
             # connect_camera = cameraInfo
+            # for item in cameraInfo:
+            #     print("相机状态::::>>>>>>>", item.get("CameraStatus"))
             CameraStatus = any(
                 item.get("CameraStatus") in ["Ready", "Busy"] for item in cameraInfo
             )
@@ -179,8 +182,36 @@ class SmartShooter(metaclass=SingletonType):
                 )
             return False, msg_send
 
+    async def SetCameraFPS(self, fps=5):
+        """
+        激活相机预览
+        """
+        camera_states, _ = await self.GetCameraInfo(is_send=False)
+        if not camera_states:
+            return False, "请先连接相机"
+        try:
+            socket, context = self.__create_req()
+            req = {}
+            req["msg_type"] = "Request"
+            req["msg_id"] = "LiveviewFPS"
+            req["msg_seq_num"] = 0
+            req["CameraSelection"] = "All"
+            req["CameraLiveviewFPS"] = fps
+            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, "设置失败"
+        except:
+            self.perview_state = False
+            socket.close()
+            context.term()
+            return False, "相机未连接或软件未打开"
+
     async def EnableCameraPreview(self, enable_status=True, msg_type=""):
         self.msg_type = msg_type
+        await self.SetCameraFPS(5)
         """
         激活相机预览
         """
@@ -261,7 +292,9 @@ class SmartShooter(metaclass=SingletonType):
             context.term()
             return False, "相机未连接或软件未打开"
 
-    async def CameraShooter(self, msg_type="", goods_art_no="", id=0, is_af=False):
+    async def CameraShooter(self, msg_type="", goods_art_no="", id=0, is_af=False,delay=1.5):
+        # 这里延迟一秒钟 等待前置命令完成
+        await asyncio.sleep(delay)
         # 对焦混用
         if is_af:
             await self.CameraAutofocus()
@@ -345,7 +378,7 @@ class SmartShooter(metaclass=SingletonType):
             await self.websocket_manager.send_personal_message(message, self.websocket)
             return False, msg_send
 
-    async def connect_listen(self):
+    def connect_listen(self):
         print("smart shooter connect_listen", self.connect_status, self.listen_init)
         if self.connect_status == True or self.listen_init == True:
             return True
@@ -354,14 +387,14 @@ class SmartShooter(metaclass=SingletonType):
         print("构建监听", self.connect_status)
         while True:
             self.listen_init = True
-            await asyncio.sleep(0.01)
+            time.sleep(0.01)
             if self.callback_listen == None:
                 continue
-            camera_states, camera_msg = await self.GetCameraInfo(is_send=False)
-            if not camera_states:
-                print("相机未连接")
-                await asyncio.sleep(0.01)  # 等待相机连接
-                continue
+            # camera_states, camera_msg = await self.GetCameraInfo(is_send=False)
+            # if not camera_states:
+            #     print("相机未连接回调打印", camera_states, camera_msg)
+            #     await asyncio.sleep(0.01)  # 等待相机连接
+            #     continue
             if self.stop_listen:
                 break
             try:
@@ -371,7 +404,8 @@ class SmartShooter(metaclass=SingletonType):
                 json_msg = json.loads(str_msg)
                 if json_msg["msg_id"] == "NetworkPing":
                     continue
-                await self.callback_listen(json_msg)
+                # self.callback_listen(json_msg)
+                asyncio.run(self.callback_listen(json_msg))
             except zmq.Again:
                 print("接收超时,继续监听...")
                 continue

+ 3 - 2
python/sockets/connect_manager.py

@@ -1,6 +1,6 @@
 from models import WebSocket
 from logger import logger
-import json
+import json, asyncio
 from starlette.websockets import WebSocketState
 class ConnectionManager:
     is_connected = False
@@ -26,7 +26,8 @@ class ConnectionManager:
 
     async def send_personal_message(self, message: str, websocket: WebSocket):
         '''向用户发送消息'''
-        await websocket.send_json(message)
+        # await websocket.send_json(message)
+        asyncio.create_task(websocket.send_json(message))
 
     async def broadcast(self, message: str):
         """广播消息"""

+ 52 - 65
python/sockets/message_handler.py

@@ -7,23 +7,6 @@ from databases import DeviceConfig, SqlQuery, CRUD, PhotoRecord, SysConfigs
 from mcu.capture.module_digicam import DigiCam
 from mcu.capture.smart_shooter_class import SmartShooter
 from models import RecordUpdate
-from sqlalchemy.exc import NoResultFound
-import os, datetime
-
-async def updateDataRecord(PhotoFilename, id):
-    await asyncio.sleep(0.01)
-    create_time = datetime.datetime.fromtimestamp(os.path.getctime(PhotoFilename))
-    data = {"id": id, "image_path": PhotoFilename, "photo_create_time": create_time}
-    # record_model = PhotoRecord(**data)
-    session = SqlQuery()
-    record_model = CRUD(PhotoRecord)
-    model = record_model.read(session, conditions={"id": id})
-    if model == None:
-        print(f"smart shooter 拍照记录更新失败,记录id:{id},不存在")
-    else:
-        # 走编辑逻辑
-        record_model.updateConditions(session, conditions={"id": id}, **data)
-        print(f"smart shooter 拍照记录更新成功,记录id:{id}")
 
 
 # socket消息发送逻辑处理方法
@@ -42,49 +25,6 @@ async def handlerSend(
     msg = receiveData.get("msg")
     data = receiveData.get("data")
 
-    async def MsgCallback(msg):
-        msg_id = msg.get("msg_id")
-        match msg_id:
-            case "PhotoUpdated":
-                PhotoFilename = msg.get("PhotoFilename")
-                PhotoLocation = msg.get("PhotoLocation")
-                PhotoOrigin = msg.get("PhotoOrigin")
-                if (PhotoFilename != "" and PhotoFilename != None) and (
-                    PhotoLocation == "Local Disk"
-                ):
-                    # temp_photo_name = PhotoFilename
-                    # 更新拍照记录
-                    print("PhotoFilename", PhotoFilename, PhotoOrigin)
-                    if PhotoOrigin != "" and PhotoOrigin != "external":
-                        goods_art_no, id = PhotoOrigin.split(",")
-                        loop.create_task(
-                            updateDataRecord(PhotoFilename, id), name="PhotoFilename"
-                        )
-                    data = manager.jsonMessage(
-                        code=0,
-                        msg=f"照片获取成功",
-                        data={"photo_file_name": PhotoFilename},
-                        msg_type="smart_shooter_photo_take",
-                    )
-                    await manager.send_personal_message(data, websocket)
-            case "LiveviewUpdated":
-                CameraLiveviewImage = msg.get("CameraLiveviewImage", None)
-                # base64_to_image(CameraLiveviewImage, "liveview.jpg")
-                # print("收到直播画面:CameraLiveviewImage")
-                data = manager.jsonMessage(
-                    code=1,
-                    msg=f"预览数据发送",
-                    data={"smart_shooter_preview": CameraLiveviewImage},
-                    msg_type="smart_shooter_enable_preview",
-                )
-                await manager.send_personal_message(data, websocket)
-
-    # 构建监听条件
-    smart_shooter.callback_listen = MsgCallback
-    loop.create_task(
-        smart_shooter.connect_listen(),
-        name="smart_shooter_connect_listen",
-    )
     match jsonType:
         case "ping":
             """发送心跳"""
@@ -184,7 +124,7 @@ async def handlerSend(
                 data = manager.jsonMessage(code=1, msg="当前没有可用配置")
                 await manager.send_personal_message(data, websocket, msg_type=msg_type)
                 return
-            action_list = [device.model_dump() for device in all_devices]
+            action_list = [dict(device.__dict__) for device in all_devices]
             print("handl send smart_shooter", smart_shooter)
             device_ctrl = DeviceControl(
                 websocket_manager=manager, smart_shooter=smart_shooter
@@ -206,6 +146,10 @@ async def handlerSend(
                 name="run_mcu_single",
             )
         case "handler_take_picture":
+            device_ctrl = DeviceControl(
+                websocket_manager=manager, smart_shooter=smart_shooter
+            )
+            await device_ctrl.controlDevice("laser_position", 0)
             blue_tooth = BlueToothMode(
                 websocket_manager=manager, smart_shooter=smart_shooter
             )
@@ -213,6 +157,8 @@ async def handlerSend(
                 blue_tooth.remote_control_v2.handlerTakePhoto(smart_shooter),
                 name="run_mcu_config",
             )
+            await asyncio.sleep(2.5)
+            await device_ctrl.controlDevice("laser_position", 1)
         case "re_take_picture":  # 重拍
             msg_type = "re_take_picture"
             record_id = data.get("record_id")
@@ -233,12 +179,13 @@ async def handlerSend(
             crud = CRUD(DeviceConfig)
             condtions = {"id": action_id}
             device_action = crud.read(session, conditions=condtions)
+            result_dict = dict(device_action.__dict__)
+            print("device_action打印输出====>>>", result_dict)
             if device_action == None:
                 # 判断是否有可用配置
                 data = manager.jsonMessage(code=1, msg="当前没有可用配置")
                 await manager.send_personal_message(data, websocket, msg_type=msg_type)
                 return
-            print("device_action", device_action)
             # 清除图片记录,执行重拍
             reset_data = {"image_path": None}
             photoRecord.update(session, record_id, **reset_data)
@@ -247,7 +194,7 @@ async def handlerSend(
             )
             loop.create_task(
                 device_ctrl.run_mcu_config_single(
-                    device_action.model_dump(),
+                    result_dict,
                     goods_art_no,
                     msg_type=msg_type,
                     image_index=image_index,
@@ -331,9 +278,49 @@ async def handlerSend(
             """
             获取相机信息,是否连接
             """
+            device_ctrl = DeviceControl(
+                websocket_manager=manager, smart_shooter=smart_shooter
+            )
+            await device_ctrl.controlDevice("laser_position", 0)
+            # 兼容主图测试
+            id = data.get("id", 0)
+            goods_art_no = data.get("goods_art_no", "")
+            is_af = True
+            loop.create_task(
+                smart_shooter.CameraShooter(
+                    msg_type="smart_shooter_photo_take",
+                    id=id,
+                    goods_art_no=goods_art_no,
+                    is_af=is_af,
+                ),
+                name="smart_shooter_photo_take",)
+            await asyncio.sleep(2.5)
+            await device_ctrl.controlDevice("laser_position", 1)
+        case "digicam_take_picture":
+            msg_type = "re_take_picture"
+            id = data.get("id", 0)
+            goods_art_no = data.get("goods_art_no", "")
+            session = SqlQuery()
+            photoRecord = CRUD(PhotoRecord)
+            goods_art_record = photoRecord.read(session, conditions={"id": id})
+            if goods_art_record == None:
+                data = manager.jsonMessage(
+                    code=1,
+                    msg=f"记录不存在,请核实后重新操作~",
+                    msg_type=msg_type,
+                )
+                await manager.send_personal_message(data, websocket)
+                return
+            reset_data = {"image_path": None}
+            photoRecord.update(session, id, **reset_data)
+            device_ctrl = DeviceControl(websocket_manager=manager)
             loop.create_task(
-                smart_shooter.CameraShooter(msg_type="smart_shooter_photo_take"),
-                name="smart_shooter_photo_take",
+                device_ctrl.only_take_photo(
+                    goods_art_no=goods_art_no,
+                    image_index=goods_art_record.image_index,
+                    record_id=id,
+                ),
+                name="sendCommand",
             )
         case _:
             data = manager.jsonMessage(code=1, msg="未知消息")

+ 2 - 2
python/sockets/socket_client.py

@@ -39,6 +39,6 @@ class SocketClient:
 
 # 创建全局 SocketManager 实例
 socket_manager = SocketClient(f"ws://{APP_HOST}:{PORT}/ws")
-def sendMsg(code=0, msg="", data=None):
+async def sendMsg(code=0, msg="", data=None):
     '''通用客户端发送消息机制'''
-    asyncio.run(socket_manager.send_message(code=code, msg=msg, data=data))
+    await socket_manager.send_message(code=code, msg=msg, data=data)

+ 62 - 2
python/sockets/socket_server.py

@@ -8,14 +8,34 @@ from mcu.BlueToothMode import BlueToothMode
 from mcu.capture.smart_shooter_class import SmartShooter
 import time
 from .socket_client import socket_manager
+from sqlalchemy.exc import NoResultFound
+import os, datetime
+
 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
+async def updateDataRecord(PhotoFilename, id):
+    await asyncio.sleep(0.01)
+    create_time = datetime.datetime.fromtimestamp(os.path.getctime(PhotoFilename))
+    data = {"id": id, "image_path": PhotoFilename, "photo_create_time": create_time}
+    # record_model = PhotoRecord(**data)
+    session = SqlQuery()
+    record_model = CRUD(PhotoRecord)
+    model = record_model.read(session, conditions={"id": id})
+    if model == None:
+        print(f"smart shooter 拍照记录更新失败,记录id:{id},不存在")
+    else:
+        # 走编辑逻辑
+        record_model.updateConditions(session, conditions={"id": id}, **data)
+        print(f"smart shooter 拍照记录更新成功,记录id:{id}")
+
+
 @app.websocket("/ws")
 async def websocket_endpoint(websocket: WebSocket):
+    # await websocket.accept()
     await conn_manager.connect(websocket)
     active_connections.add(websocket)
     smart_shooter.websocket = websocket
@@ -63,7 +83,43 @@ async def websocket_endpoint(websocket: WebSocket):
                 except Exception as e:
                     print(e)
                     break
-
+        async def MsgCallback(msg):
+            msg_id = msg.get("msg_id")
+            match msg_id:
+                case "PhotoUpdated":
+                    PhotoFilename = msg.get("PhotoFilename")
+                    PhotoLocation = msg.get("PhotoLocation")
+                    PhotoOrigin = msg.get("PhotoOrigin")
+                    if (PhotoFilename != "" and PhotoFilename != None) and (
+                        PhotoLocation == "Local Disk"
+                    ):
+                        # temp_photo_name = PhotoFilename
+                        # 更新拍照记录
+                        print("PhotoFilename", PhotoFilename, PhotoOrigin)
+                        if PhotoOrigin != "" and PhotoOrigin != "external":
+                            goods_art_no, id = PhotoOrigin.split(",")
+                            await updateDataRecord(PhotoFilename, id)
+                        data = conn_manager.jsonMessage(
+                            code=0,
+                            msg=f"照片获取成功",
+                            data={"photo_file_name": PhotoFilename},
+                            msg_type="smart_shooter_photo_take",
+                        )
+                        await conn_manager.send_personal_message(data, websocket)
+                case "LiveviewUpdated":
+                    CameraLiveviewImage = msg.get("CameraLiveviewImage", None)
+                    # base64_to_image(CameraLiveviewImage, "liveview.jpg")
+                    # print("收到直播画面:CameraLiveviewImage")
+                    data = conn_manager.jsonMessage(
+                        code=1,
+                        msg=f"预览数据发送",
+                        data={"smart_shooter_preview": CameraLiveviewImage},
+                        msg_type="smart_shooter_enable_preview",
+                    )
+                    await conn_manager.send_personal_message(data, websocket)
+        smart_shooter.callback_listen = MsgCallback
+        loop = asyncio.get_event_loop()
+        loop.run_in_executor(None, smart_shooter.connect_listen)  # 后台线程启动监听
         await asyncio.gather(handler_messages(), send_message())
     except WebSocketDisconnect:
         # socket_manager.close()
@@ -73,7 +129,11 @@ async def websocket_endpoint(websocket: WebSocket):
         # if websocket:
         #     await websocket.close()
 
-
+# @app.on_event("startup")
+# async def startup_event():
+#     loop = asyncio.get_event_loop()
+#     loop.run_in_executor(None, await smart_shooter.connect_listen)
+#     print("监听服务已启动")
 @app.on_event("shutdown")
 async def shutdown_event():
     print("Shutting down...")