Kaynağa Gözat

fix(camera): 解决相机控制软件进程状态管理问题

- 添加进程状态检查和监听功能,实时跟踪相机控制软件运行状态
- 实现进程关闭事件监听器,确保软件关闭时重置启动标志
- 优化相机连接检测逻辑,增加进程运行状态验证机制
- 统一相机硬件未连接时的错误提示信息
- 重构进程管理代码,提高相机控制软件启动和状态同步的可靠性
panqiuyao 1 hafta önce
ebeveyn
işleme
a7644a8bac
2 değiştirilmiş dosya ile 74 ekleme ve 54 silme
  1. 47 47
      electron/controller/camera.js
  2. 27 7
      electron/utils/camera.js

+ 47 - 47
electron/controller/camera.js

@@ -1,7 +1,7 @@
 'use strict';
 const { Controller } = require('ee-core');
 const Log = require('ee-core/log');
-const { checkCameraControlCmdExists, closeCameraControlTips} = require('../utils/camera');
+const { checkCameraControlCmdExists, closeCameraControlTips, isProcessRunning, onProcessClosed, removeProcessClosedListener } = require('../utils/camera');
 const {
   checkCamera,
   liveShow, liveHide, setParams, capture, getParams,CMD,captureLive,closeOtherWindow } = require('../api/camera');
@@ -10,6 +10,13 @@ const { readConfigFile } = require('../utils/config');
 
 let  isOPen = true
 let isSoftwareStarted = false; // 标记相机控制软件是否已经启动
