banboshi_V1/halftoneproject-master/Code/FrmMain.cs
2023-12-29 09:25:06 +08:00

3698 lines
198 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<string> productCodeList = new List<string>();
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<double> lstTension = new List<double>();
private List<double> lstHeight = new List<double>();
private List<double> lstLineWidth = new List<double>();
private List<double> lstPT = new List<double>();
private Queue<scannerGBmpLoc> scannerGBmpQueue = new Queue<scannerGBmpLoc>();
private Queue<scannerCBmpLoc> scannerCBmpQueue = new Queue<scannerCBmpLoc>();
//private int scannerCBmpIndex = 0;//scannerCBmpQueue中使用当前项的计数器
private int compBmpIndex = 0;//比对777图的索引
private int defectBmpNum = 0;
private int defectBmpNumResult = 0;
/// <summary>
/// 比对失败的图片
/// </summary>
private List<Bitmap> lstCompareFailZoomImage = new List<Bitmap>();
private object myLock=new object();
private WarningEnum warningLevel;//警告等级
private CurrentPTEnum currentPT;//当前点位
private CurrentStateEnum currentState;//当前状态
/// <summary>
/// 当前流程ID暂停/继续时使用
/// </summary>
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();
//}
}
/// <summary>
/// 删除修复台重复sn图片
/// </summary>
private void DeleteRepairImage(string sn)
{
List<string> imagePath = new List<string>
{
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<string> { 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);
}
}
}
//});
}
//后台线程运行
/// <summary>
/// 中断工序运行
/// </summary>
/// <returns></returns>
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<Order>()
.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 系统校正
/// <summary>
///
/// </summary>
/// <param name="model"></param>
/// <param name="stepIndex">0-n</param>
/// <returns>大于等于0正常工序 -1:结束 -2异常</returns>
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<bool>("Disable"))
{
AutoResetEvent endEvent;
uint sleepPre = processParam.Value<uint>("SleepPre");
uint sleepLater = processParam.Value<uint>("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<int>("Direction");
if (direction == IODirectionEnum. || direction == IODirectionEnum.)
{
uint IN_Waiting_Timeout = processParam.Value<uint>("IN_Waiting_Timeout");
AddTextEvent($"{stepIndex + 1}-{processName}", $"等待I/O输入信号{(IN_Waiting_Timeout > 0 ? $"(: {IN_Waiting_Timeout})" : "...")}");
string[] inValue = processParam.Value<JArray>("IN_OP_SHOW").ToObject<List<string>>().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<double>("LimitThresholdVal");
//lowerThresholdVal = processParam.Value<double>("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<double>("LimitThresholdVal");
lowerThresholdVal = processParam.Value<double>("LowerThresholdVal");
bool IsRevise = processParam.Value<bool>("IsRevise");
double relBaseValue = processParam.Value<double>("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<int>("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<bool>("Disable"))
{
//asynRun = processParam.Value<bool>("AsynRun");//异步
int AxisIndex = processParam.Value<int>("AxisIndex");
int DeviceType = processParam.Value<int>("DeviceType");
double VelLow = processParam.Value<double>("VelLow");
double VelHigh = processParam.Value<double>("VelHigh");
double Acc = processParam.Value<double>("Acc");
double Dec = processParam.Value<double>("Dec");
AxMoveMode MoveMode = (AxMoveMode)processParam.Value<int>("MoveMode");//绝对位置
double PPUValue = processParam.Value<double>("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<bool>("AsynRun");//异步
string axisSizeTag= processParam.Value<string>("SizeTag");
int useIndex = processParam.Value<int>("UseIndex");//消费posePT中的索引
AxMoveMode TagMoveMode = (AxMoveMode)processParam.Value<int>("MoveMode");//绝对位置
var AxisIndexList = processParam.Value<JArray>("AxisIndexList").ToObject<List<int>>();
double TagVelLow = processParam.Value<double>("VelLow");
double TagVelHigh = processParam.Value<double>("VelHigh");
double TagAcc = processParam.Value<double>("Acc");
double TagDec = processParam.Value<double>("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<int>("ChannelIndex"); //通道
int DigitalValue = processParam.Value<int>("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<int>("AIEngineLib");
float ExposureTime = processParam.Value<float>("ExposureTime"); //曝光
float Gain = processParam.Value<float>("Gain"); //增益
float ResultingFrameRate = processParam.Value<float>("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<float>("ExposureTime"); //曝光
float GainCC = processParam.Value<float>("Gain"); //增益
float ResultingFrameRateCC = processParam.Value<float>("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<int, string>((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<int>("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<bool>("AsynRun");//异步
limitThresholdVal = processParam.Value<double>("LimitThresholdVal");
lowerThresholdVal = processParam.Value<double>("LowerThresholdVal");
int sizeIndex = processParam.Value<int>("Index");
string sizeTag = processParam.ContainsKey("SizeTag") ? processParam.Value<string>("SizeTag") : "";
//2023-10-27
bool useMap = false;
List<double> getPosList = new List<double>();
try
{
useMap = processParam.Value<bool>("UseMapPoints");
if (useMap) {
var list = model.GetPointList.Split(',');
List<double> dList = new List<double>();
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<JArray>("GetPointList").ToObject<List<double>>();
}
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<string>("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<DefectInfo>();
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<string> { 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<string> { 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<string> { 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<SizeTagData>();
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-29PT1) 不用管,李工处理
{
//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<string> { 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成功或失败线程返回
//---
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<double>("LimitThresholdVal");
lowerThresholdVal = processParam.Value<double>("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<string>("CutSize").Split(',');
string[] aarResize = processParam.Value<string>("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<float>("Thresholds"),
thresholdsClass = processParam.Value<string>("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<DefectInfo>();
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<string> { 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<string> { 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<string> { 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<string> { 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<long>("UniqueId");
int GotoStepIndex = processParam.Value<int>("GotoStepIndex");//1-n
int LimitNum = processParam.Value<int>("LimitNum");//1-n
bool Reset = processParam.Value<bool>("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<long>("UniqueId");
int GotoStepIndex_if = processParam.Value<int>("GotoStepIndex");//1-n
int LimitNum_if = processParam.Value<int>("LimitNum");//1-n
bool Reset_if = processParam.Value<bool>("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<DefectCodeEnum>(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<Order>()
.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<string, float> getProductAreaThreshol(Product m)
{
Dictionary<string, float> dic = new Dictionary<string, float>();
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<DefectCodeEnum>();
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;
}));
}
/// <summary>
/// 报警,只响应low,high
/// </summary>
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<double> lstValidValue = new List<double>();
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<double> lstValidValue = new List<double>();
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<double> lstValidValue = new List<double>();
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<Dictionary<int, List<string>[]>> 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<string>[] list)
{
string className;
for(int i=0; i<list.Length; i++)
{
className = list[i][4];
switch (className)
{
case "dk":
order.DKCount++;
break;
case "zw":
order.ZWCount++;
break;
case "gsyc":
order.GSYCCount++;
break;
case "xws":
order.XWSCount++;
break;
case "qk":
order.QKCount++;
break;
case "zk":
order.ZKCount++;
break;
case "pp":
order.PPCount++;
break;
case "hs":
order.HSCount++;
break;
case "yx":
order.YXCount++;
break;
case "xb":
order.XBCount++;
break;
case "sx":
order.SXCount++;
break;
}
}
}
private int getDefectCountFromCode(Order order, DefectCodeEnum defectCodeEnum)
{
switch (defectCodeEnum)
{
case DefectCodeEnum.dk:
return order.DKCount;
case DefectCodeEnum.zw:
return order.ZWCount;
case DefectCodeEnum.gsyc:
return order.GSYCCount;
case DefectCodeEnum.xws:
return order.XWSCount;
case DefectCodeEnum.qk:
return order.QKCount;
case DefectCodeEnum.zk:
return order.ZKCount;
case DefectCodeEnum.pp:
return order.PPCount;
case DefectCodeEnum.hs:
return order.HSCount;
case DefectCodeEnum.yx:
return order.YXCount;
case DefectCodeEnum.xb:
return order.XBCount;
case DefectCodeEnum.sx:
return order.SXCount;
default:
return 0;
}
}
private void CheckBox_CheckedChanged(object sender, EventArgs e)
{
CheckBox ck = (CheckBox)sender;
int cout = Convert.ToInt32(this.lblDefectAddTag.Tag);
if (ck.Checked)
cout++;
else
cout--;
lblDefectAddTag.Text = $"待打标数:{cout}";
lblDefectAddTag.Tag = cout;
}
private void defectBmpBox_Click(object sender, EventArgs e)
{
// if(autoMakeTagRuning) //自动打标中不可打开人工达标窗
PictureBox picbox = sender as PictureBox;
if (!devContainer.state || defectBmpNum != defectBmpNumResult || autoMakeTagRuning || currentState != CurrentStateEnum.)//检测中
{
//只查看
FrmPhoto frm = new FrmPhoto(this.pnlBmpList.Controls, Convert.ToInt32(picbox.Name.Split(new char[] { '_' })[1]));
frm.ShowDialog(this);
}
else//完成
{
FrmPhotoTag frm = new FrmPhotoTag(this.pnlBmpList.Controls, Convert.ToInt32(picbox.Name.Split(new char[] { '_' })[1])
,(defectBmpNum == defectBmpNumResult ? this.devContainer : null));
frm.ShowDialog(this);
//
if (devContainer.state && !Config.SkipScannerCC)
{
devContainer.devScannerCC.setMode(false);
devContainer.devScannerCC.setPreviewWin(this.picScanner1.Handle);
}
}
}
private void clearDefectBmps()
{
this.pnlBmpList.Controls.Clear();
this.gboxDefectList.Text = $"缺陷图像";
this.gboxDefectList.Tag = 0;
this.lblDefectAddTag.Text = "";
this.lblDefectAddTag.Tag = 0;
}
public delegate void AddTextDelegate(string tag, string msg, WarningEnum level);
/// <summary>
/// 异步输出日志
/// </summary>
/// <param name="tag">模板标识</param>
/// <param name="msg">内容</param>
/// <param name="type"></param>
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 = $"<color=\"{(type == 1 ? "Yellow" : "Red")}\">{cont}</color>";
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();
}
/// <summary>
/// 全局中断
/// </summary>
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<int>("Direction");
if (direction == IODirectionEnum. || direction == IODirectionEnum.)
{
return Util.compareIOInput(
joJson.Value<JArray>("IN_OP_SHOW").ToObject<List<string>>().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);
}
/// <summary>
/// 启动
/// </summary>
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);
}
/// <summary>
/// 暂停
/// </summary>
/// <param name="buzzer">是否响蜂鸣</param>
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);
}
/// <summary>
/// 急停
/// </summary>
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<JArray>("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;
}
}
/// <summary>
/// 上料
/// </summary>
private void gotoUpPT()
{
try
{
JArray arrPT = Config.joPTSetting.Value<JArray>("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);
}
}
/// <summary>
/// 下料
/// </summary>
private void gotoDownPT()
{
try
{
if (currentState != CurrentStateEnum. && currentState != CurrentStateEnum. && currentState != CurrentStateEnum.)
{
AddTextEvent($"下料", $"非可下料状态:{currentState.ToString()}");
return;
}
currentState = CurrentStateEnum.;
isProductRevise = false;
JArray arrPT = Config.joPTSetting.Value<JArray>("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<Dictionary<int, List<string>[]>> list = new List<Dictionary<int, List<string>[]>>();
//Dictionary<int, List<string>[]> dir = new Dictionary<int, List<string>[]>();
//List<string>[] vs = new List<string>[1];
//vs[0] = new List<string>();
//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<string> list = new List<string>(ls.Split(','));
//lstPT = list.Select<string, double>(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<byte>(i, j) == 255)//白色
mat.Set<byte>(i, j, 0);
else
mat.Set<byte>(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<byte>(i, j) == 255)//白色
// mat.Set<byte>(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);
}
}
}