using Advantech.Motion; using HalconDotNet; using Microsoft.VisualBasic; using Models; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using OpenCvSharp; using ProductionControl.Device; using ProductionControl.UI; using ProductionControl.Utils; using SqlSugar; using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using static ProductionControl.Device.AxisDev; using static ProductionControl.Device.DefectLib; using static ProductionControl.Device.SizeLib; namespace ProductionControl { public partial class FrmMain : Form { WebService webService = new WebService(); private List productCodeList = new List(); private DevContainer devContainer = new DevContainer(); private Service.ProductService svcProduct = new Service.ProductService(); private Service.OrderService svcOrder = new Service.OrderService(); private bool bExitApp = false; //禁用蜂鸣器,门磁 private bool disableBuzzer, disableDoorSensor; //线宽,张力,厚度,PT private List lstTension = new List(); private List lstHeight = new List(); private List lstLineWidth = new List(); private List lstPT = new List(); private Queue scannerGBmpQueue = new Queue(); private Queue scannerCBmpQueue = new Queue(); //private int scannerCBmpIndex = 0;//scannerCBmpQueue中使用当前项的计数器 private int compBmpIndex = 0;//比对777图的索引 private int defectBmpNum = 0; private int defectBmpNumResult = 0; /// /// 比对失败的图片 /// private List lstCompareFailZoomImage = new List(); private object myLock=new object(); private WarningEnum warningLevel;//警告等级 private CurrentPTEnum currentPT;//当前点位 private CurrentStateEnum currentState;//当前状态 /// /// 当前流程ID,暂停/继续时使用 /// private int currProcessIndex = -1; private Models.Product currProductModel = null;//当前产品 private bool autoMakeTagRuning = false; private bool isProductRevise = false; //产品-厚度base校正点位索引 private int ProductPT_HeightBaseNum = 0; private Stopwatch stopWatch = new Stopwatch(); private Order order = new Order(); //--333输出变量供后面多个777使用 public HObject contoursAffineTrans1_Out; private System.Timers.Timer timer = new System.Timers.Timer(); private class scannerGBmpLoc { public scannerGBmpLoc(Mat mat, double xmm, double ymm) { bmp = mat; Xmm = xmm; Ymm = ymm; } public Mat bmp { get; private set; } public double Xmm { get; private set; } public double Ymm { get; private set; } } private class scannerCBmpLoc { public scannerCBmpLoc(string path, double posX, double posY) { Path = path; PosX=posX; PosY=posY; } public scannerCBmpLoc(Bitmap bmp, double posX, double posY) { BMP = bmp; PosX = posX; PosY = posY; } public Bitmap BMP { get; private set; } public string Path { get; private set; } public double PosX { get; private set; } public double PosY { get; private set; } } public FrmMain() { InitializeComponent(); this.dgvProcess.AutoGenerateColumns = false; this.tsbtnCloseDev.Visible = false; this.tsslLoginInfo.Text = $"操作员:{Config.loginUser.Code}({Config.loginUser.Name})"; this.tsslLoginTime.Text = $" 登录时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm")}"; //显示行号与列宽度自动调整 dgvProcess.RowHeadersVisible = true; dgvProcess.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders; dgvProcess.RowPostPaint += (sender, e) => { Utils.Util.showRowNum_onDataGrid_RowPostPaint(this.dgvProcess, sender, e); }; checkCustomerVer(); } private void checkCustomerVer() { //if(Config.CustomerVer=="A") // this.tsMenuOrderProduct.Visible = false; } private void FrmMian_Load(object sender, EventArgs e) { if (Config.loginUser.RoleInfo.Code!="admin") checkRoleRight(); loadProductCodeList(); this.statusStrip1.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.HorizontalStackWithOverflow; this.tsslLoginTime.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; this.tsslLoginInfo.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; this.tsAxisState.Text = ""; // webService.LogEvent = (warning, msg) => { AddTextEvent("HTTP服务", msg, warning); webService.LogEvent = null; }; webService.start(); //读取硬盘剩余空间 Config.CheckDisk(); } private void loadProductCodeList() { try { productCodeList = svcProduct.GetList().Select(m => m.Code).OrderBy(m=>m).ToList(); } catch(Exception ex) { AddTextEvent("启动", "加载产品料号失败:" + ex.Message,WarningEnum.High); } } private void checkRoleRight() { this.流程管理ToolStripMenuItem.Enabled = (Config.loginUser.RoleInfo.RightList.FirstOrDefault(m => m.Code == "Step") != null); this.产品管理ToolStripMenuItem.Enabled = (Config.loginUser.RoleInfo.RightList.FirstOrDefault(m => m.Code == "Product") != null); this.设备调试ToolStripMenuItem.Enabled = (Config.loginUser.RoleInfo.RightList.FirstOrDefault(m => m.Code == "Debug") != null); //this.tsMenuOrderQuery.Enabled = (Config.loginUser.RoleInfo.RightList.FirstOrDefault(m => m.Code == "Order") != null); //this.tsMenuStatistics.Enabled = (Config.loginUser.RoleInfo.RightList.FirstOrDefault(m => m.Code == "Statistics") != null); this.角色管理ToolStripMenuItem.Enabled = (Config.loginUser.RoleInfo.RightList.FirstOrDefault(m => m.Code == "Role") != null); this.用户管理ToolStripMenuItem.Enabled = (Config.loginUser.RoleInfo.RightList.FirstOrDefault(m => m.Code == "User") != null); this.tsbtnProductRevise.Enabled = (Config.loginUser.RoleInfo.RightList.FirstOrDefault(m => m.Code == "HeightBase") != null); this.tsMenuSysSetting.Enabled = (Config.loginUser.RoleInfo.RightList.FirstOrDefault(m => m.Code == "SysSetting") != null); this.tsMenuCmdSetting.Enabled = (Config.loginUser.RoleInfo.RightList.FirstOrDefault(m => m.Code == "CmdSetting") != null); this.tsMenuPTSetting.Enabled = (Config.loginUser.RoleInfo.RightList.FirstOrDefault(m => m.Code == "PTSetting") != null); } private void txtProductName_KeyPress(object sender, KeyPressEventArgs e) { //if (e.KeyChar == '\r' && devContainer.state && currentState == CurrentStateEnum.ScanBarcode)// && currentPT== CurrentPTEnum.UpPT ) //{ // runStep(); //} } /// /// 删除修复台重复sn图片 /// private void DeleteRepairImage(string sn) { List imagePath = new List { Config.Defect_SavePath, Config.Defect_Small_SavePath, Config.Defect_Compress_SavePath, Config.SizeBmp_Zoom_Image_SavePath, Config.SizeBmp_SavePath, Config.SizeBmp_Compare_SavePath }; //删除文件 //Task.Factory.StartNew(() => //{ for (int i = 0; i < imagePath.Count; i++) { string dirPath = Util.createSubDir(imagePath[i], new List { DateTime.Now.ToString("yyyyMMdd"), sn }); if (!Directory.Exists(dirPath)) { return; } string[] array = Directory.GetFiles(dirPath); foreach (string text in array) { try { API.OutputDebugString("清除文件:" + text + "..."); File.Delete(text); } catch (Exception ex) { API.OutputDebugString("Ex1:" + ex.Message); } } } //}); } //后台线程运行 /// /// 中断工序运行 /// /// private bool isBreakProcessRun() { return warningLevel != WarningEnum.Normal || currentState != CurrentStateEnum.运行中; } private void runStep() { compBmpIndex = defectBmpNum = defectBmpNumResult = 0; AddTextEvent("启动", "等待扫码枪扫码..."); if (devContainer.devCodeScanner != null) { devContainer.devCodeScanner.stop(); devContainer.devCodeScanner = null; } devContainer.devCodeScanner = new CodeScannerDev(); if (!devContainer.devCodeScanner.start()) { AddTextEvent("扫码枪", "扫码枪初始化失败!"); return; } //2023-12-06 无输入料号防呆 if(string.IsNullOrEmpty(this.txtProductCode.Text)) { AddTextEvent("料号", "未选择料号!"); return; } //2023-10-20 不使用扫码枪事件处理 //devContainer.devCodeScanner.ScanerEvent = (code) => string code = this.txtProductCode.Text; { if (!devContainer.state || currentState != CurrentStateEnum.等待扫码 || string.IsNullOrWhiteSpace(code)) return; // scannerGBmpQueue.Clear(); scannerCBmpQueue.Clear(); lstCompareFailZoomImage.Clear(); contoursAffineTrans1_Out = null; Thread threadtest = new System.Threading.Thread(() => { int errStep = 0; try { var model = svcProduct.GetModelNav(code); if (model != null && model.StepInfo.ProcessList.Count > 0) { errStep = 1; //根据产品设置动态加载外观检测模型文件 string onnxFile; if (!string.IsNullOrWhiteSpace(model.DefectModelFile)) onnxFile = $"{Application.StartupPath}\\onnxFiles\\{model.DefectModelFile}"; else onnxFile = $"{Application.StartupPath}\\onnxFiles\\default.onnx"; devContainer.libDefect.loadModelFile(onnxFile); // errStep = 2; string sn = ""; AutoResetEvent waitEvent = new AutoResetEvent(false); this.Invoke(new System.Action(() => { FrmInput frm = new FrmInput(null, "请输入网版编码:"); if (frm.ShowDialog() == DialogResult.OK && !string.IsNullOrWhiteSpace(frm.inputData)) sn = frm.inputData; waitEvent.Set(); })); errStep = 3; waitEvent.WaitOne(); if (string.IsNullOrWhiteSpace(sn)) { AddTextEvent("扫码枪", $"料号{code}未输入网版编码,流程中止!"); return; } AddTextEvent("扫码枪", $"料号:{code},网版编码:{sn}"); //是否闪退需观察 errStep = 4; devContainer.devCodeScanner.stop(); devContainer.devCodeScanner = null; errStep = 5; //删除重复sn用于修复台的图片 AddTextEvent("扫码枪", $"删除{sn}重复用于修复台的图片..."); DeleteRepairImage(sn); //判断SN数量是否达到批次上限 //创建表达式 if (!string.IsNullOrWhiteSpace(model.BatchId) && model.TargetCount > 0) { var exp1 = Expressionable.Create() .And(m => m.ProductId == model.Id) .And(m => m.BatchId == model.BatchId) .And(m => m.SN != sn) .ToExpression();//注意 这一句 不能少 errStep = 6; if (svcOrder.Count(exp1) >= model.TargetCount) { AddTextEvent("扫码枪", $"当前产品本批次检测数已达目标数量,请更换检测批次号!"); return; } errStep = 7; } // this.Invoke(new System.Action(() => { this.txtProductSN.Text = sn; })); // model.HeightBaseDec = ""; currentState = CurrentStateEnum.运行中; currentPT = CurrentPTEnum.Moving; currProductModel = model; AddTextEvent("扫码枪", $"{model.Name} {model.Spec} [{model.Code}]"); this.Invoke(new System.Action(() => { this.txtProductCode.Text = model.Code; this.txtProductName.Text = model.Name; this.dgvProcess.DataSource = new BindingSource(model.StepInfo.ProcessList, null); devContainer.libFor.clear(); devContainer.libIF.clear(); tsbtnSizeTag.Enabled = tsbtnSizeImage.Enabled = tsbtnDefectImage.Enabled = true; })); errStep = 8; // ProductPT_HeightBaseNum = 0; this.setButtonEnabled(this.tsbtnPause, true); this.setButtonEnabled(this.tsbtnStopNow, true); order = new Order(); order.Qualified = true;//默认合格,中间有一项指标不合格则改为false order.ProductId = currProductModel.Id; order.StepId = (int)currProductModel.StepId; order.SN = sn; order.BatchId = currProductModel.BatchId; errStep = 9; int nextStepId = 0; do { nextStepId = nextProcess(model, nextStepId); } while (nextStepId >= 0 && !isBreakProcessRun()); errStep = 10; } else AddTextEvent("扫码枪", model != null ? $"料号{code}不存在!" : $"产品({model.Name})未配置检测流程!"); } catch (Exception ex) { //AddTextEvent("扫码后", $"errcode({errStep}):" + ex.Message);//会有空对象引用,但不知哪里报的 //warning(WarningEnum.High); } }); threadtest.IsBackground = true; threadtest.Start(); }; } //model.Type=1 系统校正 /// /// /// /// /// 0-n /// 大于等于0正常工序; -1:结束 -2:异常 private int nextProcess(Models.Product model, int stepIndex) { try { //记录当前index this.currProcessIndex = stepIndex; this.Invoke(new System.Action(() => { try { this.dgvProcess.Rows[stepIndex].Selected = true; dgvProcess.CurrentCell = dgvProcess.Rows[stepIndex].Cells[1]; } catch { } })); lock (myLock) { if (isBreakProcessRun()) return stepIndex; } //开始计时 if(!isProductRevise && model.StepInfo.StartTimeIndex>0 && model.StepInfo.StartTimeIndex==stepIndex+1) stopWatch.Restart(); var processList = isProductRevise ? model.ReviseStepInfo.ProcessList : model.StepInfo.ProcessList; var processInfo = processList[stepIndex]; string processName = processInfo.ProcessName; //AddTextEvent($"{stepIndex + 1}-{processName}", $"工序开始..."); string jsonParams = null;//配方 if (model.ProductProcessList != null && model.ProductProcessList.Count > 0)//使用产品配方 { ProductProcess productProcessParams = model.ProductProcessList.First(m => m.ProcessCode == processInfo.ProcessCode); if (productProcessParams != null) { jsonParams = productProcessParams.ProcessParams; AddTextEvent($"{stepIndex + 1}-{processName}", $"使用产品专用配方:{jsonParams}"); } } if (jsonParams == null)//使用流程默认配方 { jsonParams = processInfo.ProcessParams; if (jsonParams == null) throw new Exception("配方为null!!"); AddTextEvent($"{stepIndex + 1}-{processName}", $"使用流程默认配方:{jsonParams}"); } // JObject processParam = JObject.Parse(jsonParams); if (!processParam.ContainsKey("Disable") || !processParam.Value("Disable")) { AutoResetEvent endEvent; uint sleepPre = processParam.Value("SleepPre"); uint sleepLater = processParam.Value("SleepLater"); if (sleepPre > 0) Thread.Sleep((int)sleepPre); double limitThresholdVal, lowerThresholdVal; //张力,厚度,Size,Defect //======Switch 工序类型 bool asynRun; string gbxBmpPath = ""; Models.Attachment attachmentFile; int liStatocStepIndex = stepIndex; switch (processInfo.ProcessCode) { case "IOCard": #region var direction = (IODirectionEnum)processParam.Value("Direction"); if (direction == IODirectionEnum.输入 || direction == IODirectionEnum.输入输出) { uint IN_Waiting_Timeout = processParam.Value("IN_Waiting_Timeout"); AddTextEvent($"{stepIndex + 1}-{processName}", $"等待I/O输入信号{(IN_Waiting_Timeout > 0 ? $"(超时时长: {IN_Waiting_Timeout})" : "...")}"); string[] inValue = processParam.Value("IN_OP_SHOW").ToObject>().ToArray(); uint inWaitingTime = 0; while (true) { if (isBreakProcessRun()) return stepIndex; if (Util.compareIOInput(inValue, devContainer.devIOCard.DIData)) break; Thread.Sleep(10); inWaitingTime += 10; if (IN_Waiting_Timeout>0 && inWaitingTime >= IN_Waiting_Timeout) { AddTextEvent($"{stepIndex + 1}-{processName}", $"输入等待超时告警!", WarningEnum.High); warning(WarningEnum.Low);//暂停 return stepIndex; } } AddTextEvent($"{stepIndex + 1}-{processName}", $"I/O输入信号对比完成!"); } if (direction == IODirectionEnum.输出 || direction == IODirectionEnum.输入输出) devContainer.io_output($"{stepIndex + 1}-{processName}", processParam); #endregion break; case "Tension": #region //limitThresholdVal = processParam.Value("LimitThresholdVal"); //lowerThresholdVal = processParam.Value("LowerThresholdVal"); //double tensionValue = 0; //int timeoutTension = 0; //do //{ // tensionValue = devContainer.devTension.getValue(); // setDgvContentCol(liStatocStepIndex, $"张力值:{tensionValue}"); // Thread.Sleep(10); // timeoutTension += 10; // if (tensionValue <= 0 && timeoutTension >= 600)//3秒超时 // { // AddTextEvent($"{stepIndex + 1}-{processName}", $"张力测量失败,确认设备是否正常!", WarningEnum.High); // warning(WarningEnum.Low);//暂停 // devContainer.io_output(CMDName.张力读取结束输出); // currProcessIndex--; // return stepIndex; // } //} while (tensionValue <= 0); //devContainer.io_output(CMDName.张力读取结束输出); //lstTension.Add(tensionValue); //updateTensionValue(model.TensionBaseValue+model.TensionUpFloatValue,model.TensionBaseValue-model.TensionDownFloatValue); //if (limitThresholdVal > 0 && tensionValue >= limitThresholdVal) //{ // AddTextEvent($"{stepIndex + 1}-{processName}", $"读取数据:{tensionValue},达到上限阀值:{limitThresholdVal},进行下料...", WarningEnum.Low); // currProcessIndex = stepIndex + 1; // warning(WarningEnum.Low);//暂停 // return stepIndex; //} //else if (lowerThresholdVal > 0 && tensionValue < lowerThresholdVal) //{ // AddTextEvent($"{stepIndex + 1}-{processName}", $"读取数据:{tensionValue},达到下限阀值:{lowerThresholdVal},进行下料...", WarningEnum.Low); // currProcessIndex = stepIndex + 1; // warning(WarningEnum.Low);//暂停 // return stepIndex; //} //AddTextEvent($"{stepIndex + 1}-{processName}", $"读取数据:{tensionValue}"); #endregion break; case "Height": #region if (Config.SkipHeight) { AddTextEvent($"{stepIndex + 1}-{processName}", $"设备禁用,忽略此步骤!"); setDgvContentCol(liStatocStepIndex, $"设备禁用,忽略此步骤!"); break; } while (!devContainer.devAxis.isReady())//因启用轴异步功能,使用前需等待 { Thread.Sleep(100); if (isBreakProcessRun()) { //currProcessIndex = stepIndex;//本工序没执行,step不变 return stepIndex; } } limitThresholdVal = processParam.Value("LimitThresholdVal"); lowerThresholdVal = processParam.Value("LowerThresholdVal"); bool IsRevise = processParam.Value("IsRevise"); double relBaseValue = processParam.Value("RelBaseValue"); //配方中相对偏移值 var heightValue = devContainer.devHeight.getHeight(); heightValue = Math.Round(heightValue, 2);//保留2位小数 File.AppendAllText(Application.StartupPath + "\\厚度测量记录.txt", heightValue+"\r\n");//TEMP if (!IsRevise && heightValue < 0) { AddTextEvent($"{stepIndex + 1}-{processName}", $"读取数据:{heightValue},异常数据,终止任务!", WarningEnum.Low); warning(WarningEnum.Low);//暂停 return stepIndex; } //厚度Base校正 if (isProductRevise) { setDgvContentCol(liStatocStepIndex, $"厚度值:{heightValue}"); model.HeightBaseDec += heightValue + ";"; AddTextEvent($"{stepIndex + 1}-{processName}", $"读取数据:{heightValue}"); } else if (IsRevise) { var reviseHeight = heightValue + relBaseValue; model.HeightBaseDec += reviseHeight + ";"; setDgvContentCol(liStatocStepIndex, $"base值:{reviseHeight} = 厚度值:{heightValue}+偏移值:{relBaseValue}"); AddTextEvent($"{stepIndex + 1}-{processName}", $"base值:{reviseHeight} = 厚度值:{heightValue}+偏移值:{relBaseValue},校正索引队列:{model.HeightBaseDec}"); } else { AddTextEvent($"{stepIndex + 1}-{processName}", $"读取数据:{heightValue},base值:{model.HeightBaseDec},偏移值:{relBaseValue},当前base索引:{ProductPT_HeightBaseNum}"); double heightDev = 0; var heightDev_BaseList=model.HeightBaseDec.Split(new char[] {';',','}); if (heightDev_BaseList.Count() > ProductPT_HeightBaseNum && heightDev_BaseList[ProductPT_HeightBaseNum].Trim() != "") heightDev = Convert.ToDouble(heightDev_BaseList[ProductPT_HeightBaseNum].Trim()); ProductPT_HeightBaseNum++; double heightValue2 =Math.Abs(heightDev - heightValue ) + relBaseValue; heightValue2 = Math.Round(heightValue2, 2); setDgvContentCol(liStatocStepIndex, $"厚度值:{heightValue2}"); lstHeight.Add(heightValue2); updateHeightValue(model.HeightBaseValue + model.HeightUpFloatValue, model.HeightBaseValue - model.HeightDownFloatValue); if (limitThresholdVal > 0 && heightValue2 >= limitThresholdVal) { AddTextEvent($"{stepIndex + 1}-{processName}", $"读取数据:{heightValue2},达到上限阀值:{limitThresholdVal},进行下料...", WarningEnum.Low); currProcessIndex = stepIndex + 1; warning(WarningEnum.Low);//终止 return stepIndex; } else if (lowerThresholdVal > 0 && heightValue2 < lowerThresholdVal) { AddTextEvent($"{stepIndex + 1}-{processName}", $"读取数据:{heightValue2},达到下限阀值:{lowerThresholdVal},进行下料...", WarningEnum.Low); currProcessIndex = stepIndex + 1; warning(WarningEnum.Low);//终止 return stepIndex; } AddTextEvent($"{stepIndex + 1}-{processName}", $"厚度值:{heightValue2} (Base值:{heightDev} - 读取数据:{heightValue} + 偏移值:{relBaseValue})"); } #endregion break; case "Axis": #region 多轴后遗留问题:暂停后再启动不知哪几个轴已执行 JObject processParamTmp = new JObject(); //兼容旧版单轴 if (!processParam.ContainsKey("0") && !processParam.ContainsKey("1") && !processParam.ContainsKey("2") && !processParam.ContainsKey("3")) { processParam.Add("Enable", true); processParamTmp.Add(processParam.Value("AxisIndex").ToString(), processParam); processParam = processParamTmp; } //- foreach (var processParamSub in processParam.Properties()) { processParam = processParamSub.Value as JObject; AddTextEvent($"{stepIndex + 1}-{processName}", processParam.ToString()); if (!processParam.ContainsKey("Disable") || !processParam.Value("Disable")) { //asynRun = processParam.Value("AsynRun");//异步 int AxisIndex = processParam.Value("AxisIndex"); int DeviceType = processParam.Value("DeviceType"); double VelLow = processParam.Value("VelLow"); double VelHigh = processParam.Value("VelHigh"); double Acc = processParam.Value("Acc"); double Dec = processParam.Value("Dec"); AxMoveMode MoveMode = (AxMoveMode)processParam.Value("MoveMode");//绝对位置 double PPUValue = processParam.Value("Value"); AddTextEvent($"{stepIndex + 1}-{processName}", $"轴{AxisIndex}准备({(MoveMode == AxMoveMode.绝对位置 ? "绝对" : "相对")})运动至{PPUValue}(当前轴状态:{((AxisState)devContainer.devAxis.AxState[AxisIndex]).ToString()})..."); //移动Axis前等待厚度传感器收回 if (!Config.SkipHeight) { while (devContainer.devHeight.getHeight() < (double)Math.Abs(Config.HeightDev_SafeValue)) { if (isBreakProcessRun()) return stepIndex; Thread.Sleep(10); } } while (!devContainer.devAxis.isReady(AxisIndex)) { Thread.Sleep(100); if (isBreakProcessRun()) return stepIndex; } devContainer.devAxis.setAxisVelParam(VelLow, VelHigh, Acc, Dec, AxisIndex); if (!devContainer.devAxis.move_ptp(AxisIndex, PPUValue, MoveMode)) { AddTextEvent($"{stepIndex + 1}-{processName}", $"轴{AxisIndex}运动失败!", WarningEnum.Low); warning(WarningEnum.Low);//终止 return stepIndex; } //多轴运行自动使用异步,全部执行后强制等待各轴完成 asynRun属性已无用 //AddTextEvent($"{stepIndex + 1}-{processName}", $"等待轴{AxisIndex}运行完成..."); //while (!asynRun && !devContainer.devAxis.isReady(AxisIndex)) //{ // Thread.Sleep(100); // if (isBreakProcessRun()) // { // currProcessIndex = stepIndex + 1; // return stepIndex; // } //} //if (devContainer.devAxis.isReady(AxisIndex)) // AddTextEvent($"{stepIndex + 1}-{processName}", $"轴{AxisIndex}运行完成,当前命令位置:{devContainer.devAxis.getCmdPos_mm(AxisIndex)},反馈位置:{devContainer.devAxis.getActualPos_mm(AxisIndex)}"); } } //多轴同时运行后强制等待各轴完成 AddTextEvent($"{stepIndex + 1}-{processName}", $"等待轴组运行完成..."); while (!devContainer.devAxis.isReady()) { Thread.Sleep(100); if (isBreakProcessRun()) { currProcessIndex = stepIndex + 1; return stepIndex; } } AddTextEvent($"{stepIndex + 1}-{processName}", $"轴组运行完成。"); #endregion break; case "AxisTag": #region //asynRun = processParam.Value("AsynRun");//异步 string axisSizeTag= processParam.Value("SizeTag"); int useIndex = processParam.Value("UseIndex");//消费posePT中的索引 AxMoveMode TagMoveMode = (AxMoveMode)processParam.Value("MoveMode");//绝对位置 var AxisIndexList = processParam.Value("AxisIndexList").ToObject>(); double TagVelLow = processParam.Value("VelLow"); double TagVelHigh = processParam.Value("VelHigh"); double TagAcc = processParam.Value("Acc"); double TagDec = processParam.Value("Dec"); var sizeTagObj = order.SizeTagDataList.LastOrDefault(m => m.SizeTag == axisSizeTag);//用最新的last if (sizeTagObj == null) { AddTextEvent($"{stepIndex + 1}-{processName}", $"偏移校正轴工序找不到数据提供者Tag:{axisSizeTag}!", WarningEnum.High); warning(WarningEnum.High); return stepIndex; } string[] posePT= sizeTagObj.posePT.Split(','); if(posePT.Length < useIndex+ AxisIndexList.Count) { AddTextEvent($"{stepIndex + 1}-{processName}", $"Tag:{axisSizeTag}对应消费索引:{useIndex},Axis数量:{AxisIndexList.Count} 超出postPT:{sizeTagObj.posePT} 范围!", WarningEnum.High); warning(WarningEnum.High); return stepIndex; } double[] TagPPUValue = new double[AxisIndexList.Count]; for (int i = 0; i < AxisIndexList.Count; i++) TagPPUValue[i] = double.Parse(posePT[useIndex + i]); string axisTagMsg = $"消费Tag:{axisSizeTag},索引:{useIndex}, 轴:{string.Join(",", AxisIndexList.ToList())},数据:{(TagMoveMode== AxMoveMode.绝对位置 ? "绝对" : "相对")}({string.Join(",", TagPPUValue.ToList())})"; AddTextEvent($"{stepIndex + 1}-{processName}", axisTagMsg); setDgvContentCol(liStatocStepIndex, axisTagMsg); //移动Axis前等待厚度传感器收回 if (!Config.SkipHeight) { while (devContainer.devHeight.getHeight() < (double)Math.Abs(Config.HeightDev_SafeValue)) { if (isBreakProcessRun()) return stepIndex; //如果是相对位置,这里返回会有问题 Thread.Sleep(10); } } for (int i = 0; i < AxisIndexList.Count && i < TagPPUValue.Length; i++) { while (!devContainer.devAxis.isReady(AxisIndexList[i])) { Thread.Sleep(100); if (isBreakProcessRun()) return stepIndex; } devContainer.devAxis.setAxisVelParam(TagVelLow, TagVelHigh, TagAcc, TagDec, AxisIndexList[i]); if (!devContainer.devAxis.move_ptp(AxisIndexList[i], TagPPUValue[i], TagMoveMode)) { AddTextEvent($"{stepIndex + 1}-{processName}", $"轴{AxisIndexList[i]}运动失败!", WarningEnum.Low); warning(WarningEnum.Low);//终止 return stepIndex;//如果是相对位置,这里返回会有问题 } //AddTextEvent($"{stepIndex + 1}-{processName}", $"等待轴{AxisIndexList[i]}运行完成..."); //while (!asynRun && !devContainer.devAxis.isReady(AxisIndexList[i])) //{ // Thread.Sleep(100); // if (isBreakProcessRun()) // { // currProcessIndex = stepIndex + 1; // return stepIndex;//如果是相对位置,这里返回会有问题 // } //} //if (devContainer.devAxis.isReady(AxisIndexList[i])) // AddTextEvent($"{stepIndex + 1}-{processName}", $"轴{AxisIndexList[i]}运行完成,当前命令位置:{devContainer.devAxis.getCmdPos_mm(AxisIndexList[i])},反馈位置:{devContainer.devAxis.getActualPos_mm(AxisIndexList[i])}"); } if (sizeTagObj.ConsumeStepIndex == null) sizeTagObj.ConsumeStepIndex = ""; sizeTagObj.ConsumeStepIndex += $"{stepIndex + 1}-{useIndex}, ";//消费工序ID //多轴同时运行后强制等待各轴完成 AddTextEvent($"{stepIndex + 1}-{processName}", $"等待轴组运行完成..."); while (!devContainer.devAxis.isReady()) { Thread.Sleep(100); if (isBreakProcessRun()) { currProcessIndex = stepIndex + 1; return stepIndex; } } AddTextEvent($"{stepIndex + 1}-{processName}", $"轴组运行完成。"); #endregion break; case "Light": #region if (Config.SkipLight) { AddTextEvent($"{stepIndex + 1}-{processName}", $"设备禁用,忽略此步骤!"); setDgvContentCol(liStatocStepIndex, $"设备禁用,忽略此步骤!"); break; } int ChannelIndex = processParam.Value("ChannelIndex"); //通道 int DigitalValue = processParam.Value("DigitalValue"); //亮度 int nowDiaitalValue = devContainer.devLight.getDigitalValue(ChannelIndex); AddTextEvent($"{stepIndex + 1}-{processName}", $"通道{ChannelIndex}当前值:{nowDiaitalValue},准备更新值:{DigitalValue}..."); devContainer.devLight.setDigitalValue(ChannelIndex, DigitalValue); nowDiaitalValue = devContainer.devLight.getDigitalValue(ChannelIndex); AddTextEvent($"{stepIndex + 1}-{processName}", $"通道{ChannelIndex}更新后当前值:{nowDiaitalValue}。"); #endregion break; case "Scanner_GENTL": #region if (Config.SkipScannerGL) { AddTextEvent($"{stepIndex + 1}-{processName}", $"设备禁用,忽略此步骤!"); setDgvContentCol(liStatocStepIndex, $"设备禁用,忽略此步骤!"); break; } while (!devContainer.devAxis.isReady())//因启用轴异步功能,使用前需等待 { Thread.Sleep(100); if (isBreakProcessRun()) { //currProcessIndex = stepIndex;//本工序没执行,step不变 return stepIndex; } } AIEngineLibEnum AIEngineLib = AIEngineLibEnum.缺陷库; if(processParam.ContainsKey("AIEngineLib")) AIEngineLib=(AIEngineLibEnum)processParam.Value("AIEngineLib"); float ExposureTime = processParam.Value("ExposureTime"); //曝光 float Gain = processParam.Value("Gain"); //增益 float ResultingFrameRate = processParam.Value("ResultingFrameRate"); //帧率 AddTextEvent($"{stepIndex + 1}-{processName}", $"相机开始采集照片..."); devContainer.devScannerGentl.setParam(ExposureTime, Gain, ResultingFrameRate); endEvent = new AutoResetEvent(false); devContainer.devScannerGentl.ScanEvent = (num, bmpout) => { AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片完成。"); //----缺陷队列 //bool cloneUse = false; if (AIEngineLib == AIEngineLibEnum.缺陷库 || AIEngineLib == AIEngineLibEnum.缺陷与测量库) { //cloneUse = true; var mat = OpenCvSharp.Extensions.BitmapConverter.ToMat(bmpout); scannerGBmpQueue.Enqueue(new scannerGBmpLoc(mat, devContainer.devAxis.getActualPos_mm(1), devContainer.devAxis.getActualPos_mm(2)));//Dequeue AddTextEvent($"{stepIndex + 1}-{processName}", $"缺陷图像队列数量: {scannerGBmpQueue.Count}"); } if (AIEngineLib == AIEngineLibEnum.测量库 || AIEngineLib == AIEngineLibEnum.缺陷与测量库) { //v1.2.2. 修改传图 //scannerCBmpQueue.Enqueue(new scannerCBmpLoc( // cloneUse?(Bitmap)bmpout.Clone(): bmpout, // devContainer.devAxis.getActualPos_mm(1), // devContainer.devAxis.getActualPos_mm(2)));//Dequeue scannerCBmpQueue.Enqueue(new scannerCBmpLoc( (Bitmap)bmpout.Clone(), devContainer.devAxis.getActualPos_mm(1), devContainer.devAxis.getActualPos_mm(2)));//Dequeue AddTextEvent($"{stepIndex + 1}-{processName}", $"添加尺寸图像队列,X:{devContainer.devAxis.getActualPos_mm(1)},y:{devContainer.devAxis.getActualPos_mm(2)},数量: {scannerCBmpQueue.Count}"); } endEvent.Set();//线程返回 }; //AddTextEvent($"{stepIndex + 1}-{processName}", $"软触发拍照..."); if (!devContainer.devScannerGentl.scan(1))//软触发拍照 { devContainer.devScannerGentl.ScanEvent = null; AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片失败!", WarningEnum.Low); warning(WarningEnum.Low);//终止 return stepIndex; } if (!endEvent.WaitOne(10000)) { devContainer.devScannerGentl.ScanEvent = null; AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片超时!", WarningEnum.Low); warning(WarningEnum.Low);//终止 return stepIndex; } devContainer.devScannerGentl.ScanEvent = null; #endregion break; case "Scanner_CC": #region if (Config.SkipScannerCC) { AddTextEvent($"{stepIndex + 1}-{processName}", $"设备禁用,忽略此步骤!"); setDgvContentCol(liStatocStepIndex, $"设备禁用,忽略此步骤!"); break; } while (!devContainer.devAxis.isReady())//因启用轴异步功能,使用前需等待 { Thread.Sleep(100); if (isBreakProcessRun()) { //currProcessIndex = stepIndex;//本工序没执行,step不变 return stepIndex; } } float ExposureTimeCC = processParam.Value("ExposureTime"); //曝光 float GainCC = processParam.Value("Gain"); //增益 float ResultingFrameRateCC = processParam.Value("ResultingFrameRate"); //帧率 AddTextEvent($"{stepIndex + 1}-{processName}", $"相机开始采集照片..."); devContainer.devScannerCC.setParam(ExposureTimeCC, GainCC, ResultingFrameRateCC); AddTextEvent($"{stepIndex + 1}-{processName}", $"相机参数设置完成。"); AutoResetEvent endEventCC = new AutoResetEvent(false); //devContainer.devScannerCC.ScanEvent = (num, bmp2) => //{ // AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片完成."); // scannerCBmpQueue.Enqueue(bmp2);//Dequeue // endEventCC.Set();//线程返回 //}; devContainer.devScannerCC.ScanEventPath += new System.Action((num, path2) => { AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片完成."); scannerCBmpQueue.Enqueue(new scannerCBmpLoc(path2, devContainer.devAxis.getActualPos_mm(0), devContainer.devAxis.getActualPos_mm(2)));//Dequeue AddTextEvent($"{stepIndex + 1}-{processName}", $"添加尺寸图像队列,X:{ devContainer.devAxis.getActualPos_mm(0)},y: { devContainer.devAxis.getActualPos_mm(2)},数量: { scannerCBmpQueue.Count}"); endEventCC.Set();//线程返回 }); if (!devContainer.devScannerCC.scan(1))//软触发拍照 { devContainer.devScannerCC.ScanEventPath = null; AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片失败!", WarningEnum.Low); warning(WarningEnum.Low);//终止 return stepIndex; } if (!endEventCC.WaitOne(10000)) { devContainer.devScannerCC.ScanEventPath = null; AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片超时!", WarningEnum.Low); warning(WarningEnum.Low);//终止 return stepIndex; } devContainer.devScannerCC.ScanEventPath = null; #endregion break; case "SmallAxis": #region if (Config.SkipSmallAxis) { AddTextEvent($"{stepIndex + 1}-{processName}", $"设备禁用,忽略此步骤!"); setDgvContentCol(liStatocStepIndex, $"设备禁用,忽略此步骤!"); break; } int CmdPos = processParam.Value("CmdPos"); //命令脉冲 AddTextEvent($"{stepIndex + 1}-{processName}", $"开始由起始位置{devContainer.devSmallAxis.getCurrPPU()}运动到{CmdPos}..."); devContainer.devSmallAxis.gotoPos(CmdPos, true); AddTextEvent($"{stepIndex + 1}-{processName}", $"运动完成,当前位置:{devContainer.devSmallAxis.getCurrPPU()}"); #endregion break; case "Size": #region asynRun = processParam.Value("AsynRun");//异步 limitThresholdVal = processParam.Value("LimitThresholdVal"); lowerThresholdVal = processParam.Value("LowerThresholdVal"); int sizeIndex = processParam.Value("Index"); string sizeTag = processParam.ContainsKey("SizeTag") ? processParam.Value("SizeTag") : ""; //2023-10-27 bool useMap = false; List getPosList = new List(); try { useMap = processParam.Value("UseMapPoints"); if (useMap) { var list = model.GetPointList.Split(','); List dList = new List(); if (list.Length < 28) { for (int i = 0; i < 28; i++) { dList.Add(0); } } else { for (int i = 0; i < list.Length; i++) { dList.Add(double.Parse(list[i])); } } getPosList = dList; } else { for (int i = 0; i < 28; i++) getPosList.Add(0); } //getPosList = processParam.Value("GetPointList").ToObject>(); } catch { for (int i = 0; i < 28; i++) getPosList.Add(0); } double[] getPosArray = getPosList.ToArray(); if (scannerCBmpQueue.Count < 1) { AddTextEvent($"{stepIndex + 1}-{processName}", $"尺寸检测异常,无源图像!!", WarningEnum.Low); warning(WarningEnum.Low);//暂停 return stepIndex; } var bmpCBmpQueue = scannerCBmpQueue.Dequeue(); AddTextEvent($"{stepIndex + 1}-{processName}", $"开始尺寸检测,index:{sizeIndex},posX:{bmpCBmpQueue.PosX},posY:{bmpCBmpQueue.PosY},图像队列数量: {scannerCBmpQueue.Count}..."); attachmentFile = model.AttachmentList.FirstOrDefault(x => x.Type == 0); AddTextEvent($"{stepIndex + 1}-{processName}", $"尺寸检测,index:{sizeIndex},{model.AttachmentList.Count}|{(attachmentFile == null ? "null": attachmentFile.NameTimestamp+ attachmentFile.ExtendName)}"); if (attachmentFile != null) { gbxBmpPath = Application.StartupPath + $"\\Attachment\\product\\{attachmentFile.NameTimestamp}"; if (!File.Exists(gbxBmpPath+ attachmentFile.ExtendName)) gbxBmpPath = ""; } if ((sizeIndex == 333 || sizeIndex == 777) && gbxBmpPath == "") AddTextEvent($"{stepIndex + 1}-{processName}", $"尺寸检测,index:{sizeIndex},图纸不存在!", WarningEnum.Low); //2023-10-27 //if ((sizeIndex == 3333)&&(getPosList != null) && (getPosList.Count() != 28)) // AddTextEvent($"{stepIndex + 1}-{processName}", $"尺寸检测,index:{sizeIndex},图纸读点不存在!", WarningEnum.Low); if (useMap&&(sizeIndex == 3333) && (getPosArray != null) && (getPosArray.Count() == 28) && (getPosArray[0] != 0)) AddTextEvent($"{stepIndex + 1}-{processName}", $"开始图纸读点,index:{sizeIndex},PT1:{getPosArray[0]},PT2:{getPosArray[2]},PT3:{getPosArray[4]},PT4:{getPosArray[6]},PT5:{getPosArray[8]}," + $"线宽1:[{getPosArray[10]},{getPosArray[11]}],线宽2:[{getPosArray[12]},{getPosArray[13]}],线宽3:[{getPosArray[14]},{getPosArray[15]}]," + $"线宽4:[{getPosArray[16]},{getPosArray[17]}],线宽5:[{getPosArray[18]},{getPosArray[19]}],线宽6:[{getPosArray[20]},{getPosArray[21]}]," + $"线宽7:[{getPosArray[22]},{getPosArray[23]}],线宽8:[{getPosArray[24]},{getPosArray[25]}],线宽9:[{getPosArray[26]},{getPosArray[27]}]"); //需要偏移校正,index=0时不能异步 //10,20,30...  endEvent = new AutoResetEvent(false); devContainer.libSize.add(new SizeTask() { stepIndex = stepIndex, processName = processName, sizeTag = sizeTag, engineName = processParam.Value("EngineName"), bmp = bmpCBmpQueue.BMP == null ? bmpCBmpQueue.BMP : (Bitmap)bmpCBmpQueue.BMP.Clone(),//bmp/file_path二选一,优先bmp file_path = bmpCBmpQueue.Path, drawingPagePath = gbxBmpPath, posX= bmpCBmpQueue.PosX, posY= bmpCBmpQueue.PosY, //2023-10-27 PTandLinePos = getPosArray, index = sizeIndex,// scannerCBmpIndex++, ContoursAffineTrans1_Out=this.contoursAffineTrans1_Out,//只有777时才使用最近333输出的结果 finishEvent = (res) => { try { //比对 if (res.index == 777)//比对 { if (res.isSucceed) { setDgvContentCol(liStatocStepIndex, $"index:{res.index}-{compBmpIndex},posX:{res.posX},posY:{res.posY},图像比对:{(res.CompResult ? "通过" : "未通过")} "); AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"图像比对,index:{res.index}-{compBmpIndex},posX:{res.posX},posY:{res.posY},结果:{(res.CompResult ? "通过" : "未通过")}"); // if (order.CompareResult < 2) order.CompareResult = res.CompResult ? 1 : 2; updateCompareResult(res.CompResult);//更新比对看板 if (!res.CompResult) { AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"图像比对,未通过结果:{JsonConvert.SerializeObject(res.defectInfor2RestorationDesk)}"); //转为图纸上坐标位置 if (res.defectInfor2RestorationDeskPage != null && res.defectInfor2RestorationDeskPage.Count > 0) { //AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"转换到图纸后坐标数据:{JsonConvert.SerializeObject(res.defectInfor2RestorationDeskPage)}"); if (order.DefectInfoList == null) order.DefectInfoList = new List(); foreach (var item in res.defectInfor2RestorationDeskPage) order.DefectInfoList.Add(new DefectInfo() { Type = 1, Code = item[3], X = double.Parse(item[1]), Y = double.Parse(item[2]), ZXD = double.Parse(item[4]), ModifyUserCode = Config.loginUser.Code, CreateUserCode = Config.loginUser.Code, }); } //比对失败的图片 -- 用于修复台调用 Bitmap bmpCompareFailZoomImage = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(res.Zoom_Image_mat); lstCompareFailZoomImage.Add(bmpCompareFailZoomImage); if (Config.SizeBmp_Zoom_Image_SavePath != "" && Directory.Exists(Config.SizeBmp_Zoom_Image_SavePath)) { string path = Util.createSubDir(Config.SizeBmp_Zoom_Image_SavePath, new List { order.CreateTime.ToString("yyyyMMdd"), order.SN }); //path += $"Size_SN{order.SN}_I{res.index}_X{res.Defects_X}_Y{res.Defects_Y}_C0_{ model.StepInfo.Name}"; path += $"Size_SN{order.SN}_I{compBmpIndex}_X{res.posX}_Y{res.posY}_C0_{ model.StepInfo.Name}"; bmpCompareFailZoomImage.Save(path + ".bmp", ImageFormat.Bmp); if (res.defectInfor2RestorationDesk != null && res.defectInfor2RestorationDesk.Count > 0) File.WriteAllText(path + ".json", JsonConvert.SerializeObject(res.defectInfor2RestorationDesk)); } //保存原图 if (Config.SizeBmp_Compare_SavePath != "" && Directory.Exists(Config.SizeBmp_Compare_SavePath)) { string path = Util.createSubDir(Config.SizeBmp_Compare_SavePath, new List { order.CreateTime.ToString("yyyyMMdd"), order.SN }); path += $"Size_SN{order.SN}_I{res.index}_X{res.posX}_Y{res.posY}_{ model.StepInfo.Name}.bmp"; AddTextEvent($"{res.stepIndex + 1}-{processName}", $"未通过图片保存:{path}"); if (res.bmp != null) res.bmp.Save(path, ImageFormat.Bmp); else API.CopyFile(res.file_path, path, false);//比.NET(File.Copy)更快 } } } else { //2023-12-29 加入比对失败当作NG处理 order.CompareResult = 2; updateCompareResult(false);//更新比对看板 //warning(WarningEnum.Low);//暂停 setDgvContentCol(liStatocStepIndex, $"index:{res.index},图像比对失败!"); AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"图像比对失败,index:{res.index}-{compBmpIndex}.", WarningEnum.Low); } compBmpIndex++; } //MARK else if (res.index == 111 || res.index == 222 || res.index == 333 || res.index == 444) { AddTextEvent($"{res.stepIndex + 1}-{processName}", $"Mark点 Index={res.index},结果记录..."); if (res.index == 333) this.contoursAffineTrans1_Out = res.ContoursAffineTrans1_Out;//不管成功失败都替换 if (res.isSucceed) { Thread.Sleep(100); AddTextEvent($"{res.stepIndex + 1}-{processName}", $"Mark点 Index={res.index}; 当前值:{string.Join(",", res.MarkPointList)}"); JArray markDatas; if (string.IsNullOrWhiteSpace(order.MarkData)) markDatas = new JArray() { 0, 0, 0, 0, 0, 0, 0, 0 }; else markDatas = JArray.Parse(order.MarkData); for (int i = 0; i < res.MarkPointList.Count(); i++) if (res.MarkPointList[i] != 0) markDatas[i] = res.MarkPointList[i]; order.MarkData = markDatas.ToString(); setDgvContentCol(liStatocStepIndex, $"index:{res.index},Mark点:{order.MarkData} "); AddTextEvent($"{res.stepIndex + 1}-{processName}", $"Mark点 Index={res.index};合并后:{order.MarkData}"); } else { //warning(WarningEnum.Low);//暂停 setDgvContentCol(liStatocStepIndex, $"index:{res.index},Mark点计算失败!"); AddTextEvent($"{res.stepIndex + 1}-{processName}", $"Mark点计算失败,index:{res.index}.", WarningEnum.Low); //2023-10-20 make暂停 if (Config.OpenMarkErrorStop) warning(WarningEnum.Low);//暂停 } //保存 if (Config.SizeBmp_SavePath != "" && Directory.Exists(Config.SizeBmp_SavePath)) { string path = Util.createSubDir(Config.SizeBmp_SavePath, new List { order.CreateTime.ToString("yyyyMMdd"), order.SN }); path += $"Size_SN{order.SN}_I{res.index}_X{res.posX}_Y{res.posY}_{ model.StepInfo.Name}.bmp"; if (res.bmp != null) res.bmp.Save(path, ImageFormat.Bmp); else API.CopyFile(res.file_path, path, false);//比.NET(File.Copy)更快 } } else { int roundIndex = res.index % 10; if (res.isSucceed) { string tagOutData = ""; if (res.index == 3333 && !string.IsNullOrWhiteSpace(res.sizeTag)) { tagOutData = $"Tag:{res.sizeTag},posePT:[{string.Join(",", res.posePT)}]"; if (res.posePT.Length < 2 || res.posePT.Length % 2 != 0) { AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"尺寸检测输出Tag对应posePT非法: {tagOutData}", WarningEnum.High); warning(WarningEnum.High);//急停 return; } //2023-10-27 AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"Tag对应posePT: {tagOutData}", WarningEnum.Normal); if (order.SizeTagDataList == null) order.SizeTagDataList = new List(); order.SizeTagDataList.Add(new SizeTagData() { SizeTag = res.sizeTag, CreateStepIndex = res.stepIndex + 1, posePT= string.Join(",", res.posePT)// 回转 Array.ConvertAll(sNums , double.Parse); }); } setDgvContentCol(liStatocStepIndex, $"index:{res.index},PT1:{res.PT1},PT2:{res.PT2},Shanxian:{res.Shanxian},Circle_Xmm:{res.Circle_Xmm},Circle_Ymm:{res.Circle_Ymm},offsetX:{res.offsetX},offsetY:{res.offsetY}, {tagOutData}"); AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"尺寸检测完成 index:{res.index},PT1:{res.PT1},PT2:{res.PT2},Shanxian:{res.Shanxian},Circle_Xmm:{res.Circle_Xmm},Circle_Ymm:{res.Circle_Ymm},offsetX:{res.offsetX},offsetY:{res.offsetY}, {tagOutData} "); //测量 //------TEST if (res.index>20 && res.index<30) { lock (lstPT) { lstPT.Add(Math.Round(res.PT1, 4)); updatePTValueTest(model.PTBaseValue + model.PTUpFloatValue, model.PTBaseValue - model.PTDownFloatValue); } } //------ if (roundIndex > 0)//1-9测量 { if (res.index < 10)//11-13 (PT: 7-9 => 21-29(PT1)) 不用管,李工处理 { //if (roundIndex >= 7) //{ // lock (lstPT) // { // lstPT.Add(Math.Round(res.PT1, 4)); // lstPT.Add(res.index == 8 ? 0 : Math.Round(res.PT2, 4)); // updatePTValue(model.PTBaseValue + model.PTUpFloatValue, model.PTBaseValue - model.PTDownFloatValue); // } //} lock (lstLineWidth) { lstLineWidth.Add(res.Shanxian > 0 ? Math.Round(res.Shanxian, 2) : 0); updateLineWidthValue(model.LineWidthBaseValue + model.LineWidthUpFloatValue, model.LineWidthBaseValue - model.LineWidthDownFloatValue); } } } //校正偏移 10,20,30...:偏移 else { AxMoveMode axSizeMode = AxMoveMode.绝对位置; double xPos = 0; double yPos = 0; //绝对偏移 if (res.offsetX != 0 || res.offsetY != 0) { xPos += res.offsetX; yPos += res.offsetY; AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"offsetX/Y绝对校正, 0轴:{xPos}mm, 2轴:{yPos}mm"); } else if (res.Circle_Xmm != 0 || res.Circle_Ymm != 0)//相对偏移校正 { axSizeMode = AxMoveMode.相对位置; AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"原点相对校正, 0轴:{res.Circle_Xmm}mm, 2轴:{res.Circle_Ymm}mm"); if (res.Circle_Xmm != 0) xPos = res.Circle_Xmm; if (res.Circle_Ymm != 0) yPos = res.Circle_Ymm; } //当前工序直接移动 if (xPos != 0 || yPos != 0) { devContainer.devAxis.setAxisVelParam(0.1, 1, 1, 1, 0); devContainer.devAxis.setAxisVelParam(0.1, 1, 1, 1, 2); if (xPos != 0) devContainer.devAxis.move_ptp(0, xPos, axSizeMode); if (yPos != 0) devContainer.devAxis.move_ptp(2, yPos, axSizeMode); while (!devContainer.devAxis.isReady(0) || !devContainer.devAxis.isReady(2)) { Thread.Sleep(100); if (isBreakProcessRun()) break; } } } //保存 //string sizeFileName = Config.Size_SavePath + "\\" + DateTime.Now.ToString("yyyyMMdd_HHmmss_fff"); //API.CopyFile(res.file_path, defectFileName + ".bmp", false);//更快 //File.WriteAllText(defectFileName + ".json", JsonConvert.SerializeObject(res.informationList)); } //失败 else { //------TEST if (res.index > 20 && res.index < 30) { lock (lstPT) { lstPT.Add(0); updatePTValueTest(model.PTBaseValue + model.PTUpFloatValue, model.PTBaseValue - model.PTDownFloatValue); } } //------ if (roundIndex > 0) { //if (roundIndex >= 7) //{ // lock (lstPT) // { // lstPT.Add(0); // lstPT.Add(0); // updatePTValue(model.PTBaseValue + model.PTUpFloatValue, model.PTBaseValue - model.PTDownFloatValue); // } //} lock (lstLineWidth) { lstLineWidth.Add(0); updateLineWidthValue(model.LineWidthBaseValue + model.LineWidthUpFloatValue, model.LineWidthBaseValue - model.LineWidthDownFloatValue); } } setDgvContentCol(liStatocStepIndex, $"失败:{res.resultInfo}"); AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"尺寸检测失败index:{res.index}:{res.resultInfo}"); //warning(WarningEnum.Low);//暂停 这里不能暂停,stepIndex和scannerBmpQueue队列也不对了 } //保存 if (Config.SizeBmp_SavePath != "" && Directory.Exists(Config.SizeBmp_SavePath)) { string path = Util.createSubDir(Config.SizeBmp_SavePath, new List { order.CreateTime.ToString("yyyyMMdd"), order.SN }); path += $"Size_SN{order.SN}_I{res.index}_X{res.posX}_Y{res.posY}_{ model.StepInfo.Name}.bmp"; if (res.bmp != null) res.bmp.Save(path, ImageFormat.Bmp); else API.CopyFile(res.file_path, path, false);//比.NET(File.Copy)更快 } } } catch(Exception ex) { AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"尺寸检测回调处理异常 index:{res.index},ex={ex.Message}"); } // //if (!asynRun)//是否异步执行endEvent.Set()都没问题 endEvent.Set();//roundIndex=0成功或失败线程返回 //--- if (res.bmp != null) { res.bmp.Dispose(); res.bmp = null; } else { API.DeleteFile(res.file_path); } } }); //需等上面异步回调中的相对偏移校正完成再继续 if (!asynRun || sizeIndex % 10==0) { if (!endEvent.WaitOne(60000)) AddTextEvent($"{stepIndex + 1}-{processName}", $"{sizeIndex}等待超时,忽略继续!", WarningEnum.Low); } #endregion break; case "Defect": #region limitThresholdVal = processParam.Value("LimitThresholdVal"); lowerThresholdVal = processParam.Value("LowerThresholdVal"); if (scannerGBmpQueue.Count < 1) { AddTextEvent($"{stepIndex + 1}-{processName}", $"缺陷检测异常,无源图像!!", WarningEnum.Low); warning(WarningEnum.Low);//终止 return stepIndex; } var bmpLoc = scannerGBmpQueue.Dequeue(); AddTextEvent($"{stepIndex + 1}-{processName}", $"开始缺陷检测,源图索引:{defectBmpNum},图像队列数量: {scannerGBmpQueue.Count}..."); string[] aarCut_size = processParam.Value("CutSize").Split(','); string[] aarResize = processParam.Value("Resize").Split(','); //图纸 attachmentFile = model.AttachmentList.FirstOrDefault(x => x.Type == 0); if (attachmentFile != null) { gbxBmpPath = Application.StartupPath + $"\\Attachment\\product\\{attachmentFile.NameTimestamp}"; if (!File.Exists(gbxBmpPath + attachmentFile.ExtendName)) gbxBmpPath = ""; } AddTextEvent($"{stepIndex + 1}-{processName}", $"图纸路径:{gbxBmpPath}"); devContainer.libDefect.add(new DefectTask() { stepIndex= stepIndex, processName= processName, drawingPagePath= gbxBmpPath, index = defectBmpNum++, bmp = bmpLoc.bmp, Xmm = bmpLoc.Xmm, Ymm = bmpLoc.Ymm, cut_size = new System.Drawing.Size(Convert.ToInt32(aarCut_size[0]), Convert.ToInt32(aarCut_size[1])), resize = new System.Drawing.Size(Convert.ToInt32(aarResize[0]), Convert.ToInt32(aarResize[1])), thresholds = processParam.Value("Thresholds"), thresholdsClass = processParam.Value("ThresholdsClass"), recAreaThreshold= getProductAreaThreshol(model), //qxName,面积; qxName,面积; qxName,面积; finishEvent = (res) => { if (res.isSucceed) { setDgvContentCol(liStatocStepIndex, $"源图索引:{res.index},缺陷数:{res.defectCount},处理时间(ms):{string.Join("->", res.stopwatch.Select(i => i.ToString()).ToArray())}"); AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"缺陷检测完成(源图索引:{res.index}),缺陷数:{res.defectCount},处理时间(ms):{string.Join("->", res.stopwatch.Select(i => i.ToString()).ToArray())}"); string path; if (res.defectCount > 0) { //UI显示小图 (含统计缺陷类型数量) showDefectSmallBmps(res.bmps_tag, res.bmps_cut, res.Xmm, res.Ymm, res.informationList); if (res.defectInfor2RestorationDeskPage != null && res.defectInfor2RestorationDeskPage.Count > 0) { AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"转换后坐标数据:{JsonConvert.SerializeObject(res.defectInfor2RestorationDeskPage)}"); if (order.DefectInfoList == null) order.DefectInfoList = new List(); foreach (var item in res.defectInfor2RestorationDeskPage) order.DefectInfoList.Add(new DefectInfo() { Type = 0, Code = item[3], X = double.Parse(item[1]), Y = double.Parse(item[2]), ZXD = double.Parse(item[4]), ModifyUserCode = Config.loginUser.Code, CreateUserCode = Config.loginUser.Code, }); } //保存原始大图 if (Config.Defect_SavePath != "" && Directory.Exists(Config.Defect_SavePath)) { path = Util.createSubDir(Config.Defect_SavePath, new List { order.CreateTime.ToString("yyyyMMdd"), order.SN }); path += $"Defect_SN{order.SN}_I{res.index}_X{res.Xmm}_Y{res.Ymm}_C{res.defectCount}_{ model.StepInfo.Name}"; //API.CopyFile(res.file_path, defectFileName + ".bmp", false);//比.NET(File.Copy)更快 //res.bmp.SaveImage(path + ".bmp");//opencv保存格式与BMP不同 OpenCvSharp.Extensions.BitmapConverter.ToBitmap(res.bmp).Save(path + ".bmp", ImageFormat.Bmp); File.WriteAllText(path + ".json", JsonConvert.SerializeObject(res.informationList)); } //保存小图 if (Config.Defect_Small_SavePath != "" && Directory.Exists(Config.Defect_Small_SavePath)) { path = Util.createSubDir(Config.Defect_Small_SavePath, new List { order.CreateTime.ToString("yyyyMMdd"), order.SN }); path += $"Defect_SN{order.SN}_I{res.index}_X{res.Xmm}_Y{res.Ymm}_{ model.StepInfo.Name}"; for (int i = 0; i < res.bmps_tag.Count(); i++) res.bmps_tag[i].Save(path + $"_i{i}.bmp", ImageFormat.Bmp); } //保存压缩大图 -- 用于修复台调用 if (Config.Defect_Compress_SavePath != "" && Directory.Exists(Config.Defect_Compress_SavePath)) { path = Util.createSubDir(Config.Defect_Compress_SavePath, new List { order.CreateTime.ToString("yyyyMMdd"), order.SN }); path += $"Defect_SN{order.SN}_I{res.index}_X{res.Xmm}_Y{res.Ymm}_C{res.defectCount}_{ model.StepInfo.Name}"; //res.bmpCompress.SaveImage(path + ".bmp");//opencv保存格式与BMP不同 OpenCvSharp.Extensions.BitmapConverter.ToBitmap(res.bmpCompress).Save(path + ".bmp", ImageFormat.Bmp); File.WriteAllText(path + ".json", JsonConvert.SerializeObject(res.defectInfor2RestorationDesk)); } } else//没有缺陷 { if (Config.SaveAllDefectImg && Config.Defect_SavePath != "" && Directory.Exists(Config.Defect_SavePath)) { path = Util.createSubDir(Config.Defect_SavePath, new List { order.CreateTime.ToString("yyyyMMdd"), order.SN }); path += $"Defect_SN{order.SN}_I{res.index}_X{res.Xmm}_Y{res.Ymm}_C{res.defectCount}_{ model.StepInfo.Name}"; //API.CopyFile(res.file_path, defectFileName + ".bmp", false);//比.NET(File.Copy)更快 //res.bmp.SaveImage(path + ".bmp");//opencv保存格式与BMP不同 OpenCvSharp.Extensions.BitmapConverter.ToBitmap(res.bmp).Save(path + ".bmp", ImageFormat.Bmp); } } } else { setDgvContentCol(liStatocStepIndex, $"失败:{res.resultInfo}"); AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"缺陷检测失败:{res.resultInfo}"); //warning(WarningEnum.Low);//暂停 这里不能暂停,stepIndex和scannerBmpQueue队列也不对了 } defectBmpNumResult++; foreach (var item in res.bmps_cut) item.Dispose(); res.bmp.Dispose(); res.bmp = null; res.bmps_tag = null; if (res.bmpCompress != null) { res.bmpCompress.Dispose(); res.bmpCompress = null; } System.GC.Collect(); } }); #endregion break; case "For": #region long UniqueId = processParam.Value("UniqueId"); int GotoStepIndex = processParam.Value("GotoStepIndex");//1-n int LimitNum = processParam.Value("LimitNum");//1-n bool Reset = processParam.Value("Reset"); if (GotoStepIndex - 1 == stepIndex) { AddTextEvent($"{stepIndex + 1}-{processName}", $"For死循环!!!"); warning(WarningEnum.High); return stepIndex; } if (!devContainer.libFor.dicData.ContainsKey(UniqueId)) devContainer.libFor.dicData.Add(UniqueId, 0); // int Num = devContainer.libFor.dicData[UniqueId]; Num++; if (Num <= LimitNum) { if (Num == LimitNum) { setDgvContentCol(liStatocStepIndex, $"第[{Num}/{LimitNum}]次,循环完成"); AddTextEvent($"{stepIndex + 1}-{processName}", $"第[{Num}/{LimitNum}]次,循环完成。"); } else { setDgvContentCol(liStatocStepIndex, $"第[{Num}/{LimitNum}]次"); AddTextEvent($"{stepIndex + 1}-{processName}", $"第[{Num}/{LimitNum}]次跳转到步骤[{GotoStepIndex}]..."); stepIndex = GotoStepIndex - 2; } devContainer.libFor.dicData[UniqueId] = Num; } else { setDgvContentCol(liStatocStepIndex, $"已失效不执行"); AddTextEvent($"{stepIndex + 1}-{processName}", $"本循环已失效不执行!"); } //达到limit重置0 if (devContainer.libFor.dicData[UniqueId] >= LimitNum && Reset) { devContainer.libFor.dicData[UniqueId] = 0; setDgvContentCol(liStatocStepIndex, $"第[0/{LimitNum}]次"); AddTextEvent($"{stepIndex + 1}-{processName}", $"计数器已重置。"); } #endregion break; case "If": #region long UniqueId_if = processParam.Value("UniqueId"); int GotoStepIndex_if = processParam.Value("GotoStepIndex");//1-n int LimitNum_if = processParam.Value("LimitNum");//1-n bool Reset_if = processParam.Value("Reset"); if (GotoStepIndex_if - 1 == stepIndex) { AddTextEvent($"{stepIndex + 1}-{processName}", $"If死循环,不可自我跳转!!!"); warning(WarningEnum.High); return stepIndex; } // if (!devContainer.libIF.dicData.ContainsKey(UniqueId_if)) devContainer.libIF.dicData.Add(UniqueId_if, 0); // int Num_if = devContainer.libIF.dicData[UniqueId_if]; Num_if++; if (Num_if <= LimitNum_if) { if (Num_if == LimitNum_if) { setDgvContentCol(liStatocStepIndex, $"第[{Num_if}/{LimitNum_if}]次,跳转至[{GotoStepIndex_if}]"); AddTextEvent($"{stepIndex + 1}-{processName}", $"计数器[{Num_if}/{LimitNum_if}],跳转至步骤[{GotoStepIndex_if}]..."); stepIndex = GotoStepIndex_if - 2; } else { setDgvContentCol(liStatocStepIndex, $"第[{Num_if}/{LimitNum_if}]次,不跳转"); AddTextEvent($"{stepIndex + 1}-{processName}", $"计数器[{Num_if}/{LimitNum_if}],不跳转。"); } // devContainer.libIF.dicData[UniqueId_if] = Num_if; } else { setDgvContentCol(liStatocStepIndex, $"已失效不执行"); AddTextEvent($"{stepIndex + 1}-{processName}", $"本IF已失效不执行。"); } //达到limit重置0 if (devContainer.libIF.dicData[UniqueId_if] >= LimitNum_if && Reset_if) { devContainer.libIF.dicData[UniqueId_if] = 0; setDgvContentCol(liStatocStepIndex, $"第[0/{LimitNum_if}]次"); AddTextEvent($"{stepIndex + 1}-{processName}", $"计数器已重置。"); } #endregion break; default: AddTextEvent($"{stepIndex + 1}-{processName}", $"未知工序:{processInfo.ProcessCode}"); warning(WarningEnum.High); return stepIndex; } if (sleepLater > 0) Thread.Sleep((int)sleepLater); } //============结束,判断是否自动下料 if (stepIndex == processList.Count - 1) { //厚度校正 直接更新并保存 if (isProductRevise) { isProductRevise = false; if (MessageBox.Show($"厚度校正完成,是否保存?\r\nBase值:{model.HeightBaseDec}", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { //保存 //更新指定列 if (svcProduct.Update(it => new Product() { HeightBaseDec = model.HeightBaseDec }, it => it.Id == model.Id)) AddTextEvent($"产品校正", $"保存成功。"); else AddTextEvent($"产品校正", $"保存失败!!"); } //下料 currentState = CurrentStateEnum.自动流程结束; gotoDownPT(); } else//生产 { //等待缺陷图显示完成 while (defectBmpNum != defectBmpNumResult) Thread.Sleep(100); //判断是否合格 DefectCodeEnum defectCode; string defectNames = ""; if (model.QualifiedCriterionList!= null && model.QualifiedCriterionList.Count >0) { int itemDefectCount; foreach (var item in model.QualifiedCriterionList) { defectCode = EnumUtil.Convert2Enum(item.DefectCode); itemDefectCount = getDefectCountFromCode(order, defectCode); if (item.MaxDefectCount>-1 && itemDefectCount > item.MaxDefectCount) { order.Qualified = false; defectNames += $"{((DefectNameEnum)(int)defectCode).ToString()}({itemDefectCount}),"; } } } stopWatch.Stop(); long timeLen = stopWatch.ElapsedMilliseconds / 1000; this.BeginInvoke(new System.Action(() => { lblTimeLen.Visible = true; lblTimeLen.Text = $"检测时长: {timeLen} 秒"; if (defectNames != "") { lblDefectResult.Text = "未通过"; lblDefectResultCount.Text = defectNames.Substring(0, defectNames.Length - 1); this.toolTip1.SetToolTip(lblDefectResultCount, lblDefectResultCount.Text); lblDefectResult.ForeColor = lblDefectResultCount.ForeColor = Color.Red; } })); order.TimeLen = timeLen; order.DefectCount = (int)this.gboxDefectList.Tag; order.Succeed = true; order.ModifyUserCode = order.CreateUserCode = Config.loginUser.Code; order.Abnormalities = "";//无异常 order.RepairCode = "";//无修复人员 //如SN检测已存在,先删除 var oldSNOrder= svcOrder.GetFirst(m=> m.SN==order.SN); if(oldSNOrder!=null) { AddTextEvent("删除记录", $"删除上一重复SN检测记录:SN={oldSNOrder.SN}, Date={oldSNOrder.CreateTime}"); svcOrder.DelNav(oldSNOrder); } if (!svcOrder.InsertNav(order))//导航插入 AddTextEvent("保存失败", $"保存生产记录失败!"); //更新本批次检测数量 if (!string.IsNullOrWhiteSpace(model.BatchId)) { var expOrder = Expressionable.Create() .And(m => m.ProductId == model.Id) .And(m => m.BatchId == model.BatchId) .ToExpression();//注意 这一句 不能少 currProductModel.CompleteCount = svcOrder.Count(expOrder); } //以主键为条件更新CompleteCount单列值 svcProduct.Update(it => new Product() { CompleteCount = currProductModel.CompleteCount }, it => it.Id == currProductModel.Id); if (Config.MakeTag && order.DefectCount > 0)//要打标 and 有缺陷图 { AddTextEvent("完成", $"工序结束,用时 {order.TimeLen} 秒;缺陷 {order.DefectCount} 张."); //+(Config.MakeTag ? "开始自动打标...":"手动打标...")); currentPT = CurrentPTEnum.MakeTag; currentState = CurrentStateEnum.打标中; setButtonEnabled(tsbtnGoDownPT, true); setButtonEnabled(tsbtnReset, true); setButtonEnabled(btnMakeTags, true); //if (!Config.MakeTag)//自动打标 { this.Invoke(new System.Action(() => { btnMakeTag_Click(null, null); })); } } else//下料 { AddTextEvent("完成", $"用时 {order.TimeLen} 秒,进行下料..."); currentState = CurrentStateEnum.自动流程结束; gotoDownPT(); } } currProcessIndex = -1; return -1; } else //继续 { return ++stepIndex; //return nextProcess(model, ++stepIndex); } } catch (Exception ex) { AddTextEvent("工序", $"[{stepIndex+1}] Err:" + ex.Message+"\n"+ex.StackTrace); warning(WarningEnum.Low); return -2; } } private Dictionary getProductAreaThreshol(Product m) { Dictionary dic = new Dictionary(); foreach(var item in m.QualifiedCriterionList) dic.Add(item.DefectCode, (float)(item.Size * 25.4 * 25.4 / m.HoleCount / m.HoleCount) );//网目 => mm^2 //全缺陷项 var lstDefect = Utils.EnumUtil.GetArrayList(); foreach (DictionaryEntry item in lstDefect) { string code = item.Value.ToString(); if (!dic.ContainsKey(code)) dic.Add(code, 0); } return dic; } private void setDgvContentCol(int rowIndex, string info) { int row = rowIndex;//why -1 ??? this.Invoke(new System.Action(() => { this.dgvProcess.Rows[row].Cells["colValue"].Value = info; })); } /// /// 报警,只响应low,high /// private void warning(WarningEnum level, bool buzzer = true) { if (level == WarningEnum.Normal) return; lock(myLock) warningLevel = level; if (level == WarningEnum.Low)//暂停 { currentState = CurrentStateEnum.暂停; pauseCommand(buzzer); } else if (level == WarningEnum.High)//急停 { currentState = CurrentStateEnum.急停; devContainer.devAxis.stopNow(); stopNowCommand(); } //启用报警消除按钮 this.Invoke(new System.Action(() => { tsbtnWarning.Enabled = true; })); } private void updateTensionValue(double upperLimit,double lowerLimit) { int count = lstTension.Count(); if (count < 1) return; switch (count) { case 1: order.Tension1 = lstTension[count - 1]; AddTextEvent("张力值", $"张力1:{order.Tension1}"); break; case 2: order.Tension2 = lstTension[count - 1]; AddTextEvent("张力值", $"张力2:{order.Tension2}"); break; case 3: order.Tension3 = lstTension[count - 1]; AddTextEvent("张力值", $"张力3:{order.Tension3}"); break; case 4: order.Tension4 = lstTension[count - 1]; AddTextEvent("张力值", $"张力4:{order.Tension4}"); break; case 5: order.Tension5 = lstTension[count - 1]; AddTextEvent("张力值", $"张力5:{order.Tension5}"); break; } double value = Math.Round(lstTension.Average(), 2); double valueMax = lstTension.Max(); double valueMin = lstTension.Min(); if (order != null) order.TensionValue = value; Color color = (upperLimit+ lowerLimit>0 && (value > upperLimit || value < lowerLimit)) ? Color.Red : Color.White; Color colorMax = (upperLimit + lowerLimit > 0 && (valueMax > upperLimit || valueMax < lowerLimit)) ? Color.Red : Color.White; Color colorMin = (upperLimit + lowerLimit > 0 && (valueMin > upperLimit || valueMin < lowerLimit)) ? Color.Red : Color.White; this.BeginInvoke(new System.Action(() => { this.lblTension.Text = Math.Round(value, 2).ToString(); this.lblTension.ForeColor = color; this.lblTensionMax.Text = Math.Round(valueMax, 2).ToString(); this.lblTensionMax.ForeColor = colorMax; this.lblTensionMin.Text = Math.Round(valueMin, 2).ToString(); this.lblTensionMin.ForeColor = colorMin; })); //不合格 if (color == Color.Red) order.Qualified = false; } private void updateHeightValue(double upperLimit, double lowerLimit) { int count = lstHeight.Count(); if (count < 1) return; AddTextEvent("厚度", string.Join(",", lstHeight)); switch (count) { case 1: order.Height1 = lstHeight[count - 1]; AddTextEvent("厚度值", $"厚度1:{order.Height1}"); break; case 2: order.Height2 = lstHeight[count - 1]; AddTextEvent("厚度值", $"厚度2:{order.Height2}"); break; case 3: order.Height3 = lstHeight[count - 1]; AddTextEvent("厚度值", $"厚度3:{order.Height3}"); break; case 4: order.Height4 = lstHeight[count - 1]; AddTextEvent("厚度值", $"厚度4:{order.Height4}"); break; case 5: order.Height5 = lstHeight[count - 1]; AddTextEvent("厚度值", $"厚度5:{order.Height5}"); break; } double value = Math.Round(lstHeight.Average(), 2); double valueMax = lstHeight.Max(); double valueMin = lstHeight.Min(); if (order != null) order.HeightValue = value; Color color = (upperLimit + lowerLimit > 0 && (value > upperLimit || value < lowerLimit)) ? Color.Red : Color.White; Color colorMax = (upperLimit + lowerLimit > 0 && (valueMax > upperLimit || valueMax < lowerLimit)) ? Color.Red : Color.White; Color colorMin = (upperLimit + lowerLimit > 0 && (valueMin > upperLimit || valueMin < lowerLimit)) ? Color.Red : Color.White; this.Invoke(new System.Action(() => { this.lblHeight.Text = Math.Round(value, 2).ToString(); this.lblHeight.ForeColor = color; this.lblHeightMax.Text = Math.Round(valueMax, 2).ToString(); this.lblHeightMax.ForeColor = colorMax; this.lblHeightMin.Text = Math.Round(valueMin, 2).ToString(); this.lblHeightMin.ForeColor = colorMin; })); //不合格 if (color == Color.Red) order.Qualified = false; } private void updateLineWidthValue(double upperLimit, double lowerLimit) { int count = lstLineWidth.Count(); if (count < 1) return; switch (count) { case 1: order.LineWidth1 = lstLineWidth[count - 1]; AddTextEvent("线宽值", $"线宽1:{order.LineWidth1}"); break; case 2: order.LineWidth2 = lstLineWidth[count - 1]; AddTextEvent("线宽值", $"线宽2:{order.LineWidth2}"); break; case 3: order.LineWidth3 = lstLineWidth[count - 1]; AddTextEvent("线宽值", $"线宽3:{order.LineWidth3}"); break; case 4: order.LineWidth4 = lstLineWidth[count - 1]; AddTextEvent("线宽值", $"线宽4:{order.LineWidth4}"); break; case 5: order.LineWidth5 = lstLineWidth[count - 1]; AddTextEvent("线宽值", $"线宽5:{order.LineWidth5}"); break; case 6: order.LineWidth6 = lstLineWidth[count - 1]; AddTextEvent("线宽值", $"线宽6:{order.LineWidth6}"); break; case 7: order.LineWidth7 = lstLineWidth[count - 1]; AddTextEvent("线宽值", $"线宽7:{order.LineWidth7}"); break; case 8: order.LineWidth8 = lstLineWidth[count - 1]; AddTextEvent("线宽值", $"线宽8:{order.LineWidth8}"); break; case 9: order.LineWidth9 = lstLineWidth[count - 1]; AddTextEvent("线宽值", $"线宽9:{order.LineWidth9}"); break; } List lstValidValue = new List(); for (int i = 0; i < count; i++) { if (lstLineWidth[i] > 0) lstValidValue.Add(lstLineWidth[i]); } if (lstValidValue.Count < 1) return;//WLQ 前面失败时会向lstLineWidth.add(0) double value = Math.Round(lstValidValue.Average(), 2); double valueMax = lstValidValue.Max(); double valueMin = lstValidValue.Min(); if (order != null) order.LineWidthValue = value; Color color = (upperLimit + lowerLimit > 0 && (value > upperLimit || value < lowerLimit)) ? Color.Red : Color.White; Color colorMax = (upperLimit + lowerLimit > 0 && (valueMax > upperLimit || valueMax < lowerLimit)) ? Color.Red : Color.White; Color colorMin = (upperLimit + lowerLimit > 0 && (valueMin > upperLimit || valueMin < lowerLimit)) ? Color.Red : Color.White; this.Invoke(new System.Action(() => { this.lblLineWidth.Text = Math.Round(value, 2).ToString(); this.lblLineWidth.ForeColor = color; this.lblLineWidthMax.Text = Math.Round(valueMax, 2).ToString(); this.lblLineWidthMax.ForeColor = colorMax; this.lblLineWidthMin.Text = Math.Round(valueMin, 2).ToString(); this.lblLineWidthMin.ForeColor = colorMin; })); //不合格 if (color == Color.Red) order.Qualified = false; } private void updatePTValue(double upperLimit, double lowerLimit) { //每次加2个:PT1,PT2 int count = lstPT.Count(); if (count < 1) return; switch (count) { case 2: order.PT1 = lstPT[count - 2]; order.PT2 = lstPT[count - 1]; AddTextEvent("PT值",$"PT1:{order.PT1},PT2:{order.PT2}"); break; case 4: order.PT3 = lstPT[count - 2]; order.PT4 = lstPT[count - 1]; AddTextEvent("PT值", $"PT3:{order.PT3},PT4:{order.PT4}"); break; case 6: order.PT5 = lstPT[count - 2]; order.PT6 = lstPT[count - 1]; AddTextEvent("PT值", $"PT5:{order.PT5},PT6:{order.PT6}"); break; } List lstValidValue = new List(); for (int i = 0; i < count; i++) { if (lstPT[i] > 0) lstValidValue.Add(lstPT[i]); } double value = Math.Round(lstValidValue.Average(), 4); double valueMax = lstValidValue.Max(); double valueMin = lstValidValue.Min(); if (order != null) order.PTValue = value; Color color = (upperLimit + lowerLimit > 0 && (value > upperLimit || value < lowerLimit)) ? Color.Red : Color.White; Color colorMax = (upperLimit + lowerLimit > 0 && (valueMax > upperLimit || valueMax < lowerLimit)) ? Color.Red : Color.White; Color colorMin = (upperLimit + lowerLimit > 0 && (valueMin > upperLimit || valueMin < lowerLimit)) ? Color.Red : Color.White; this.Invoke(new System.Action(() => { this.lblPT.Text = value.ToString(); this.lblPT.ForeColor = color; this.lblPTMax.Text = Math.Round(valueMax, 4).ToString(); this.lblPTMax.ForeColor = colorMax; this.lblPTMin.Text = Math.Round(valueMin, 4).ToString(); this.lblPTMin.ForeColor = colorMin; })); //不合格 if (color == Color.Red) order.Qualified = false; } private void updatePTValueTest(double upperLimit, double lowerLimit) { //每次加2个:PT1,PT2 int count = lstPT.Count(); if (count < 1) return; switch (count) { case 1: order.PT1 = lstPT[count - 1]; AddTextEvent("PT1", $"PT1:{order.PT1}"); break; case 2: order.PT2 = lstPT[count - 1]; AddTextEvent("PT2", $"PT2:{order.PT2}"); break; case 3: order.PT3 = lstPT[count - 1]; order.PT4 = 0; AddTextEvent("PT3", $"PT3:{order.PT3}"); break; case 4: order.PT5 = lstPT[count - 1]; AddTextEvent("PT4", $"PT4:{order.PT5}"); break; case 5: order.PT6 = lstPT[count - 1]; AddTextEvent("PT5", $"PT5:{order.PT6}"); break; } List lstValidValue = new List(); for (int i = 0; i < count; i++) { if (lstPT[i] > 0) lstValidValue.Add(lstPT[i]); } double value = Math.Round(lstValidValue.Average(), 4); double valueMax = lstValidValue.Max(); double valueMin = lstValidValue.Min(); if (order != null) order.PTValue = value; Color color = (upperLimit + lowerLimit > 0 && (value > upperLimit || value < lowerLimit)) ? Color.Red : Color.White; Color colorMax = (upperLimit + lowerLimit > 0 && (valueMax > upperLimit || valueMax < lowerLimit)) ? Color.Red : Color.White; Color colorMin = (upperLimit + lowerLimit > 0 && (valueMin > upperLimit || valueMin < lowerLimit)) ? Color.Red : Color.White; this.Invoke(new System.Action(() => { this.lblPT.Text = value.ToString(); this.lblPT.ForeColor = color; this.lblPTMax.Text = Math.Round(valueMax, 4).ToString(); this.lblPTMax.ForeColor = colorMax; this.lblPTMin.Text = Math.Round(valueMin, 4).ToString(); this.lblPTMin.ForeColor = colorMin; })); //不合格 if (color == Color.Red) order.Qualified = false; } private void updateCompareResult(bool compareResult) { this.Invoke(new System.Action(() => { this.lblCompareResult.Text = (order.CompareResult==1 ? "通过" : "未通过"); if (!compareResult) { this.lblCompareResultCount.Text = (Convert.ToInt16(lblCompareResultCount.Text) + 1).ToString(); this.lblCompareResult.ForeColor = lblCompareResultCount.ForeColor=Color.Red; //不合格 order.Qualified = false; } })); } private void resetUIValue() { this.Invoke(new System.Action(() => { //保持产品名称和料号 //txtProductName.Text = txtProductCode.Text = txtProductSN.Text = ""; txtProductSN.Text = ""; lstHeight.Clear(); lstLineWidth.Clear(); lstTension.Clear(); lstPT.Clear(); this.lblTension.Text = this.lblHeight.Text = this.lblLineWidth.Text = "0.00"; this.lblPT.Text = this.lblPTMax.Text= this.lblPTMin.Text="0.0000"; this.lblCompareResult.Text =this.lblDefectResult.Text = "无"; this.lblTensionMax.Text = this.lblHeightMax.Text = this.lblLineWidthMax.Text = this.lblTensionMin.Text = this.lblHeightMin.Text = this.lblLineWidthMin.Text = "0.00"; this.lblCompareResultCount.Text = "0"; this.lblDefectResultCount.Text = "无"; this.toolTip1.SetToolTip(lblDefectResultCount, lblDefectResultCount.Text); // this.lblTension.ForeColor = this.lblHeight.ForeColor = this.lblLineWidth.ForeColor = this.lblPT.ForeColor = this.lblCompareResult.ForeColor= this.lblDefectResult.ForeColor=Color.White; this.lblTensionMax.ForeColor = this.lblHeightMax.ForeColor = this.lblLineWidthMax.ForeColor = this.lblPTMax.ForeColor = this.lblTensionMin.ForeColor = this.lblHeightMin.ForeColor = this.lblLineWidthMin.ForeColor = this.lblPTMin.ForeColor = Color.White; this.lblCompareResultCount.ForeColor = this.lblDefectResultCount.ForeColor=Color.White; this.dgvProcess.DataSource = null; this.lstLog.Items.Clear(); this.clearDefectBmps(); this.picScanner1.Image = this.picScanner2.Image = null; picScanner1.Refresh(); picScanner2.Refresh(); this.btnMakeTags.Enabled = false; })); } //info: [{"1":[["92.7542","80.85799","99.54083","86.05363","dk","0.52"]]}, private void showDefectSmallBmps(Bitmap[] bmps, Mat[] bmps_cut, double Xmm, double Ymm, List[]>> info) { this.Invoke(new System.Action(() => { int imgWidth = this.pnlBmpList.ClientSize.Width - 50; int imgHeight = (int)((bmps[0].Height * 1.0f / bmps[0].Width) * imgWidth + 0.5); int splitWidth = 20; int pnlWidth = this.pnlBmpList.ClientSize.Width; int index = (int)this.gboxDefectList.Tag; for (int x = 0; x < info.Count(); x++) { foreach (var item in info[x]) //单个info[x] = {"1":[["92.7542","80.85799","99.54083","86.05363","dk","0.52"]]} { //统计缺陷类型 countDefectClass(item.Value);//[["92.7542","80.85799","99.54083","86.05363","dk","0.52"]] // PictureBox picbox = new PictureBox(); picbox.Width = imgWidth; picbox.Height = imgHeight; CheckBox checkBox = new CheckBox(); picbox.Image = (Bitmap)bmps[x].Clone(); picbox.Name = "imgDefect_" + index; picbox.Tag = item.Key + "," + Xmm + "," + Ymm; checkBox.Tag = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(bmps_cut[item.Key]); //Mat转Bitmap ;//原始小图 checkBox.Name = "chkDefect_" + index; checkBox.Text = $"第{index + 1}张"; checkBox.CheckedChanged += new System.EventHandler(this.CheckBox_CheckedChanged); if (Config.MakeTag)//自动打标 { checkBox.Checked = true; checkBox.Enabled = false; } picbox.Click += new EventHandler(defectBmpBox_Click); picbox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; picbox.BorderStyle = BorderStyle.FixedSingle; picbox.Margin = new Padding((pnlWidth - picbox.Width) / 2, splitWidth,0, 0); checkBox.Margin = new Padding((pnlWidth - checkBox.Width) / 2 + splitWidth, 0, 0, 0); // //if (this.pnlBmpList.Controls.Count > 0) //{ // if ((this.pnlBmpList.Controls[this.pnlBmpList.Controls.Count - 1].Right + imgWidth + splitWidth) > this.pnlBmpList.Width) // picbox.Location = new System.Drawing.Point(splitWidth, this.pnlBmpList.Controls[this.pnlBmpList.Controls.Count - 1].Bottom + splitWidth); // else // picbox.Location = new System.Drawing.Point(this.pnlBmpList.Controls[this.pnlBmpList.Controls.Count - 1].Right + splitWidth, this.pnlBmpList.Controls[this.pnlBmpList.Controls.Count - 1].Location.Y); //} //else //{ // picbox.Location = new System.Drawing.Point(splitWidth, 0); //} //checkBox.Location = new System.Drawing.Point(picbox.Location.X + 5, picbox.Location.Y + 5); //checkBox.ForeColor = Color.Black; this.pnlBmpList.Controls.Add(picbox); this.pnlBmpList.Controls.Add(checkBox); break; } // index++; }; this.gboxDefectList.Tag = index; this.gboxDefectList.Text = $"缺陷图像:{index} 张"; if (Config.MakeTag) { lblDefectAddTag.Text = $"待打标数:{index}"; lblDefectAddTag.Tag = index; } pnlBmpList.VerticalScroll.Value = pnlBmpList.VerticalScroll.Maximum; })); } //统计缺陷类型 [["92.7542","80.85799","99.54083","86.05363","dk","0.52"]] private void countDefectClass(List[] list) { string className; for(int i=0; i /// 异步输出日志 /// /// 模板标识 /// 内容 /// private void AddTextEvent(string tag, string msg, WarningEnum level = WarningEnum.Normal) { try { if (InvokeRequired) { Invoke(new AddTextDelegate(AddTextEvent), new object[] { tag, msg, level }); } else { if (tag != null && tag != "") tag = $" - [{tag}]"; var now = DateTime.Now; msg = now.ToString("HH:mm:ss fff") + tag + " - " + msg; //cont = MyHelper.subString(cont, 300); //写日志,warn和error日志直接写 writeLog(now, level, msg); // //if (type > 0) // cont = $"{cont}"; msg = (level == WarningEnum.Normal ? "B" : level == WarningEnum.Low ? "Y" : "R") + msg; this.Invoke(new System.Action(() => { if (this.lstLog.Items.Count > 1000) this.lstLog.Items.Clear(); lstLog.Items.Insert(0, msg); })); //日志滚动 //lstLog.SelectedIndex = lstLog.Items.Count - 1; } } catch (Exception ex) { //MessageBox.Show("AddTextEvent ex=(" + ex.Message + ")", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, 0); } } private void lstLog_DrawItem(object sender, DrawItemEventArgs e) { e.DrawBackground(); if (e.Index < 0) return; try { string str = lstLog.Items[e.Index].ToString(); e.Graphics.DrawString(str.Substring(1), e.Font, new SolidBrush(str[0] == 'R' ? Color.Red : (str[0] == 'Y' ? Color.Orange : Color.Black)), e.Bounds); } catch { ; } } private void writeLog(DateTime now, WarningEnum level, string text) { string directory = Config.LogPath + "\\" + DateTime.Now.ToString("yyyyMM") + "\\"; //if (type == 0) directory = Application.StartupPath + "\\Log\\Info\\"; //else if (type == 1) directory = Application.StartupPath + "\\Log\\Warn\\"; //else directory = Application.StartupPath + "\\Log\\Error\\"; if (!System.IO.Directory.Exists(directory)) System.IO.Directory.CreateDirectory(directory); File.AppendAllText(directory + now.ToString("yyyyMMdd") + ".log", text + "\r\n"); } private void FrmMian_FormClosing(object sender, FormClosingEventArgs e) { if (devContainer.state) { MessageBox.Show("请先停止生产后才能关闭程序!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning); e.Cancel = true; return; } if (!bExitApp && MessageBox.Show($"确认退出?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) { e.Cancel = true; return; } } private void FrmMian_FormClosed(object sender, FormClosedEventArgs e) { webService.stop(); Application.Exit(); System.GC.Collect(); System.Environment.Exit(0); } private void tsbtnOpenDev_Click(object sender, EventArgs e) { //FrmGetPosByPic frr = new FrmGetPosByPic(new SizeLibProp()); //frr.ShowDialog(); Config.LoadAllConfig(); //设置程序最小/大线程池 // Get the current settings. int minWorker, minIOC; ThreadPool.GetMinThreads(out minWorker, out minIOC); ThreadPool.SetMinThreads(25, minIOC); //ThreadPool.SetMaxThreads(256, 256); this.tsbtnProductRevise.Enabled = false; this.tsbtnOpenDev.Enabled = false; //scannerCBmpIndex = 0; isProductRevise = false; this.resetUIValue(); currProcessIndex = -1; currentState = CurrentStateEnum.等待复位; warningLevel = WarningEnum.Normal; currentPT = CurrentPTEnum.InitPT; this.tsbtnWarning.Enabled=this.tsbtnGoDownPT.Enabled=this.tsbtnStart.Enabled=this.tsbtnStopNow.Enabled=this.tsbtnPause.Enabled=this.tsbtnReset.Enabled=false; //后台线程回调事件 devContainer.StateChange = (state, msg) => { if (state) { //全局中断 devContainer.devIOCard.INEvent = globalBreakEvent; devContainer.OutDebugEvent = (tag, debugInfo) => { AddTextEvent(tag, debugInfo); }; // AddTextEvent("设备启动", "请先进行复位操作!"); this.Invoke(new System.Action(() => { this.tsbtnReset.Enabled = true; tsbtnWarning.Enabled = this.tsbtnStart.Enabled = this.tsbtnGoDownPT.Enabled = this.tsbtnPause.Enabled = this.tsbtnStopNow.Enabled = false; this.tsbtnOpenDev.Enabled = true; this.tsbtnOpenDev.Visible = false; this.tsbtnCloseDev.Visible = true; })); timer.Elapsed += Timer_Elapsed; timer.Interval = 500; timer.Start(); } else { AddTextEvent("设备启动", $"启动失败,{msg}", WarningEnum.High); this.Invoke(new System.Action(() => { this.tsbtnOpenDev.Enabled = true; this.tsbtnOpenDev.Visible = true; this.tsbtnCloseDev.Visible = false; })); } }; devContainer.WarningEvent = (level, msg) => { AddTextEvent("设备事件", msg, level); if (level == WarningEnum.High) warning(level,true); }; devContainer.start(this.picScanner1.Handle, this.picScanner2.Handle); } private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { this.Invoke(new System.Action(() => { this.tsAxisState.Text = $"[命令位:{devContainer.devAxis.CmdPos[0]} 反馈位:{devContainer.devAxis.ActualPos[0]}] | " + $"[命令位:{devContainer.devAxis.CmdPos[1]} 反馈位:{devContainer.devAxis.ActualPos[1]}] | " + $"[命令位:{devContainer.devAxis.CmdPos[2]} 反馈位:{devContainer.devAxis.ActualPos[2]}] | " + $"[命令位:{devContainer.devAxis.CmdPos[3]} 反馈位:{devContainer.devAxis.ActualPos[3]}]"; })); } private void tsbtnCloseDev_Click(object sender, EventArgs e) { AddTextEvent("设备停止", $"设备停止..."); this.tsbtnProductRevise.Enabled = false; this.tsbtnOpenDev.Visible = true; this.tsbtnCloseDev.Visible = false; this.btnMakeTags.Enabled = false; this.lblTimeLen.Visible = false; this.tsbtnReset.Enabled = tsbtnWarning.Enabled = this.tsbtnStart.Enabled = this.tsbtnGoDownPT.Enabled = this.tsbtnPause.Enabled = this.tsbtnStopNow.Enabled = false; this.tsbtnSizeTag.Enabled = tsbtnSizeImage.Enabled = tsbtnDefectImage.Enabled = false; if (devContainer.state) { devContainer.devIOCard.reset(); devContainer.io_output(CMDName.IO默认输出); } timer.Stop(); devContainer.stop(); } /// /// 全局中断 /// private void globalBreakEvent(int portIndex, byte data) { if (compareIOInput(CMDName.启动按钮) && this.tsbtnStart.Enabled) startCommand(); else if (compareIOInput(CMDName.暂停按钮) && this.tsbtnPause.Enabled) warning(WarningEnum.Low, false); else if (compareIOInput(CMDName.复位按钮) && this.tsbtnReset.Enabled) resetCommand(); else if (compareIOInput(CMDName.张力读取) && currentPT == CurrentPTEnum.Moving) readTension(); else if (!this.disableBuzzer && compareIOInput(CMDName.门磁告警输入)) warning(WarningEnum.Low, true); else if (!this.disableBuzzer && compareIOInput(CMDName.喷墨告警输入)) warning(WarningEnum.Low, true); } private bool compareIOInput(CMDName key) { JObject joJson = Config.CMDProcess[key]; IODirectionEnum direction = (IODirectionEnum)joJson.Value("Direction"); if (direction == IODirectionEnum.输入 || direction == IODirectionEnum.输入输出) { return Util.compareIOInput( joJson.Value("IN_OP_SHOW").ToObject>().ToArray(), devContainer.devIOCard.DIData); } return false; } private void readTension() { if (Config.SkipTension) { AddTextEvent("张力读取", $"张力设备禁用,忽略此步骤!"); return; } devContainer.io_output(CMDName.张力读取); double tensionValue = devContainer.devTension.getValue() + Config.Tension_Offset;//加入张力偏差 tensionValue=Math.Round(tensionValue, 2);//保留2位小数 AddTextEvent("张力读取", $"张力值:{tensionValue}"); devContainer.io_output(CMDName.张力读取,false,true,500); lstTension.Add(tensionValue); updateTensionValue(currProductModel.TensionBaseValue + currProductModel.TensionUpFloatValue, currProductModel.TensionBaseValue - currProductModel.TensionDownFloatValue); } /// /// 启动 /// private void startCommand() { this.setButtonEnabled(this.tsbtnProductRevise, false); //2023-10-23 运行前清除过期图片文件 Config.DelectPictureFile(); if (!devContainer.state || warningLevel != WarningEnum.Normal || currentState != CurrentStateEnum.等待启动) return; if (currentPT == CurrentPTEnum.MakeTag) { AddTextEvent("启动", "打标未结束,非可启动状态!", warningLevel); return; } if (!devContainer.devAxis.isReady()) { AddTextEvent("启动", "轴状态异常,不可启动!", warningLevel); return; } if (!devContainer.devAxis.IsReset) { AddTextEvent("启动", "轴需先进行复位操作!", WarningEnum.High); return; } devContainer.io_output(CMDName.启动按钮); devContainer.io_output(CMDName.绿灯输出); devContainer.io_output(CMDName.暂停按钮, false, true, 0); devContainer.io_output(CMDName.红灯输出, false, true, 0); devContainer.io_output(CMDName.黄灯输出, false, true, 0); //暂停-》继续 if (currProcessIndex >= 0 && currentPT == CurrentPTEnum.Moving && currentState == CurrentStateEnum.等待启动) { AddTextEvent("启动", $"暂停 -> 继续 当前工序索引:{currProcessIndex + 1}"); threadProcess = new System.Threading.Thread(() => { int nextStepId = currProcessIndex; do { currentState = CurrentStateEnum.运行中; nextStepId = nextProcess(currProductModel, nextStepId); } while (nextStepId >= 0 && !isBreakProcessRun()); //nextProcess(currProductModel, currProcessIndex); }); threadProcess.IsBackground = true; threadProcess.Start(); this.setButtonEnabled(this.tsbtnPause, true); this.setButtonEnabled(this.tsbtnStopNow, true); } else//开始/重新开始 { //校正从复位-》运行,不会新启动 isProductRevise = false; resetUIValue(); AddTextEvent("启动", "移动至上料位..."); gotoUpPT(); this.Invoke(new System.Action(() => { //新开始 lblTimeLen.Visible = false; runStep(); })); this.setButtonEnabled(this.tsbtnPause, false); this.setButtonEnabled(this.tsbtnStopNow, false); } this.setButtonEnabled(this.tsbtnStart, false); this.setButtonEnabled(this.tsbtnReset, false); this.setButtonEnabled(this.tsbtnGoDownPT, false); } /// /// 暂停 /// /// 是否响蜂鸣 private void pauseCommand(bool buzzer = false) { devContainer.io_output(CMDName.暂停按钮); if (buzzer) { devContainer.io_output(CMDName.红灯输出); devContainer.io_output(CMDName.蜂鸣器输出); } else devContainer.io_output(CMDName.黄灯输出); devContainer.io_output(CMDName.启动按钮, false, true, 0); devContainer.io_output(CMDName.绿灯输出, false, true, 0); this.setButtonEnabled(this.tsbtnWarning, true); this.setButtonEnabled(this.tsbtnGoDownPT, false); this.setButtonEnabled(this.tsbtnStart, false); this.setButtonEnabled(this.tsbtnPause, false); this.setButtonEnabled(this.tsbtnStopNow, false); this.setButtonEnabled(this.tsbtnReset, false); AddTextEvent("暂停", $"当前工序索引:{currProcessIndex + 1}", WarningEnum.Low); } /// /// 急停 /// private void stopNowCommand() { if (!devContainer.state) { this.setButtonEnabled(this.tsbtnStopNow, false); return; } devContainer.io_output(CMDName.Y轴复位输出, false, true, 0); devContainer.io_output(CMDName.红灯输出); if (!this.disableBuzzer) devContainer.io_output(CMDName.蜂鸣器输出); devContainer.io_output(CMDName.暂停按钮, false, true, 0); devContainer.io_output(CMDName.黄灯输出, false, true, 0); devContainer.io_output(CMDName.启动按钮, false, true, 0); devContainer.io_output(CMDName.绿灯输出, false, true, 0); this.setButtonEnabled(this.tsbtnWarning, true); this.setButtonEnabled(this.tsbtnGoDownPT, false); this.setButtonEnabled(this.tsbtnStart, false); this.setButtonEnabled(this.tsbtnPause, false); this.setButtonEnabled(this.tsbtnStopNow, false); this.setButtonEnabled(this.tsbtnReset, false); AddTextEvent("急停", $"当前工序索引:{currProcessIndex + 1}", WarningEnum.High); } private bool reseting = false; private void resetCommand() { currentState = CurrentStateEnum.等待复位; warningLevel = WarningEnum.Normal; currentPT = CurrentPTEnum.InitPT; this.Invoke(new System.Action(() => { lblTimeLen.Visible = false; this.tsbtnWarning.Enabled = this.tsbtnGoDownPT.Enabled = this.tsbtnStart.Enabled = this.tsbtnStopNow.Enabled = this.tsbtnPause.Enabled = this.tsbtnReset.Enabled = false; })); try { if (devContainer.state && !reseting) { reseting = true; isProductRevise = false; resetUIValue(); AddTextEvent("复位", $"设备复位中..."); currProcessIndex = -1; this.setButtonEnabled(this.tsbtnReset, false); // I/O reset后,输出默认状态 AddTextEvent("复位", $"I/O复位中..."); if (!devContainer.devIOCard.reset()) { AddTextEvent("复位", "I/O板卡复位失败!", WarningEnum.High); return; } if (!devContainer.io_output(CMDName.IO默认输出)) { //AddTextEvent("复位", "I/O板卡复位默认值失败!", WarningEnum.High); //return; } //板卡复位输出灯 devContainer.io_output(CMDName.复位按钮); devContainer.io_output(CMDName.黄灯输出, true); //4.5X if(!Config.SkipSmallAxis) devContainer.devSmallAxis.gotoPos((int)SmallAxCmdPos.倍率4_5X, false); //移动Axis前等待厚度传感器收回 AddTextEvent("复位", $"检测厚度传感器安全值..."); if (!Config.SkipHeight) { while (devContainer.devHeight.getHeight() < (double)Math.Abs(Config.HeightDev_SafeValue)) { if (!devContainer.state || currentState != CurrentStateEnum.等待复位) return; Thread.Sleep(100); Application.DoEvents(); } } //goto ORG AddTextEvent("复位", $"轴正在回原点..."); devContainer.devAxis.closeJogMode(); devContainer.devAxis.resetAxisState(-1);//reset state //AddTextEvent("复位", $"重置轴状态..."); for (int i = 0; i < Config.Axis_HomeMode.Length; i++) { //到起始位速度使用回HOME速度 devContainer.devAxis.setAxisVelParam((double)Config.Axis_HomeVelLow[i], (double)Config.Axis_HomeVelHigh[i], (double)Config.Axis_HomeAcc[i], (double)Config.Axis_HomeDec[i], i); if (i != 2) { //devContainer.devAxis.setAxisVelParam(40000,200000,5000000, 5000000,i,true); devContainer.devAxis.home(i, (uint)Config.Axis_HomeMode[i], (uint)Config.Axis_HomeDir[i]); } else//Y轴 I/O控制回HOME { devContainer.io_output(CMDName.Y轴复位输出); } } AddTextEvent("复位", $"等待轴状态完成..."); while (!devContainer.devAxis.isReady()) { if (!devContainer.state || currentState != CurrentStateEnum.等待复位) { AddTextEvent("复位", $"当前状态:"+ ((CurrentStateEnum)currentState).ToString()); return; } //AddTextEvent("复位", $"轴0状态:"+ ((AxisState)devContainer.devAxis.AxState[0]).ToString()); //AddTextEvent("复位", $"轴1状态:" + ((AxisState)devContainer.devAxis.AxState[1]).ToString()); //AddTextEvent("复位", $"轴2状态:" + ((AxisState)devContainer.devAxis.AxState[2]).ToString()); //AddTextEvent("复位", $"轴3状态:" + ((AxisState)devContainer.devAxis.AxState[3]).ToString()); Thread.Sleep(1000); Application.DoEvents(); } //判断Y轴回原点完成I/O信号 AddTextEvent("复位", $"等待Y轴回HOME完成..."); while (!this.compareIOInput(CMDName.Y轴复位完成输入)) { Thread.Sleep(100); Application.DoEvents(); } AddTextEvent("复位", $"Y轴回HOME已完成."); devContainer.io_output(CMDName.Y轴复位输出, false, true, 0); AddTextEvent("复位", $"重置Y轴反馈位置与命令位置."); devContainer.devAxis.resetCmdPosition(2); devContainer.devAxis.resetActualPosition(2); // if (devContainer.devAxis.isError()) throw new Exception("轴回原点失败!"); if (Config.OpenAxisXCalibration) { //2023-11-29 加入X1X2回原之后启动补偿 devContainer.io_output(CMDName.X1轴复位输出, false, true, 300); devContainer.io_output(CMDName.X2轴复位输出, false, true, 300); } // //goto InitPT //AddTextEvent("复位", $"轴回原点完成,回到初始位..."); JArray arrPT = Config.joPTSetting.Value("initPT"); for (int i = 0; i < arrPT.Count; i++) { if (!devContainer.state || currentState != CurrentStateEnum.等待复位) return; AddTextEvent($"复位", $"轴{i}准备运动至初始位:{(double)arrPT[i]}(当前轴状态:{((AxisState)devContainer.devAxis.AxState[i]).ToString()})..."); devContainer.devAxis.move_ptp(i, (double)arrPT[i], AxMoveMode.绝对位置); } while (!devContainer.devAxis.isReady()) { if (!devContainer.state || warningLevel != WarningEnum.Normal) return; Thread.Sleep(100); } if (devContainer.devAxis.isError()) throw new Exception("轴移动至初始位失败!"); // this.setButtonEnabled(this.tsbtnReset, true); this.setButtonEnabled(this.tsbtnStart, true); this.setButtonEnabled(this.tsbtnStopNow, true); this.setButtonEnabled(this.tsbtnPause, false); this.setButtonEnabled(this.tsbtnGoDownPT, false); this.setButtonEnabled(this.tsbtnWarning, false); devContainer.io_output(CMDName.复位按钮, false, true, 0);//熄灭 devContainer.io_output(CMDName.黄灯输出);//长亮 currentPT = CurrentPTEnum.InitPT; currentState = CurrentStateEnum.等待启动; AddTextEvent("复位", $"复位完成。"); this.setButtonEnabled(this.tsbtnProductRevise, true); } else { AddTextEvent("复位", "非可复位状态,请先停止后再复位!", WarningEnum.High); } } catch (Exception ex) { AddTextEvent("复位", "复位失败 Err:" + ex.Message, WarningEnum.High); warning(WarningEnum.High, true); } finally { reseting = false; } } /// /// 上料 /// private void gotoUpPT() { try { JArray arrPT = Config.joPTSetting.Value("upPT"); for (int i = 0; i < arrPT.Count; i++) { if (!devContainer.state || warningLevel != WarningEnum.Normal) return; AddTextEvent($"上料", $"轴{i}准备运动至上料位:{(double)arrPT[i]}(当前轴状态:{((AxisState)devContainer.devAxis.AxState[i]).ToString()})..."); devContainer.devAxis.move_ptp(i, (double)arrPT[i], AxMoveMode.绝对位置); } while (!devContainer.devAxis.isReady()) { if (!devContainer.state || warningLevel != WarningEnum.Normal) return; Thread.Sleep(100); } if (devContainer.devAxis.isError()) throw new Exception("轴移动至上料位失败!"); // currentPT = CurrentPTEnum.UpPT; currentState = CurrentStateEnum.等待扫码; AddTextEvent($"上料", "到达上料位!"); } catch (Exception ex) { AddTextEvent("上料", "上料初始失败 Err:" + ex.Message, WarningEnum.High); warning(WarningEnum.High); } } /// /// 下料 /// private void gotoDownPT() { try { if (currentState != CurrentStateEnum.打标中 && currentState != CurrentStateEnum.等待启动 && currentState != CurrentStateEnum.自动流程结束) { AddTextEvent($"下料", $"非可下料状态:{currentState.ToString()}"); return; } currentState = CurrentStateEnum.下料中; isProductRevise = false; JArray arrPT = Config.joPTSetting.Value("downPT"); for (int i = 0; i < arrPT.Count; i++) { if (!devContainer.state || warningLevel != WarningEnum.Normal || currentState != CurrentStateEnum.下料中) return; AddTextEvent($"下料", $"轴{i}准备运动至下料位:{(double)arrPT[i]}(当前轴状态:{((AxisState)devContainer.devAxis.AxState[i]).ToString()})..."); devContainer.devAxis.move_ptp(i, (double)arrPT[i], AxMoveMode.绝对位置); } while (!devContainer.devAxis.isReady()) { if (!devContainer.state || warningLevel != WarningEnum.Normal || currentState != CurrentStateEnum.下料中) return; Thread.Sleep(100); } if (devContainer.devAxis.isError()) throw new Exception("轴移动至下料位失败!"); // currentPT = CurrentPTEnum.DownPT; currentState = CurrentStateEnum.等待启动; devContainer.io_output(CMDName.下料完成输出); setButtonEnabled(tsbtnStart, true); AddTextEvent($"下料", "下料完成!"); } catch (Exception ex) { AddTextEvent("下料", "下料失败 Err:" + ex.Message, WarningEnum.High); warning(WarningEnum.High); } } private void setButtonEnabled(ToolStripButton button, bool Enabled) { this.Invoke(new System.Action(() => { button.Enabled = Enabled; })); } private void setButtonEnabled(ToolStripMenuItem button, bool Enabled) { this.Invoke(new System.Action(() => { button.Enabled = Enabled; })); } private void setButtonEnabled(Control button, bool Enabled) { this.Invoke(new System.Action(() => { button.Enabled = Enabled; })); } private void FrmMian_Shown(object sender, EventArgs e) { } private void FrmMian_Resize(object sender, EventArgs e) { } private void 流程管理ToolStripMenuItem_Click(object sender, EventArgs e) { if (devContainer.state) { MessageBox.Show("请先停止生产,再进行流程修改!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } FrmStepList frm = new FrmStepList(); frm.ShowDialog(); } private void 产品管理ToolStripMenuItem_Click(object sender, EventArgs e) { if (devContainer.state) { MessageBox.Show("请先停止生产,再进行产品修改!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } FrmProductList frm = new FrmProductList(); frm.ShowDialog(); loadProductCodeList(); } private void tsbtnProductRevise_Click(object sender, EventArgs e) { if (!devContainer.state) { MessageBox.Show("请先启动设备!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (currentPT != CurrentPTEnum.InitPT || currentState != CurrentStateEnum.等待启动) { MessageBox.Show("请先复位设备!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } FrmProductList frm = new FrmProductList(true); if (frm.ShowDialog() == DialogResult.Yes && frm.Product != null)//执行校正 { AddTextEvent("校正", "开始执行产品base厚度校正..."); isProductRevise = true; currProductModel = frm.Product; currProductModel.HeightBaseDec = ""; this.txtProductCode.Text = currProductModel.Code; this.txtProductName.Text = currProductModel.Name; this.txtProductSN.Text = ""; this.dgvProcess.DataSource = new BindingSource(currProductModel.ReviseStepInfo.ProcessList, null); devContainer.libFor.clear(); devContainer.libIF.clear(); // this.setButtonEnabled(this.tsbtnStart, false); this.setButtonEnabled(this.tsbtnPause, true); this.setButtonEnabled(this.tsbtnStopNow, true); threadProcess = new System.Threading.Thread(() => { int nextStepId = 0; do { currentState = CurrentStateEnum.运行中; nextStepId = nextProcess(currProductModel, nextStepId); } while (nextStepId >= 0 && !isBreakProcessRun()); }); threadProcess.IsBackground = true; threadProcess.Start(); } } private void 设备调试ToolStripMenuItem_Click(object sender, EventArgs e) { if (devContainer.state) { MessageBox.Show("请先停止生产,再进行设备调试!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } FrmDebug3 frm = new FrmDebug3(); frm.ShowDialog(); } private void 角色管理ToolStripMenuItem_Click(object sender, EventArgs e) { FrmRoleRight frm = new FrmRoleRight(); frm.ShowDialog(this); } private void 用户管理ToolStripMenuItem_Click(object sender, EventArgs e) { FrmUserList frm = new FrmUserList(); frm.ShowDialog(this); } private void 退出ToolStripMenuItem_Click(object sender, EventArgs e) { Application.Exit(); System.GC.Collect(); System.Environment.Exit(0); } private void 注销ToolStripMenuItem_Click(object sender, EventArgs e) { if (devContainer.state) { MessageBox.Show("请先停止生产再退出!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } if (MessageBox.Show($"确认退出?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { this.bExitApp = true; Process.Start(Application.StartupPath + "\\ProductionControl.exe"); this.Close(); } } private void splitContainer1_Panel1_Resize(object sender, EventArgs e) { int allWidth = this.splitContainer1.Panel1.Width; this.gpbProductInfo.Width = this.flpnlResultData.Width = this.gpbProcessList.Width = this.gpbLog.Width = allWidth; // this.txtProductName.Width = this.txtProductCode.Width = this.gpbProductInfo.Width - this.txtProductName.Left - 8; this.txtProductSN.Width = this.txtBatchId.Width = (this.txtProductName.Width- lblBatchId.Width)/2; this.lblBatchId.Left = this.txtProductSN.Right ; this.txtBatchId.Left = this.lblBatchId.Right; // int spliceWidth = 5; kanban1.Width = kanban2.Width = kanban3.Width = kanban4.Width = kanban5.Width = kanban6.Width = (flpnlResultData.Width-20) / 6; //2023-10-17 更新log和步骤列表显示 this.gpbProcessList.Height = this.splitContainer1.Panel1.Height - this.gpbProcessList.Top - this.gpbLog.Height; this.gpbLog.Top = this.splitContainer1.Panel1.Height - this.gpbLog.Height; } private void 关于ToolStripMenuItem_Click(object sender, EventArgs e) { AboutBox1 aboutBox1 = new AboutBox1(); aboutBox1.Show(); } private void 系统设置ToolStripMenuItem_Click(object sender, EventArgs e) { FrmSysSetting frmSetting = new FrmSysSetting(); frmSetting.ShowDialog(); } private void dgvProcess_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e) { //string processCode; //for (int i = 0; i < this.dgvProcess.Rows.Count; i++) //{ //processCode = dgvProcess.Rows[i].Cells[0].Value.ToString(); //dgvProcess.Rows[i].Cells[1].Value = Config.dicDevType[processCode]; //} } private void tsbtnWarning_Click(object sender, EventArgs e) { //if (warningLevel == WarningEnum.Normal) //{ // tsbtnWarning.Enabled = false; // return; //} //重置AXIS状态 devContainer.devAxis.resetAxisState(); if (!devContainer.devAxis.isReady()) { AddTextEvent("解除报警", "轴状态未恢复,解除报警失败!", warningLevel); return; } if (devContainer.devAxis.isError()) { AddTextEvent("解除报警", "轴IO状态异常,解除报警失败!", warningLevel); return; } if (!this.disableDoorSensor && compareIOInput(CMDName.门磁告警输入)) { AddTextEvent("解除报警", "门磁告警未清除 ,解除报警失败!", warningLevel); return; } if (!this.disableDoorSensor && compareIOInput(CMDName.喷墨告警输入)) { AddTextEvent("解除报警", "喷墨告警输入未清除 ,解除报警失败!", warningLevel); return; } //关闭蜂鸣器 devContainer.io_output(CMDName.蜂鸣器输出, false, true, 0); devContainer.io_output(CMDName.红灯输出, false, true, 0); devContainer.io_output(CMDName.复位按钮, false, true, 0); if (warningLevel == WarningEnum.High) { AddTextEvent("解除报警", "急停告警已解除,但必需进行复位操作!", warningLevel); currentState = CurrentStateEnum.等待复位; this.tsbtnReset.Enabled = true; tsbtnWarning.Enabled = this.tsbtnStart.Enabled = this.tsbtnGoDownPT.Enabled = this.tsbtnPause.Enabled = this.tsbtnStopNow.Enabled = this.btnMakeTags.Enabled= false; } else { devContainer.io_output(CMDName.黄灯输出); AddTextEvent("解除报警", "告警已解除,请继续选择下一步操作!", warningLevel); if (currentPT == CurrentPTEnum.MakeTag) currentState = CurrentStateEnum.打标中; else currentState = CurrentStateEnum.等待启动; tsbtnWarning.Enabled = false; this.tsbtnStart.Enabled = this.tsbtnGoDownPT.Enabled = true; this.tsbtnReset.Enabled = this.tsbtnPause.Enabled = this.tsbtnStopNow.Enabled = true; } warningLevel = WarningEnum.Normal; } private void tsbtnGoDownPT_Click(object sender, EventArgs e) { if (!devContainer.state || warningLevel!= WarningEnum.Normal) return; if (!devContainer.devAxis.isReady()) { AddTextEvent("下料失败", "轴状态异常!", WarningEnum.Low); return; } gotoDownPT(); } //急停 private void tsbtnStopNow_Click(object sender, EventArgs e) { this.warning(WarningEnum.High); } private Thread threadProcess; private void tsbtnStart_Click(object sender, EventArgs e) { this.startCommand(); } private void tsbtnPause_Click(object sender, EventArgs e) { warning(WarningEnum.Low,false); } //复位 private void tsbtnReset_Click(object sender, EventArgs e) { this.resetCommand(); } private void tsbtnGButSetting_Click(object sender, EventArgs e) { if (devContainer.state) { MessageBox.Show("请先停止生产,再进行设置!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } FrmCMDProcess from = new FrmCMDProcess(); from.ShowDialog(); } private void tsbtnPTSetting_Click(object sender, EventArgs e) { if (devContainer.state) { MessageBox.Show("请先停止生产,再进行设置!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } FrmPTSetting from = new FrmPTSetting(); from.ShowDialog(); } private void tsMenuModifyPW_Click(object sender, EventArgs e) { FrmModifyPW frm = new FrmModifyPW(); frm.ShowDialog(); } //分拆面板平均分配 private void splitContainer1_ClientSizeChanged(object sender, EventArgs e) { if (this.WindowState == FormWindowState.Minimized) return; SplitContainer sc = (SplitContainer)sender; sc.SplitterDistance = sc.Width / 7*3; } private void splitContainer3_ClientSizeChanged(object sender, EventArgs e) { if (this.WindowState == FormWindowState.Minimized) return; SplitContainer sc = (SplitContainer)sender; sc.SplitterDistance = sc.Height / 2; } private void Menu查询统计_Click(object sender, EventArgs e) { FrmWeb frm = new FrmWeb("查询统计", $"reportRecordSN?CustomerVer={Config.CustomerVer}"); frm.Show(); } private void tsMenuOrder_Click(object sender, EventArgs e) { //FrmOrderList frm = new FrmOrderList(); string subject = (sender as ToolStripMenuItem).Text; FrmWeb frm = new FrmWeb(subject, $"reportRecordSN?CustomerVer={Config.CustomerVer}"); frm.Show(); } private void tsMenuOrderProduct_Click(object sender, EventArgs e) { string subject = (sender as ToolStripMenuItem).Text; FrmWeb frm = new FrmWeb(subject, $"reportRecordProduct?CustomerVer={Config.CustomerVer}"); frm.Show(); } private void tsMenuStatistics_Click(object sender, EventArgs e) { string subject = (sender as ToolStripMenuItem).Text; FrmWeb frm = new FrmWeb(subject, $"bigscreen/index.html", "http://127.0.0.1:18082/static/"); frm.Show(); } private void toolStripButton1_Click(object sender, EventArgs e) { //Bitmap[] bmps = new Bitmap[2]; //bmps[0] = new Bitmap(@"f:\1.bmp"); //bmps[1] = new Bitmap(@"f:\111.bmp"); //List[]>> list = new List[]>>(); //Dictionary[]> dir = new Dictionary[]>(); //List[] vs = new List[1]; //vs[0] = new List(); //dir.Add(0, vs); //list.Add(dir); //showDefectSmallBmps(bmps, list); var bmp = Bitmap.FromFile("f:\\1.jpg"); int pnlWidth = this.pnlBmpList.ClientSize.Width; for (int i = 0; i < 5; i++) { int x = i; this.Invoke(new System.Action(() => { int imgWidth = 224; int imgHeight = 200; int splitWidth = 10; int index = Convert.ToInt32(this.gboxDefectList.Tag); PictureBox picbox = new PictureBox(); picbox.Width = imgWidth; picbox.Height = imgHeight; CheckBox checkBox = new CheckBox(); picbox.Image = bmp; picbox.Name = "imgDefect_" + index; picbox.Tag ="1,2,3"; checkBox.Name = "chkDefect_" + index; checkBox.Text = $"第{index + 1}张"; checkBox.CheckedChanged += new System.EventHandler(this.CheckBox_CheckedChanged); picbox.Click += new EventHandler(defectBmpBox_Click); picbox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; picbox.BorderStyle = BorderStyle.FixedSingle; picbox.Margin = new Padding((pnlWidth - picbox.Width) / 2, splitWidth, 0, 0); checkBox.Margin = new Padding((pnlWidth - checkBox.Width) / 2+ splitWidth, 0, 0, 0); // //if (this.pnlBmpList.Controls.Count > 0) // { // if ((this.pnlBmpList.Controls[this.pnlBmpList.Controls.Count - 1].Right + imgWidth + splitWidth) > this.pnlBmpList.Width) // picbox.Location = new System.Drawing.Point(splitWidth, this.pnlBmpList.Controls[this.pnlBmpList.Controls.Count - 1].Bottom + splitWidth); // else // picbox.Location = new System.Drawing.Point(this.pnlBmpList.Controls[this.pnlBmpList.Controls.Count - 1].Right + splitWidth, this.pnlBmpList.Controls[this.pnlBmpList.Controls.Count - 1].Location.Y); // } // else // { // picbox.Location = new System.Drawing.Point(splitWidth, 0); // } // checkBox.Location = new System.Drawing.Point(picbox.Location.X + 5, picbox.Location.Y + 5); // checkBox.ForeColor = Color.Black; //} this.pnlBmpList.Controls.Add(picbox); this.pnlBmpList.Controls.Add(checkBox); // index++; this.gboxDefectList.Tag = index; this.gboxDefectList.Text = $"缺陷图像:{index} 张"; pnlBmpList.VerticalScroll.Value = pnlBmpList.VerticalScroll.Maximum; })); } } private void chkBuzzer_CheckedChanged(object sender, EventArgs e) { this.disableBuzzer = chkBuzzer.Checked; if (devContainer.state && this.disableBuzzer) devContainer.io_output(CMDName.蜂鸣器输出, false, true, 0); } private void chkDoorSensor_CheckedChanged(object sender, EventArgs e) { this.disableDoorSensor = chkDoorSensor.Checked; } private void tsbtnLight_Click(object sender, EventArgs e) { if (devContainer.state) { if(tsbtnLight.Text.Trim()== "开灯") { if(devContainer.io_output(CMDName.日光灯输出)) tsbtnLight.Text = " 关灯 "; } else { if (devContainer.io_output(CMDName.日光灯输出, false, true, 0)) tsbtnLight.Text = " 开灯 "; } } } private void btnMakeTag_Click(object sender, EventArgs e) { if(currentPT != CurrentPTEnum.MakeTag) { AddTextEvent("打标失败", "非可打标状态!"); return; } btnMakeTags.Enabled = false; autoMakeTagRuning = true; Thread threadtest = new System.Threading.Thread(() => { try { if (!devContainer.state) { AddTextEvent("打标", "设备已停机!"); return; } if ((int)this.lblDefectAddTag.Tag < 1) { AddTextEvent("打标", "打标队列为空!"); return; } int tagIndex; double Xmm, Ymm; Bitmap currBmp; string[] tags; for (int i = 0; i < this.pnlBmpList.Controls.Count; i += 2) { CheckBox cb = this.pnlBmpList.Controls[i + 1] as CheckBox; if (cb.Checked) { PictureBox picBox = this.pnlBmpList.Controls[i] as PictureBox; tags = picBox.Tag.ToString().Split(','); tagIndex = Convert.ToInt32(tags[0]); Xmm = Convert.ToDouble(tags[1]); Ymm = Convert.ToDouble(tags[2]); currBmp = (Bitmap)picBox.Image; //打标 AddTextEvent("打标", $"第{i / 2 + 1}/{this.pnlBmpList.Controls.Count / 2}张 [索引:{tagIndex}, X:{Xmm}mm, Y:{Ymm}mm]"); var list = devContainer.libDefect.makeTag(tagIndex, Xmm, Ymm, currBmp.Width, currBmp.Height); devContainer.devAxis.move_ptp(1, list[0], AxMoveMode.绝对位置); devContainer.devAxis.move_ptp(2, list[1], AxMoveMode.绝对位置); while (!devContainer.devAxis.isReady(1) || !devContainer.devAxis.isReady(2)) { Application.DoEvents(); Thread.Sleep(100); if (!devContainer.state) throw new Exception("设备停止,打标中止!"); } // if (!devContainer.io_output(CMDName.喷墨输出, false, true, 500)) throw new Exception("请确认[喷墨输出]指令设置是否正确!"); this.Invoke(new System.Action(() => { cb.Checked = false; })); } } //自动下料 AddTextEvent("打标完成", $"批量打标完成,进行下料..."); currentState = CurrentStateEnum.自动流程结束; gotoDownPT(); } catch (Exception ex) { AddTextEvent("打标失败", ex.Message, WarningEnum.High); warning(WarningEnum.Low, true); } finally { autoMakeTagRuning=false; } }); threadtest.IsBackground = true; threadtest.Start(); } private void btnInputCode_Click(object sender, EventArgs e) { txtProductCode_DoubleClick(null, null); } private void txtProductName_DoubleClick(object sender, EventArgs e) { txtProductCode_DoubleClick(null, null); } private void txtProductCode_DoubleClick(object sender, EventArgs e) { //不需要等待扫码才能选择 //if (currentState != CurrentStateEnum.等待扫码) return; FrmInput frm = new FrmInput(productCodeList, "请选择产品料号:"); if (frm.ShowDialog() != DialogResult.OK && string.IsNullOrWhiteSpace(frm.inputData)) return; //显示料号 //this.txtProductCode.Text = frm.inputData; var model = svcProduct.GetModelNav(frm.inputData); if (model != null && model.StepInfo.ProcessList.Count > 0) { this.txtProductCode.Text = model.Code; this.txtProductName.Text = model.Name; } /*//屏蔽扫码枪事件 Task.Factory.StartNew(() => { devContainer.devCodeScanner.ScanerEvent?.Invoke(frm.inputData); }); */ //string code = Interaction.InputBox("请输入产品编码", "输入框", "", -1, -1).Trim(); //if(code != "") //{ // Task.Factory.StartNew(() => // { // devContainer.devCodeScanner.ScanerEvent?.Invoke(frm.inputData); // }); //} } private void txtProductSN_DoubleClick(object sender, EventArgs e) { //if (currentState != CurrentStateEnum.等待扫码 || this.txtProductCode.Text.Trim()=="") return; //string sn = Interaction.InputBox("请输入产品SN码", "输入框", "", -1, -1).Trim(); //if (sn != "") //{ // this.txtProductSN.Text = sn; // string code = this.txtProductCode.Text.Trim(); // Task.Factory.StartNew(() => // { // devContainer.devCodeScanner.ScanerEvent?.Invoke(code); // }); //} } private void 测试ToolStripMenuItem_Click(object sender, EventArgs e) { tsbtnDefectImage.Enabled = tsbtnSizeImage.Enabled=true; return; Form1 frm = new Form1(); frm.Show(); //tsbtnDefectImage_Click(null, null); return; try { //string ls = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,182.257722637742,182.257727282667,0,0"; //List list = new List(ls.Split(',')); //lstPT = list.Select(q => Convert.ToDouble(q)).ToList(); //updatePTValue(1,2); //lstPT.Add(10); //lstPT.Add(0); //updatePTValue(1, 2); //{ // lstLineWidth.Add(res.Shanxian > 0 ? res.Shanxian : 0); // updateLineWidthValue(model.LineWidthBaseValue + model.LineWidthUpFloatValue, model.LineWidthBaseValue - model.LineWidthDownFloatValue); //} //return; //loadProductCodeList(); //FrmInput frm = new FrmInput(null, "请选择产品编码:"); //if (frm.ShowDialog() != DialogResult.OK) // return; //var model = svcProduct.GetModelNav(frm.inputData); //if (model == null) // throw new Exception("没有此产品!"); //order.ProductId = model.Id; //order.BatchId = model.BatchId; //order.StepId = model.StepId==null? 0:(int)model.StepId; //frm = new FrmInput(null, "请输入SN:"); //if (frm.ShowDialog() != DialogResult.OK) // return; //order.SN = frm.inputData; //frm = new FrmInput(null, "请输入主机台Mark点数据:", "[0,0,0,0,0,0,0,0]"); //if (frm.ShowDialog() != DialogResult.OK) // return; //order.MarkData= frm.inputData; //order.Tension1 = order.Tension2 = order.Tension3 = order.Tension4 = order.Tension5 = order.Tension5 + 3; //order.PT1 = order.PT4 = order.PT5 = order.PT6 = order.PT6 + 1.33; //order.LineWidth2 = order.LineWidth3 = order.LineWidth5 = order.LineWidth6 = +order.LineWidth6 + 1.22; //order.HeightValue = order.Height1 = order.Height3 = order.Height4 = 55; //order.DefectCount = order.DefectCount + 22; //order.YXCount = order.PPCount = 33; //order.TimeLen = 1000; //order.Succeed = true; //order.ModifyUserCode = order.CreateUserCode = Config.loginUser.Code; //if (!svcOrder.Insert(order)) // AddTextEvent("保存失败", $"保存生产记录失败!"); //MessageBox.Show("成功!"); //--------------- this.lstCompareFailZoomImage.Add((Bitmap)Bitmap.FromFile(@"f:\1.bmp")); this.lstCompareFailZoomImage.Add((Bitmap)Bitmap.FromFile(@"f:\2.bmp")); this.lstCompareFailZoomImage.Add((Bitmap)Bitmap.FromFile(@"f:\3.bmp")); } catch(Exception ex) { MessageBox.Show(ex.Message); } } private void toolStripSeparator4_Click(object sender, EventArgs e) { } private void chkHttpLog_CheckedChanged(object sender, EventArgs e) { if (this.chkHttpLog.Checked) { webService.LogEvent = (warning, msg) => { AddTextEvent("HTTP服务", msg, warning); }; } else webService.LogEvent = null; } //打开比对失败的图片 private void lblCompareResult_Click(object sender, EventArgs e) { if (lstCompareFailZoomImage.Count < 1) return; FrmPhotoShow frm = new FrmPhotoShow(lstCompareFailZoomImage); frm.ShowDialog(); } //过程变量查看 private void tsbtnSizeTag_Click(object sender, EventArgs e) { if (order == null || order.SizeTagDataList == null || order.SizeTagDataList.Count<1) return; FrmShowSizeTag frm = new FrmShowSizeTag(order); frm.Show(); } //缺陷+比对与图纸查看 private void tsbtnDefectImage_Click(object sender, EventArgs e) { //currProductModel = svcProduct.GetModelNav(53); //order = svcOrder.GetModelNav("20230814002"); AddTextEvent("打开窗口", "1"); if (currProductModel ==null || order == null || order.DefectInfoList == null || order.DefectInfoList.Count < 1) return; AddTextEvent("打开窗口", "2"); //图纸 try { string gbxBmpPath = ""; var attachmentFile = currProductModel.AttachmentList.FirstOrDefault(x => x.Type == 0); if (attachmentFile != null) { gbxBmpPath = Application.StartupPath + $"\\Attachment\\product\\{attachmentFile.NameTimestamp}"; if (!File.Exists(gbxBmpPath + ".bmp")) gbxBmpPath = ""; } AddTextEvent("打开窗口", "3"); if (string.IsNullOrEmpty(gbxBmpPath)) { MessageBox.Show("图纸文件不存在!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } AddTextEvent("打开窗口", "4"); if (!File.Exists(gbxBmpPath + ".jpg"))//转背景后的图纸文件 { AddTextEvent("打开窗口", "5"); //换背景JPG Mat mat = Cv2.ImRead(gbxBmpPath + ".bmp"); Cv2.CvtColor(mat, mat, ColorConversionCodes.RGB2GRAY);//转灰度图 for (int i = 0; i < mat.Height; i++) { for (int j = 0; j < mat.Width; j++) { if (mat.At(i, j) == 255)//白色 mat.Set(i, j, 0); else mat.Set(i, j, 255); } } AddTextEvent("打开窗口", "6"); //灰转彩 //Cv2.CvtColor(mat, mat, ColorConversionCodes.GRAY2RGB); //for (int i = 0; i < mat.Height; i++) //{ // for (int j = 0; j < mat.Width; j++) // { // if (mat.At(i, j) == 255)//白色 // mat.Set(i, j, 0); //黄色 // } //} OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat).Save(gbxBmpPath + ".jpg", ImageFormat.Jpeg); } AddTextEvent("打开窗口", "7"); // ToolStripButton btn = sender as ToolStripButton; AddTextEvent("打开窗口", btn.Tag.ToString()); FrmShowDefectImage frm = new FrmShowDefectImage(gbxBmpPath + ".jpg", order, string.IsNullOrEmpty(btn.Tag.ToString()) ? 0 : Convert.ToInt32(btn.Tag.ToString())); frm.Show(); AddTextEvent("打开窗口", "9"); } catch (Exception ex) { MessageBox.Show(ex.Message, "异常", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, 0); } } private void tsbtnLog_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(Config.LogPath)) return; string lsPath = (Config.LogPath + "\\" + DateTime.Now.ToString("yyyyMM") + "\\").Replace("\\\\", "\\"); if(!Directory.Exists(lsPath)) Directory.CreateDirectory(lsPath); System.Diagnostics.Process.Start("explorer.exe", lsPath); } } }