| | |
| | | using System.Drawing.Imaging; |
| | | using System.IO; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using Windows.ApplicationModel.Appointments; |
| | | using Windows.Networking; |
| | | using static Org.BouncyCastle.Math.EC.ECCurve; |
| | |
| | | |
| | | public M141Process(string productCode) : base(productCode) { } |
| | | #endregion |
| | | TaskFactory _taskFactory = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.LongRunning); |
| | | |
| | | public event Action<string, P_PRODUCT_DETAIL, string> OnSinglePostionDetectResultUpdate; |
| | | protected M141Config M141Config => Config as M141Config; |
| | | |
| | | public static object _productListLock = new object(); |
| | | public List<ProductModel> ProductList = new List<ProductModel>(); |
| | | MachineLearningBase ML = null; |
| | | TcpListenerWrap TcpListener = null; |
| | | Spec _errorSpec = null; |
| | | public List<ProductModel> ProductSpecResultList { get; set; } = new List<ProductModel>(); |
| | | TcpListenerWrap _realTimeServer = null; |
| | | |
| | | volatile int _productIndex = 0; |
| | | |
| | | int _backgroundImageWidth = 2448; |
| | | public event Action<string, string, List<IShapeElement>> OnPositionResultUpdated; |
| | | public event Action<ProductModel> OnNewProductEnqueued; |
| | | public event Action<ProductModel> OnProductDequeued; |
| | | public event Action<List<int>> RefreshUIplc; |
| | | public event Action<string> RefreshState; |
| | | |
| | | List<ZipImage> ZipImages = new List<ZipImage>(); |
| | | List<OKNGImage> OKNGImages = new List<OKNGImage>(); |
| | | |
| | | public override void InitialProcessMethods() |
| | | { |
| | | base.InitialProcessMethods(); |
| | | OldDataClear.Instance.RunClearOldData(M141Config.DBDataTimeLimit); |
| | | InitialInspectionConfig(); |
| | | InitialSummaryData(); |
| | | |
| | | |
| | | |
| | | |
| | | if (ThHeartPlc == null) |
| | | { |
| | | ThHeartPlc = new Thread(Heartplc); |
| | | ThHeartPlc.IsBackground = true; |
| | | ThHeartPlc.Start(); |
| | | } |
| | | } |
| | | |
| | | 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; |
| | | Thread ThHeartPlc; |
| | | Spec _errorSpec; |
| | | bool isstart = false; |
| | | public override void Open() |
| | | { |
| | | base.Open(); |
| | |
| | | } |
| | | _errorSpec = M141Config.SpecCollection.FirstOrDefault(u => u.Code == M141Config.CheckErrorSpecCode) as Spec; |
| | | |
| | | InitialProductList(); |
| | | |
| | | |
| | | NetWarmUp(); |
| | | |
| | |
| | | _positionSpecHeads.Clear(); |
| | | |
| | | |
| | | if (ThHeartPlc == null) |
| | | { |
| | | ThHeartPlc = new Thread(Heartplc); |
| | | ThHeartPlc.IsBackground = true; |
| | | ThHeartPlc.Start(); |
| | | } |
| | | |
| | | InitialContinuousNGAlarm(); |
| | | |
| | | |
| | | int vava = 0; |
| | | if (M141Config.channelva == 3) |
| | | { |
| | | vava = 0; |
| | | } |
| | | else if (M141Config.channelva == 2) |
| | | { |
| | | vava = 1; |
| | | } |
| | | |
| | | Plc1.WriteSingleAddress(3006, vava, out _); |
| | | |
| | | isstart = true; |
| | | |
| | | } |
| | | |
| | | |
| | | public override void Close() |
| | | { |
| | | isstart = false; |
| | | base.Close(); |
| | | } |
| | | |
| | | public void Heartplc() |
| | | { |
| | | Thread.Sleep(1000); |
| | | |
| | | string _statisticFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Statistic.json"); |
| | | if (File.Exists(_statisticFilePath)) |
| | | { |
| | | try |
| | | { |
| | | string dataStr = ""; |
| | | using (StreamReader reader = new StreamReader(_statisticFilePath, System.Text.Encoding.UTF8)) |
| | | { |
| | | dataStr = reader.ReadToEnd(); |
| | | } |
| | | |
| | | lock (StatisticRecordsFull) |
| | | { |
| | | var temRecords = JsonConvert.DeserializeObject<StatisticRecords_Full>(dataStr); |
| | | if (StatisticRecordsFull != null && temRecords != null) |
| | | { |
| | | StatisticRecordsFull.CurRecord = temRecords.CurRecord; |
| | | StatisticRecordsFull.HistoryRecord = temRecords.HistoryRecord; |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"产品统计信息反序列化异常"); |
| | | StatisticRecordsFull = new StatisticRecords_Full(); |
| | | } |
| | | } |
| | | int state = 0; |
| | | int state2 = 0; |
| | | int numsum = 0; |
| | | DateTime dtday = DateTime.Now; |
| | | while (true) |
| | | { |
| | | Thread.Sleep(1000); |
| | | |
| | | |
| | | if (!isstart) |
| | | { |
| | | continue; |
| | | } |
| | | numsum++; |
| | | |
| | | try |
| | | { |
| | |
| | | { |
| | | |
| | | } |
| | | Thread.Sleep(1000); |
| | | |
| | | |
| | | |
| | | try |
| | | { |
| | | var tem = Plc1.Read(3030, 17, out _); |
| | | if (M141Config.WorkShiftList != null && M141Config.WorkShiftList.Count > 0 && numsum >= 0) |
| | | { |
| | | for (int i = 0; i < M141Config.WorkShiftList.Count; i++) |
| | | { |
| | | |
| | | double timeshap = (DateTime.Now - M141Config.WorkShiftList[i].ShiftTime_Start).TotalMinutes % 1440; |
| | | double timeshap2 = (DateTime.Now - M141Config.WorkShiftList[i].ShiftTime_End).TotalMinutes % 1440; |
| | | |
| | | |
| | | if (timeshap2 > 0 && timeshap2 < 1) |
| | | { |
| | | if (M141Config.WorkShiftList[i].IsRecordProductSummary) |
| | | { |
| | | string csvPathAll = Path.Combine(M141Config.LogPath, "Alldata.csv"); |
| | | |
| | | using (StreamWriter writer = new StreamWriter(csvPathAll, true, Encoding.UTF8)) |
| | | { |
| | | try |
| | | { |
| | | int sum = StatisticRecordsFull.CurRecord.ProductSummary.RecordsList.Where(u => u.IsStatistic).Sum(u => u.Amount); |
| | | int OKnum = 0; |
| | | string okpercent = ""; |
| | | string headcsv = "日期,班次,总数,OK,OK占比"; |
| | | string datacsv = ""; |
| | | |
| | | StatisticRecordsFull.CurRecord.ProductSummary.RecordsList.ForEach(u => |
| | | { |
| | | if (u.ClassDesc.ToUpper() == "OK") |
| | | { |
| | | OKnum = u.Amount; |
| | | okpercent = u.PercentStr; |
| | | } |
| | | else |
| | | { |
| | | headcsv += $",{u.ClassDesc},{u.ClassDesc}占比"; |
| | | datacsv += $",{u.Amount},{u.PercentStr}"; |
| | | } |
| | | |
| | | }); |
| | | |
| | | string daystr = DateTime.Now.ToString("yyyyMMdd"); |
| | | if (M141Config.WorkShiftList[i].ShiftTime_End.TimeOfDay < M141Config.WorkShiftList[i].ShiftTime_Start.TimeOfDay) |
| | | { |
| | | daystr = DateTime.Now.AddDays(-1).ToString("yyyyMMdd"); |
| | | } |
| | | |
| | | datacsv = $"{daystr}T,{M141Config.WorkShiftList[i].ShiftName},{sum},{OKnum},{OKnum}" + datacsv; |
| | | |
| | | writer.WriteLine(headcsv); |
| | | writer.WriteLine(datacsv); |
| | | |
| | | } |
| | | catch (Exception exx) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, exx.ToString()); |
| | | } |
| | | } |
| | | |
| | | } |
| | | numsum = -62; |
| | | } |
| | | |
| | | if (timeshap > 0 && timeshap < 1) |
| | | { |
| | | |
| | | if (M141Config.WorkShiftList[i].IsClearProductSummary) |
| | | { |
| | | StatisticRecordsFull.CurRecord.ProductSummary.RecordsList.Clear(); |
| | | StatisticRecordsFull.CurRecord.DefectSummary.RecordsList.Clear(); |
| | | } |
| | | numsum = -62; |
| | | } |
| | | } |
| | | } |
| | | |
| | | lock (StatisticRecordsFull) |
| | | { |
| | | if (numsum > 20) |
| | | { |
| | | numsum = 0; |
| | | using (FileStream fileStream = new FileStream(_statisticFilePath, FileMode.OpenOrCreate, FileAccess.Write)) |
| | | { |
| | | fileStream.Seek(0L, SeekOrigin.Begin); |
| | | string s = JsonConvert.SerializeObject(StatisticRecordsFull); |
| | | byte[] bytes = Encoding.UTF8.GetBytes(s); |
| | | fileStream.Write(bytes, 0, bytes.Length); |
| | | fileStream.SetLength(bytes.Length); |
| | | fileStream.Flush(); |
| | | fileStream.Close(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | try |
| | | { |
| | | var tem = Plc1.Read(3030, 18, out _); |
| | | if (tem != null && RefreshUIplc != null) |
| | | { |
| | | RefreshUIplc.Invoke(tem); |
| | |
| | | { |
| | | |
| | | } |
| | | |
| | | try |
| | | { |
| | | var tem = Plc1.Read(3010, 8, out _); |
| | |
| | | { |
| | | var tem = Plc1.Read(3027, 1, out _)[0]; |
| | | var tem2 = Plc1.Read(3028, 1, out _)[0]; |
| | | |
| | | |
| | | if (state != tem || state2 != tem2) |
| | | { |
| | | state = tem; |
| | |
| | | { |
| | | |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | |
| | | try |
| | | { |
| | | Plc1.WriteSingleAddress(add, va, out _); |
| | | var tem = Plc1.Read(3030, 16, out _); |
| | | var tem = Plc1.Read(3030, 18, out _); |
| | | if (tem != null && RefreshUIplc != null) |
| | | { |
| | | RefreshUIplc.Invoke(tem); |
| | |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, "算法预热完成"); |
| | | } |
| | | |
| | | |
| | | |
| | | static object _positionCheckTimeLock = new object(); |
| | | Dictionary<string, List<int>> _positionCheckTimeDict = new Dictionary<string, List<int>>(); |
| | | Dictionary<string, List<string>> _positionSpecHeads = new Dictionary<string, List<string>>(); |
| | | public ResponseMessage RunImageCheck(IOperationConfig config) |
| | | { |
| | | ResponseMessage msg = new ResponseMessage(); |
| | | msg.Result = 1; |
| | | List<MeasureBind> measureBinds = new List<MeasureBind>(); |
| | | string inputSequence = ""; |
| | | var triggerDatas = config.TriggerStr.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); |
| | | try |
| | | { |
| | | RunImageCheckPreTreat(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<string> cameraIds = measureBinds.Select(u => u.CameraId).ToList(); |
| | | try |
| | | { |
| | | ConcurrentDictionary<MeasureBind, IImageSet> imgSetDicts = new ConcurrentDictionary<MeasureBind, IImageSet>(); |
| | | |
| | | measureBinds.AsParallel().ForAll(b => |
| | | { |
| | | var camera = DeviceCollection.FirstOrDefault(u => u.Id == b.CameraId) as CameraBase; |
| | | if (camera == null) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"检测配置{b.GetDisplayText()}未能获取相机设备"); |
| | | imgSetDicts[b] = null; |
| | | return; |
| | | } |
| | | imgSetDicts[b] = null; |
| | | //if (config.TriggerStr.Split(',')[0].Contains("2")) |
| | | //{ |
| | | //camera.ClearImageBufferQueue(); |
| | | try |
| | | { |
| | | imgSetDicts[b] = CollectHImage(camera, b.SnapshotOpConfig); |
| | | camera.ClearImageBufferQueue(); |
| | | } |
| | | catch (Exception ea) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"工位{measureBinds[0].WorkPosition}的第{measureBinds[0].CheckIndex}检测获取图像信息异常 {ea.ToString()}"); |
| | | } |
| | | finally |
| | | { |
| | | //try |
| | | //{ |
| | | // if (imgSetDicts[b] == null || imgSetDicts[b].HImage == null) |
| | | // { |
| | | // LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"工位{measureBinds[0].WorkPosition}的第{measureBinds[0].CheckIndex}检测获取图像信息为null "); |
| | | // //if (camera is InsCameraDriver insCamera) |
| | | // //{ |
| | | // // insCamera.Restart(); |
| | | // //} |
| | | // } |
| | | //} |
| | | //catch (Exception ec) |
| | | //{ |
| | | // LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, "ins相机重连异常" + ec.ToString()); |
| | | //} |
| | | } |
| | | |
| | | |
| | | var pList = b.ProductIndices.Select(pi => |
| | | { |
| | | string pid = $"{inputSequence}_{pi}"; |
| | | return FindProductBySequence(pid, true); |
| | | }).ToList(); |
| | | |
| | | RunImageCheckAsync(pList, config.TriggerStr, config.TriggerSource, imgSetDicts[b], b); |
| | | |
| | | }); |
| | | |
| | | |
| | | //if (imgSetDicts.Values.Any(u => u == null || u.HImage == null)) |
| | | //{ |
| | | // //msg.Result = -1; |
| | | // //msg.Message = $"工位{measureBinds[0].WorkPosition}的第{measureBinds[0].CheckIndex}检测获取图像信息失败"; |
| | | // //return msg; |
| | | // throw new ProcessException($"工位{measureBinds[0].WorkPosition}的第{measureBinds[0].CheckIndex}检测获取图像信息失败"); |
| | | //} |
| | | |
| | | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"检测处理异常,{ex.GetExceptionMessage()}"); |
| | | msg.Result = -1; |
| | | msg.Message = ex.Message; |
| | | |
| | | return msg; |
| | | } |
| | | |
| | | |
| | | //if (triggerDatas[0].Contains("1")) |
| | | //{ |
| | | // msg.Result = -1; |
| | | // return msg; |
| | | //} |
| | | |
| | | CheckPositionDoneAsync(measureBinds[0].WorkPosition, inputSequence, config, cameraIds); |
| | | return msg; |
| | | } |
| | | |
| | | public ResponseMessage RunImageCheck1(IOperationConfig config) |
| | | { |
| | | ResponseMessage msg = new ResponseMessage(); |
| | | msg.Result = 1; |
| | | List<MeasureBind> measureBinds = new List<MeasureBind>(); |
| | | string inputSequence = ""; |
| | | |
| | | try |
| | | { |
| | | RunImageCheckPreTreat1(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<string> cameraIds = measureBinds.Select(u => u.CameraId).ToList(); |
| | | try |
| | | { |
| | | ConcurrentDictionary<MeasureBind, IImageSet> imgSetDicts = new ConcurrentDictionary<MeasureBind, IImageSet>(); |
| | | |
| | | measureBinds.AsParallel().ForAll(b => |
| | | { |
| | | var camera = DeviceCollection.FirstOrDefault(u => u.Id == b.CameraId) as CameraBase; |
| | | if (camera == null) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"检测配置{b.GetDisplayText()}未能获取相机设备"); |
| | | imgSetDicts[b] = null; |
| | | return; |
| | | } |
| | | imgSetDicts[b] = null; |
| | | |
| | | try |
| | | { |
| | | imgSetDicts[b] = CollectHImage(camera, b.SnapshotOpConfig); |
| | | camera.ClearImageBufferQueue(); |
| | | } |
| | | catch (Exception ea) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"工位{measureBinds[0].WorkPosition}的第{measureBinds[0].CheckIndex}检测获取图像信息失败 {ea.ToString()}"); |
| | | } |
| | | |
| | | |
| | | var pList = b.ProductIndices.Select(pi => |
| | | { |
| | | string pid = $"{inputSequence}_{pi}"; |
| | | return FindProductBySequence(pid, true); |
| | | }).ToList(); |
| | | |
| | | RunImageCheckAsync(pList, config.TriggerStr, config.TriggerSource, imgSetDicts[b], b); |
| | | |
| | | }); |
| | | //DateTime.Now.DayOfWeek |
| | | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"检测处理异常,{ex.GetExceptionMessage()}"); |
| | | msg.Result = -1; |
| | | msg.Message = ex.Message; |
| | | |
| | | return msg; |
| | | } |
| | | |
| | | |
| | | CheckPositionDoneAsync1(measureBinds[0].WorkPosition, inputSequence, config, cameraIds); |
| | | return msg; |
| | | } |
| | | |
| | | |
| | | |
| | | public void RunImageCheckPreTreat1(IOperationConfig config, out List<MeasureBind> measureBinds, out string inputSequence) |
| | | { |
| | | Task.Run(() => |
| | | { |
| | | SetProcessRunState(EnumHelper.RunState.Running); |
| | | }); |
| | | |
| | | measureBinds = new List<MeasureBind>(); |
| | | 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], 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}检测前清理缓存完成"); |
| | | } |
| | | }); |
| | | |
| | | if (positionSet.IsSendClearSingal) |
| | | { |
| | | var sourceData = config.TriggerSource.Split(':'); |
| | | string ip = ""; |
| | | int port = 0; |
| | | if (sourceData.Length >= 2) |
| | | { |
| | | ip = sourceData[0]; |
| | | port = int.Parse(sourceData[1]); |
| | | } |
| | | |
| | | TcpListener?.WriteAndRead(positionSet.ClearStr, out _, out _, false, ip, port); |
| | | } |
| | | |
| | | inputSequence = triggerDatas[triggerDatas.Length - 1]; |
| | | |
| | | string tempPID = 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 = $"{tempPID}_{i}"; |
| | | p.PID = $"{pidstr}T_{i}"; |
| | | p.Initial(M141Config.StationCode, M141Config.WorkPositionCollection.Select(u => u.PositionName).ToList()); |
| | | NewProductIntoList(p, true); |
| | | }); |
| | | }); |
| | | |
| | | |
| | | int de = 2; |
| | | //if (triggerDatas[0].Contains("11111")) |
| | | //{ |
| | | // de = 2; |
| | | //} |
| | | //else |
| | | //{ |
| | | |
| | | // de = 2; |
| | | //} |
| | | |
| | | |
| | | measureBinds.Where(b => (b.CheckIndex == de || b.CheckIndex == 1) && b.ImageIndex == 0).AsParallel().ForAll(b => |
| | | { |
| | | List<int> temint = new List<int>(); |
| | | if (triggerDatas[0].Contains("11111")) |
| | | { |
| | | if (triggerDatas[1] == "1") |
| | | { |
| | | temint = new List<int>() { 1 }; |
| | | } |
| | | else |
| | | { |
| | | temint = new List<int>() { 2 }; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | temint = new List<int>() { 1, 2 }; |
| | | } |
| | | |
| | | |
| | | //new List<int>() { 1, 2 }.ForEach(i => |
| | | temint.ForEach(i => |
| | | { |
| | | string sequence = $"{tempPID}_{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); |
| | | |
| | | //p.ClearPositionResult(M141Config.StationCode, b.WorkPosition); |
| | | 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 void RunImageCheckPreTreat(IOperationConfig config, out List<MeasureBind> measureBinds, out string inputSequence) |
| | | { |
| | | Task.Run(() => |
| | | { |
| | | SetProcessRunState(EnumHelper.RunState.Running); |
| | | }); |
| | | |
| | | measureBinds = new List<MeasureBind>(); |
| | | 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}检测前清理缓存完成"); |
| | | } |
| | | }); |
| | | |
| | | if (positionSet.IsSendClearSingal) |
| | | { |
| | | var sourceData = config.TriggerSource.Split(':'); |
| | | string ip = ""; |
| | | int port = 0; |
| | | if (sourceData.Length >= 2) |
| | | { |
| | | ip = sourceData[0]; |
| | | port = int.Parse(sourceData[1]); |
| | | } |
| | | |
| | | TcpListener?.WriteAndRead(positionSet.ClearStr, out _, out _, false, ip, port); |
| | | } |
| | | |
| | | inputSequence = triggerDatas[triggerDatas.Length - 1]; |
| | | |
| | | string tempPID = 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 = $"{tempPID}_{i}"; |
| | | p.PID = $"{pidstr}T_{i}"; |
| | | p.Initial(M141Config.StationCode, M141Config.WorkPositionCollection.Select(u => u.PositionName).ToList()); |
| | | NewProductIntoList(p, true); |
| | | }); |
| | | }); |
| | | |
| | | |
| | | int de = 0; |
| | | if (triggerDatas[0].Contains("1") || triggerDatas[0].Contains("0")) |
| | | { |
| | | de = 2; |
| | | } |
| | | else |
| | | { |
| | | de = 1; |
| | | } |
| | | |
| | | |
| | | measureBinds.Where(b => (b.CheckIndex == de || b.CheckIndex == 1) && b.ImageIndex == 0).AsParallel().ForAll(b => |
| | | { |
| | | List<int> temint = new List<int>(); |
| | | if (triggerDatas[0].Contains("1") || triggerDatas[0].Contains("0")) |
| | | { |
| | | if (triggerDatas[1].Contains("1")) |
| | | { |
| | | temint = new List<int>() { 1 }; |
| | | } |
| | | else |
| | | { |
| | | temint = new List<int>() { 2 }; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | temint = new List<int>() { 1, 2 }; |
| | | } |
| | | |
| | | |
| | | //new List<int>() { 1, 2 }.ForEach(i => |
| | | temint.ForEach(i => |
| | | { |
| | | string sequence = $"{tempPID}_{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); |
| | | |
| | | //p.ClearPositionResult(M141Config.StationCode, b.WorkPosition); |
| | | 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<List<ProductModel>> CheckPositionDoneAsync(string positionName, string inputSequence, IOperationConfig config, List<string> cameraIds) |
| | | { |
| | | string triggerSource = config.TriggerSource; |
| | | return await _taskFactory.StartNew(() => |
| | | { |
| | | try |
| | | { |
| | | |
| | | if (positionName.Contains("1") || positionName.Contains("0")) |
| | | { |
| | | |
| | | string index = config.TriggerStr.Split(',')[1]; |
| | | var positionSet = M141Config.WorkPositionCollection.FirstOrDefault(u => u.PositionName == positionName); |
| | | |
| | | var checkRemains = _positionCheckTimeDict[positionName]; |
| | | //if (checkRemains.Count != 0) |
| | | //{ |
| | | // LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"工位{positionName}检测未完成,剩余:{string.Join(",", checkRemains)}"); |
| | | // return null; |
| | | //} |
| | | |
| | | string replyData = M141Config.WorkPositionCollection.FirstOrDefault(u => u.PositionName == positionName).TriggerValue; |
| | | |
| | | |
| | | //if (checkRemains.Count != 0) |
| | | //{ |
| | | replyData += "," + index; |
| | | //} |
| | | //else |
| | | //{ |
| | | // replyData += ",2"; |
| | | //} |
| | | |
| | | var pIndices = M141Config.MeasureBindCollection.Where(u => u.WorkPosition == positionName).SelectMany(u => u.ProductIndices).Distinct().OrderBy(u => u).ToList(); |
| | | if (index.Contains("1")) |
| | | { |
| | | pIndices = new List<int> { 1 }; |
| | | } |
| | | else |
| | | { |
| | | pIndices = new List<int> { 2 }; |
| | | } |
| | | //var measureNum = M141Config.MeasureBindCollection.Count(u => u.WorkPosition == positionName && u.ProductIndices.Contains(pIndices[0])); |
| | | //if (measureNum > 1) |
| | | //{ |
| | | // replyData += ",C"; |
| | | //} |
| | | |
| | | var pList = pIndices.Select(u => |
| | | { |
| | | string sequence = $"{inputSequence}_{u}"; |
| | | return FindProductBySequence(sequence, true); |
| | | }).ToList(); |
| | | |
| | | if (pList.Any(u => u == null)) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"获取工位{positionName}汇总结果时产品信息为空"); |
| | | pList.ForEach(u => |
| | | { |
| | | replyData += ",NG"; |
| | | }); |
| | | } |
| | | 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 |
| | | { |
| | | 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); |
| | | replyData += $",{(isOK ? "OK" : "NG")}"; |
| | | List<string> specHeads = new List<string>(); |
| | | string head = p.GetCSVHead(ref specHeads, positionName); |
| | | if (!_positionSpecHeads.ContainsKey(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(); |
| | | UpdatePositionResultDisplay(detail, isOK, positionName, seqData[seqData.Count - 1]); |
| | | if (IsInspectionDoing) |
| | | { |
| | | OnSinglePostionDetectResultUpdate.Invoke(positionName, detail, seqData[seqData.Count - 1]); |
| | | } |
| | | |
| | | if (positionSet.IsLastPosition) |
| | | { |
| | | UpdateProductResultAsync(p); |
| | | UpdateOverAllProductResultToUI(p, isOK); |
| | | OnNewProductEnqueued?.Invoke(p); |
| | | OnProductDequeued?.Invoke(p); |
| | | } |
| | | |
| | | SetSpecResult(p); |
| | | }); |
| | | |
| | | if (positionSet.IsLastPosition) |
| | | { |
| | | if (_ct != null) |
| | | { |
| | | UpdateCT(null, (float)((DateTime.Now - _ct.Value).TotalSeconds / 2.0)); |
| | | } |
| | | _ct = DateTime.Now; |
| | | } |
| | | //replyData += ",No Read,No Read"; |
| | | if (positionName.Contains("0")) |
| | | { |
| | | var isOK = pList[0].GetPositionResult(M141Config.StationCode, positionName, out P_PRODUCT_DETAIL detail); |
| | | |
| | | if (index.Contains("1")) |
| | | { |
| | | replyData = "0#,Scan1,Scan" + (isOK ? "OK" : "NG") + "1"; |
| | | } |
| | | else |
| | | { |
| | | replyData = "0#,Scan2,Scan" + (isOK ? "OK" : "NG") + "2"; |
| | | //replyData = "0#,Scan2,ScanOK2"; |
| | | } |
| | | } |
| | | |
| | | ReplyTcpData(positionName, triggerSource, replyData); |
| | | |
| | | 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; |
| | | } |
| | | else |
| | | { |
| | | var positionSet = M141Config.WorkPositionCollection.FirstOrDefault(u => u.PositionName == positionName); |
| | | |
| | | var checkRemains = _positionCheckTimeDict[positionName]; |
| | | if (checkRemains.Count != 0) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"工位{positionName}检测未完成,剩余:{string.Join(",", checkRemains)}"); |
| | | return null; |
| | | } |
| | | |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"工位{positionName}检测已完成,等待输出结果"); |
| | | |
| | | string replyData = M141Config.WorkPositionCollection.FirstOrDefault(u => u.PositionName == positionName).TriggerValue; |
| | | |
| | | var pIndices = M141Config.MeasureBindCollection.Where(u => u.WorkPosition == positionName).SelectMany(u => u.ProductIndices).Distinct().OrderBy(u => u).ToList(); |
| | | |
| | | var measureNum = M141Config.MeasureBindCollection.Count(u => u.WorkPosition == positionName && u.ProductIndices.Contains(pIndices[0])); |
| | | if (measureNum > 1) |
| | | { |
| | | replyData += ",C"; |
| | | } |
| | | |
| | | var pList = pIndices.Select(u => |
| | | { |
| | | string sequence = $"{inputSequence}_{u}"; |
| | | return FindProductBySequence(sequence, true); |
| | | }).ToList(); |
| | | |
| | | if (pList.Any(u => u == null)) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"获取工位{positionName}汇总结果时产品信息为空"); |
| | | pList.ForEach(u => |
| | | { |
| | | replyData += ",NG"; |
| | | }); |
| | | } |
| | | 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 |
| | | { |
| | | 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); |
| | | replyData += $",{(isOK ? "OK" : "NG")}"; |
| | | |
| | | List<string> specHeads = new List<string>(); |
| | | string head = p.GetCSVHead(ref specHeads, positionName); |
| | | if (!_positionSpecHeads.ContainsKey(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(); |
| | | UpdatePositionResultDisplay(detail, isOK, positionName, seqData[seqData.Count - 1]); |
| | | if (IsInspectionDoing) |
| | | { |
| | | OnSinglePostionDetectResultUpdate.Invoke(positionName, detail, seqData[seqData.Count - 1]); |
| | | } |
| | | |
| | | if (positionSet.IsLastPosition) |
| | | { |
| | | UpdateProductResultAsync(p); |
| | | UpdateOverAllProductResultToUI(p, isOK); |
| | | OnNewProductEnqueued?.Invoke(p); |
| | | OnProductDequeued?.Invoke(p); |
| | | } |
| | | |
| | | SetSpecResult(p); |
| | | }); |
| | | |
| | | if (positionSet.IsLastPosition) |
| | | { |
| | | if (_ct != null) |
| | | { |
| | | UpdateCT(null, (float)((DateTime.Now - _ct.Value).TotalSeconds / 2.0)); |
| | | } |
| | | _ct = DateTime.Now; |
| | | } |
| | | replyData += "," + pList[0]?.SN + "," + pList[1]?.SN; |
| | | |
| | | |
| | | ReplyTcpData(positionName, triggerSource, replyData); |
| | | |
| | | 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 async Task<List<ProductModel>> CheckPositionDoneAsync1(string positionName, string inputSequence, IOperationConfig config, List<string> cameraIds) |
| | | { |
| | | string triggerSource = config.TriggerSource; |
| | | return await _taskFactory.StartNew(() => |
| | | { |
| | | |
| | | var positionSet = M141Config.WorkPositionCollection.FirstOrDefault(u => u.PositionName == positionName); |
| | | |
| | | var checkRemains = _positionCheckTimeDict[positionName]; |
| | | if (checkRemains.Count != 0) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"工位{positionName}检测未完成,剩余:{string.Join(",", checkRemains)}"); |
| | | return null; |
| | | } |
| | | |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"工位{positionName}检测已完成,等待输出结果"); |
| | | |
| | | string replyData = M141Config.WorkPositionCollection.FirstOrDefault(u => u.PositionName == positionName).TriggerValue; |
| | | |
| | | var pIndices = M141Config.MeasureBindCollection.Where(u => u.WorkPosition == positionName).SelectMany(u => u.ProductIndices).Distinct().OrderBy(u => u).ToList(); |
| | | |
| | | var measureNum = M141Config.MeasureBindCollection.Count(u => u.WorkPosition == positionName && u.ProductIndices.Contains(pIndices[0])); |
| | | if (measureNum > 1) |
| | | { |
| | | replyData += ",C"; |
| | | } |
| | | |
| | | var pList = pIndices.Select(u => |
| | | { |
| | | string sequence = $"{inputSequence}_{u}"; |
| | | return FindProductBySequence(sequence, true); |
| | | }).ToList(); |
| | | |
| | | if (pList.Any(u => u == null)) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"获取工位{positionName}汇总结果时产品信息为空"); |
| | | pList.ForEach(u => |
| | | { |
| | | replyData += ",NG"; |
| | | }); |
| | | } |
| | | 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 |
| | | { |
| | | 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); |
| | | replyData += $",{(isOK ? "OK" : "NG")}"; |
| | | |
| | | List<string> specHeads = new List<string>(); |
| | | string head = p.GetCSVHead(ref specHeads, positionName); |
| | | if (!_positionSpecHeads.ContainsKey(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(); |
| | | UpdatePositionResultDisplay(detail, isOK, positionName, seqData[seqData.Count - 1]); |
| | | |
| | | |
| | | if (IsInspectionDoing) |
| | | { |
| | | OnSinglePostionDetectResultUpdate.Invoke(positionName, detail, seqData[seqData.Count - 1]); |
| | | } |
| | | |
| | | |
| | | if (positionSet.IsLastPosition) |
| | | { |
| | | UpdateProductResultAsync(p); |
| | | UpdateOverAllProductResultToUI(p, isOK); |
| | | OnNewProductEnqueued?.Invoke(p); |
| | | OnProductDequeued?.Invoke(p); |
| | | } |
| | | |
| | | SetSpecResult(p); |
| | | }); |
| | | |
| | | if (positionSet.IsLastPosition) |
| | | { |
| | | if (_ct != null) |
| | | { |
| | | UpdateCT(null, (float)((DateTime.Now - _ct.Value).TotalSeconds / 2.0)); |
| | | } |
| | | _ct = DateTime.Now; |
| | | } |
| | | replyData += "," + pList[0].SN + "," + pList[1].SN; |
| | | if (!positionName.Contains("0")) |
| | | { |
| | | ReplyTcpData(positionName, triggerSource, replyData); |
| | | } |
| | | else |
| | | { |
| | | //replyData += "," + pList[0].SN=="NOREAD" + "," + pList[1]?.SN; |
| | | |
| | | |
| | | //replyData = "0#,2,"+ ((pList[0].SN == "NOREAD" || pList[1]?.SN=="NOREAD")? "NG":"OK") +","+ pList[0].SN+ ","+ pList[1].SN; |
| | | replyData = "0#,2,OK," + pList[0].SN + "," + pList[1].SN; |
| | | |
| | | ReplyTcpData(positionName, triggerSource, replyData); |
| | | } |
| | | |
| | | |
| | | 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; |
| | | |
| | | }); |
| | | } |
| | | |
| | | |
| | | public async Task<List<ProductModel>> CheckPositionDoneAsyncforsb(string positionName, string inputSequence, IOperationConfig config, List<string> cameraIds) |
| | | { |
| | | string triggerSource = config.TriggerSource; |
| | | return await _taskFactory.StartNew(() => |
| | | { |
| | | |
| | | var positionSet = M141Config.WorkPositionCollection.FirstOrDefault(u => u.PositionName == positionName); |
| | | |
| | | var checkRemains = _positionCheckTimeDict[positionName]; |
| | | if (checkRemains.Count != 0) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"工位{positionName}检测未完成,剩余:{string.Join(",", checkRemains)}"); |
| | | return null; |
| | | } |
| | | |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"工位{positionName}检测已完成,等待输出结果"); |
| | | |
| | | string replyData = M141Config.WorkPositionCollection.FirstOrDefault(u => u.PositionName == positionName).TriggerValue; |
| | | |
| | | var pIndices = M141Config.MeasureBindCollection.Where(u => u.WorkPosition == positionName).SelectMany(u => u.ProductIndices).Distinct().OrderBy(u => u).ToList(); |
| | | |
| | | var measureNum = M141Config.MeasureBindCollection.Count(u => u.WorkPosition == positionName && u.ProductIndices.Contains(pIndices[0])); |
| | | if (measureNum > 1) |
| | | { |
| | | replyData += ",C"; |
| | | } |
| | | |
| | | var pList = pIndices.Select(u => |
| | | { |
| | | string sequence = $"{inputSequence}_{u}"; |
| | | return FindProductBySequence(sequence, true); |
| | | }).ToList(); |
| | | |
| | | if (pList.Any(u => u == null)) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"获取工位{positionName}汇总结果时产品信息为空"); |
| | | pList.ForEach(u => |
| | | { |
| | | replyData += ",NG"; |
| | | }); |
| | | } |
| | | 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 |
| | | { |
| | | 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); |
| | | replyData += $",{(isOK ? "OK" : "NG")}"; |
| | | |
| | | List<string> specHeads = new List<string>(); |
| | | string head = p.GetCSVHead(ref specHeads, positionName); |
| | | if (!_positionSpecHeads.ContainsKey(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(); |
| | | UpdatePositionResultDisplay(detail, isOK, positionName, seqData[seqData.Count - 1]); |
| | | |
| | | var temokimage = OKNGImages.Where(u => u.pid == p.PID).ToList(); |
| | | |
| | | if (isOK) |
| | | { |
| | | if (temokimage.Any(u => u.issave)) |
| | | { |
| | | for (int i = 0; i < temokimage.Count; i++) |
| | | { |
| | | string realpath = Path.Combine(temokimage[i].path, $"{temokimage[i].name}.{temokimage[i].post}"); |
| | | temokimage[i].bitmap.Save(realpath, temokimage[i].ImageFormat); |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if (temokimage.Any(u => u.issave)) |
| | | { |
| | | var temin = temokimage.FirstOrDefault(u => u.result == "NG"); |
| | | if (temin != null) |
| | | { |
| | | for (int i = 0; i < temokimage.Count; i++) |
| | | { |
| | | string realpath = Path.Combine(temin.path, $"{temokimage[i].name}.{temokimage[i].post}"); |
| | | temokimage[i].bitmap.Save(realpath, temokimage[i].ImageFormat); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | for (int i = 0; i < temokimage.Count; i++) |
| | | { |
| | | string realpath = Path.Combine(temokimage[i].path, $"{temokimage[i].name}.{temokimage[i].post}"); |
| | | temokimage[i].bitmap.Save(realpath, temokimage[i].ImageFormat); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | //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图片已保存"); |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | if (IsInspectionDoing) |
| | | { |
| | | OnSinglePostionDetectResultUpdate.Invoke(positionName, detail, seqData[seqData.Count - 1]); |
| | | } |
| | | |
| | | |
| | | if (positionSet.IsLastPosition) |
| | | { |
| | | UpdateProductResultAsync(p); |
| | | UpdateOverAllProductResultToUI(p, isOK); |
| | | OnNewProductEnqueued?.Invoke(p); |
| | | OnProductDequeued?.Invoke(p); |
| | | } |
| | | |
| | | SetSpecResult(p); |
| | | }); |
| | | |
| | | |
| | | OKNGImages.ForEach(x => |
| | | { |
| | | x.bitmap.Dispose(); |
| | | }); |
| | | OKNGImages.Clear(); |
| | | |
| | | |
| | | if (positionSet.IsLastPosition) |
| | | { |
| | | if (_ct != null) |
| | | { |
| | | UpdateCT(null, (float)((DateTime.Now - _ct.Value).TotalSeconds / 2.0)); |
| | | } |
| | | _ct = DateTime.Now; |
| | | } |
| | | replyData += "," + pList[0].SN + "," + pList[1].SN; |
| | | if (!positionName.Contains("0")) |
| | | { |
| | | ReplyTcpData(positionName, triggerSource, replyData); |
| | | } |
| | | else |
| | | { |
| | | //replyData += "," + pList[0].SN=="NOREAD" + "," + pList[1]?.SN; |
| | | |
| | | |
| | | //replyData = "0#,2,"+ ((pList[0].SN == "NOREAD" || pList[1]?.SN=="NOREAD")? "NG":"OK") +","+ pList[0].SN+ ","+ pList[1].SN; |
| | | replyData = "0#,2,OK," + pList[0].SN + "," + pList[1].SN; |
| | | |
| | | ReplyTcpData(positionName, triggerSource, replyData); |
| | | } |
| | | |
| | | |
| | | 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; |
| | | |
| | | }); |
| | | } |
| | | |
| | | private async void UpdatePositionResultDisplay(P_PRODUCT_DETAIL detail, bool isOK, string positionName, string productSequence) |
| | | { |
| | | await Task.Run(() => |
| | | { |
| | | if (detail == null) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Warning, $"无法显示检测明细信息"); |
| | | return; |
| | | } |
| | | |
| | | List<IShapeElement> eleList = new List<IShapeElement>(); |
| | | |
| | | TextDisplay txt = new TextDisplay(); |
| | | txt.LineLimit = 30; |
| | | eleList.Add(txt); |
| | | |
| | | txt.StartX = txt.StartY = 0; |
| | | |
| | | txt.AddText($"{detail.SN} {(isOK ? "OK" : "NG")}", isOK ? Color.Lime : Color.White, isOK ? Color.Transparent : Color.Red); |
| | | |
| | | txt.AddText(" ", Color.Transparent, Color.Transparent); |
| | | |
| | | var ngSpecCode = new List<string>(); |
| | | |
| | | detail.SpecList.ToList().ForEach(s => |
| | | { |
| | | GetIndicatorFromSpec(s, eleList, txt, ngSpecCode); |
| | | |
| | | }); |
| | | |
| | | detail.ResultList.ToList().SelectMany(u => u.Specs).ToList().ForEach(s => |
| | | { |
| | | GetIndicatorFromSpec(s, eleList, txt, ngSpecCode); |
| | | }); |
| | | |
| | | var defects = new List<string>(detail.DefectList); |
| | | defects.AddRange(detail.ResultList.GetDefectDescList()); |
| | | |
| | | defects = defects.Except(ngSpecCode).Distinct().ToList(); |
| | | defects.ForEach(u => |
| | | { |
| | | txt.AddText(u, Color.Red, Color.Transparent); |
| | | |
| | | var indicator = M141Config.DefectIndicatorCollection.FirstOrDefault(d => d.DefectName == u); |
| | | if (indicator != null) |
| | | { |
| | | var cloneIndicator = indicator.Clone() as DefectRectangleIndicator; |
| | | eleList.Add(cloneIndicator); |
| | | } |
| | | }); |
| | | |
| | | OnPositionResultUpdated?.Invoke(positionName, productSequence, eleList); |
| | | |
| | | //LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{detail.PID} 序号{productSequence} 工位{positionName}显示信息{JsonConvert.SerializeObject(detail)}"); |
| | | }); |
| | | } |
| | | |
| | | private void GetIndicatorFromSpec(ISpec s, List<IShapeElement> eleList, TextDisplay txt, List<string> ngSpecCode) |
| | | { |
| | | txt.AddText($"{s.Code} {s.GetMeasureValueStr()}", s.MeasureResult == true ? Color.Lime : Color.Red, Color.Transparent); |
| | | |
| | | var indicator = M141Config.DefectIndicatorCollection.FirstOrDefault(u => u.DefectName == s.Code); |
| | | if (indicator != null) |
| | | { |
| | | var cloneIndicator = indicator.Clone() as DefectRectangleIndicator; |
| | | cloneIndicator.DefectName += $"{s.Code} {s.GetMeasureValueStr()}"; |
| | | cloneIndicator.IsOK = s.MeasureResult == true; |
| | | |
| | | eleList.Add(cloneIndicator); |
| | | } |
| | | |
| | | if (s.MeasureResult != true) |
| | | { |
| | | ngSpecCode.Add(s.Code); |
| | | } |
| | | } |
| | | |
| | | private async void UpdateOverAllProductResultToUI(ProductModel product, bool isOK) |
| | | { |
| | | await Task.Run(() => |
| | | { |
| | | List<IShapeElement> eleList = new List<IShapeElement>(); |
| | | |
| | | TextDisplay txt = new TextDisplay(); |
| | | txt.LineLimit = 30; |
| | | eleList.Add(txt); |
| | | |
| | | txt.StartX = txt.StartY = 0; |
| | | |
| | | txt.AddText($"{product.SN} {product.Result}", isOK ? Color.Lime : Color.White, isOK ? Color.Transparent : Color.Red); |
| | | |
| | | txt.AddText(" ", Color.Transparent, Color.Transparent); |
| | | |
| | | var ngSpecCode = new List<string>(); |
| | | |
| | | product.Details.ForEach(d => |
| | | { |
| | | d.SpecList.ForEach(s => |
| | | { |
| | | GetIndicatorFromSpec(s, eleList, txt, ngSpecCode); |
| | | }); |
| | | |
| | | d.ResultList.SelectMany(u => u.Specs).ToList().ForEach(s => |
| | | { |
| | | GetIndicatorFromSpec(s, eleList, txt, ngSpecCode); |
| | | }); |
| | | |
| | | var defects = new List<string>(d.DefectList); |
| | | defects.AddRange(d.ResultList.GetDefectDescList()); |
| | | |
| | | defects = defects.Except(ngSpecCode).Distinct().ToList(); |
| | | defects.ForEach(u => |
| | | { |
| | | txt.AddText(u, Color.Red, Color.Transparent); |
| | | |
| | | var indicator = M141Config.DefectIndicatorCollection.FirstOrDefault(d => d.DefectName == u); |
| | | if (indicator != null) |
| | | { |
| | | var cloneIndicator = indicator.Clone() as DefectRectangleIndicator; |
| | | eleList.Add(cloneIndicator); |
| | | } |
| | | }); |
| | | }); |
| | | |
| | | OnPositionResultUpdated?.Invoke("", product.SEQUENCE.Split("_")[product.SEQUENCE.Split("_").Count() - 1], eleList); |
| | | }); |
| | | } |
| | | |
| | | public virtual int UploadProductDataToMES(List<ProductModel> pList) |
| | | { |
| | | List<int> isUploadOK = new List<int>(); |
| | | pList.ForEach(p => |
| | | { |
| | | var pData = GetProductUploadMESData(p, p.Result); |
| | | |
| | | ResponseMessage response = UploadDataToMES(new OperationConfigBase() { TriggerStr = pData }, null, null); |
| | | |
| | | if (response.Result == -1) |
| | | { |
| | | //先上传一次,如果失败再试2次 |
| | | for (int i = 0; i < 2; i++) |
| | | { |
| | | Thread.Sleep(500); |
| | | response = UploadDataToMES(new OperationConfigBase() { TriggerStr = pData }, null, null); |
| | | if (response.Result != -1) |
| | | { |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | if (p.SN.Replace(" ", "").ToLower().Contains("noread") && response.Result == 1000) |
| | | { |
| | | isUploadOK.Add(3); |
| | | } |
| | | else |
| | | { |
| | | isUploadOK.Add(response.Result); |
| | | } |
| | | }); |
| | | if (isUploadOK.All(u => u == 1000)) |
| | | { |
| | | return 0; |
| | | } |
| | | else if (isUploadOK.Contains(1)) |
| | | { |
| | | return 1; |
| | | } |
| | | else if (isUploadOK.Contains(4)) |
| | | { |
| | | return 4; |
| | | } |
| | | else if (isUploadOK.Contains(-1)) |
| | | { |
| | | return 2; |
| | | } |
| | | else if (isUploadOK.Contains(3)) |
| | | { |
| | | return 3; |
| | | } |
| | | return 2; |
| | | } |
| | | |
| | | volatile int uploadId = 0; |
| | | private string GetProductUploadMESData(ProductModel p, string pResult) |
| | | { |
| | | JObject jObj = new JObject(); |
| | | Interlocked.Increment(ref uploadId); |
| | | //jObj.Add($"id", uploadId); |
| | | //jObj.Add($"Createor", Config.StationCode ?? "2966AOI3"); |
| | | //jObj.Add($"CreateTime", p.CREATE_TIME.Value.ToString("yyyy-MM-dd HH:mm:ss")); |
| | | //jObj.Add($"Project", M141Config.MESProjectCode); |
| | | //jObj.Add($"MachineNumber", M141Config.MESMachineNum); |
| | | //jObj.Add($"DateTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); |
| | | //jObj.Add($"Cycle", ((p.EndTime ?? DateTime.Now) - p.CREATE_TIME.Value).TotalSeconds.ToString("f2")); |
| | | //jObj.Add($"SN", p.SN); |
| | | //jObj.Add($"Result", pResult == "OK" ? "OK" : "NG"); |
| | | |
| | | |
| | | //jObj.Add($"id", uploadId); |
| | | //jObj.Add($"Createor", Config.StationCode ?? "2966AOI3"); |
| | | jObj.Add($"CreateTime", p.CREATE_TIME.Value.ToString("yyyy-MM-dd HH:mm:ss")); |
| | | jObj.Add($"SN", p.SN); |
| | | jObj.Add($"Project", M141Config.MESProjectCode); |
| | | jObj.Add($"MachineNumber", M141Config.MESMachineNum); |
| | | jObj.Add($"DateTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); |
| | | |
| | | List<string> ngitem = new List<string>(); |
| | | foreach (var v in p.Details) |
| | | { |
| | | ngitem.AddRange(v.ResultList.GetDefectDescList()); |
| | | ngitem.AddRange(v.DefectList); |
| | | } |
| | | ngitem = ngitem.Distinct().ToList(); |
| | | |
| | | |
| | | //LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"MES 产品NG项汇总:{string.Join(",", ngitem)}"); |
| | | //LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"MES :{JsonConvert.SerializeObject(p)}"); |
| | | |
| | | |
| | | List<string> ngitemD = ngitem.Where(u => u.ToUpper().Contains("FAI")).ToList(); |
| | | |
| | | List<string> ngitemC = ngitem.Where(u => !u.ToUpper().Contains("FAI")).ToList(); |
| | | |
| | | jObj.Add($"Result_Dimension", ngitemD.Count == 0 ? "OK" : "NG"); |
| | | jObj.Add($"Dimension_NGItems", string.Join(",", ngitemD)); |
| | | //jObj.Add("NGItems", string.Join(",", defectList)); |
| | | jObj.Add($"Result_Cosmetic", ngitemC.Count == 0 ? "OK" : "NG"); |
| | | jObj.Add($"Cosmetic_NGItems", string.Join(",", ngitemC)); |
| | | |
| | | jObj.Add($"CycleTime", ((p.EndTime ?? DateTime.Now) - p.CREATE_TIME.Value).TotalSeconds.ToString("f2")); |
| | | |
| | | var specList = p.Details.SelectMany(u => u.ResultList.SelectMany(r => r.Specs)).ToList(); |
| | | p.Details.SelectMany(u => u.SpecList).ToList().ForEach(s => |
| | | { |
| | | if (!specList.Any(u => u.Code == s.Code)) |
| | | { |
| | | specList.Add(s); |
| | | } |
| | | }); |
| | | |
| | | List<string> temmescode = new List<string>(); |
| | | specList.ForEach(s => |
| | | { |
| | | var mapping = M141Config.MESCodeMappingCollection.FirstOrDefault(u => u.SpcCode == s.Code); |
| | | if (mapping != null) |
| | | { |
| | | if (!temmescode.Contains(mapping.MESCode)) |
| | | { |
| | | temmescode.Add(mapping.MESCode); |
| | | jObj.Add(mapping.MESCode, s.GetMeasureValueStr(4)); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if (!temmescode.Contains(s.Code)) |
| | | { |
| | | temmescode.Add(s.Code); |
| | | jObj.Add(s.Code, s.GetMeasureValueStr(4)); |
| | | } |
| | | } |
| | | }); |
| | | |
| | | var defectList = p.Details.SelectMany(u => u.ResultList).ToList().GetDefectDescList(); |
| | | defectList.AddRange(p.Details.SelectMany(u => u.DefectList)); |
| | | |
| | | defectList = defectList.Except(specList.Select(u => u.Code)).Distinct().ToList(); |
| | | //jObj.Add("NGItems", string.Join(",", defectList)); |
| | | |
| | | return JsonConvert.SerializeObject(jObj); |
| | | } |
| | | |
| | | protected void ReplyTcpData(string positionName, string triggerSource, string replyData) |
| | | { |
| | | if (!string.IsNullOrWhiteSpace(triggerSource)) |
| | | { |
| | | var sourceData = triggerSource.Split(':'); |
| | | string ip = ""; |
| | | int port = 0; |
| | | if (sourceData.Length >= 2) |
| | | { |
| | | ip = sourceData[0]; |
| | | port = int.Parse(sourceData[1]); |
| | | } |
| | | |
| | | string error = ""; |
| | | if (!(TcpListener?.WriteAndRead(replyData, out error, out _, false, ip, port) ?? false)) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"工位{positionName}检测结果反馈异常,{error}"); |
| | | } |
| | | else |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"工位{positionName}检测结果反馈完成,{replyData}"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | public void NewProductIntoList(ProductModel p, bool isSaveDB) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | if (isSaveDB) |
| | | { |
| | | var isNewDone = _manager_P_Product.NewProduct(p, p.Details, out string msg); |
| | | if (!isNewDone) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"产品{p.PID}数据库新增异常,{msg}"); |
| | | } |
| | | } |
| | | //if (isSaveDB) |
| | | //{ |
| | | // var isNewDone = _manager_P_Product.NewProduct(p, p.Details, out string msg); |
| | | // if (!isNewDone) |
| | | // { |
| | | // LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"产品{p.PID}数据库新增异常,{msg}"); |
| | | // } |
| | | //} |
| | | |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"{p.PID}_{p.SEQUENCE}产品入列完成"); |
| | | } |
| | |
| | | } |
| | | else |
| | | { |
| | | var pDB = _manager_P_Product.QueryProductBySequence(sequence); |
| | | if (pDB != null) |
| | | { |
| | | p = new ProductModel(pDB); |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"从数据库获取产品对象{pDB.PID},序号{pDB.SEQUENCE},条码{pDB.SN}"); |
| | | } |
| | | //var pDB = _manager_P_Product.QueryProductBySequence(sequence); |
| | | //if (pDB != null) |
| | | //{ |
| | | // p = new ProductModel(pDB); |
| | | // LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"从数据库获取产品对象{pDB.PID},序号{pDB.SEQUENCE},条码{pDB.SN}"); |
| | | //} |
| | | |
| | | if (p == null) |
| | | { |
| | |
| | | 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, $"未能从数据库获取产品对象,使用临时新建产品对象"); |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Warning, $"未能获取产品对象,使用临时新建产品对象"); |
| | | } |
| | | |
| | | NewProductIntoList(p, false); |
| | |
| | | |
| | | return p; |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | public async Task RunImageCheckAsync(List<ProductModel> products, string triggerText, string triggerSource, IImageSet imgSet, MeasureBind measureBind) |
| | | { |
| | |
| | | }); |
| | | } |
| | | |
| | | |
| | | public async Task RunImageCheckAsyncForSB(List<ProductModel> products, string triggerText, string triggerSource, IImageSet imgSet, MeasureBind measureBind) |
| | | { |
| | | await Task.Run(() => |
| | | { |
| | | List<DetectResult> resultList = new List<DetectResult>(); |
| | | if (products == null || products.Count == 0) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"工位{measureBind.WorkPosition}检测时产品信息为空"); |
| | | imgSet.HImage?.Dispose(); |
| | | imgSet.HImage = null; |
| | | return; |
| | | } |
| | | |
| | | try |
| | | { |
| | | List<string> 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<string> pidList2 = new List<string>();//pidList.Select(u => u.Split('_')[u.Split('_').Length - 1]).ToList(); |
| | | //Dictionary<string, string> dicpid = new Dictionary<string, string>(); |
| | | |
| | | //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<DetectResult> detectResults = ML?.RunMLDetectionSync(imgSet, pidList, measureBind.DetectionId); |
| | | List<DetectResult> ngResults = new List<DetectResult>(); |
| | | |
| | | |
| | | //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<ISpec>() { errorSpec }, PID = u.Key }; |
| | | 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<DetectResult>() |
| | | { |
| | | new DetectResult() |
| | | { |
| | | Specs = new List<ISpec>() |
| | | { |
| | | 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 (!products[0].SEQUENCE.ToLower().Contains("test")) |
| | | { |
| | | SaveZipPreparation(string.Join("_", products.Select(u => $"{u.PID}_{u.SN}")) + $"-{measureBind.ImageIndex}_{DateTime.Now.ToString("HHmmssfff")}", imgSet, measureBind.WorkPosition); |
| | | } |
| | | |
| | | //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图片已保存"); |
| | | |
| | | OKNGImages.Add(new OKNGImage() |
| | | { |
| | | pid = products[0].PID, |
| | | name = id, |
| | | path = folder, |
| | | post = post, |
| | | result = "NG", |
| | | bitmap = imgSet.HImage.ConvertHImageToBitmap(), |
| | | ImageFormat = M141Config.ImageFormatNG, |
| | | issave = measureBind.NGImageSwitch |
| | | }); |
| | | |
| | | |
| | | |
| | | } |
| | | //} |
| | | } |
| | | else |
| | | { |
| | | if (!products[0].SEQUENCE.ToLower().Contains("test")) |
| | | { |
| | | SaveZipPreparation(string.Join("_", products.Select(u => $"{u.PID}_{u.SN}")) + $"-{measureBind.ImageIndex}_{DateTime.Now.ToString("HHmmssfff")}", imgSet, measureBind.WorkPosition); |
| | | } |
| | | //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图片已保存"); |
| | | OKNGImages.Add(new OKNGImage() |
| | | { |
| | | pid = products[0].PID, |
| | | name = id, |
| | | path = folder, |
| | | post = post, |
| | | result = "OK", |
| | | bitmap = imgSet.HImage.ConvertHImageToBitmap(), |
| | | ImageFormat = M141Config.ImageFormatOK, |
| | | issave = measureBind.OKImageSwitch |
| | | }); |
| | | } |
| | | //} |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"{measureBind.WorkPosition},产品{string.Join(",", products.Select(u => u.PID))}的NG图片保存异常,{ex.GetExceptionMessage()}"); |
| | | } |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"图片{imgSet.PID}开始释放"); |
| | | imgSet.HImage?.Dispose(); |
| | | imgSet.HImage = null; |
| | | imgSet.Dispose(); |
| | | imgSet = null; |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"图片已释放"); |
| | | |
| | | } |
| | | }); |
| | | } |
| | | |
| | | private void RunCustomizedMethod(List<ProductModel> products, string triggerText, string triggerSource, IImageSet imgSet, string methodId, List<DetectResult> resultList) |
| | | { |
| | | try |
| | |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"自定义检测过程异常,{ex.GetExceptionMessage()}"); |
| | | } |
| | | } |
| | | |
| | | private void SetSpecResult(ProductModel productModel) |
| | | { |
| | | // 更新既有的检测记录内容 |
| | | var existProduct = ProductSpecResultList.FirstOrDefault(x => x.PID == productModel.PID); |
| | | if (existProduct != null) |
| | | { |
| | | existProduct.Details = productModel.Details; |
| | | return; |
| | | } |
| | | |
| | | // 新增检测产品记录 |
| | | ProductSpecResultList.Insert(0, productModel); |
| | | while (ProductSpecResultList.Count > M141Config.MaxProductListAmount) |
| | | { |
| | | ProductSpecResultList.RemoveAt(ProductSpecResultList.Count - 1); |
| | | } |
| | | } |
| | | |
| | | |
| | | [ProcessMethod("", "HeartBeat", "心跳", InvokeType.TestInvoke)] |
| | | public ResponseMessage HeartBeat(IOperationConfig config, IDevice invokeDevice, IDevice sourceDevice) |
| | | { |
| | | ResponseMessage msg = new ResponseMessage(); |
| | | msg.IsReply = true; |
| | | msg.DataStr = M141Config.Heartstr; |
| | | |
| | | if (M141Config.PointState) |
| | | { |
| | | if (!CheckInspectionInPeriodic(3000)) |
| | | { |
| | | msg.IsReply = false; |
| | | } |
| | | } |
| | | |
| | | //DateTime now = DateTime.Now; |
| | | //DateTime today8am = new DateTime(now.Year, now.Month, now.Day, 8, 0, 0); |
| | | //DateTime today20am = new DateTime(now.Year, now.Month, now.Day, 20, 0, 0); |
| | | |
| | | |
| | | //InitialOEEStatistic() |
| | | |
| | | return msg; |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | public void SaveZip(string pid, string result) |
| | | { |
| | | try |
| | | { |
| | | if (M141Config.SaveStateZip) |
| | | { |
| | | lock (ZipImages) |
| | | { |
| | | var zipimagespid = ZipImages.Where(u => u.name.Contains(pid)).ToList(); |
| | | if (zipimagespid != null) |
| | | { |
| | | for (int i = 0; i < zipimagespid.Count; i++) |
| | | { |
| | | string ngImageFile = Path.Combine(zipimagespid[i].path, $"{zipimagespid[i].name}_{result}.{zipimagespid[i].post}"); |
| | | var bitmap = zipimagespid[i].image.ConvertHImageToBitmap(); |
| | | bitmap.Save(ngImageFile, M141Config.ImageFormatZip); |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{zipimagespid[i].name}压缩图片已保存"); |
| | | zipimagespid[i].image.Dispose(); |
| | | zipimagespid[i].image = null; |
| | | bitmap.Dispose(); |
| | | } |
| | | ZipImages.RemoveAll(u => u.name.Contains(pid)); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"压缩图片保存异常{e.ToString()}"); |
| | | } |
| | | } |
| | | |
| | | |
| | | #region plc |
| | | public ResponseMessage RunImageCheck_plc(IOperationConfig config, int plcnum) |
| | | { |
| | |
| | | return msg; |
| | | } |
| | | |
| | | |
| | | public void RunImageCheckPreTreat_plc(IOperationConfig config, out List<MeasureBind> measureBinds, out string inputSequence) |
| | | { |
| | | Task.Run(() => |
| | |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"相机{camera.Name}检测前清理缓存完成"); |
| | | } |
| | | }); |
| | | |
| | | if (positionSet.IsSendClearSingal) |
| | | { |
| | | var sourceData = config.TriggerSource.Split(':'); |
| | | string ip = ""; |
| | | int port = 0; |
| | | if (sourceData.Length >= 2) |
| | | { |
| | | ip = sourceData[0]; |
| | | port = int.Parse(sourceData[1]); |
| | | } |
| | | |
| | | TcpListener?.WriteAndRead(positionSet.ClearStr, out _, out _, false, ip, port); |
| | | } |
| | | |
| | | inputSequence = triggerDatas[triggerDatas.Length - 1]; |
| | | |
| | |
| | | }); |
| | | } |
| | | |
| | | |
| | | public virtual void ReplyPlcData(List<bool> result, int plcnum) |
| | | { |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | #endregion |
| | | |
| | | |
| | | |
| | | public void wirtePLC(int add, int value) |
| | |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |