Browse Source

增加流程可选对应的深度学习模版
修改流程架构尝试优化ct

KWD 3 months ago
parent
commit
5785830763

+ 1 - 0
TeamAAS-VM/Core/ImageHelper.cs

@@ -1,5 +1,6 @@
 using Cognex.VisionPro;
 using OpenCvSharp;
+using OpenCvSharp.Extensions;
 using System;
 using System.Collections.Generic;
 using System.Drawing;

+ 95 - 73
TeamAAS-VM/Core/Management.cs

@@ -1623,7 +1623,6 @@ namespace TeamAAS_VP.Core
                         }
                     }
                 }
-
                 // 固定相机检测拍照
                 else if (addressConfig.In_FixedCameracheckExe.Address.Contains(tuple.nodeId))
                 {
@@ -1660,44 +1659,24 @@ namespace TeamAAS_VP.Core
                             try
                             {
                                 if (targetPoint.CameraProcedureId1 != Guid.Empty && !procIds.Contains(targetPoint.CameraProcedureId1)) procIds.Add(targetPoint.CameraProcedureId1);
-                            }
-                            catch { }
-                            try
-                            {
+
                                 if (targetPoint.CameraProcedureId2 != Guid.Empty && !procIds.Contains(targetPoint.CameraProcedureId2)) procIds.Add(targetPoint.CameraProcedureId2);
-                            }
-                            catch { }
-                            try
-                            {
+
                                 if (targetPoint.CameraProcedureId3 != Guid.Empty && !procIds.Contains(targetPoint.CameraProcedureId3)) procIds.Add(targetPoint.CameraProcedureId3);
-                            }
-                            catch { }
-                            try
-                            {
+
                                 if (targetPoint.CameraProcedureId4 != Guid.Empty && !procIds.Contains(targetPoint.CameraProcedureId4)) procIds.Add(targetPoint.CameraProcedureId4);
-                            }
-                            catch { }
-                            try
-                            {
+
                                 if (targetPoint.CameraProcedureId5 != Guid.Empty && !procIds.Contains(targetPoint.CameraProcedureId5)) procIds.Add(targetPoint.CameraProcedureId5);
-                            }
-                            catch { }
-                            try
-                            {
+
                                 if (targetPoint.CameraProcedureId6 != Guid.Empty && !procIds.Contains(targetPoint.CameraProcedureId6)) procIds.Add(targetPoint.CameraProcedureId6);
-                            }
-                            catch { }
-                            try
-                            {
+
                                 if (targetPoint.CameraProcedureId7 != Guid.Empty && !procIds.Contains(targetPoint.CameraProcedureId7)) procIds.Add(targetPoint.CameraProcedureId7);
-                            }
-                            catch { }
-                            try
-                            {
+
                                 if (targetPoint.CameraProcedureId8 != Guid.Empty && !procIds.Contains(targetPoint.CameraProcedureId8)) procIds.Add(targetPoint.CameraProcedureId8);
                             }
                             catch { }
                             var sysConfig = _configService.GetSystemConfiguration();
+
                             if (sysConfig.ScannerUse == true && cameraIndex == 1 && sysConfig.CodeUse2 == true)
                             {
                                 ScanValue = "";
@@ -1974,7 +1953,6 @@ namespace TeamAAS_VP.Core
                                 return;
                             }
 
-
                             if (procIds.Count == 0 && cameraIndex != currentProduct.PhotoCountStop)
                             {
                                 SendTaskMessage($"Point#{cameraIndex} 未配置任何视觉流程 (CameraProcedureId1/2/3)", MessageLevel.Alarm);
@@ -2371,7 +2349,7 @@ namespace TeamAAS_VP.Core
                                 if (sysConfig.PhotosUse == true)
                                 {
                                     bool Is3dPhoto = Is3D(prcId);
-                                    var tt = await GrabImageEx(cameraIndex, prcId, Is3dPhoto);
+                                    var tt = await GrabImageEx(cameraIndex, prcId, Is3dPhoto, currentProduct, sysConfig);
                                     if (tt.IsSucceed == false)
                                     {
                                         SendTaskMessage($"图像采集失败!{cameraIndex}: {prcId}", MessageLevel.Alarm);
@@ -2382,7 +2360,7 @@ namespace TeamAAS_VP.Core
                                 else
                                 {
                                     bool Is3dPhoto = Is3D(prcId);
-                                    _ImageTaskList.Add(GrabImageEx(cameraIndex, prcId, Is3dPhoto));
+                                    _ImageTaskList.Add(GrabImageEx(cameraIndex, prcId, Is3dPhoto, currentProduct, sysConfig));
                                 }
 
                                 if (sysConfig.TurnOnAllLightUse == false)
@@ -2390,11 +2368,13 @@ namespace TeamAAS_VP.Core
                                     await _remoteCommandService.TurnOffLightAfterPhoto(selectedProcedure);
                                 }
                             }
+
                             if (cameraIndex != currentProduct.PhotoCountStop)
                             {
                                 //直接放行,执行下一个检测点
                                 await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPickStatus.Address, (Int16)1);
                             }
+
                             if (_ImageTaskList.Count > 0)//如果2D取图有队列
                             {
                                 var ImageTaskResults = await Task.WhenAll(_ImageTaskList);
@@ -2412,6 +2392,7 @@ namespace TeamAAS_VP.Core
                                     }
                                 }
                             }
+
                             //如果最后一个拍照点,则需要等待前面所有的拍照处理完成
                             if (cameraIndex == currentProduct.PhotoCountStop)
                             {
@@ -2434,7 +2415,6 @@ namespace TeamAAS_VP.Core
                                     //等待所有的图像处理流程处理完成
                                     var results = await Task.WhenAll(_PrcTaskList);
 
-
                                     foreach (var item in results)
                                     {
                                         if (!item.IsSucceed || item.Result == null)
@@ -2455,8 +2435,6 @@ namespace TeamAAS_VP.Core
                                         }
                                     }
                                 }
-
-
                                 //全部OK
                                 if (resultFlog)
                                 {
@@ -2470,6 +2448,7 @@ namespace TeamAAS_VP.Core
                                     await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPickStatus.Address, (Int16)2);
                                 }
                             }
+                            return;
                         }
                         else
                         {
@@ -2478,7 +2457,6 @@ namespace TeamAAS_VP.Core
                         }
                     }
                 }
-
                 // 翻转相机检测拍照
                 else if (addressConfig.In_FzCameraPixExe.Address.Contains(tuple.nodeId))
                 {
@@ -2702,6 +2680,7 @@ namespace TeamAAS_VP.Core
                                 {
                                     //这里缺少从MES获取产品配方的内容,需要补充
                                     _LastMesCheckTime[i] = (await _mesService.GetServerTimeAsync(code, 2)).Now;
+                                    ProductMainSN = "";
                                     var stationConfig2 = _configService.GetDeviceInfo(0);
                                     if (homeview.IsNoCode == false)
                                     {
@@ -2802,7 +2781,7 @@ namespace TeamAAS_VP.Core
                                                                 break;
                                                             }
                                                         }
-                                                        //if(kb_sn==)
+                                                        //if (kb_sn ==)
                                                         if (currentProduct.ID != productId || productWithMes.ProductKBSN != kb_sn)
                                                         {
                                                             //切换产品
@@ -2817,16 +2796,23 @@ namespace TeamAAS_VP.Core
                                             await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)1);
                                             LogHelper.WriteLogMes($"【mes结束QUERY】");
                                             SendTaskMessage($"mes结束QUERY", MessageLevel.Info);