+
+// 注册进程关闭事件监听器,当软件被关闭时重置标志
+onProcessClosed(() => {
+  Log.info('相机控制软件已关闭,重置 isSoftwareStarted 标志');
+  isSoftwareStarted = false;
+});
+
 class CameraController extends Controller {
   constructor(ctx) {
     super(ctx);
@@ -19,10 +26,28 @@ class CameraController extends Controller {
     try {
       console.log('==================');
       console.log(readConfigFile());
+
+      // 主动检测:即使 isSoftwareStarted 为 true,也要检查进程是否还在运行(兜底机制)
+      if (isSoftwareStarted && !isProcessRunning()) {
+        Log.info('检测到 isSoftwareStarted 为 true 但进程已关闭,重置标志');
+        isSoftwareStarted = false;
+      }
+
       if(readConfigFile().controlType === 'digiCamControl'){
         console.log('========1==========');
 
-        // 首先尝试获取相机参数
+        // 主动检测:如果软件未启动或进程已关闭,先启动软件
+        if (!isSoftwareStarted || !isProcessRunning()) {
+          console.log('启动 digiCamControl 软件...');
+          await checkCameraControlCmdExists();
+          await CMD('All_Minimize');
+          await closeCameraControlTips();
+          isSoftwareStarted = true;
+          console.log('digiCamControl 软件启动完成,等待初始化...');
+          await new Promise(resolve => setTimeout(resolve, 5000)); // 等待软件初始化
+        }
+
+        // 获取相机参数
         let res = await getParams('iso').catch(e=>{
           console.log('getParams failed:', e);
           isOPen = false;
@@ -30,29 +55,9 @@ class CameraController extends Controller {
         });
 
         if(res === '未将对象引用设置到对象的实例。' || !res){
-          // 相机未连接,检查是否需要启动软件
-          if (!isSoftwareStarted) {
-            console.log('启动 digiCamControl 软件...');
-            await checkCameraControlCmdExists();
-            await CMD('All_Minimize');
-            await closeCameraControlTips();
-            isSoftwareStarted = true;
-            console.log('digiCamControl 软件启动完成,等待初始化...');
-            await new Promise(resolve => setTimeout(resolve, 5000)); // 等待软件初始化
-
-            // 软件启动后再次检查相机状态
-            res = await getParams('iso').catch(e=>{
-              console.log('软件启动后检查相机失败:', e);
-              return null;
-            });
-          }
-
-          // 如果仍然失败,返回错误
-          if(res === '未将对象引用设置到对象的实例。' || !res) {
-            return {
-              status:-1,
-              msg: isSoftwareStarted ? "相机硬件未连接,请检查相机连接。" : "相机控制软件启动失败。",
-            }
+          return {
+            status:-1,
+            msg: "相机硬件未连接,请检查相机连接。",
           }
         }
 
@@ -62,33 +67,28 @@ class CameraController extends Controller {
         }
       }else{
         // SmartShooter 逻辑
+        // 主动检测:如果软件未启动或进程已关闭,先启动软件
+        if (!isSoftwareStarted || !isProcessRunning()) {
+          Log.info('启动 SmartShooter 软件...');
+          await checkCameraControlCmdExists();
+          isSoftwareStarted = true;
+          Log.info('SmartShooter 软件启动完成,等待初始化...');
+          await new Promise(resolve => setTimeout(resolve, 10000)); // 等待软件初始化
+        }
+
+        // 检查相机状态
         let res = await checkCamera().catch(e=>{
           Log.info('checkCamera:'+e);
           isOPen = false;
+          return { device_status: -1 }; // 返回错误状态,让后续逻辑处理
         })
 
-        if(res?.device_status  === -1 ){
-          // 相机未连接,检查是否需要启动软件
-          if (!isSoftwareStarted) {
-            Log.info('启动 SmartShooter 软件...');
-            await checkCameraControlCmdExists();
-            isSoftwareStarted = true;
-            Log.info('SmartShooter 软件启动完成,等待初始化...');
-            await new Promise(resolve => setTimeout(resolve, 10000)); // 等待软件初始化
-
-            // 软件启动后再次检查相机状态
-            res = await checkCamera().catch(e=>{
-              Log.info('软件启动后检查相机失败:'+e);
-            });
-          }
-
-          // 无论是否启动了软件,如果相机还是未连接,返回相应状态
-          if (res?.device_status === -1) {
-            return {
-              status: -1,
-              msg: isSoftwareStarted ? "相机硬件未连接,请检查相机连接。" : "相机控制软件启动失败。",
-            };
-          }
+        // 如果相机未连接
+        if (res?.device_status === -1) {
+          return {
+            status: -1,
+            msg: "相机硬件未连接,请检查相机连接。",
+          };
         }
 
         if(res?.device_status  === 2){

+ 27 - 7
electron/utils/camera.js

@@ -4,6 +4,7 @@ const path = require('path');
 const fs = require('fs');
 const Log = require('ee-core/log');
 const { spawn } = require('child_process');
+const { EventEmitter } = require('events');
 const { liveShow, liveHide, setParams, capture, getParams,CMD,captureLive,closeOtherWindow,minimizeSmartShooter } = require('../api/camera');
 
 const { dialog } = require('electron'); // 引入 electron 的 dialog 模块
@@ -12,6 +13,11 @@ const CoreWindow = require("ee-core/electron/window");
 
 const { readConfigFile, writeConfigFile } = require('../utils/config');
 
+// 进程状态管理
+let cameraProcess = null;        // 子进程引用
+let isProcessRunning = false;    // 进程运行状态
+const processEmitter = new EventEmitter(); // 进程事件发射器
+
 const exe = {
   "digiCamControl":"CameraControl.exe",
   "SmartShooter":"SmartShooter5.exe",
@@ -106,16 +112,26 @@ async function openCameraControlCmd(digiCamControlPath) {
       await fs.promises.access(exePath, fs.constants.F_OK);
       try {
 
-        const child = spawn(exePath);
+        // 保存进程引用并标记为运行中
+        cameraProcess = spawn(exePath);
+        isProcessRunning = true;
 
-        child.stdout.on('data', (data) => {
+        cameraProcess.stdout.on('data', (data) => {
           resolve(true)
         });
 
-        child.on('close', (code) => {
-          if (code === 0) {
-            reject(false)
-          }
+        // 监听进程关闭事件
+        cameraProcess.on('close', (code) => {
+          isProcessRunning = false;
+          cameraProcess = null;
+          Log.info(`相机控制软件已关闭,退出码: ${code}`);
+          processEmitter.emit('camera-process-closed');
+        });
+
+        cameraProcess.on('error', (err) => {
+          isProcessRunning = false;
+          cameraProcess = null;
+          Log.error('相机控制软件进程错误:', err);
         });
 
 
@@ -146,5 +162,9 @@ async function closeCameraControlTips() {
 module.exports = {
   checkCameraControlCmdExists,
   closeCameraControlTips,
-  minimizeSmartShooter
+  minimizeSmartShooter,
+  // 进程状态管理
+  isProcessRunning: () => isProcessRunning,
+  onProcessClosed: (callback) => processEmitter.on('camera-process-closed', callback),
+  removeProcessClosedListener: (callback) => processEmitter.removeListener('camera-process-closed', callback),
 };