using Bro.Common.Base; using Bro.Common.Helper; using Bro.Common.Interface; using Bro.Common.Model; using Bro.Device.InsCamera; using Bro.M135.Common; using Bro.M135.DBManager; using Bro.Process; using Bro.Process.DataBase.Models; using Bro.UI.Model.Winform; using HalconDotNet; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NPOI.SS.Formula.Functions; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Ocsp; using ScottPlot.Drawing.Colormaps; using Sunny.UI; using Sunny.UI.Win32; using System.Collections.Concurrent; using System.Collections.Generic; using System.Drawing.Imaging; using System.IO; using System.Linq; using Windows.ApplicationModel.Appointments; using static Org.BouncyCastle.Math.EC.ECCurve; namespace Bro.M141.Process { public partial class M141Process : ProcessControl { #region constructor public M141Process() { } public M141Process(string productCode) : base(productCode) { } #endregion TaskFactory _taskFactory = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.LongRunning); public event Action OnSinglePostionDetectResultUpdate; protected M141Config M141Config => Config as M141Config; public static object _productListLock = new object(); public List ProductList = new List(); MachineLearningBase ML = null; TcpListenerWrap TcpListener = null; Spec _errorSpec = null; TcpListenerWrap _realTimeServer = null; volatile int _productIndex = 0; int _backgroundImageWidth = 2448; M141Process_Mysql mysqlhelper = new M141Process_Mysql(); public override void InitialProcessMethods() { base.InitialProcessMethods(); } public override void ProcessRunStateChanged() { base.ProcessRunStateChanged(); //if (CurrentState == EnumHelper.RunState.Running) //{ // OldDataClear.Instance.SetAllowFlag(false, M141Config.DBDataTimeLimit); //} //else //{ // OldDataClear.Instance.SetAllowFlag(true, M141Config.DBDataTimeLimit); //} } public PLCBase Plc1; PLCBase Plc2; Thread ThHeartPlc; public override void Open() { base.Open(); ML = DeviceCollection.FirstOrDefault(u => u is MachineLearningBase) as MachineLearningBase; if (ML == null) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, $"未设置ML实例"); } Plc1 = DeviceCollection.FirstOrDefault(u => u is PLCBase) as PLCBase; if (Plc1 == null) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"未设置plc"); } _errorSpec = M141Config.SpecCollection.FirstOrDefault(u => u.Code == M141Config.CheckErrorSpecCode) as Spec; //InitialProductList(); NetWarmUp(); _positionCheckTimeDict.Clear(); _positionSpecHeads.Clear(); mysqlhelper.IniDBIP(M141Config.IPforall); if (ThHeartPlc == null) { ThHeartPlc = new Thread(Heartplc); ThHeartPlc.IsBackground = true; ThHeartPlc.Start(); } } public override void Close() { base.Close(); try { if (ThHeartPlc != null) { ThHeartPlc.Abort(); } } catch { } ThHeartPlc = null; } public void Heartplc() { while (true) { try { if (Plc1 != null) { Plc1.WriteSingleAddress(1505, 0, out _); } } catch { } Thread.Sleep(3000); } } /// /// 网络预热 /// /// private void NetWarmUp() { string warmUpImageFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "WarmUp"); if (!Directory.Exists(warmUpImageFolder)) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"程序根目录下没有\"WarmUp\"预热图片文件夹"); return; } var ml = DeviceCollection.FirstOrDefault(u => u is MachineLearningBase && u.CurrentState == EnumHelper.DeviceState.DSOpen) as MachineLearningBase; if (ml == null) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"预热时未能获取开启的深度学习驱动"); return; } var netNames = ml.IConfig.NetCollections.Where(u => u.IsEnabled).Select(u => u.Name).ToList(); var imageFiles = new DirectoryInfo(warmUpImageFolder).GetFiles().Select(u => u.FullName).ToList(); Parallel.ForEach(netNames, n => { Parallel.ForEach(imageFiles, i => { HImage hImage = new HImage(); hImage.ReadImage(i); ml.RunNetEvaluate(n, hImage); hImage.Dispose(); hImage = null; }); }); LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, "深度学习驱动预热完成"); //if (M141Config.WarmUp && M141Config.WarmUpList.Count > 0) //{ // M141Config.WarmUpList.AsParallel().ForAll(x => // { // try // { // HImage im = new HImage(x.PicFilePath); // var tool = GetHalconTool(null, "", x.HalconFilePath); // if (tool != null) // { // //int num = 0; // //for (int i = 0; i < 10; i++) // //{ // try // { // var res = tool.RunProcedure(null, new Dictionary() { { "INPUT_Image", im } }, new List() { "OUTPUT_Results_1", "OUTPUT_Results_2" }, null); // //if (res != null) // //{ // // if (res.Item1&& res.Item2[$"OUTPUT_Results_{i}"].HTupleToDouble()[0]!=-1234) // // { // // num++; // // if (num >= 2) // // { // // LogAsync(DateTime.Now, EnumHelper.LogLevel.Detail, $"算法{x.HalconFilePath}预热完成{i}"); // // break; // // } // // } // //} // } // catch // { // } // //if (i==9) // //{ // // LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"算法{x.HalconFilePath}预热失败{num}"); // //} // //} // } // im.Dispose(); // } // catch // { // LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"算法{x.HalconFilePath}预热失败"); // } // }); //} //LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, "算法预热完成"); } static object _positionCheckTimeLock = new object(); Dictionary> _positionCheckTimeDict = new Dictionary>(); Dictionary> _positionSpecHeads = new Dictionary>(); volatile int uploadId = 0; public void NewProductIntoList(ProductModel p, bool isSaveDB) { lock (_productListLock) { ProductList.RemoveAll(u => u.PID == p.PID || u.SEQUENCE == p.SEQUENCE); ProductList.Insert(0, p); while (ProductList.Count > 200) { ProductList.RemoveAt(ProductList.Count - 1); } } if (isSaveDB) { if (M141Config.Isreadbasketcode) { p.BasketCode = M141Config.basketcode; } else { p.BasketCode = mysqlhelper.Getbasketcode(p.SEQUENCE); if ("NoRead".Equals(p.BasketCode)) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"{p.PID}_{p.SEQUENCE}获取框具码失败 赋值Noread"); } } mysqlhelper.NewProduct(p); } LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"{p.PID}_{p.SEQUENCE}产品入列完成"); } public virtual ProductModel FindProductBySequence(string sequence, bool isEnabelQueue) { ProductModel p = null; if (isEnabelQueue) { lock (_productListLock) { p = ProductList.FirstOrDefault(u => u.SEQUENCE == sequence); } } if (p != null) { return p; } else { p = mysqlhelper.GetProduct(sequence); if (p == null) { p = new ProductModel(); p.SEQUENCE = sequence; p.PID = p.PID + "_" + sequence.Split('_')[sequence.Split('_').Length - 1]; p.Initial(M141Config.StationCode, M141Config.WorkPositionCollection.Where(u => u.IsEnabled).Select(u => u.PositionName).ToList()); LogAsync(DateTime.Now, EnumHelper.LogLevel.Warning, $"未能从数据库获取产品对象,使用临时新建产品对象"); } NewProductIntoList(p, false); } return p; } public async Task RunImageCheckAsync(List products, string triggerText, string triggerSource, IImageSet imgSet, MeasureBind measureBind) { await Task.Run(() => { List resultList = new List(); if (products == null || products.Count == 0) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"工位{measureBind.WorkPosition}检测时产品信息为空"); imgSet.HImage?.Dispose(); imgSet.HImage = null; return; } try { List pidList = products.Select(u => u.PID).OrderBy(u => u).ToList(); if (imgSet == null || imgSet.HImage == null) { throw new Exception($"产品{string.Join(",", pidList)}检测{measureBind.GetDisplayText()}未能获取图片对象"); } //检测顺序 ML->自定义检测 if (!string.IsNullOrWhiteSpace(measureBind.DetectionId)) { string detectionName = (ML.InitialConfig as MLInitialConfigBase).DetectionConfigs.FirstOrDefault(u => u.Id == measureBind.DetectionId)?.Name; //List pidList2 = new List();//pidList.Select(u => u.Split('_')[u.Split('_').Length - 1]).ToList(); //Dictionary dicpid = new Dictionary(); //for (int i = 0; i < pidList.Count; i++) //{ // var tem = pidList[i].Split('_')[pidList[i].Split('_').Length - 1]; // pidList2.Add(tem); // dicpid[tem] = pidList[i]; //} List detectResults = ML?.RunMLDetectionSync(imgSet, pidList, measureBind.DetectionId); List ngResults = new List(); //for (int i = 0; i < detectResults.Count; i++) //{ // detectResults[i].PID = dicpid[detectResults[i].PID]; //} detectResults.GroupBy(u => u.PID).ToList().ForEach(u => { if (u.ToList().Count > 0 && u.ToList().Any(m => m.ResultState != EnumHelper.ResultState.OK)) { if (u.ToList().GetDefectDescList().Count == 0) { var errorSpec = _errorSpec.Copy(); errorSpec.Code = "检测TBD"; errorSpec.ActualValue = -999; DetectResult ngResult = new DetectResult() { Specs = new List() { errorSpec }, PID = u.Key ,Id=Guid.NewGuid().ToString()}; ngResults.Add(ngResult); } } }); detectResults.AddRange(ngResults); resultList.AddRange(detectResults); } RunCustomizedMethod(products, triggerText, triggerSource, imgSet, measureBind.CustomizedMonitorId, resultList); RunCustomizedMethod(products, triggerText, triggerSource, imgSet, measureBind.CustomizedCombineMethodId, resultList); } catch (Exception ex) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"工位{measureBind.WorkPosition}检测过程异常,{ex.ToString()}"); var errorSpec = _errorSpec.Copy(); errorSpec.ActualValue = -999; products.ForEach(p => { p.AddNewDetectResults(M141Config.StationCode, measureBind.WorkPosition, new List() { new DetectResult() { Specs = new List() { errorSpec }, PID = p.PID, } }); }); } finally { try { if (resultList.Count > 0) { products.ForEach(p => { var pResults = resultList.Where(u => u.PID == p.PID).ToList(); p.AddNewDetectResults(M141Config.StationCode, measureBind.WorkPosition, pResults); LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"产品{p.PID}_{p.SEQUENCE}添加工位{measureBind.WorkPosition}检测结果,数量{pResults.Count}"); }); } products.ForEach(p => { if (p.PositoinCheckDone(measureBind.WorkPosition, measureBind.CheckIndex, out string msg)) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"产品{p.PID}_{p.SEQUENCE}工位{measureBind.WorkPosition}的第{measureBind.CheckIndex}检测完成,该工位检测全部结束"); } else { LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"产品{p.PID}_{p.SEQUENCE}工位{measureBind.WorkPosition}的第{measureBind.CheckIndex}检测完成,{msg}"); } }); if (resultList.Any(u => u.ResultState != EnumHelper.ResultState.OK)) { if (measureBind.NGImageSwitch) { if (string.IsNullOrWhiteSpace(M141Config.NGImageFolder)) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"未配置NG图片保存目录"); } else { string folder = Path.Combine(M141Config.NGImageFolder, DateTime.Now.ToString("yyyyMMdd"), measureBind.WorkPosition, "NG"); if (!Directory.Exists(folder)) { Directory.CreateDirectory(folder); } string id = string.Join("_", products.Select(u => $"{u.PID}_{u.SN}")) + $"-{measureBind.ImageIndex}_{DateTime.Now.ToString("HHmmssfff")}"; string post = ""; if (ImageSet.ImageFormatPostDict.ContainsKey(M141Config.ImageFormatNG)) { post = ImageSet.ImageFormatPostDict[M141Config.ImageFormatNG]; } else { post = M141Config.ImageFormatNG.ToString().ToLower(); } string ngImageFile = Path.Combine(folder, $"{id}.{post}"); var bitmap = imgSet.HImage.ConvertHImageToBitmap(); bitmap.Save(ngImageFile, M141Config.ImageFormatNG); LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{id}NG图片已保存"); bitmap.Dispose(); } } } else { if (measureBind.OKImageSwitch) { if (string.IsNullOrWhiteSpace(M141Config.NGImageFolder)) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"未配置NG图片保存目录"); } else { string folder = Path.Combine(M141Config.NGImageFolder, DateTime.Now.ToString("yyyyMMdd"), measureBind.WorkPosition, "OK"); if (!Directory.Exists(folder)) { Directory.CreateDirectory(folder); } string id = string.Join("_", products.Select(u => $"{u.PID}_{u.SN}")) + $"-{measureBind.ImageIndex}_{DateTime.Now.ToString("HHmmssfff")}"; string post = ""; if (ImageSet.ImageFormatPostDict.ContainsKey(M141Config.ImageFormatOK)) { post = ImageSet.ImageFormatPostDict[M141Config.ImageFormatOK]; } else { post = M141Config.ImageFormatOK.ToString().ToLower(); } string ngImageFile = Path.Combine(folder, $"{id}.{post}"); var bitmap = imgSet.HImage.ConvertHImageToBitmap(); bitmap.Save(ngImageFile, M141Config.ImageFormatOK); LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{id}OK图片已保存"); bitmap.Dispose(); } } } } catch (Exception ex) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"{measureBind.WorkPosition},产品{string.Join(",", products.Select(u => u.PID))}的NG图片保存异常,{ex.GetExceptionMessage()}"); } try { if (imgSet != null && imgSet.HImage != null) { var camera = DeviceCollection.FirstOrDefault(u => u.Id == measureBind.CameraId) as CameraBase; List eleList = new List(); TextDisplay txt = new TextDisplay(); txt.LineLimit = M141Config.LineLimit_p; txt.FontSize = M141Config.FontSize_p; eleList.Add(txt); txt.StartX = txt.StartY = 0; txt.AddText(products[0].SN, products[0].SN != "NOREAD" ? Color.Lime : Color.Red, Color.Transparent); txt.AddText(" ", Color.Transparent, Color.Transparent); var specList = products[0].Details.SelectMany(u => u.ResultList.SelectMany(r => r.Specs)).ToList(); specList.ForEach(v => { txt.AddText($"{v.Code} {v.GetMeasureValueStr(3)}", v.MeasureResult == true ? Color.Lime : Color.Red, Color.Transparent); }); camera.SaveFitImage(eleList, imgSet); } } catch { } LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"图片{imgSet.PID}开始释放"); imgSet.HImage?.Dispose(); imgSet.HImage = null; imgSet.Dispose(); imgSet = null; LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"图片已释放"); } }); } public async Task RunImageCheckAsync(List products, string triggerText, string triggerSource, MeasureBind measureBind) { await Task.Run(() => { List resultList = new List(); if (products == null || products.Count == 0) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"工位{measureBind.WorkPosition}检测时产品信息为空"); return; } try { RunCustomizedMethod(products, triggerText, triggerSource, null, measureBind.CustomizedMonitorId, resultList); RunCustomizedMethod(products, triggerText, triggerSource, null, measureBind.CustomizedCombineMethodId, resultList); } catch (Exception ex) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"工位{measureBind.WorkPosition}检测过程异常,{ex.ToString()}"); var errorSpec = _errorSpec.Copy(); errorSpec.ActualValue = -999; products.ForEach(p => { p.AddNewDetectResults(M141Config.StationCode, measureBind.WorkPosition, new List() { new DetectResult() { Specs = new List() { errorSpec }, PID = p.PID, } }); }); } finally { try { if (resultList.Count > 0) { products.ForEach(p => { var pResults = resultList.Where(u => u.PID == p.PID).ToList(); p.AddNewDetectResults(M141Config.StationCode, measureBind.WorkPosition, pResults); LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"产品{p.PID}_{p.SEQUENCE}添加工位{measureBind.WorkPosition}检测结果,数量{pResults.Count}"); }); } products.ForEach(p => { if (p.PositoinCheckDone(measureBind.WorkPosition, measureBind.CheckIndex, out string msg)) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"产品{p.PID}_{p.SEQUENCE}工位{measureBind.WorkPosition}的第{measureBind.CheckIndex}检测完成,该工位检测全部结束"); } else { LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"产品{p.PID}_{p.SEQUENCE}工位{measureBind.WorkPosition}的第{measureBind.CheckIndex}检测完成,{msg}"); } }); } catch (Exception ex) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"{measureBind.WorkPosition},产品{string.Join(",", products.Select(u => u.PID))}的NG图片保存异常,{ex.GetExceptionMessage()}"); } } }); } private void RunCustomizedMethod(List products, string triggerText, string triggerSource, IImageSet imgSet, string methodId, List resultList) { try { if (!string.IsNullOrWhiteSpace(methodId)) { var monitorSet = Config.GetAllMonitorSet().FirstOrDefault(u => u.Id == methodId); if (monitorSet.OpConfig is IImageCheckOperationConfig iConfig) { var opConfig = iConfig.Clone(); opConfig.Products = new List(products); opConfig.ImageSet = imgSet; opConfig.TriggerStr = triggerText; opConfig.TriggerSource = triggerSource; //LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"图片id,{imgSet.id}"); var res = RunSelectedMonitorSetByManual(methodId, opConfig); if (res.DataObj is List dr) { dr.ForEach(r => { r.IsPreTreatDone = r.IsNetCheckDone = r.IsAfterTreatDone = true; r.SetResult(); }); resultList.AddRange(dr); } if (res.Result != 1) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"自定义检测过程异常,{res.Message}"); } } } } catch (Exception ex) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"自定义检测过程异常,{ex.GetExceptionMessage()}"); } } #region plc public ResponseMessage RunImageCheck_plc(IOperationConfig config) { ResponseMessage msg = new ResponseMessage(); msg.Result = 1; List measureBinds = new List(); string inputSequence = ""; var triggerDatas = config.TriggerStr.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); try { RunImageCheckPreTreat_plc(config, out measureBinds, out inputSequence); } catch (Exception ex) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"检测预处理异常,{ex.GetExceptionMessage()}"); msg.Result = -1; msg.Message = ex.Message; return msg; } List cameraIds = measureBinds.Select(u => u.CameraId).ToList(); try { ConcurrentDictionary imgSetDicts = new ConcurrentDictionary(); var positionSet = M141Config.WorkPositionCollection.Where(u => u.IsEnabled).FirstOrDefault(u => u.TriggerValue == triggerDatas[0]); measureBinds.AsParallel().ForAll(b => { var camera = DeviceCollection.FirstOrDefault(u => u.Id == b.CameraId) as CameraBase; if (camera != null) { imgSetDicts[b] = null; try { imgSetDicts[b] = CollectHImage(camera, b.SnapshotOpConfig); if (positionSet.ispiccover) { Plc1.WriteSingleAddress(positionSet.plcover,1,out _); } } catch (Exception ea) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"工位{measureBinds[0].WorkPosition}的第{measureBinds[0].CheckIndex}检测获取图像信息异常 {ea.ToString()}"); } var pList = b.ProductIndices.Select(pi => { string sequence = $"{inputSequence}_{pi}"; return FindProductBySequence(sequence, true); }).ToList(); RunImageCheckAsync(pList, config.TriggerStr, config.TriggerSource, imgSetDicts[b], b); } else { var pList = b.ProductIndices.Select(pi => { string sequence = $"{inputSequence}_{pi}"; return FindProductBySequence(sequence, true); }).ToList(); RunImageCheckAsync(pList, config.TriggerStr, config.TriggerSource, b); } }); } catch (Exception ex) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"检测处理异常,{ex.GetExceptionMessage()}"); msg.Result = -1; msg.Message = ex.Message; return msg; } CheckPositionDoneAsync_plc(measureBinds[0].WorkPosition, inputSequence, config, cameraIds); return msg; } public void RunImageCheckPreTreat_plc(IOperationConfig config, out List measureBinds, out string inputSequence) { Task.Run(() => { SetProcessRunState(EnumHelper.RunState.Running); }); measureBinds = new List(); inputSequence = ""; var triggerDatas = config.TriggerStr.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (triggerDatas.Length < 2) { throw new ProcessException($"触发文本{config.TriggerStr}解析失败,数据长度小于2"); } string positionValue = triggerDatas[0]; int checkIndex = -1; if (!int.TryParse(triggerDatas[1].Replace("Scan", ""), out checkIndex)) { throw new ProcessException($"触发文本{config.TriggerStr}解析失败,未能获取检测序号"); } var positionSet = M141Config.WorkPositionCollection.Where(u => u.IsEnabled).FirstOrDefault(u => u.TriggerValue == positionValue); if (positionSet == null) { throw new ProcessException($"触发文本{config.TriggerStr}未能获取{positionValue}对应的可用工位信息"); } measureBinds = M141Config.MeasureBindCollection.Where(u => u.WorkPosition == positionSet.PositionName && u.CheckIndex == checkIndex).ToList(); if (measureBinds.Count == 0) { throw new ProcessException($"未能获取工位{positionSet.PositionName}的第{checkIndex}检测配置信息"); } measureBinds.Select(u => u.CameraId).ToList().ForEach(c => { var camera = DeviceCollection.FirstOrDefault(u => u.Id == c) as CameraBase; if (camera != null) { camera.ClearImageBufferQueue(); LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"相机{camera.Name}检测前清理缓存完成"); } }); inputSequence = triggerDatas[triggerDatas.Length - 1]; string tempSequence = inputSequence; string pidstr = DateTime.Now.ToString("yyyyMMddHHmmssfff"); measureBinds.Where(b => b.IsFirstPosition).ToList().ForEach(b => { b.ProductIndices.ForEach(i => { ProductModel p = new ProductModel(); p.SEQUENCE = $"{tempSequence}_{i}"; p.PID = $"{pidstr}T_{i}"; if (positionSet.IsLastPosition) { p.Initial(M141Config.StationCode, new List() { positionSet.PositionName }); } else { p.Initial(M141Config.StationCode, M141Config.WorkPositionCollection.Select(u => u.PositionName).ToList()); } NewProductIntoList(p, true); }); }); int de = 0; measureBinds.Where(b => (b.CheckIndex == de || b.CheckIndex == 1) && b.ImageIndex == 0).AsParallel().ForAll(b => { List temint = new List(); temint = new List() { 1 }; temint.ForEach(i => { string sequence = $"{tempSequence}_{i}"; var p = FindProductBySequence(sequence, b.IsEnabelQueryFromQueue); //初始化产品的检测次数 var checkIndexList = M141Config.MeasureBindCollection.Where(u => u.WorkPosition == b.WorkPosition && u.ProductIndices.Contains(i)).Select(u => u.CheckIndex).OrderBy(u => u).ToList(); p.InitialPositionCheckList(b.WorkPosition, checkIndexList); LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{p.PID}_{p.SEQUENCE}已清理{b.WorkPosition}检测数据。当前已完成工位{string.Join(",", p.Details.Select(u => u.PositionName))}"); }); //初始化工位的检测次数 var positionCheckTimes = M141Config.MeasureBindCollection.Where(u => u.WorkPosition == b.WorkPosition).Select(u => u.CheckIndex).ToList(); lock (_positionCheckTimeLock) { _positionCheckTimeDict[b.WorkPosition] = positionCheckTimes; LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"工位{b.WorkPosition}初始化检测次数:{string.Join(",", positionCheckTimes)}"); } }); measureBinds.AsParallel().ForAll(b => { lock (_positionCheckTimeLock) { _positionCheckTimeDict[b.WorkPosition].RemoveAll(u => u == b.CheckIndex); LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"工位{b.WorkPosition}开始第{b.CheckIndex}次检测,待检测序号:{string.Join(",", _positionCheckTimeDict[b.WorkPosition])}"); } }); } public async Task> CheckPositionDoneAsync_plc(string positionName, string inputSequence, IOperationConfig config, List cameraIds) { string triggerSource = config.TriggerSource; return await _taskFactory.StartNew(() => { try { string index = config.TriggerStr.Split(',')[1]; var positionSet = M141Config.WorkPositionCollection.FirstOrDefault(u => u.PositionName == positionName); var checkRemains = _positionCheckTimeDict[positionName]; var pIndices = M141Config.MeasureBindCollection.Where(u => u.WorkPosition == positionName).SelectMany(u => u.ProductIndices).Distinct().OrderBy(u => u).ToList(); pIndices = new List { 1 }; var pList = pIndices.Select(u => { string sequence = $"{inputSequence}_{u}"; return FindProductBySequence(sequence, true); }).ToList(); List plcresult = new List(); if (pList.Any(u => u == null)) { plcresult = new List() { false, false, false }; LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"获取工位{positionName}汇总结果时产品信息为空"); } else { int waitInterval = 300; int repeatTime = M141Config.DetectTimeout / waitInterval; do { if (!pList.All(p => { p.GetPositionResult(M141Config.StationCode, positionName, out P_PRODUCT_DETAIL detail); return detail?.IsDone ?? false; })) { Thread.Sleep(waitInterval); repeatTime--; } else { Thread.Sleep(50); LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"成功完成工位{positionName}产品{string.Join(",", pList.Select(u => $"{u.PID}_{u.SEQUENCE}"))}检测"); break; } if (repeatTime < 0) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"工位{positionName}产品{string.Join(",", pList.Select(u => $"{u.PID}_{u.SEQUENCE}"))}检测获取结果超时"); break; } } while (true); } pList.ForEach(p => { var isOK = p.GetPositionResult(M141Config.StationCode, positionName, out P_PRODUCT_DETAIL detail); plcresult.Add(isOK); List specHeads = new List(); string head = p.GetCSVHead(ref specHeads, positionName); _positionSpecHeads[positionName] = specHeads; string data = p.GetCSVData(_positionSpecHeads[positionName], positionName); CSVRecordAsync($"{positionName}_Record_{DateTime.Now.ToString("yyyyMMdd")}.csv", data, head); //UpdatePositionResultToDB(detail); //var seqData = p.SEQUENCE.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries).ToList(); mysqlhelper.UpdateProduct(p); if (positionSet.IsLastPosition) { UpdateProductResultAsync(p); mysqlhelper.NewForAll(p, M141Config.StationCode); if (M141Config.IsfinDevice) { SummaryAllprodata(p); } } }); ReplyPlcData(positionSet, plcresult); if (positionSet.IsLastPosition) { if (_ct != null) { UpdateCT(null, (float)((DateTime.Now - _ct.Value).TotalSeconds)); } _ct = DateTime.Now; } //ReplyPlcData(positionName, config.TriggerValue); cameraIds.ForEach(c => { var camera = DeviceCollection.FirstOrDefault(u => u.Id == c) as CameraBase; if (camera != null) { camera.ClearImageBufferQueue(); LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"相机{camera.Name}清理缓存"); } }); return pList; } catch (Exception ex) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, ex.ToString()); return null; } }); } public void ReplyPlcData(WorkPositionSet p, List result) { if (p.plcresult != 0) { Plc1.WriteSingleAddress(p.plcresult, result[0] ? 1 : 2, out _); } Plc1.WriteSingleAddress(p.plcover, 1, out _); } public void SummaryAllprodata(ProductModel p) { _taskFactory.StartNew(() => { try { ProductModel newp = new ProductModel(); newp.SEQUENCE = p.SEQUENCE; newp.PID = p.PID; newp.BasketCode = p.BasketCode; newp.Result = p.Result; newp.SN = p.SN; newp.Details.AddRange(p.Details); var plist = mysqlhelper.GetProductList(p.SEQUENCE); if (plist != null) { foreach (var item in plist) { newp.Details.AddRange(item.Details); } } List specHeadListforall = new List(); List positionListforall = new List(); string csvHeadforall = p.GetCSVHead(ref specHeadListforall, ref positionListforall); CSVRecordAsync($"AllDeviceProductRecord.csv", p.GetCSVData(specHeadListforall, positionListforall), csvHeadforall); } catch(Exception exx) { LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, "AllDeviceProductRecord数据汇总异常 " + exx.ToString()); } }); } #endregion } }