-                                           // return;
+                                            // return;
                                         }
                                         else
                                         {
                                             await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)2);
 
-                                            LogHelper.WriteLogMes($"询问mes失败");
-                                            SendTaskMessage($"询问mes失败:{response}", MessageLevel.Error);
+                                            LogHelper.WriteLogMes($"二次询问mes失败");
+                                            SendTaskMessage($"二次询问mes失败:{response}", MessageLevel.Error);
                                         }
-                                    }                                   
+                                    }
+                                    else
+                                    {
+                                        await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)2);
+
+                                        LogHelper.WriteLogMes($"询问mes失败");
+                                        SendTaskMessage($"询问mes失败:{response}", MessageLevel.Error);
+                                    }
                                 }
                                 // 上传本站数据
                                 else if (state == 2)
@@ -2837,6 +2823,8 @@ namespace TeamAAS_VP.Core
                                     List<DataFormCtq> DFC = new List<DataFormCtq>();
                                     SendTaskMessage($"收到{i}上传本站数据请求...", MessageLevel.Debug);
 
+                                    await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)3);
+
                                     //这里缺少上传MES的本站数据结果及开始和结束时间,需要补充
                                     //从服务器中获取当前时间
                                     var serverTimeResult = await _mesService.GetServerTimeAsync(ProductMainSN, 2);
@@ -2923,7 +2911,7 @@ namespace TeamAAS_VP.Core
 
                                         if (keyData != null)
                                         {
-                                            ok = CheckKeyBoardValue(keyData,name, out string msg);
+                                            ok = CheckKeyBoardValue(keyData, name, out string msg);
                                         }
 
                                         if (ok && resultIndex == 1 ? true : false && isValueOk)
@@ -2933,7 +2921,7 @@ namespace TeamAAS_VP.Core
                                         else
                                         {
                                             ShowMes_Result = false;
-                                        }                                       
+                                        }
                                     }
 
                                     ShowMes_Result = resultIndex == 1 ? true : false;
@@ -2983,7 +2971,7 @@ namespace TeamAAS_VP.Core
                                         LogHelper.WriteLogMes($"上传mes失败");
                                         SendTaskMessage($"上传mes失败", MessageLevel.Error);
                                     }
-                                    await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)3);
+                                    //await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)3);
 
 
                                     //是否保存当前的产品记录至CSV?
@@ -2992,7 +2980,7 @@ namespace TeamAAS_VP.Core
                                         string saveppid = "NA";
                                         string names = currentProduct.Name;
                                         if (stationConfig.SaveCsvPPID) saveppid = ppid;
-                                        
+
                                         // Dictionary<string, double> adjacentDiffDict1 = GetAdjacentDiffDict(keyData1);
                                         //判断锁付路径字符串是否为空,如果不为空则保存,否则不保存
                                         if (!string.IsNullOrEmpty(stationConfig.SaveCsvPath))
@@ -3014,6 +3002,45 @@ namespace TeamAAS_VP.Core
                                                     //    item.PhotoName = "_" + k.ToString();
                                                     //}
                                                 }
+
+                                                string temp_COMMODITY_TYPE = stationConfig.DataInfo.COMMODITY_TYPE;
+
+                                                if (item.PhotoName.Contains("A1b"))
+                                                {
+                                                    temp_COMMODITY_TYPE = "Mechanical Hardware LCD CVR";
+                                                }
+                                                if (item.PhotoName.Contains("A1c") || item.PhotoName.Contains("A1d"))
+                                                {
+                                                    temp_COMMODITY_TYPE = "Mechanical Hardware_LCD BZL";
+                                                }
+                                                if (item.PhotoName.Contains("A2"))
+                                                {
+                                                    temp_COMMODITY_TYPE = "CAMERA";
+                                                }
+                                                if (item.PhotoName.Contains("A4"))
+                                                {
+                                                    temp_COMMODITY_TYPE = "Mechanical Hardware_HNG CVR";
+                                                }
+                                                if (item.PhotoName.Contains("C4"))
+                                                {
+                                                    temp_COMMODITY_TYPE = "Mechanical Hardware_PLMRST";
+                                                }
+                                                if (item.PhotoName.Contains("D5"))
+                                                {
+                                                    temp_COMMODITY_TYPE = "Mechanical Hardware_DOOR";
+                                                }
+                                                if (item.PhotoName.Contains("B1"))
+                                                {
+                                                    temp_COMMODITY_TYPE = "Mechanical Hardware_KB BKT";
+                                                }
+                                                if (item.PhotoName.Contains("B2"))
+                                                {
+                                                    temp_COMMODITY_TYPE = "Mechanical Hardware_TP BKT";
+                                                }
+                                                if (item.PhotoName.Contains("D1"))
+                                                {
+                                                    temp_COMMODITY_TYPE = "Mechanical Hardware_BTM CVR";
+                                                }
                                                 DFC.Add(new DataFormCtq
                                                 {
                                                     PPID = saveppid,
@@ -3026,7 +3053,7 @@ namespace TeamAAS_VP.Core
                                                     CTQ_USL = item.UpLimit,
                                                     PROCESS_END_TIME = serverTimeResult.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffffff") + "+08:00",
                                                     SUPPLIER_NAME = stationConfig.DataInfo.SUPPLIER_NAME,
-                                                    COMMODITY_TYPE = stationConfig.DataInfo.COMMODITY_TYPE,
+                                                    COMMODITY_TYPE = temp_COMMODITY_TYPE,
                                                     REVISION = stationConfig.DataInfo.REVISION + "_" + stage,//
                                                     WO = wo,//
                                                     MFG_LOT = stationConfig.DataInfo.MFG_LOT,//
@@ -3109,11 +3136,11 @@ namespace TeamAAS_VP.Core
                                                 }
                                             }
 
-                                        //测试使用,强制上传mes为pass
-                                        //if (sysConfig.IsMesResult)
-                                        //{
-                                        //    resultToMes.Clear();
-                                        //}
+                                            //测试使用,强制上传mes为pass
+                                            //if (sysConfig.IsMesResult)
+                                            //{
+                                            //    resultToMes.Clear();
+                                            //}
                                             bool recordResult = RecordStationResult(i, DFC, ProductMainSN, serverTimeResult.Now.Subtract(_LastMesCheckTime[i]).TotalSeconds, _LastMesCheckTime[i], stationConfig.SaveCsvPath);
                                             // bool recordResult1 = WriteProductLog( ProductMainSN, serverTimeResult.Now.Subtract(_LastMesCheckTime[i]).TotalSeconds, _LastMesCheckTime[i], stationConfig.SaveCsvPath, DFC);
 
@@ -3238,11 +3265,10 @@ namespace TeamAAS_VP.Core
                                         keyData1.Clear();
                                     }
 
-                                    ProductMainSN = "";
+                                    //ProductMainSN = "";
                                     LogHelper.WriteLogMes($"【mes结束ADD】");
                                     SendTaskMessage($"mes结束ADD", MessageLevel.Info);
                                 }
-
                                 else
                                 {
                                     SendTaskMessage($"{i}过站检查信号:state={state},处理为默认状态", MessageLevel.Alarm);
@@ -3252,10 +3278,6 @@ namespace TeamAAS_VP.Core
                         }
                     }
                 }
