| | |
| | | using Bro.Device.InsCamera; |
| | | using Bro.M135.Common; |
| | | using Bro.M135.DBManager; |
| | | using Bro.M141.Process.UI; |
| | | using Bro.Process; |
| | | using Bro.Process.DataBase.Models; |
| | | using Bro.UI.Model.Winform; |
| | | using HalconDotNet; |
| | | using MySql.Data.MySqlClient; |
| | | using Newtonsoft.Json; |
| | | using Newtonsoft.Json.Linq; |
| | | using NPOI.SS.Formula.Function; |
| | | 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; |
| | | using System.Collections.Concurrent; |
| | | using System.Collections.Generic; |
| | | using System.Diagnostics; |
| | | using System.Drawing.Imaging; |
| | | using System.Drawing.Printing; |
| | | using System.IO; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using Windows.ApplicationModel.Appointments; |
| | | using Windows.Devices.PointOfService; |
| | | using ZXing; |
| | | using ZXing.QrCode; |
| | | using static Bro.Common.Helper.EnumHelper; |
| | | using static Bro.Process.ProcessControl; |
| | | 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; |
| | | |
| | | TcpListenerWrap _realTimeServer = null; |
| | | //volatile int _productIndex = 0; |
| | | |
| | | volatile int _productIndex = 0; |
| | | public M141Process_Mysql mysqlhelper = new M141Process_Mysql(); |
| | | |
| | | int _backgroundImageWidth = 2448; |
| | | public event Action RerefreshBasketcodeUI; |
| | | |
| | | M141Process_Mysql mysqlhelper = new M141Process_Mysql(); |
| | | public Action<bool, string> OnContinuousNGAlarmRaised; |
| | | |
| | | public void RerefreshBasketcode() |
| | | { |
| | | RerefreshBasketcodeUI?.Invoke(); |
| | | } |
| | | |
| | | |
| | | |
| | |
| | | { |
| | | base.InitialProcessMethods(); |
| | | |
| | | |
| | | if (ThHeartPlc == null) |
| | | { |
| | | ThHeartPlc = new Thread(Heartplc); |
| | | ThHeartPlc.IsBackground = true; |
| | | ThHeartPlc.Start(); |
| | | } |
| | | |
| | | printDocument1.PrintPage += new PrintPageEventHandler(printDocument_Print); |
| | | } |
| | | |
| | | public override void ProcessRunStateChanged() |
| | |
| | | public PLCBase Plc1; |
| | | bool devicestate = false; |
| | | PLCBase Plc2; |
| | | public PLCBase Plc3; |
| | | public Thread ThHeartPlc; |
| | | |
| | | public RabbitMQHelper mqtt; |
| | | |
| | | |
| | | |
| | | public override void Open() |
| | | { |
| | | base.Open(); |
| | | |
| | | devicestate = true; |
| | | ML = DeviceCollection.FirstOrDefault(u => u is MachineLearningBase) as MachineLearningBase; |
| | | if (ML == null) |
| | |
| | | } |
| | | _errorSpec = M141Config.SpecCollection.FirstOrDefault(u => u.Code == M141Config.CheckErrorSpecCode) as Spec; |
| | | |
| | | |
| | | |
| | | //InitialProductList(); |
| | | |
| | | NetWarmUp(); |
| | |
| | | _positionSpecHeads.Clear(); |
| | | |
| | | mysqlhelper.IniDBIP(M141Config.IPforall); |
| | | RerefreshBasketcode(); |
| | | |
| | | |
| | | if (M141Config.ISupMES) |
| | | { |
| | | mqtt = new RabbitMQHelper(M141Config.zIP, M141Config.zport, M141Config.zuser, M141Config.zpassword); |
| | | mqtt.Connect(M141Config.MESchannel); |
| | | } |
| | | else |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, $"已关闭上传mes"); |
| | | } |
| | | |
| | | InitialContinuousNGAlarm(); |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | } |
| | | |
| | | |
| | | public void Heartplc() |
| | | { |
| | | Thread.Sleep(1000); |
| | | |
| | | //Open(); |
| | | |
| | | string _statisticFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Statistic.json"); |
| | | if (File.Exists(_statisticFilePath)) |
| | | { |
| | |
| | | |
| | | |
| | | Dictionary<string, List<int>> StateDIC = new Dictionary<string, List<int>>(); |
| | | List<string> AlarmTypeList = new List<string>(); |
| | | |
| | | |
| | | int numplc = 0; |
| | | while (true) |
| | | { |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | lock (StatisticRecordsFull) |
| | | if (numsum > 20) |
| | | { |
| | | 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(); |
| | | } |
| | | } |
| | | numsum = 0; |
| | | StatisticRecordsFull.SaveSummaryRecord(); |
| | | } |
| | | //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) |
| | | { |
| | |
| | | } |
| | | |
| | | var alrams = item1.AlarmDetails; |
| | | |
| | | var plcdev = DeviceCollection.FirstOrDefault(u => u.Id == item1.plcname) as PLCBase; |
| | | |
| | | if (!StateDIC.ContainsKey(plcdev.Name)) |
| | | { |
| | | StateDIC[plcdev.Name] = new List<int>(); |
| | | } |
| | | |
| | | |
| | | foreach (var item in alrams.GroupBy(u => u.address)) |
| | | { |
| | | int add = item.Key; |
| | | |
| | | var readres = plcdev.Read(add, 1, out _)[0]; |
| | | |
| | | var Allbin = Convert.ToString(readres, 2).PadLeft(16, '0').Select(c => c - '0').ToArray(); |
| | |
| | | foreach (var item2 in item) |
| | | { |
| | | item2.value = Allbin[item2.address2]; |
| | | |
| | | if (!AlarmTypeList.Contains(item2.alarmtype)) |
| | | { |
| | | |
| | | AlarmTypeList.Add(item2.alarmtype); |
| | | |
| | | |
| | | } |
| | | } |
| | | } |
| | | |
| | | string StateDICKey = ""; |
| | | |
| | | foreach (var item in AlarmTypeList) |
| | | { |
| | | |
| | | StateDICKey = plcdev.Name +"_"+ item; |
| | | |
| | | if (!StateDIC.ContainsKey(StateDICKey)) |
| | | { |
| | | |
| | | StateDIC[StateDICKey] = new List<int>(); |
| | | |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | List<int> list = new List<int>(); |
| | | |
| | | Dictionary<string, AlarmTypeData> AlarmType = new Dictionary<string, AlarmTypeData>(); |
| | | |
| | | foreach (var item in alrams) |
| | | { |
| | | csvhead += $",{item.alarmname}"; |
| | | csvdata += $",{(item.value == 1 ? "1" : "")}"; |
| | | list.Add(item.value); |
| | | } |
| | | string key = item.alarmtype; |
| | | |
| | | if (!StateDIC[plcdev.Name].SequenceEqual(list)) |
| | | if (!AlarmType.TryGetValue(key, out var alarmData)) |
| | | { |
| | | // 不存在,创建新的 |
| | | alarmData = new AlarmTypeData() |
| | | { |
| | | CSVhead = csvhead, |
| | | CSVdata = csvdata, |
| | | }; |
| | | AlarmType.Add(item.alarmtype, alarmData); |
| | | |
| | | } |
| | | |
| | | alarmData.CSVhead += $",{item.alarmname}"; |
| | | alarmData.CSVdata += $",{(item.value == 1 ? "1" : "")}"; |
| | | alarmData.AlarmTypeValue.Add(item.value); |
| | | |
| | | } |
| | | foreach(var item in AlarmType.Keys) |
| | | { |
| | | StateDIC[plcdev.Name].Clear(); |
| | | StateDIC[plcdev.Name].AddRange(list); |
| | | |
| | | CSVRecordAsync($"PLCstate_{plcdev.Name}.csv", csvdata, csvhead); |
| | | list = AlarmType[item].AlarmTypeValue; |
| | | |
| | | var showdata = alrams.Where(u => u.value == 1).Select(u => u.alarmname).ToList(); |
| | | string key = plcdev.Name+"_"+item; |
| | | |
| | | if (showdata == null) |
| | | if (!StateDIC[key].SequenceEqual(list)) |
| | | { |
| | | showdata = new List<string>(); |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Detail, $"{plcdev.Name}报警类型:{item}的信号发生变化,保存的数据为{AlarmType[item].CSVdata}"); |
| | | |
| | | StateDIC[key].Clear(); |
| | | |
| | | StateDIC[key].AddRange(list); |
| | | |
| | | CSVRecordAsync($"PLCstate_{DateTime.Now.ToString("yyyyMMdd")}_{key}.csv", AlarmType[item].CSVdata, AlarmType[item].CSVhead); |
| | | |
| | | var showdata = alrams.Where(u => u.value == 1).Select(u => u.alarmname).ToList(); |
| | | |
| | | if (showdata == null) |
| | | { |
| | | showdata = new List<string>(); |
| | | } |
| | | |
| | | if (showdata.Count > 0) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"{plcdev.Name}报警 个数:{showdata.Count} {string.Join(',', showdata)}"); |
| | | } |
| | | else |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Detail, $"{plcdev.Name}报警 个数:0"); |
| | | } |
| | | } |
| | | |
| | | if (showdata.Count > 0) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"{plcdev.Name}报警 个数:{showdata.Count} {string.Join(',', showdata)}"); |
| | | } |
| | | else |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Detail, $"{plcdev.Name}报警 个数:0"); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch |
| | | catch(Exception EXC) |
| | | { |
| | | |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"PLC报警存储记录发生异常 {EXC.ToString()}"); |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | } |
| | | |
| | | try |
| | | { |
| | | if (Plc1 != null) |
| | | { |
| | | DateTime dt = DateTime.Now; |
| | | Plc1.WriteSingleAddress(10, dt.Year, out _); |
| | | Plc1.WriteSingleAddress(11, dt.Month, out _); |
| | | Plc1.WriteSingleAddress(12, dt.Day, out _); |
| | | Plc1.WriteSingleAddress(13, dt.Hour, out _); |
| | | Plc1.WriteSingleAddress(14, dt.Minute, out _); |
| | | Plc1.WriteSingleAddress(15, dt.Second, out _); |
| | | Plc1.WriteSingleAddress(16, (int)dt.DayOfWeek, out _); |
| | | } |
| | | } |
| | | catch |
| | | { |
| | | |
| | | } |
| | | |
| | | Thread.Sleep(1000); |
| | | } |
| | | } |
| | | |
| | | public class AlarmTypeData |
| | | { |
| | | public List <int> AlarmTypeValue = new List<int>(); |
| | | |
| | | public string CSVhead; |
| | | |
| | | public string CSVdata; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | /// <summary> |
| | | /// 网络预热 |
| | |
| | | Dictionary<string, List<string>> _positionSpecHeads = new Dictionary<string, List<string>>(); |
| | | |
| | | |
| | | |
| | | |
| | | volatile int uploadId = 0; |
| | | |
| | | |
| | |
| | | throw new Exception($"产品{string.Join(",", pidList)}检测{measureBind.GetDisplayText()}未能获取图片对象"); |
| | | } |
| | | |
| | | RunCustomizedMethod(products, triggerText, triggerSource, imgSet, measureBind.CustomizedMonitorId, resultList); |
| | | RunCustomizedMethod(products, triggerText, triggerSource, imgSet, measureBind.CustomizedCombineMethodId, resultList); |
| | | |
| | | //检测顺序 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, false, null, null, "", products[0].ImagePaths); |
| | | |
| | | |
| | | List<DetectResult> detectResults = ML?.RunMLDetectionSync(imgSet, pidList, measureBind.DetectionId); |
| | | |
| | | if (measureBind.WorkPosition == "P1" && M141Config.StationCode == "S5" && detectResults.GetDefectDescList().Count == 0) |
| | | { |
| | | var defecttem1 = detectResults.SelectMany(u => u.AllNetResults).SelectMany(m => m.DetectDetails).Select(detail => detail.ClassName).ToList(); |
| | | |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Detail, $"{products[0].SN} S3S5检测 缺陷名称集合为{string.Join(",", defecttem1)}"); |
| | | |
| | | var defecttem = detectResults.SelectMany(u => u.AllNetResults.SelectMany(m => m.DetectDetails)).Where(u => u.ClassName == M141Config.defectname).ToList(); |
| | | |
| | | List<Netdefectdetail> Netdefectdetails = mysqlhelper.GetNetdefectdetails(products[0].SEQUENCE); |
| | | |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Detail, $"{products[0].SN} S3S5检测 S3数据{Netdefectdetails.Count} S5数据{defecttem.Count}"); |
| | | |
| | | Netdefectdetails.ForEach(x => |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Detail, $"{products[0].SN} S3S5检测 S3数据{x.name} {x.centerX},{x.centerY} "); |
| | | }); |
| | | |
| | | int num = 0; |
| | | foreach (var item1 in defecttem) |
| | | { |
| | | double x1 = item1.Rect.Point_LU.X + item1.Rect.Width / 2.0; |
| | | double y1 = item1.Rect.Point_LU.Y + item1.Rect.Height / 2.0; |
| | | num++; |
| | | |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Detail, $"{products[0].SN} S3S5检测 原坐标{num} {x1},{y1}"); |
| | | HOperatorSet.ProjectiveTransPixel(new HTuple(products[0].Centermatrix.ToArray()), y1, x1, out HTuple qx, out HTuple qy); |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Detail, $"{products[0].SN} S3S5检测 新坐标{num} {qx},{qy}"); |
| | | |
| | | |
| | | Netdefectdetail temc = new Netdefectdetail() |
| | | { |
| | | centerX = qx, |
| | | centerY = qy, |
| | | name = M141Config.defectname, |
| | | }; |
| | | if (Netdefectdetails.Any(u => u == temc)) |
| | | { |
| | | item1.IsAbandoned = false; |
| | | item1.FinalResult = ResultState.NG; |
| | | |
| | | //products[0].Result = M141Config.defectname; |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"产品{products[0].PID}_{products[0].SEQUENCE}工位{measureBind.WorkPosition} S3S5组合检测检出缺陷:{item1.NetName},产品结果为{products[0].Result}"); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | 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)) |
| | |
| | | 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) |
| | | { |
| | |
| | | } |
| | | |
| | | 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(); |
| | | //var bitmap = imgSet.HImage.ConvertHImageToBitmap(); |
| | | //bitmap.Save(ngImageFile, M141Config.ImageFormatNG); |
| | | //LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{id}NG图片已保存"); |
| | | //bitmap.Dispose(); |
| | | try |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{id}NG图片测试转存{ngImageFile}"); |
| | | imgSet.HImage.WriteImage(M141Config.ImageFormatOK.ToString().ToLower(), 0, ngImageFile); |
| | | } |
| | | catch (Exception) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"{id}NG图片保存失败"); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | 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(); |
| | | //var bitmap = imgSet.HImage.ConvertHImageToBitmap(); |
| | | //bitmap.Save(ngImageFile, M141Config.ImageFormatOK); |
| | | //LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{id}OK图片已保存"); |
| | | //bitmap.Dispose(); |
| | | try |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{id}OK图片测试转存{ngImageFile}"); |
| | | imgSet.HImage.WriteImage(M141Config.ImageFormatOK.ToString().ToLower(), 0, ngImageFile); |
| | | } |
| | | catch (Exception) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"{id}OK图片保存失败"); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | }); |
| | | } |
| | | |
| | | |
| | | public async Task RunImageCheckAsync(List<ProductModel> products, string triggerText, string triggerSource, MeasureBind measureBind) |
| | | { |
| | | await Task.Run(() => |
| | |
| | | { |
| | | products.ForEach(p => |
| | | { |
| | | var pResults = resultList.Where(u => u.PID == p.PID).ToList(); |
| | | var pResults = resultList.ToList(); |
| | | p.AddNewDetectResults(M141Config.StationCode, measureBind.WorkPosition, pResults); |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"产品{p.PID}_{p.SEQUENCE}添加工位{measureBind.WorkPosition}检测结果,数量{pResults.Count}"); |
| | | }); |
| | |
| | | } |
| | | }); |
| | | } |
| | | |
| | | |
| | | private void RunCustomizedMethod(List<ProductModel> products, string triggerText, string triggerSource, IImageSet imgSet, string methodId, List<DetectResult> resultList) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | #region plc |
| | | public ResponseMessage RunImageCheck_plc(IOperationConfig config) |
| | | { |
| | | |
| | | ResponseMessage msg = new ResponseMessage(); |
| | | msg.Result = 1; |
| | | List<MeasureBind> measureBinds = new List<MeasureBind>(); |
| | |
| | | } |
| | | |
| | | CheckPositionDoneAsync_plc(measureBinds[0].WorkPosition, inputSequence, config, cameraIds); |
| | | |
| | | return msg; |
| | | |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | }); |
| | | |
| | | |
| | | |
| | | inputSequence = triggerDatas[triggerDatas.Length - 1]; |
| | | |
| | | string tempSequence = inputSequence; |
| | |
| | | if (M141Config.Isreadbasketcode) |
| | | { |
| | | p.BasketCode = M141Config.basketcode; |
| | | p.Zword = M141Config.zwoid; |
| | | } |
| | | else |
| | | { |
| | | p.BasketCode = mysqlhelper.Getbasketcode(p.SEQUENCE, out string sntem); |
| | | p.BasketCode = mysqlhelper.Getbasketcode(p.SEQUENCE, out string sntem, out string zword); |
| | | p.Zword = zword; |
| | | p.SN = sntem; |
| | | p.PID = $"{sntem}_{i}"; |
| | | if ("NoRead".Equals(p.BasketCode)) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"{p.PID}_{p.SEQUENCE}获取框具码失败 赋值Noread"); |
| | |
| | | |
| | | //初始化产品的检测次数 |
| | | 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.InitialPositionCheckList(b.WorkPosition, checkIndexList, M141Config.StationCode); |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{p.PID}_{p.SEQUENCE}已清理{b.WorkPosition}检测数据。当前已完成工位{string.Join(",", p.Details.Select(u => u.PositionName))}"); |
| | | |
| | | }); |
| | | |
| | | //初始化工位的检测次数 |
| | |
| | | |
| | | public async Task<List<ProductModel>> CheckPositionDoneAsync_plc(string positionName, string inputSequence, IOperationConfig config, List<string> cameraIds) |
| | | { |
| | | |
| | | string triggerSource = config.TriggerSource; |
| | | return await _taskFactory.StartNew(() => |
| | | { |
| | |
| | | |
| | | //UpdatePositionResultToDB(detail); |
| | | //var seqData = p.SEQUENCE.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries).ToList(); |
| | | ReplyPlcData(positionSet, plcresult); |
| | | |
| | | if (M141Config.StationCode == "S4" && isOK) |
| | | { |
| | | ////mysqlhelper.GetS2Result(productList[0].SEQUENCE); |
| | | //Plc1.WriteSingleAddress(1526, mysqlhelper.GetS2Result(productList[0].SEQUENCE) ? 1 : 2, out _); |
| | | |
| | | bool temS2 = mysqlhelper.GetS2Result(p.SEQUENCE); |
| | | ReplyPlcData(positionSet, new List<bool>() { temS2 }); |
| | | if (!temS2) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"{p.SN} S2工站NG抛料"); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | ReplyPlcData(positionSet, plcresult); |
| | | } |
| | | |
| | | |
| | | |
| | | mysqlhelper.UpdateProduct(p); |
| | | |
| | | |
| | | |
| | | if (positionSet.IsLastPosition) |
| | | { |
| | | UpdateProductResultAsync(p); |
| | | mysqlhelper.NewForAll(p, M141Config.StationCode); |
| | | //班次统计时间划分 |
| | | if (M141Config.WorkShiftList.Count == 0) |
| | | { |
| | | //生成一个报表 |
| | | string name = $"ProductRecord_{DateTime.Now.ToString("yyyyMMdd")}.csv"; |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"创建{name}数据报表"); |
| | | UpdateProductResultAsync(p, name); |
| | | } |
| | | else |
| | | { |
| | | foreach (var item in M141Config.WorkShiftList) |
| | | { |
| | | DateTime now = DateTime.Now; |
| | | |
| | | if (item.ShiftTime_Start < item.ShiftTime_End) |
| | | { |
| | | if (now.TimeOfDay >= item.ShiftTime_Start.TimeOfDay && now.TimeOfDay < item.ShiftTime_End.TimeOfDay) |
| | | { |
| | | //生成一个报表 |
| | | string name = $"ProductRecord_{DateTime.Now.ToString("yyyyMMdd")}_{item.ShiftName}.csv"; |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"创建{name}数据报表"); |
| | | UpdateProductResultAsync(p, name); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if (now.TimeOfDay >= item.ShiftTime_Start.TimeOfDay) |
| | | { |
| | | //生成一个报表 |
| | | string name = $"ProductRecord_{DateTime.Now.ToString("yyyyMMdd")}_{item.ShiftName}.csv"; |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"创建{name}数据报表"); |
| | | UpdateProductResultAsync(p, name); |
| | | } |
| | | if (now.TimeOfDay < item.ShiftTime_End.TimeOfDay) |
| | | { |
| | | // 生成一个报表 |
| | | string name = $"ProductRecord_{DateTime.Now.AddDays(-1).ToString("yyyyMMdd")}_{item.ShiftName}.csv"; |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"创建{name}数据报表"); |
| | | UpdateProductResultAsync(p, name); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | //UpdateProductResultAsync(p); |
| | | mysqlhelper.NewForAll(p, M141Config.StationCode, M141Config.defectname); |
| | | |
| | | 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 => |
| | | { |
| | |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"相机{camera.Name}清理缓存"); |
| | | } |
| | | }); |
| | | |
| | | //ReplyPlcData(positionSet, plcresult); |
| | | if (positionSet.IsLastPosition) |
| | | { |
| | | if (_ct != null) |
| | | { |
| | | UpdateCT(null, (float)((DateTime.Now - _ct.Value).TotalSeconds)); |
| | | } |
| | | _ct = DateTime.Now; |
| | | |
| | | if (M141Config.ISupMES && (M141Config.MESchannel == -1 || M141Config.MESchannel == 1)) |
| | | { |
| | | if (M141Config.numpro >= 50) |
| | | { |
| | | M141Config.numpro = 0; |
| | | } |
| | | |
| | | string Msgreceice = null; |
| | | |
| | | if (pList[0].Result == "OK") |
| | | { |
| | | //M141Config.numpro++; |
| | | //Msgreceice = Task.Run(() => mqtt.MESForProduceAsync(pList[0], M141Config.mesnum2.ToString(), M141Config.numpro)).Result; |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{pList[0].PID}汇总OK暂时不上传"); |
| | | } |
| | | else |
| | | { |
| | | if (M141Config.ISupNG) |
| | | { |
| | | Msgreceice = Task.Run(() => mqtt.MESForProduceAsync(pList[0], M141Config.mesnum2.ToString(), M141Config.numpro)).Result; |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{pList[0].PID}启动NG上传"); |
| | | |
| | | } |
| | | else |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{pList[0].PID}关闭NG上传"); |
| | | } |
| | | } |
| | | M141Config.mesnum2++; |
| | | if (Msgreceice == null && !M141Config.ISupNG) |
| | | { |
| | | if (!M141Config.ISupNG) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{pList[0].PID}数据NG,开启关闭NG上传MES"); |
| | | } |
| | | else |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"产品{pList[0].PID}数据上传MES异常 返回数据为null"); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | try |
| | | { |
| | | var obj = JsonConvert.DeserializeObject<AutoLineMacBarcodeQueueBak>(Msgreceice); |
| | | |
| | | if (obj.zstatus == "200") |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{pList[0].PID}数据上传MES成功 {Msgreceice}"); |
| | | |
| | | if (M141Config.Isprint && !string.IsNullOrEmpty(obj.tary_label)) |
| | | { |
| | | StartPrint(obj.tary_label, "Honeywell PX240S(300 dpi)"); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"产品{pList[0].PID}数据上传MES失败 {Msgreceice}"); |
| | | } |
| | | } |
| | | catch |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"产品{pList[0].PID}数据上传MES异常 {Msgreceice}"); |
| | | } |
| | | } |
| | | |
| | | int numplca = Convert.ToInt32(pList[0].SEQUENCE.Split('_')[0]); |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"plc给出的产品序号为{numplca}"); |
| | | |
| | | lock (plcnumlock)//1-29999 |
| | | { |
| | | |
| | | if (PlcNumForAll == -1) |
| | | { |
| | | PlcNumForAll = numplca; |
| | | } |
| | | |
| | | int differ = numplca - PlcNumForAll; |
| | | |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"两个产品中间的差值differ为{differ}"); |
| | | |
| | | if (differ > 1) |
| | | { |
| | | for (int i = PlcNumForAll + 1; i < numplca; i++) |
| | | { |
| | | try |
| | | { |
| | | var plist = mysqlhelper.GetProductList(i + "_1"); |
| | | ProductModel newp = new ProductModel(); |
| | | newp.SEQUENCE = plist[0].SEQUENCE; |
| | | newp.PID = plist[0].PID; |
| | | newp.BasketCode = plist[0].BasketCode; |
| | | newp.Zword = plist[0].Zword; |
| | | newp.Result = "NG"; |
| | | newp.SN = plist[0].SN; |
| | | |
| | | if (M141Config.IsfinDevice) |
| | | { |
| | | SummaryAllprodata(newp); |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{newp.PID}提前NG加入汇总数据报表统计"); |
| | | } |
| | | if (M141Config.ISupNG) |
| | | { |
| | | var tems = Task.Run(() => mqtt.MESForProduceAsync(newp, M141Config.mesnum2.ToString(), M141Config.numpro)).Result; |
| | | M141Config.mesnum2++; |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{newp.PID}启动NG上传"); |
| | | } |
| | | else |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{newp.PID}关闭NG上传"); |
| | | } |
| | | |
| | | } |
| | | catch |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{i + "_1"}上传失败"); |
| | | } |
| | | } |
| | | } |
| | | else if (differ == -29998 && differ == 1 && differ == 0) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"生产过程中未失去产品"); |
| | | } |
| | | else if (differ < 0 && differ > -29998) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"PlcNumForAll为{PlcNumForAll},numplca为{numplca}"); |
| | | //产品从新计数时 |
| | | for (int i = PlcNumForAll + 1; i <= 29999; i++) |
| | | { |
| | | try |
| | | { |
| | | var plist = mysqlhelper.GetProductList(i + "_1"); |
| | | ProductModel newp = new ProductModel(); |
| | | newp.SEQUENCE = plist[0].SEQUENCE; |
| | | newp.PID = plist[0].PID; |
| | | newp.Zword = plist[0].Zword; |
| | | newp.BasketCode = plist[0].BasketCode; |
| | | newp.Result = "NG"; |
| | | newp.SN = plist[0].SN; |
| | | if (M141Config.IsfinDevice) |
| | | { |
| | | SummaryAllprodata(newp); |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{newp.PID}提前NG加入汇总数据报表统计"); |
| | | } |
| | | if (M141Config.ISupNG) |
| | | { |
| | | var tems = Task.Run(() => mqtt.MESForProduceAsync(newp, M141Config.mesnum2.ToString(), M141Config.numpro)).Result; |
| | | M141Config.mesnum2++; |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{newp.PID}启动NG上传"); |
| | | } |
| | | else |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{newp.PID}关闭NG上传"); |
| | | } |
| | | |
| | | } |
| | | catch |
| | | { |
| | | |
| | | } |
| | | } |
| | | for (int i = 1; i < numplca; i++) |
| | | { |
| | | try |
| | | { |
| | | var plist = mysqlhelper.GetProductList(i + "_1"); |
| | | ProductModel newp = new ProductModel(); |
| | | newp.SEQUENCE = plist[0].SEQUENCE; |
| | | newp.PID = plist[0].PID; |
| | | newp.BasketCode = plist[0].BasketCode; |
| | | newp.Zword = plist[0].Zword; |
| | | newp.Result = "NG"; |
| | | newp.SN = plist[0].SN; |
| | | if (M141Config.IsfinDevice) |
| | | { |
| | | SummaryAllprodata(newp); |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{newp.PID}提前NG加入汇总数据报表统计"); |
| | | } |
| | | if (M141Config.ISupNG) |
| | | { |
| | | var tems = Task.Run(() => mqtt.MESForProduceAsync(newp, M141Config.mesnum2.ToString(), M141Config.numpro)).Result; |
| | | M141Config.mesnum2++; |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{newp.PID}启动NG上传"); |
| | | } |
| | | else |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{newp.PID}关闭NG上传"); |
| | | } |
| | | |
| | | //var tems = Task.Run(() => mqtt.MESForProduceAsync(newp, M141Config.mesnum2.ToString(), M141Config.numpro)).Result; |
| | | //M141Config.mesnum2++; |
| | | //LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"numplca,前站NG排料且plc触发清零产品{newp.PID}数据上传,结果为{newp.Result}"); |
| | | } |
| | | catch |
| | | { |
| | | } |
| | | } |
| | | } |
| | | PlcNumForAll = numplca; |
| | | } |
| | | |
| | | } |
| | | else |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, $"已关闭mes连接或者数据上传接口"); |
| | | } |
| | | } |
| | | |
| | | //ReplyPlcData(positionName, config.TriggerValue); |
| | | |
| | | return pList; |
| | | |
| | |
| | | |
| | | public void SummaryAllprodata(ProductModel p) |
| | | { |
| | | |
| | | _taskFactory.StartNew(() => |
| | | { |
| | | try |
| | |
| | | newp.SEQUENCE = p.SEQUENCE; |
| | | newp.PID = p.PID; |
| | | newp.BasketCode = p.BasketCode; |
| | | newp.Zword = p.Zword; |
| | | newp.Result = p.Result; |
| | | newp.SN = p.SN; |
| | | |
| | | Thread.Sleep(500); |
| | | var plist = mysqlhelper.GetProductList(p.SEQUENCE); |
| | | |
| | | |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Detail, $"产品{p.PID}检测结果为{p.Result}从数据库中获取的数据为产品{plist[0].PID}检测结果为{plist[0].Result}"); |
| | | if (plist != null) |
| | | { |
| | | foreach (var item in plist) |
| | |
| | | } |
| | | } |
| | | |
| | | //LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"AllDeviceProductRecord从数据库获取到数据{p.SEQUENCE} plist数量{plist.Count} Details数量{newp.Details.Count}"); |
| | | |
| | | //newp.Details.AddRange(p.Details); |
| | | |
| | | List<string> specHeadListforall = new List<string>(); |
| | | List<string> positionListforall = new List<string>(); |
| | | string csvHeadforall = newp.GetCSVHead(ref specHeadListforall, ref positionListforall); |
| | | CSVRecordAsync($"AllDeviceProductRecord.csv", newp.GetCSVData(specHeadListforall, positionListforall), csvHeadforall); |
| | | string csvDataforall = newp.GetCSVData(specHeadListforall, positionListforall); |
| | | |
| | | string data = ""; |
| | | |
| | | string Head = "时间,PID,栏具码,物料码,条码,汇总检测结果,S2_P1检测明细,S2_P2检测明细,S2_P3检测明细,S3_P1检测明细,S3_P2检测明细,S4_P1检测明细,S4_P2检测明细,S5_P1检测明细,S5_P2检测明细,S5_P3检测明细,Barcode,SPC_A,SPC_BF_A1,SPC_BF_A2,SPC_BF_A3,SPC_BF_A4,SPC_BF_A5,SPC_BF_A6,SPC_BF_A7,SPC_BF_A8,SPC_BF_A9,SPC_BS_A1,SPC_BS_A2,SPC_BS_A3,SPC_BS_A4,SPC_BS_A5,SPC_BS_A6,SPC_BS_A7,SPC_BS_A8,SPC_BS_A9,SPC_BT_A100RES,SPC_BT_A101RES,SPC_BT_A102RES,SPC_BT_A103RES,SPC_BT_A104RES,SPC_BT_A105RES,SPC_BT_A106RES,SPC_BT_A107RES,SPC_BT_A108RES,SPC_BT_A109RES,SPC_BT_A10RES,SPC_BT_A110RES,SPC_BT_A111RES,SPC_BT_A112RES,SPC_BT_A113RES,SPC_BT_A11RES,SPC_BT_A12RES,SPC_BT_A13RES,SPC_BT_A14RES,SPC_BT_A15RES,SPC_BT_A16RES,SPC_BT_A17RES,SPC_BT_A18RES,SPC_BT_A19RES,SPC_BT_A1RES,SPC_BT_A20RES,SPC_BT_A21RES,SPC_BT_A22RES,SPC_BT_A23RES,SPC_BT_A24RES,SPC_BT_A25RES,SPC_BT_A26RES,SPC_BT_A27RES,SPC_BT_A28RES,SPC_BT_A29RES,SPC_BT_A2RES,SPC_BT_A30RES,SPC_BT_A31RES,SPC_BT_A32RES,SPC_BT_A33RES,SPC_BT_A34RES,SPC_BT_A35RES,SPC_BT_A36RES,SPC_BT_A37RES,SPC_BT_A38RES,SPC_BT_A39RES,SPC_BT_A3RES,SPC_BT_A40RES,SPC_BT_A41RES,SPC_BT_A42RES,SPC_BT_A43RES,SPC_BT_A44RES,SPC_BT_A45RES,SPC_BT_A46RES,SPC_BT_A47RES,SPC_BT_A48RES,SPC_BT_A49RES,SPC_BT_A4RES,SPC_BT_A50RES,SPC_BT_A51RES,SPC_BT_A52RES,SPC_BT_A53RES,SPC_BT_A54RES,SPC_BT_A55RES,SPC_BT_A56RES,SPC_BT_A57RES,SPC_BT_A58RES,SPC_BT_A59RES,SPC_BT_A5RES,SPC_BT_A60RES,SPC_BT_A61RES,SPC_BT_A62RES,SPC_BT_A63RES,SPC_BT_A64RES,SPC_BT_A65RES,SPC_BT_A66RES,SPC_BT_A67RES,SPC_BT_A68RES,SPC_BT_A69RES,SPC_BT_A6RES,SPC_BT_A70RES,SPC_BT_A71RES,SPC_BT_A72RES,SPC_BT_A73RES,SPC_BT_A74RES,SPC_BT_A75RES,SPC_BT_A76RES,SPC_BT_A77RES,SPC_BT_A78RES,SPC_BT_A79RES,SPC_BT_A7RES,SPC_BT_A80RES,SPC_BT_A81RES,SPC_BT_A82RES,SPC_BT_A83RES,SPC_BT_A84RES,SPC_BT_A85RES,SPC_BT_A86RES,SPC_BT_A87RES,SPC_BT_A88RES,SPC_BT_A89RES,SPC_BT_A8RES,SPC_BT_A90RES,SPC_BT_A91RES,SPC_BT_A92RES,SPC_BT_A93RES,SPC_BT_A94RES,SPC_BT_A95RES,SPC_BT_A96RES,SPC_BT_A97RES,SPC_BT_A98RES,SPC_BT_A99RES,SPC_BT_A9RES,SPC_C"; |
| | | |
| | | for (int i = 0; i < Head.Split(",").ToList().Count(); i++) |
| | | { |
| | | int index = csvHeadforall.Split(",").ToList().IndexOf(Head.Split(",").ToList()[i]); |
| | | if (index != -1) |
| | | { |
| | | data += $"{string.Join(" ", csvDataforall.Split(",").ToList()[index])},"; |
| | | } |
| | | else |
| | | { |
| | | data += "NA,"; |
| | | } |
| | | } |
| | | CSVRecordAsync($"AllDeviceProductRecord_{DateTime.Now.ToString("yyyyMMdd")}.csv", data, Head); |
| | | |
| | | } |
| | | catch (Exception exx) |
| | |
| | | |
| | | |
| | | #endregion |
| | | |
| | | List<DefectNGRecord> DefectNGRecordList = new List<DefectNGRecord>(); |
| | | |
| | | public void InitialContinuousNGAlarm() |
| | | { |
| | | DefectNGRecordList = M141Config.ContinuousNGAlarmColletion.Where(u => u.IsEnabled).Select(u => |
| | | { |
| | | DefectNGRecord record = new DefectNGRecord(); |
| | | record.DefectName = u.DefectType; |
| | | record.AlarmSetting = u; |
| | | return record; |
| | | }).ToList(); |
| | | OnContinuousNGAlarmRaised = NGAlarmRaised; |
| | | if (M141Config.ContinuousNGAlarmAddress > 0 && Plc1 != null) |
| | | { |
| | | if (!Plc1.WriteSingleAddress(M141Config.ContinuousNGAlarmAddress, 0, out string error)) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"连续NG监控通知PLC重置报警失败,{error}"); |
| | | } |
| | | } |
| | | } |
| | | public async void CheckContinuousNGAlarmAsync(ProductModel product) |
| | | { |
| | | await Task.Run(() => |
| | | { |
| | | if (!M141Config.IsEnableContinuousNGAlarm) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"连续NG报警总开关已关闭"); |
| | | return; |
| | | } |
| | | |
| | | if (DefectNGRecordList.Count == 0) |
| | | return; |
| | | |
| | | string allMsg = ""; |
| | | bool isAlarmRaised = false; |
| | | int alarmType = 0; |
| | | string ngItem = ""; |
| | | try |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"连续NG数据记录"); |
| | | DefectNGRecordList.ForEach(d => |
| | | { |
| | | string alarmMsg = ""; |
| | | int alarmTypeTemp = 0; |
| | | |
| | | if (product.Result == "OK") |
| | | { |
| | | if (d.CheckIsAlarmRaised(product.Result == "OK", out alarmMsg, out alarmTypeTemp)) |
| | | { |
| | | allMsg += $"{alarmMsg}\r\n"; |
| | | |
| | | isAlarmRaised = true; |
| | | ngItem = "产品结果"; |
| | | alarmType = alarmTypeTemp; |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{product.PID}数据结果为{product.Result}参与连续NG统计"); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if (product.Result.Contains(d.DefectName)) |
| | | { |
| | | if (d.CheckIsAlarmRaised(!product.Result.Contains(d.DefectName), out alarmMsg, out alarmTypeTemp)) |
| | | { |
| | | allMsg += $"{alarmMsg}\r\n"; |
| | | isAlarmRaised = true; |
| | | ngItem = "产品结果"; |
| | | alarmType = alarmTypeTemp; |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{product.PID}数据结果为{product.Result}参与连续NG统计"); |
| | | } |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Warning, $"连续NG数据记录失败"); |
| | | } |
| | | if (isAlarmRaised) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Warning, $"连续NG监控报警,{allMsg}"); |
| | | if (M141Config.IsOperatorReset) |
| | | { |
| | | if (M141Config.ContinuousNGAlarmAddress > 0 && Plc1 != null) |
| | | { |
| | | if (!Plc1.WriteSingleAddress(M141Config.ContinuousNGAlarmAddress, 1, out string error)) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"连续NG监控通知PLC重置报警失败,{error}"); |
| | | } |
| | | } |
| | | OnContinuousNGAlarmRaised?.Invoke(true, allMsg); |
| | | } |
| | | else |
| | | { |
| | | Task.Delay(50).Wait(); |
| | | ResetContinuousNGAlarm(); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | object _continuousNGAlarmLock = new object(); |
| | | |
| | | FrmContinuousNGAlarm _continuousNGAlarmFrm = null; |
| | | private async void NGAlarmRaised(bool isRaiseAlarm, string alarmMsg) |
| | | { |
| | | await Task.Run(() => |
| | | { |
| | | if (isRaiseAlarm) |
| | | { |
| | | if (_continuousNGAlarmFrm == null) |
| | | { |
| | | lock (_continuousNGAlarmLock) |
| | | { |
| | | if (_continuousNGAlarmFrm == null) |
| | | { |
| | | _continuousNGAlarmFrm = new FrmContinuousNGAlarm(); |
| | | |
| | | _continuousNGAlarmFrm.TopMost = true; |
| | | |
| | | _continuousNGAlarmFrm.FormClosed += _continuousNGAlarmFrm_FormClosed; |
| | | |
| | | Task.Run(() => |
| | | { |
| | | _continuousNGAlarmFrm.ShowDialog(); |
| | | |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | Task.Delay(100).Wait(); |
| | | _continuousNGAlarmFrm.ShowAlarmMsg(alarmMsg); |
| | | } |
| | | else |
| | | { |
| | | if (_continuousNGAlarmFrm != null) |
| | | { |
| | | _continuousNGAlarmFrm.Close(); |
| | | } |
| | | |
| | | } |
| | | }); |
| | | |
| | | } |
| | | |
| | | private void _continuousNGAlarmFrm_FormClosed(object? sender, FormClosedEventArgs e) |
| | | { |
| | | ResetContinuousNGAlarm(); |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"连续NG报警已复位"); |
| | | _continuousNGAlarmFrm = null; |
| | | } |
| | | |
| | | public void ResetContinuousNGAlarm() |
| | | { |
| | | //连续NG复位 |
| | | DefectNGRecordList.Where(u => u.IsAlarmRaised).ToList().ForEach(u => u.ResetAlarm()); |
| | | if (M141Config.ContinuousNGAlarmAddress > 0 && Plc1 != null) |
| | | { |
| | | if (!Plc1.WriteSingleAddress(M141Config.ContinuousNGAlarmAddress, 0, out string error)) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"连续NG监控通知PLC重置报警失败,{error}"); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | [ProcessMethod("", "ContinuousNGAlarmTest", "连续NG报警测试", InvokeType.TestInvoke)] |
| | | public ResponseMessage ContinuousNGAlarmTest(IOperationConfig config, IDevice invokeDevice, IDevice sourceDevice) |
| | | { |
| | | ProductModel p = new ProductModel(); |
| | | |
| | | p.Result = config.TriggerStr; |
| | | |
| | | CheckContinuousNGAlarmAsync(p); |
| | | |
| | | return new ResponseMessage(); |
| | | } |
| | | |
| | | |
| | | #region 打印机相关 |
| | | PrintDocument printDocument1 = new PrintDocument(); |
| | | string Printmessage = ""; |
| | | |
| | | public void StartPrint(string str, string PrinterName) |
| | | { |
| | | try |
| | | { |
| | | int ttwith = 240; |
| | | int ttheigh = 80; |
| | | Printmessage = str; |
| | | |
| | | this.printDocument1.DefaultPageSettings.PrinterSettings.PrinterName = "Honeywell PX240S (300 dpi)"; |
| | | this.printDocument1.DefaultPageSettings.PaperSize = new PaperSize("Custum", ttwith, ttheigh); |
| | | |
| | | this.printDocument1.PrintController = new System.Drawing.Printing.StandardPrintController(); |
| | | this.printDocument1.Print(); |
| | | |
| | | } |
| | | catch |
| | | { |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | //C229M2508250500002 |
| | | private void printDocument_Print(object sender, PrintPageEventArgs e) |
| | | { |
| | | Font fntTxt = new Font("黑体", 15, System.Drawing.FontStyle.Bold);//正文文字 |
| | | System.Drawing.Brush brush = new SolidBrush(System.Drawing.Color.Black);//画刷 |
| | | try |
| | | { |
| | | var g = e.Graphics; |
| | | g.Clear(Color.White); |
| | | BarcodeWriter writer = new BarcodeWriter(); |
| | | writer.Format = BarcodeFormat.QR_CODE; |
| | | QrCodeEncodingOptions options = new QrCodeEncodingOptions() |
| | | { |
| | | DisableECI = true,//设置内容编码 |
| | | CharacterSet = "UTF-8", //设置二维码的宽度和高度 |
| | | Width = 60, |
| | | Height = 60, |
| | | Margin = 1//设置二维码的边距,单位不是固定像素 |
| | | }; |
| | | |
| | | writer.Options = options; |
| | | Bitmap map = writer.Write(Printmessage); |
| | | e.Graphics.DrawImage(map, new System.Drawing.Point(90, 4)); |
| | | |
| | | // 在二维码下方画内容文字 |
| | | using (Font font = new Font("Arial", 10)) |
| | | using (Brush brush3 = new SolidBrush(Color.Black)) |
| | | { |
| | | // 让文字居中到二维码下方 |
| | | SizeF textSize = e.Graphics.MeasureString(Printmessage, font); |
| | | float textX = 90 + (map.Width - textSize.Width) / 2; |
| | | float textY = 1 + map.Height; |
| | | |
| | | e.Graphics.DrawString(Printmessage, font, brush3, textX, textY); |
| | | } |
| | | |
| | | } |
| | | catch (Exception ee) |
| | | { |
| | | |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, ee.ToString()); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | #endregion |
| | | |
| | | } |
| | | |
| | | public class DefectNGRecord |
| | | { |
| | | public string DefectName { get; set; } |
| | | public List<DateTime> NGRecords { get; set; } = new List<DateTime>(); |
| | | public int ContinuousNGNum { get; set; } = 0; |
| | | public ContinuousNGAlarm AlarmSetting { get; set; } |
| | | |
| | | private object _lockObj = new object(); |
| | | |
| | | public bool IsAlarmRaised = false; |
| | | |
| | | bool _isContinuousAlarm = false; |
| | | |
| | | } |
| | | bool _timeAlarm = false; |
| | | |
| | | public bool CheckIsAlarmRaised(bool isOK, out string alarmMsg, out int alarmType) |
| | | { |
| | | alarmType = 0; |
| | | alarmMsg = ""; |
| | | bool isAlarmRasied = false; |
| | | |
| | | if (IsAlarmRaised) |
| | | return false; |
| | | |
| | | lock (_lockObj) |
| | | { |
| | | if (IsAlarmRaised) |
| | | return false; |
| | | |
| | | if (isOK) |
| | | { |
| | | ContinuousNGNum = 0; |
| | | } |
| | | else |
| | | { |
| | | //连续NG数量阈值 |
| | | if (AlarmSetting.ContinuousNumThreshold > 0) |
| | | { |
| | | ContinuousNGNum++; |
| | | CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{DefectName}连续NG数量为:{ContinuousNGNum}个"); |
| | | } |
| | | //时间内NG数量阈值 |
| | | if (AlarmSetting.TimePeriodNumThresold > 0) |
| | | { |
| | | NGRecords.Add(DateTime.Now); |
| | | } |
| | | } |
| | | |
| | | if (NGRecords.Count >= AlarmSetting.TimePeriodNumThresold && NGRecords.Count > 0) |
| | | { |
| | | |
| | | NGRecords = NGRecords.Skip(NGRecords.Count - AlarmSetting.TimePeriodNumThresold).OrderBy(u => u).ToList(); |
| | | |
| | | int timeInMinute = (int)Math.Ceiling((NGRecords[NGRecords.Count - 1] - NGRecords[0]).TotalMinutes); |
| | | //监控时间段 |
| | | if (timeInMinute <= AlarmSetting.TimePeriod) |
| | | { |
| | | isAlarmRasied = true; |
| | | alarmMsg += $"{DefectName}{timeInMinute}分钟内NG{NGRecords.Count}个 "; |
| | | alarmType = AlarmSetting.TimePeriodAlarmType; |
| | | _timeAlarm = true; |
| | | } |
| | | } |
| | | |
| | | if (ContinuousNGNum >= AlarmSetting.ContinuousNumThreshold) |
| | | { |
| | | isAlarmRasied = true; |
| | | alarmMsg += $"{DefectName}连续NG{ContinuousNGNum}个 "; |
| | | alarmType = AlarmSetting.ContinuousAlarmType; |
| | | _isContinuousAlarm = true; |
| | | } |
| | | IsAlarmRaised = isAlarmRasied; |
| | | return isAlarmRasied; |
| | | } |
| | | } |
| | | |
| | | public void ResetAlarm() |
| | | { |
| | | string msg = ""; |
| | | lock (_lockObj) |
| | | { |
| | | IsAlarmRaised = false; |
| | | if (_isContinuousAlarm) |
| | | { |
| | | _isContinuousAlarm = false; |
| | | ContinuousNGNum = 0; |
| | | msg += "连续NG报警 "; |
| | | } |
| | | |
| | | if (_timeAlarm) |
| | | { |
| | | |
| | | _timeAlarm = false; |
| | | NGRecords.Clear(); |
| | | msg += "时段内NG报警 "; |
| | | } |
| | | } |
| | | CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{DefectName}{msg}已重置"); |
| | | } |
| | | |
| | | } |
| | | } |