| | |
| | | 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.Functions; |
| | |
| | | public M141Process_Mysql mysqlhelper = new M141Process_Mysql(); |
| | | |
| | | public event Action RerefreshBasketcodeUI; |
| | | |
| | | public Action<bool, string> OnContinuousNGAlarmRaised; |
| | | |
| | | public void RerefreshBasketcode() |
| | | { |
| | |
| | | mqtt.Connect(M141Config.MESchannel); |
| | | } |
| | | |
| | | |
| | | InitialContinuousNGAlarm(); |
| | | } |
| | | |
| | | |
| | | |
| | | public override void Close() |
| | | { |
| | | devicestate = false; |
| | |
| | | double y1 = item1.Rect.Point_LU.Y + item1.Rect.Height / 2.0; |
| | | num++; |
| | | |
| | | //HOperatorSet.AffineTransPoint2d(new HTuple(products[0].Centermatrix.ToArray()), x1, y1, out HTuple qx, out HTuple qy); |
| | | //HOperatorSet.ProjectiveTransPixel(new HTuple(products[0].Centermatrix.ToArray()), x1, y1, out HTuple qx, out HTuple qy); |
| | | |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Detail, $"{products[0].SN} S3S5检测 原坐标{num} {x1},{y1}"); |
| | | HOperatorSet.ProjectiveTransPixel(new HTuple(products[0].Centermatrix.ToArray()), x1, y1, out HTuple qx, out HTuple qy); |
| | | 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}"); |
| | | |
| | | |
| | |
| | | { |
| | | 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; |
| | |
| | | post = M141Config.ImageFormatOK.ToString().ToLower(); |
| | | } |
| | | |
| | | string ngImageFile = Path.Combine(folder, $"{id}.{post}"); |
| | | 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图片已保存"); |
| | |
| | | try |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{id}OK图片测试转存{ngImageFile}"); |
| | | imgSet.HImage.WriteImage(M141Config.ImageFormatOK.ToString().ToLower(), 0, ngImageFile); |
| | | imgSet.HImage.WriteImage(M141Config.ImageFormatOK.ToString().ToLower(), 0, ngImageFile); |
| | | } |
| | | catch (Exception) |
| | | { |
| | |
| | | |
| | | |
| | | mysqlhelper.UpdateProduct(p); |
| | | |
| | | |
| | | |
| | | if (positionSet.IsLastPosition) |
| | | { |
| | | UpdateProductResultAsync(p); |
| | | |
| | | |
| | | //班次统计时间划分 |
| | | 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); |
| | | |
| | | } |
| | | } |
| | | }); |
| | |
| | | |
| | | if (pList[0].Result == "OK") |
| | | { |
| | | M141Config.numpro++; |
| | | M141Config.numpro++; |
| | | Msgreceice = Task.Run(() => mqtt.MESForProduceAsync(pList[0], M141Config.mesnum2.ToString(), M141Config.numpro)).Result; |
| | | } |
| | | else |
| | |
| | | { |
| | | 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) |
| | | if (Msgreceice == null && !M141Config.ISupNG) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"产品{pList[0].PID}数据上传MES异常 返回数据为null"); |
| | | 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 |
| | | { |
| | |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{newp.PID}关闭NG上传"); |
| | | } |
| | | |
| | | |
| | | } |
| | | catch |
| | | { |
| | | |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{i + "_1"}上传失败"); |
| | | } |
| | | } |
| | | } |
| | |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"生产过程中未失去产品"); |
| | | } |
| | | else if ( differ<0 && differ>-29998) |
| | | else if (differ < 0 && differ > -29998) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"PlcNumForAll为{PlcNumForAll},numplca为{numplca}"); |
| | | //产品从新计数时 |
| | |
| | | //var tems = Task.Run(() => mqtt.MESForProduceAsync(newp, M141Config.mesnum2.ToString(), M141Config.numpro)).Result; |
| | | //M141Config.mesnum2++; |
| | | //LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"PlcNumForAll,前站NG排料且plc触发清零产品{newp.PID}数据上传,结果为{newp.Result}"); |
| | | |
| | | |
| | | } |
| | | catch |
| | | { |
| | |
| | | |
| | | //ReplyPlcData(positionName, config.TriggerValue); |
| | | |
| | | |
| | | |
| | | return pList; |
| | | |
| | | } |
| | |
| | | |
| | | public void SummaryAllprodata(ProductModel p) |
| | | { |
| | | |
| | | _taskFactory.StartNew(() => |
| | | { |
| | | try |
| | |
| | | newp.Details.AddRange(item.Details); |
| | | } |
| | | } |
| | | |
| | | //LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"AllDeviceProductRecord从数据库获取到数据{p.SEQUENCE} plist数量{plist.Count} Details数量{newp.Details.Count}"); |
| | | |
| | | //newp.Details.AddRange(p.Details); |
| | |
| | | |
| | | |
| | | #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(); |
| | | } |
| | | } |
| | | |
| | | 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}已重置"); |
| | | } |
| | | |
| | | } |
| | | } |