-
-
-
-
             }
             catch (Exception ex)
             {
@@ -3550,7 +3572,7 @@ namespace TeamAAS_VP.Core
                                                     SendTaskMessage($"检测项{lockResult1.PhotoName}结果{ResData}超出上下限!", MessageLevel.Error);
                                                     resultflog = false;
                                                 }
-                                                if (resultflog )
+                                                if (resultflog)
                                                 {
                                                     lockResult1.PhotoPassed = "OK";
                                                     results.Add(true);
@@ -3595,10 +3617,10 @@ namespace TeamAAS_VP.Core
                                             }
                                             else
                                             {
-                                                SendTaskMessage($"检测项{lockResult1.PhotoName}结果{ResData}超出上下限!",MessageLevel.Error);
+                                                SendTaskMessage($"检测项{lockResult1.PhotoName}结果{ResData}超出上下限!", MessageLevel.Error);
                                                 resultflog = false;
                                             }
-                                            if (resultflog )
+                                            if (resultflog)
                                             {
                                                 lockResult1.PhotoPassed = "OK";
                                                 results.Add(true);
@@ -4416,7 +4438,7 @@ namespace TeamAAS_VP.Core
                 ["F12"] = new List<string> { "F11", "Insert", "=" },
                 ["Insert"] = new List<string> { "F12", "Backspace", "Delete" },
                 ["Delete"] = new List<string> { "Insert", "Power", "Backspace" },
-                ["Power"] = new List<string> { "Insert" , "Delete" , "Backspace" },
+                ["Power"] = new List<string> { "Insert", "Delete", "Backspace" },
                 // ==============================================
                 // 第二行:` 1 2 3 4 5 6 7 8 9 0 _ = Backspace
                 // ==============================================
@@ -4611,18 +4633,18 @@ namespace TeamAAS_VP.Core
         #endregion
 
         #region 保存CSV
-        public bool  WriteProductLogKB(IEnumerable<DataFormCtq> lockResults, string rfid)
+        public bool WriteProductLogKB(IEnumerable<DataFormCtq> lockResults, string rfid)
         {
             try
             {
                 DateTime dt = DateTime.Now;
-                if (rfid == null||rfid.Count()==0)
+                if (rfid == null || rfid.Count() == 0)
                 {
                     rfid = dt.ToString("MM-dd-mm");
                 }
-                if (lockResults.Count()==0 || lockResults == null)
+                if (lockResults.Count() == 0 || lockResults == null)
                 {
-                    SendTaskMessage("保存KB数据为空",MessageLevel.Error);
+                    SendTaskMessage("保存KB数据为空", MessageLevel.Error);
                     return false;
 
                 }
@@ -4634,11 +4656,11 @@ namespace TeamAAS_VP.Core
                 foreach (var item in lockResults)
                 {
                     try
-                    { 
+                    {
                         //!item.CTQ_NAME.Contains("Left")|| !item.CTQ_NAME.Contains("Right")||!item.CTQ_NAME.Contains("Updown")|| !item.CTQ_NAME.Contains("Down") 
                         if (item.CTQ_NAME.Contains("Left") || item.CTQ_NAME.Contains("Down") || item.CTQ_NAME.Contains("Right") || item.CTQ_NAME.Contains("Updown"))
                         {
-                            
+
                         }
                         else
                         {
@@ -4649,7 +4671,7 @@ namespace TeamAAS_VP.Core
                     catch (Exception)
                     {
                         sb.Append($",,,,,,,,,,,,,,");
-                        
+
                         return false;
                     }
                 }
@@ -4686,7 +4708,7 @@ namespace TeamAAS_VP.Core
             try
             {
                 DateTime dt = DateTime.Now;
-                if (rfid==null||rfid.Count()==0)
+                if (rfid == null || rfid.Count() == 0)
                 {
                     rfid = dt.ToString("MM-dd-mm");
                 }
@@ -4907,10 +4929,10 @@ namespace TeamAAS_VP.Core
         /// </summary>
         /// <param name="procedureId"></param>
         /// <returns></returns>
-        private async Task<(bool IsSucceed, ICogImage[] imges, string Message, int pointIndex, Guid procedureId)> GrabImageEx(int pointIndex, Guid procedureId, bool Is3dPhoto)
+        private async Task<(bool IsSucceed, ICogImage[] imges, string Message, int pointIndex, Guid procedureId)> GrabImageEx(int pointIndex, Guid procedureId, bool Is3dPhoto, ProductModel currentProduct, SystemConfiguration sysConfig)
         {
             // 获取当前产品
-            var currentProduct = _productService.GetCurrentProduct();
+            //var currentProduct = _productService.GetCurrentProduct();
             if (currentProduct == null)
             {
                 return (false, null, "当前产品为空,未加载产品!", pointIndex, procedureId);
@@ -4950,13 +4972,13 @@ namespace TeamAAS_VP.Core
                 SendTaskMessage($"开始执行 AOI 流程 (Point#{pointIndex}) 流程Id={pointIndex}", MessageLevel.Debug);
                 try
                 {
-                    var sysConfig = _configService.GetSystemConfiguration();
+                    //var sysConfig = _configService.GetSystemConfiguration();
                     if (selectedProcedure.Id == currentProduct.FixedDownCameraProcedureId && sysConfig.TurnOnAllLightUse == true)
                     {
                         await _remoteCommandService.SetLightBeforePhoto(selectedProcedure);
                     }
                     //1. 执行拍照
-                    var res = await _remoteCommandService.ExecuteGrabImageAsync(selectedProcedure, Is3dPhoto);
+                    var res = await _remoteCommandService.ExecuteGrabImageAsync(selectedProcedure, Is3dPhoto, sysConfig);
                     return (res.IsSucceed, res.Image, res.Msg, pointIndex, procedureId);
                 }
                 catch (Exception ex)

+ 1 - 1
TeamAAS-VM/Interfaces/IRemoteCommandService.cs

@@ -273,7 +273,7 @@ namespace TeamAAS_VP.Interfaces
         /// </summary>
         /// <param name="procedure"></param>
         /// <returns></returns>
-        Task<(bool IsSucceed, ICogImage[] Image, string Msg)> ExecuteGrabImageAsync(ProcedureModel procedure,bool Is3dPhoto);
+        Task<(bool IsSucceed, ICogImage[] Image, string Msg)> ExecuteGrabImageAsync(ProcedureModel procedure,bool Is3dPhoto, SystemConfiguration sysConfig);
 
         /// <summary>
         /// 执行相机拍照获取单个点位结果

+ 47 - 21
TeamAAS-VM/Models/Product/ProcedureModel.cs

@@ -40,6 +40,31 @@ namespace TeamAAS_VP.Models
             set { SetProperty(ref _CameraNo, value); }
         }
 
+        /// <summary>
+        /// AI Train 文件夹名称
+        /// </summary>
+        private string _CameraTrainFolder;
+
+        public string CameraTrainFolder
+        {
+            get { return _CameraTrainFolder; }
+            set
+            {
+                if (value == null)
+                {
+                    return;
+                }
+                if (value=="Null")
+                {
+                    SetProperty(ref _CameraTrainFolder, null);
+                }
+                else
+                {
+                    SetProperty(ref _CameraTrainFolder, value);
+                }
+            }
+        }
+
         /// <summary>
         /// 视觉图像处理模式
         /// </summary>
@@ -48,7 +73,7 @@ namespace TeamAAS_VP.Models
         /// <summary>
         /// 触发相机命令
         /// </summary>
-        public string TriggerCommand {  get; set; }
+        public string TriggerCommand { get; set; }
 
         /// <summary>
         /// 机器人
@@ -80,7 +105,7 @@ namespace TeamAAS_VP.Models
         /// <summary>
         /// 主页图像显示窗口的名称
         /// </summary>
-        public string DisplayName {  get; set; }
+        public string DisplayName { get; set; }
 
         /// <summary>
         /// 视觉流程输出集合
@@ -88,7 +113,7 @@ namespace TeamAAS_VP.Models
         public ObservableCollection<ProcedureOutput> ProcedureOutputs
         {
             get { return _ProcedureOutputs; }
-            set { SetProperty(ref _ProcedureOutputs,value); }
+            set { SetProperty(ref _ProcedureOutputs, value); }
         }
 
         private string _OutputSeparator = ";";
@@ -109,7 +134,7 @@ namespace TeamAAS_VP.Models
         public FeederWorks FeederWorks
         {
             get { return _FeederWorks; }
-            set { SetProperty(ref _FeederWorks,value); }
+            set { SetProperty(ref _FeederWorks, value); }
         }
 
         private FeederStockWorks _FeederStockWorks;
@@ -150,7 +175,7 @@ namespace TeamAAS_VP.Models
         public float ExposureTime
         {
             get { return _ExposureTime; }
-            set { SetProperty(ref _ExposureTime, value);}
+            set { SetProperty(ref _ExposureTime, value); }
         }
 
         private float _ExposureTime2;
@@ -236,7 +261,7 @@ namespace TeamAAS_VP.Models
         /// <summary>
         /// 第二次拍照光源3亮度
         /// </summary>
-        public int Photo2Light3   
+        public int Photo2Light3
         {
             get { return _Photo2Light3; }
             set { SetProperty(ref _Photo2Light3, value); }
@@ -259,7 +284,7 @@ namespace TeamAAS_VP.Models
         public CogToolBlock ToolBlock
         {
             get { return _ToolBlock; }
-            set { SetProperty(ref _ToolBlock,value); }
+            set { SetProperty(ref _ToolBlock, value); }
         }
 
         private ObservableCollection<ToolInfo> _ToolInfo = new ObservableCollection<ToolInfo>();
@@ -322,7 +347,7 @@ namespace TeamAAS_VP.Models
             set { SetProperty(ref _OutputPointMode, value); }
         }
 
-        private int _OutputPointCountMax=100;
+        private int _OutputPointCountMax = 100;
         /// <summary>
         /// 每次发送给机器人的点数最大值
         /// </summary>
@@ -337,12 +362,12 @@ namespace TeamAAS_VP.Models
         /// 是否剔除本次识别到的物料与上一次识别到的物料位置过近的点
         /// </summary>
         public bool IsExcludeNearPoint
-            {
+        {
             get { return _IsExcludeNearPoint; }
             set { SetProperty(ref _IsExcludeNearPoint, value); }
         }
 
-        private double _ExcludeNearPointThreshol=1;
+        private double _ExcludeNearPointThreshol = 1;
         /// <summary>
         /// 物料位置过近阈值
         /// </summary>
@@ -473,15 +498,15 @@ namespace TeamAAS_VP.Models
         {
             Id = Guid.NewGuid();
             ProcedureOutputs = new ObservableCollection<ProcedureOutput>();
-            ToolInfo= new ObservableCollection<ToolInfo>();
-            FeederFindFrequency= new FeederFrequencyModel();
-            UserDefineParameters= new ObservableCollection<ProcedureUserDefineParam>();
+            ToolInfo = new ObservableCollection<ToolInfo>();
+            FeederFindFrequency = new FeederFrequencyModel();
+            UserDefineParameters = new ObservableCollection<ProcedureUserDefineParam>();
             FeederWorks = new FeederWorks();
-            FeederStockWorks= new FeederStockWorks();
+            FeederStockWorks = new FeederStockWorks();
             LightChannels = new ObservableCollection<ChannelConfig>();
         }
 
-        public ProcedureModel(string name, string cameraName, Guid cameraId,int camerano)
+        public ProcedureModel(string name, string cameraName, Guid cameraId, int camerano)
         {
             Id = Guid.NewGuid();
             Name = name;
@@ -503,10 +528,11 @@ namespace TeamAAS_VP.Models
             {
                 Id = this.Id,
                 Name = this.Name,
-                CameraName=this.CameraName,
-                CameraNo=this.CameraNo,
+                CameraName = this.CameraName,
+                CameraNo = this.CameraNo,
                 VisionModel = this.VisionModel,
-                TriggerCommand=this.TriggerCommand,
+                CameraTrainFolder = this.CameraTrainFolder,
+                TriggerCommand = this.TriggerCommand,
                 RobotId = this.RobotId,
                 FeederId = this.FeederId,
                 CameraId = this.CameraId,
@@ -534,10 +560,10 @@ namespace TeamAAS_VP.Models
                 ImageFileNameFormat = this.ImageFileNameFormat,
                 IsCompress = this.IsCompress,
                 FeederFindFrequency = this.FeederFindFrequency?.Copy(),
-                IsExcludeNearPoint=this.IsExcludeNearPoint,
+                IsExcludeNearPoint = this.IsExcludeNearPoint,
                 ExcludeNearPointThreshol = this.ExcludeNearPointThreshol,
-                OutputPointMode=this.OutputPointMode,
-                OutputSeparator=this.OutputSeparator,
+                OutputPointMode = this.OutputPointMode,
+                OutputSeparator = this.OutputSeparator,
                 UserDefineParameters = new ObservableCollection<ProcedureUserDefineParam>(this.UserDefineParameters.Select(udp => udp.Copy())),
                 LightChannels = this.LightChannels == null ? new ObservableCollection<ChannelConfig>() : new ObservableCollection<ChannelConfig>(this.LightChannels.Select(ch => new ChannelConfig
                 {

+ 118 - 79
TeamAAS-VM/Services/RemoteCommandService.cs

@@ -106,6 +106,9 @@ namespace TeamAAS_VP.Services
         /// </summary>
         public event EventHandler<TimeSpan> CycleTimingTicked;
 
+        public float TempExposureTime = 0;
+        public float TempGain = 0;
+
         /// <summary>
         /// 构造函数,注入必要的系统服务。
         /// </summary>
@@ -1715,7 +1718,7 @@ namespace TeamAAS_VP.Services
                         IsCompress = procedure.IsCompress,
                         ProceductName = procedure.Name,
                         ImageFileName = imgName,
-                        Is3DModel=true
+                        Is3DModel = true
                     });
                     return true;
                 }
@@ -1777,7 +1780,7 @@ namespace TeamAAS_VP.Services
         /// 执行相机拍照并运行 ToolBlock,返回是否成功并通过 out 参数返回 Outputs。
         /// 该方法会发布 RenderUpdateNotification 以更新 UI。
         /// </summary>
-        public  bool  ExecutePhoto2(ProcedureModel procedure, Dictionary<string, string> InputTerminal, out CogToolBlockTerminalCollection outputCollection)
+        public bool ExecutePhoto2(ProcedureModel procedure, Dictionary<string, string> InputTerminal, out CogToolBlockTerminalCollection outputCollection)
         {
             try
             {
@@ -1811,7 +1814,7 @@ namespace TeamAAS_VP.Services
                 // 2. 为ToolBlock传入其他输入终端
                 if (InputTerminal != null)
                 {
-                    
+
                     LogHelper.WriteLogInfo($"为ToolBlock传入输入终端");
                     foreach (var item in InputTerminal)
                     {
@@ -1880,7 +1883,7 @@ namespace TeamAAS_VP.Services
                         IsCompress = procedure.IsCompress,
                         ProceductName = procedure.Name,
                         ImageFileName = imgName,
-                        Is3DModel=false
+                        Is3DModel = false
                     });
                     return true;
                 }
@@ -1922,7 +1925,7 @@ namespace TeamAAS_VP.Services
                         SavePath = procedure.SavePath,
                         ProceductName = procedure.Name,
                         ImageFileName = imgName,
-                        Is3DModel=false
+                        Is3DModel = false
                     });
                     return false;
                 }
@@ -1939,17 +1942,17 @@ namespace TeamAAS_VP.Services
         /// 执行相机拍照并运行 ToolBlock,返回是否成功并通过 out 参数返回 Outputs。
         /// 该方法会发布 RenderUpdateNotification 以更新 UI。
         /// </summary>
-        public bool ExecutePhoto(ProcedureModel procedure,ICogImage[] imges,Dictionary<string, string> InputTerminal, out CogToolBlockTerminalCollection outputCollection,bool is3dmodel, float confThreshold = 0.25f, float iouThreshold = 0.45f)
+        public bool ExecutePhoto(ProcedureModel procedure, ICogImage[] imges, Dictionary<string, string> InputTerminal, out CogToolBlockTerminalCollection outputCollection, bool is3dmodel, float confThreshold = 0.25f, float iouThreshold = 0.45f)
         {
             try
             {
-                
+
                 procedure.ToolBlock.Inputs["InputImage"].Value = imges[0];
-                if(is3dmodel==true || imges.Length > 1)
+                if (is3dmodel == true || imges.Length > 1)
                 {
                     procedure.ToolBlock.Inputs["InputImage2"].Value = imges[1];
                 }
-                
+
                 // 2. 为ToolBlock传入其他输入终端
                 if (InputTerminal != null)
                 {
@@ -1974,11 +1977,14 @@ namespace TeamAAS_VP.Services
                 // photoAiValue 可能为 null/空,建议给个默认值
                 bool enablePhotoAi = photoAiValue == "1";
                 if (enablePhotoAi == true)
-                {                    
+                {
                     string exeDir = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
 
-                    string modelPath = System.IO.Path.Combine(exeDir, "TrainPhoto", "weights", "best_openvino_model", "best.xml");
-                    string metadataPath = System.IO.Path.Combine(exeDir, "TrainPhoto", "weights", "best_openvino_model", "metadata.yaml");
+                    string trainFolderName = string.IsNullOrWhiteSpace(procedure.CameraTrainFolder) ? "TrainPhoto" : procedure.CameraTrainFolder;
+                    string trainRoot = System.IO.Path.Combine(exeDir, "Train", trainFolderName);
+
+                    string modelPath = System.IO.Path.Combine(exeDir, trainRoot, "weights", "best_openvino_model", "best.xml");
+                    string metadataPath = System.IO.Path.Combine(exeDir, trainRoot, "weights", "best_openvino_model", "metadata.yaml");
 
                     // (可选)如果你希望缺文件时给出更明确提示:
                     if (!File.Exists(modelPath))
@@ -1997,7 +2003,7 @@ namespace TeamAAS_VP.Services
                         {
                             var results = yolo.Infer(bitmap);
                             procedure.ToolBlock.Inputs["PhotoData"].Value = "";
-                            procedure.ToolBlock.Inputs["Confidence"].Value ="";
+                            procedure.ToolBlock.Inputs["Confidence"].Value = "";
                             // 输出结果
                             SendTaskMessage($"识别的个数:{results.Count()}", MessageLevel.Alarm);
                             string ClassName = "";
@@ -2014,6 +2020,9 @@ namespace TeamAAS_VP.Services
                             // 绘制结果 - 使用 OpenCvSharp
                             using (var image2 = ImageHelper.ICogImageConvertMat(imges[0]))
                             {
+
+                                var OriginyoloColorCogImage = ImageHelper.MatConvertICogImage(image2, true);
+
                                 // 定义颜色映射
                                 var colors = new[]
                                 {
@@ -2078,14 +2087,17 @@ namespace TeamAAS_VP.Services
                                         HersheyFonts.HersheySimplex, 0.6, Scalar.White, 2);
                                 }
 
-                                // 保存结果图像
-                                //string outputPath = @"G:\TEST\文件\左上插线\result.jpg";
-                                //Cv2.ImWrite(outputPath, image2);
-                                //Console.WriteLine($"结果已保存到: {outputPath}");
-                                var cogImage = ImageHelper.MatConvertICogImage(image2);
-                                procedure.ToolBlock.Inputs["InputImage"].Value = cogImage;
+                                // 关键:这里转成彩色 ICogImage
+                                var yoloColorCogImage = ImageHelper.MatConvertICogImage(image2);
+
+                                // 模板检测如果需要原图,可以用 imges[0]
+                                // 如果你希望模板也拿 YOLO 画框图,就用 yoloColorCogImage
+                                procedure.ToolBlock.Inputs["InputImage"].Value = yoloColorCogImage;
+
                                 procedure.ToolBlock.Run();
-                                outputCollection = procedure.ToolBlock.Outputs;     //获取输出终端集合
+
+                                outputCollection = procedure.ToolBlock.Outputs;
+
                                 ICogRecord record = null;
                                 foreach (CogToolBlockTerminal item in outputCollection)
                                 {
@@ -2094,6 +2106,7 @@ namespace TeamAAS_VP.Services
                                 }
 
                                 bool Found = (bool)(outputCollection["Found"].Value);
+
                                 //获取图片存储的图片文件名
                                 string imgName = string.Empty;
                                 if (procedure.IsSaveImage && !string.IsNullOrEmpty(procedure.ImageFileNameFormat))
@@ -2111,11 +2124,36 @@ namespace TeamAAS_VP.Services
                                     // 生成文件名
                                     imgName = template.Generate();
                                 }
+
+                                _eventAggregator.GetEvent<RenderUpdateNotification>().Publish(new ShowRender()
+                                {
+                                    Id = procedure.DisplayId,
+                                    DisplayName = procedure.DisplayName,
+
+                                    Image = OriginyoloColorCogImage,
+
+                                    Graphic = outputCollection["Graphic"].Value as CogGraphicCollection,
+                                    Record = record,
+                                    Result = Found,
+                                    IsShow = false,
+                                    IsSaveImage = procedure.IsSaveImage,
+                                    SaveImageModel = procedure.SaveImageModel,
+                                    SaveImagePathModel = procedure.SaveImagePathModel,
+                                    SavePath = procedure.SavePath,
+                                    IsCompress = procedure.IsCompress,
+                                    ProceductName = procedure.Name,
+                                    ImageFileName = imgName,
+                                    Is3DModel = is3dmodel,
+                                });
+
                                 _eventAggregator.GetEvent<RenderUpdateNotification>().Publish(new ShowRender()
                                 {
                                     Id = procedure.DisplayId,
                                     DisplayName = procedure.DisplayName,
-                                    Image = cogImage,
+
+                                    // 显示和保存用 YOLO 彩色图
+                                    Image = yoloColorCogImage,
+
                                     Graphic = outputCollection["Graphic"].Value as CogGraphicCollection,
                                     Record = record,
                                     Result = Found,
@@ -2128,12 +2166,8 @@ namespace TeamAAS_VP.Services
                                     ProceductName = procedure.Name,
                                     ImageFileName = imgName,
                                     Is3DModel = is3dmodel,
-                                    //RangeImage = (CogImage16Range)procedure.ToolBlock.Outputs["RangeImage"].Value,
-                                    //GreyImage = (CogImage16Grey)procedure.ToolBlock.Outputs["GreyImage"].Value
                                 });
-                                // 可选:显示图像
-                                //Cv2.ImShow("Detection Result", image2);
-                                //Cv2.WaitKey(0);
+     
                             }
 
                         }
@@ -2199,8 +2233,8 @@ namespace TeamAAS_VP.Services
                                         SavePath = procedure.SavePath,
                                         IsCompress = procedure.IsCompress,
                                         ProceductName = procedure.Name,
-                                        ImageFileName = imgName+"image2",
-                                        Is3DModel = is3dmodel,
+                                        ImageFileName = imgName + "image2",
+                                        Is3DModel = false,
                                     });
                                 }
                                 _eventAggregator.GetEvent<RenderUpdateNotification>().Publish(new ShowRender()
@@ -2246,7 +2280,7 @@ namespace TeamAAS_VP.Services
                                         IsCompress = procedure.IsCompress,
                                         ProceductName = procedure.Name,
                                         ImageFileName = imgName + "image2",
-                                        Is3DModel = is3dmodel,
+                                        Is3DModel = false,
                                     });
                                 }
                                 _eventAggregator.GetEvent<RenderUpdateNotification>().Publish(new ShowRender()
@@ -2293,7 +2327,7 @@ namespace TeamAAS_VP.Services
                                     IsCompress = procedure.IsCompress,
                                     ProceductName = procedure.Name,
                                     ImageFileName = imgName + "image2",
-                                    Is3DModel = is3dmodel,
+                                    Is3DModel = false,
                                 });
                             }
                             _eventAggregator.GetEvent<RenderUpdateNotification>().Publish(new ShowRender()
@@ -2429,7 +2463,7 @@ namespace TeamAAS_VP.Services
                         return false;
                     }
                 }
-                
+
             }
             catch (Exception ex)
             {
@@ -2445,12 +2479,12 @@ namespace TeamAAS_VP.Services
         /// </summary>
         /// <param name="procedure"></param>
         /// <returns></returns>
-        public async Task <(bool IsSucceed, ICogImage[] Image, string Msg)> ExecuteGrabImageAsync(ProcedureModel procedure,bool Is3dPhoto)
+        public async Task<(bool IsSucceed, ICogImage[] Image, string Msg)> ExecuteGrabImageAsync(ProcedureModel procedure, bool Is3dPhoto, SystemConfiguration sysConfig)
         {
             try
             {
-                var sysConfig = _configService.GetSystemConfiguration();
-                
+                //var sysConfig = _configService.GetSystemConfiguration();
+
                 if (sysConfig.PhotosUse == true)
                 {
                     // 1. 采集图像
@@ -2562,6 +2596,7 @@ namespace TeamAAS_VP.Services
                     {
                         image = camera.Grab();
                         image2 = camera.Grab2();
+
                         LogHelper.WriteLogInfo($"采集图像完成;用时:{(DateTime.Now - nowtime).Milliseconds}ms");
                         if (image == null || image2 == null)
                         {
@@ -2573,15 +2608,15 @@ namespace TeamAAS_VP.Services
                     }
                     else
                     {
-                        
+
                         LogHelper.WriteLogInfo($"采集图像完成;用时:{(DateTime.Now - nowtime).Milliseconds}ms");
-                        if (image == null )
+                        if (image == null)
                         {
 
                             SendTaskMessage(Lang.图像采集失败, MessageLevel.Error);
                             return (false, null, "图像采集失败");
                         }
-                        if(procedure.PhotoCount>1)
+                        if (procedure.PhotoCount > 1)
                         {
                             if (image2 == null)
                             {
@@ -2591,7 +2626,7 @@ namespace TeamAAS_VP.Services
                             }
                             return (true, new ICogImage[] { image, image2 }, "成功");
                         }
-                        return (true, new ICogImage[] { image}, "成功");
+                        return (true, new ICogImage[] { image }, "成功");
 
                     }
                 }
@@ -2599,16 +2634,39 @@ namespace TeamAAS_VP.Services
                 {
                     // 1. 采集图像
                     var camera = _cameraService.GetCamera(procedure.CameraId);
-                    bool succed = camera.SetExposureTime(procedure.ExposureTime);
-                    if (!succed)
+                    if (TempExposureTime != procedure.ExposureTime)
                     {
-                        SendTaskMessage($"相机曝光设置失败!", MessageLevel.Error);
+                        bool succed1 = camera.SetExposureTime(procedure.ExposureTime);
+                        if (!succed1)
+                        {
+                            SendTaskMessage($"相机曝光设置失败!", MessageLevel.Error);
+                        }
+                        else
+                        {
+                            TempExposureTime = procedure.ExposureTime;
+                        }
                     }
-                    succed = camera.SetGain(procedure.Gain);
-                    if (!succed)
+                    //else
+                    //{
+                    //    SendTaskMessage($"相机曝光重复", MessageLevel.Error);
+                    //}
+                    if (TempGain != procedure.Gain)
                     {
-                        SendTaskMessage($"相机增益设置失败!", MessageLevel.Error);
+                        bool succed2 = camera.SetGain(procedure.Gain);
+                        if (!succed2)
+                        {
+                            SendTaskMessage($"相机增益设置失败!", MessageLevel.Error);
+                        }
+                        else
+                        {
+                            TempGain = procedure.Gain;
+                        }
                     }
+                    //else
+                    //{
+                    //    SendTaskMessage($"相机增益重复", MessageLevel.Error);
+                    //}
+
                     DateTime nowtime = DateTime.Now;
                     LogHelper.WriteLogInfo("开始采集图像");
                     //var image = camera.Grab();
@@ -2631,19 +2689,18 @@ namespace TeamAAS_VP.Services
                         LogHelper.WriteLogInfo($"采集图像完成;用时:{(DateTime.Now - nowtime).Milliseconds}ms");
                         if (image == null)
                         {
-
                             SendTaskMessage(Lang.图像采集失败, MessageLevel.Error);
                             return (false, null, "图像采集失败");
                         }
                         return (true, new ICogImage[] { image }, "成功");
                     }
                 }
-                
-                
+
+
             }
             catch (Exception ex)
             {
-                LogHelper.WriteLogError("采集图像失败!",ex);
+                LogHelper.WriteLogError("采集图像失败!", ex);
                 return (false, null, "图像采集失败");
             }
         }
@@ -2656,7 +2713,7 @@ namespace TeamAAS_VP.Services
         /// <param name="robotCoord"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task<(bool IsSucceed, string[] Items, double Count)> ExecutePhotoGetSinglePoint1(ProcedureModel procedure, ICogImage[] imges, Dictionary<string, string> InputTerminal, double[] robotCoord, CancellationToken cancellationToken,bool is3dmodel, float confThreshold = 0.25f, float iouThreshold = 0.45f)
+        public async Task<(bool IsSucceed, string[] Items, double Count)> ExecutePhotoGetSinglePoint1(ProcedureModel procedure, ICogImage[] imges, Dictionary<string, string> InputTerminal, double[] robotCoord, CancellationToken cancellationToken, bool is3dmodel, float confThreshold = 0.25f, float iouThreshold = 0.45f)
         {
             DateTime nowtime = DateTime.Now;
             try
@@ -2689,37 +2746,19 @@ namespace TeamAAS_VP.Services
                     //    continue;
                     //}
 
-                    SendTaskMessage(Lang.拍照OK, MessageLevel.Debug);
+                    //SendTaskMessage(Lang.拍照OK, MessageLevel.Debug);
 
                     int Count = (int)(outputCollection["Count"].Value);
                     string[] PhotoRes = new string[100];
                     for (int k = 1; k <= Count; k++)
                     {
-                       
+
                         PhotoRes[k] = (string)(outputCollection[$"dis{k}"].Value);
                         //PhotoRes[k] = "222";
                     }
                     // 3. 获取视觉输出结果
                     LogHelper.WriteLogInfo("开始获取视觉输出结果");
-                    /*
-                    //获取相机校准
-                    var calib = _calibrationService.GetCalibration(procedure.CalibrationId);
-                    string points = (string)(outputCollection["Point"].Value);
-                    string[] strpoints = points.Split(';');
-                    //先将pos按照逗号进行分隔,拿到数组
-                    var posParts = strpoints[0].Split(',');
-                    double _pixel_x = double.Parse(posParts[0]);
-                    double _pixel_y = double.Parse(posParts[1]);
-                    double _pixel_u = double.Parse(posParts[2]);
-                    //转换点位-像素转换成机器人绝对坐标
-                    var calibResult = _calibrationService.ConvertPixelToPosition((_pixel_x, _pixel_y, _pixel_u), robotCoord, calib, RobotBrand.XYZ_Platform);
-                    if (!calibResult.IsSucceed)
-                    {
-                        return (false, 0, 0, 0);
-                    }
-
-                    return (true, calibResult.X, calibResult.Y, calibResult.U);
-                    */
+               
                     return (true, PhotoRes, Count);
                 }
                 SendTaskMessage(Lang.多次拍照失败, MessageLevel.Alarm);
@@ -2757,7 +2796,7 @@ namespace TeamAAS_VP.Services
             {
                 await SetLightBeforePhoto(procedure);
             }
-            
+
             try
             {
                 //拍照失败时,需要多次拍照
@@ -2838,13 +2877,13 @@ namespace TeamAAS_VP.Services
         /// <param name="outImage"></param>
         /// <param name="outGraphicCollection"></param>
         /// <returns></returns>
-        public bool ExecutePhotoEx(ProcedureModel procedure, Dictionary<string, string> InputTerminal, out CogToolBlockTerminalCollection outputCollection,out ICogImage outImage,out CogGraphicCollection outGraphicCollection)
+        public bool ExecutePhotoEx(ProcedureModel procedure, Dictionary<string, string> InputTerminal, out CogToolBlockTerminalCollection outputCollection, out ICogImage outImage, out CogGraphicCollection outGraphicCollection)
         {
             outImage = null;
             outGraphicCollection = null;
             try
             {
-                
+
                 // 1. 采集图像
                 var camera = _cameraService.GetCamera(procedure.CameraId);
                 bool succed = camera.SetExposureTime(procedure.ExposureTime);
@@ -2867,7 +2906,7 @@ namespace TeamAAS_VP.Services
                     outputCollection = null;
                     return false;
                 }
-                outImage= image;
+                outImage = image;
                 procedure.ToolBlock.Inputs["InputImage"].Value = image;
                 LogHelper.WriteLogInfo($"采集图像完成;用时:{(DateTime.Now - nowtime).Milliseconds}ms");
 
@@ -2905,7 +2944,7 @@ namespace TeamAAS_VP.Services
                         if (item.Value is ICogRecord)
                             record = item.Value as ICogRecord;
                     }
-                    outGraphicCollection= outputCollection["Graphic"].Value as CogGraphicCollection;
+                    outGraphicCollection = outputCollection["Graphic"].Value as CogGraphicCollection;
                     return true;
                 }
                 else
@@ -2987,7 +3026,7 @@ namespace TeamAAS_VP.Services
                     //{
                     //    return (false, 0, 0, 0);
                     //}
-                    return (true, 0,0, 0);
+                    return (true, 0, 0, 0);
                 }
                 SendTaskMessage(Lang.多次拍照失败, MessageLevel.Alarm);
                 return (false, 0, 0, 0);
@@ -3112,8 +3151,8 @@ namespace TeamAAS_VP.Services
         {
             DateTime nowtime = DateTime.Now;
             await SetLightBeforePhoto(procedure);
-            ICogImage outImage=null;
-            CogGraphicCollection outGraphicCollection=null;
+            ICogImage outImage = null;
+            CogGraphicCollection outGraphicCollection = null;
             try
             {
                 //拍照失败时,需要多次拍照
@@ -3601,7 +3640,7 @@ namespace TeamAAS_VP.Services
             {
                 return;
             }
-               
+
             //判断当前流程是否启用光源控制
             if (procedure.IsControlLightChannels)
             {

+ 29 - 1
TeamAAS-VM/ViewModels/Product/ProcessBasicsViewModel.cs

@@ -13,6 +13,7 @@ using System.ComponentModel;
 using System.Diagnostics.Eventing.Reader;
 using System.IO;
 using System.Linq;
+using System.Reflection;
 using TeamAAS_VP;
 using TeamAAS_VP.Core;
 using TeamAAS_VP.Events;
@@ -38,6 +39,14 @@ namespace TeamAAS_VP.ViewModels.Product
 
         #region 属性
 
+
+        private ObservableCollection<string> _CameraTrainFolderOptions;
+        public ObservableCollection<string> CameraTrainFolderOptions
+        {
+            get { return _CameraTrainFolderOptions; }
+            set { SetProperty(ref _CameraTrainFolderOptions, value); }
+        }
+
         private ProductModel _SelectProduct;
 
         /// <summary>
@@ -68,6 +77,7 @@ namespace TeamAAS_VP.ViewModels.Product
                 }
                 else
                 {
+
                     SelectRobot = _configService.GetAllRobots().FirstOrDefault(p => p.Id == value.RobotId);
                     SelectFeeder = _configService.GetAllFeeders().FirstOrDefault(p => p.Id == value.FeederId);
                     SelectCalibration = _calibrationService.GetAllCalibrations().FirstOrDefault(p => p.Id == value.CalibrationId);
@@ -85,6 +95,7 @@ namespace TeamAAS_VP.ViewModels.Product
             }
         }
 
+
         private ObservableCollection<ProcedureModel> _ProcedureModels;
 
         /// <summary>
@@ -512,11 +523,28 @@ namespace TeamAAS_VP.ViewModels.Product
             FeederList = new ObservableCollection<FeederInfo>(_configService.GetAllFeeders());
             CalibrationList = new ObservableCollection<CalibrationInfo>(_calibrationService.GetAllCalibrations());
             DisplatConfigs = new ObservableCollection<DisplayConfig>();
-            
+
             if (navigationContext.Parameters.ContainsKey("SelectedProcedure"))
             {
                 SelectProcedure = navigationContext.Parameters.GetValue<ProcedureModel>("SelectedProcedure");
             }
+
+            string exeDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+            var trainRoot = Path.Combine(exeDir, "Train");
+            if (!Directory.Exists(trainRoot))
+            {
+                return;
+            }
+            CameraTrainFolderOptions = new ObservableCollection<string>();
+            foreach (var directory in Directory.GetDirectories(trainRoot).OrderBy(p => p))
+            {
+                var folderName = Path.GetFileName(directory);
+                if (!string.IsNullOrWhiteSpace(folderName))
+                {
+                    CameraTrainFolderOptions.Add(folderName);
+                }
+            }
+            CameraTrainFolderOptions.Add("Null");
         }
 
         /// <summary>

+ 44 - 0
TeamAAS-VM/Views/AddScrewView.xaml

@@ -0,0 +1,44 @@
+<Window x:Class="TeamAAS_VP.Views.AddScrewView"
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+        xmlns:local="clr-namespace:TeamAAS_VP.Views"
+        mc:Ignorable="d"
+        Title="AddScrewView" Height="450" Width="800">
+    <Grid Margin="20">
+        <Grid.RowDefinitions>
+            <RowDefinition Height="Auto"/>
+            <RowDefinition Height="Auto"/>
+            <RowDefinition Height="Auto"/>
+        </Grid.RowDefinitions>
+
+        <TextBlock Grid.Row="0" 
+                   Text="请扫描螺丝条码:" 
+                   FontSize="14" 
+                   Margin="0,0,0,10"/>
+
+        <!-- 输入框会自动接收并显示扫码枪的结果 -->
+        <TextBox x:Name="BarcodeTextBox" 
+                 Grid.Row="1" 
+                 Height="30" 
+                 FontSize="14"
+                 Margin="0,0,0,20"/>
+
+        <StackPanel Grid.Row="2" 
+                    Orientation="Horizontal" 
+                    HorizontalAlignment="Right">
+            <Button x:Name="OkButton" 
+                    Content="确定" 
+                    Width="80" 
+                    Height="30" 
+                    Margin="0,0,10,0"
+                    Click="OkButton_Click"/>
+            <Button x:Name="CancelButton" 
+                    Content="取消" 
+                    Width="80" 
+                    Height="30"
+                    Click="CancelButton_Click"/>
+        </StackPanel>
+    </Grid>
+</Window>

+ 77 - 0
TeamAAS-VM/Views/AddScrewView.xaml.cs

@@ -0,0 +1,77 @@
+using Prism.Events;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+using TeamAAS_VP.Enums;
+using TeamAAS_VP.Events;
+using TeamAAS_VP.Interfaces;
+
+namespace TeamAAS_VP.Views
+{
+    /// <summary>
+    /// AddScrewView.xaml 的交互逻辑
+    /// </summary>
+    public partial class AddScrewView : Window
+    {
+        IConfigService _configService;
+        IEventAggregator _eventAggregator;
+        public string ScannedBarcode { get; private set; }
+        public AddScrewView()
+        {
+            InitializeComponent();
+            // 窗口加载完成后,自动让输入框获得焦点
+            this.Loaded += (s, e) =>
+            {
+                BarcodeTextBox.Focus();
+            };
+        }
+        private void OkButton_Click(object sender, RoutedEventArgs e)
+        {
+            var stationConfig = _configService.GetDeviceInfo(0);
+            ScannedBarcode = BarcodeTextBox.Text;
+
+            if (string.IsNullOrWhiteSpace(ScannedBarcode))
+            {
+                MessageBox.Show("请先扫描螺丝条码", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
+                BarcodeTextBox.Focus(); // 重新聚焦
+                return;
+            }
+            if (ScannedBarcode == stationConfig.DataInfo.Screwsize1 || ScannedBarcode == stationConfig.DataInfo.Screwsize2)
+            {
+                MessageBox.Show("螺丝型号匹配成功", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
+                SendTaskMessage($"螺丝型号匹配成功", MessageLevel.Info);
+            }
+            else
+            {
+                MessageBox.Show("螺丝型号匹配失败", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
+                SendTaskMessage($"螺丝型号匹配失败", MessageLevel.Error);
+            }
+            DialogResult = true;
+            Close();
+        }
+
+        private void CancelButton_Click(object sender, RoutedEventArgs e)
+        {
+            DialogResult = false;
+            Close();
+        }
+
+        public void SendTaskMessage(string msg, MessageLevel level)
+        {
+            App.Current.Dispatcher.Invoke(() =>
+            {
+                _eventAggregator.GetEvent<TaskMessageNotification>().Publish(new Models.MessageStruct() { Message = msg, level = level });
+            });
+        }
+    }
+}

+ 32 - 7
TeamAAS-VM/Views/Product/ProcessBasics.xaml

@@ -131,6 +131,11 @@
                                    MinHeight="35" />
                     <RowDefinition Height="auto"
                                    MinHeight="35" />
+                    <RowDefinition Height="auto"
+               MinHeight="35" />
+                    <RowDefinition Height="auto"
+               MinHeight="35" />
+
                 </Grid.RowDefinitions>
                 <Grid.ColumnDefinitions>
                     <ColumnDefinition Width="auto" />
@@ -224,16 +229,16 @@
                 </ComboBox>
 
                 <TextBlock Text="{lex:Loc 是否控制光源通道亮灭,Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}"
-                           Grid.Row="8"
+                           Grid.Row="9"
                            Grid.Column="0" />
-                <ToggleButton Grid.Row="8"
+                <ToggleButton Grid.Row="9"
                               Grid.Column="1"
                               Width="60"
                               Height="30"
                               HorizontalAlignment="Left"
                               IsChecked="{Binding SelectProcedure.IsControlLightChannels,Mode=TwoWay}" />
 
-                <Button Grid.Row="8"
+                <Button Grid.Row="9"
                         Grid.Column="1"
                         HorizontalAlignment="Right"
                         materialDesign:HintAssist.Hint="{lex:Loc 选择光源通道}"
@@ -246,10 +251,10 @@
 
                 <!-- 光源通道配置(已改为弹窗选择) -->
                 <TextBlock Text="{lex:Loc 光源通道,Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}"
-                           Grid.Row="9"
+                           Grid.Row="10"
                            Grid.RowSpan="1" />
 
-                <ListBox Grid.Row="9"
+                <ListBox Grid.Row="10"
                          Grid.Column="1"
                          ItemsSource="{Binding SelectProcedure.LightChannels}"
                          SelectedItem="{Binding SelectedLightChannel}"
@@ -311,10 +316,30 @@
                     </ComboBox.ItemTemplate>
                 </ComboBox>
 
+                <TextBlock Text="AI Train: "
+                      Grid.Row="7"
+                      Grid.Column="0" />
+                           <ComboBox Grid.Row="7"
+                     Grid.Column="1"
+                     materialDesign:HintAssist.Hint="选择AI Train"
+                     materialDesign:TextFieldAssist.HasClearButton="True"
+                     ItemsSource="{Binding CameraTrainFolderOptions}"
+                     SelectedItem="{Binding CameraTrainFolder,Mode=TwoWay}">
+                    <ComboBox.ItemTemplate>
+                        <DataTemplate>
+                            <StackPanel Orientation="Horizontal">
+                                <materialDesign:PackIcon Kind="Dais" />
+                                <TextBlock Text="{Binding}"
+                           Margin="6,0" />
+                            </StackPanel>
+                        </DataTemplate>
+                    </ComboBox.ItemTemplate>
+                </ComboBox>
+
                 <TextBlock Text="{lex:Loc 触发命令,Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}"
-                           Grid.Row="7"
+                           Grid.Row="8"
                            Grid.Column="0" />
-                <TextBox Grid.Row="7"
+                <TextBox Grid.Row="8"
                          Grid.Column="1"
                          materialDesign:HintAssist.Hint="{lex:Loc 触发命令}"
                          Text="{Binding SelectProcedure.TriggerCommand}" />