AOI_V1/MaiMuAOI/MaiMuAOI/SysCtrl/SysMgr.cs

3414 lines
167 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 HalconDotNet;
using HZH_Controls.Forms;
using MaiMuAOI.ImageProcessing;
using MaiMuAOI.SysUI.ProductAndStep;
using MaiMuControl.Device;
using MaiMuControl.Device.AxisDev;
using MaiMuControl.Device.AxisDev.Advantech;
using MaiMuControl.Device.CamDev;
using MaiMuControl.Device.IOCardDev;
using MaiMuControl.Device.IOCardDev.Advantech;
using MaiMuControl.Device.LightDev;
using MaiMuControl.Device.LightDev.CST;
using MaiMuControl.Device.LightDev.Rsee;
using MaiMuControl.SysStatusMgr.StatusMgr;
using MaiMuControl.SysStatusMgr.UserMgr;
using MaiMuControl.Utils;
using Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OpenCvSharp;
using OpenCvSharp.Flann;
using ProductionControl;
using ProductionControl.UI;
using ProductionControl.UIExtend;
using Service;
using SqlSugar;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using ToolKits.Disk;
using ToolKits.EnumTool;
using ToolKits.mAPI;
using static MaiMuAOI.ImageProcessing.DefectLib;
using static MaiMuAOI.ImageProcessing.SizeLib;
using static System.Net.Mime.MediaTypeNames;
namespace MaiMuAOI.SysCtrl
{
/// <summary>
/// 主系统控制
/// </summary>
public class SysMgr
{
#region singleton实例化
private static SysMgr _instance;
private static readonly object _lock = new object();
public static SysMgr Instance
{
get
{
if (_instance == null)
{
lock (_lock)
{
if (_instance == null)
{
_instance = new SysMgr();
}
}
}
return _instance;
}
}
#endregion
//系统信息
public string Info = "软件名称AOI\r\n软件版本V1.0.2\r\n公司迈沐智能科技有限公司\r\n地址";
public CameraEnumType SysUseCam = CameraEnumType.MVSCamera_CC;
public LightDevNameEnum SysUseLight = LightDevNameEnum.CST;
//主流程
private Thread _mainThread;
private CancellationTokenSource _cts;
/// <summary>
/// 流程序号
/// </summary>
private int CurrProcessIndex = 0;
/// <summary>
/// 总计时
/// </summary>
private Stopwatch stopWatch;
//运动曲线 默认S型 1
public int MotionST;
public double DefaultSpeed = 200;
//系统状态
private StatusMgr statusMgr;
public StatusMgr StatusMgr { get { return statusMgr; } }
//用户管理
private UserMgr userMgr;
public UserMgr UserMgr { get { return userMgr; } }
//系统配置管理
private ConfMgr confMgr;
//web服务器
private WebService webService;
//产品列表
private List<string> productCodeList = new List<string>();
public List<string> ProductCodeList { get { return productCodeList; } }
//产品ID列表
private List<int> productIdList = new List<int>();
public List<int> ProductIdList { get { return productIdList; } }
//近期SN列表
private List<string> productSNList = new List<string>();
public List<string> ProductSNList { get { return productSNList; } }
Service.ProductService PdtService;
Service.OrderService OrderService;
Service.ClassesService ClassesService;
//可用步骤
public static Dictionary<string, string> dicDevType = new Dictionary<string, string>();
//图像处理
private DefectLib defectLib;
public DefectLib DefectLib { get { return defectLib; } }
private SizeLib sizeLib;
public SizeLib SizeLib { get { return sizeLib; } }
private int SizeNGCnt;
//流程处理
private ForLib forLib;
private IFLib ifLib;
/// <summary>
/// 当前产品
/// </summary>
private Models.Product CurrProductModel = null;
/// <summary>
/// 当前料号
/// </summary>
private Order order = new Order();
#region
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(HObject himg, double posX, double posY)
{
Himage = himg;
PosX = posX;
PosY = posY;
}
public HObject Himage { get; private set; }
public string Path { get; private set; }
public double PosX { get; private set; }
public double PosY { get; private set; }
}
private Queue<scannerGBmpLoc> scannerGBmpQueue = new Queue<scannerGBmpLoc>();
private Queue<scannerCBmpLoc> scannerCBmpQueue = new Queue<scannerCBmpLoc>();
/// <summary>
/// 比对失败的图片
/// </summary>
private List<Bitmap> lstCompareFailZoomImage = new List<Bitmap>();
/// <summary>
/// --333输出变量供后面多个777使用
/// </summary>
public HObject contoursAffineTrans1_Out;
/// <summary>
/// 对比引索
/// </summary>
private int compBmpIndex = 0;//比对777图的索引
/// <summary>
/// 缺陷处理图片张数
/// </summary>
private int defectBmpNum = 0;
/// <summary>
/// 缺陷处理结果
/// </summary>
private int defectBmpNumResult = 0;
/// <summary>
/// 缺陷总不良数
/// </summary>
private int AllDefectCount = 0;
#endregion
private SysMgr()
{
_isInit = false;
_isRuning = false;
statusMgr = StatusMgr.Instance;
confMgr = ConfMgr.Instance;
//设置本机为主机数据库
statusMgr.SetMySqlIPaddr("127.0.0.1");
userMgr = new UserMgr(statusMgr.MySqlIP);
Service.InitDB.ConnectionString = confMgr.DBConStr;
PdtService = new Service.ProductService();
OrderService = new OrderService();
ClassesService = new ClassesService();
webService = new WebService();
scannerGBmpQueue = new Queue<scannerGBmpLoc>();
scannerCBmpQueue = new Queue<scannerCBmpLoc>();
lstCompareFailZoomImage = new List<Bitmap>();
MotionST = 1;
DefaultSpeed = 200;
_cts = new CancellationTokenSource();
InitDevDic();
}
/// <summary>
/// 初始化记录报警和显示
/// </summary>
/// <param name="tag">标头</param>
/// <param name="msg">内容</param>
/// <param name="warning">报警状态</param>
private void InitLog(string msg, string tag = "初始化", WarningEnum warning = WarningEnum.Normal)
{
OnInitRuning(new InitEventArgs(msg));
statusMgr.GotoWarning(warning, tag, msg);
}
/// <summary>
/// 记录报警和显示
/// </summary>
/// <param name="tag">标头</param>
/// <param name="msg">内容</param>
/// <param name="warning">报警状态</param>
private void Log(string tag, string msg, WarningEnum warning = WarningEnum.Normal)
{
OnMainRuning(new MainEventArgs(tag, msg, warning));
statusMgr.GotoWarning(warning, tag, msg);
}
#region
private AxisDev axisDev;
/// <summary>
/// 运动板卡
/// </summary>
public AxisDev AxisDev { get { return axisDev; } }
private BoardCfgParams boardCfgParams;
private HomeVelocityParams homeParamsX;
public HomeVelocityParams HomeParamsX { get { return homeParamsX; } }
private HomeVelocityParams homeParamsY;
public HomeVelocityParams HomeParamsY { get { return homeParamsY; } }
private HomeVelocityParams homeParamsZ;
public HomeVelocityParams HomeParamsZ { get { return homeParamsZ; } }
private IOCardDev ioCardDev;
/// <summary>
/// io控制卡
/// </summary>
public IOCardDev IOCardDev { get { return ioCardDev; } }
private LightDev lightDev;
/// <summary>
/// 光源控制
/// </summary>
public LightDev LightDev { get { return lightDev; } }
public string LightName { get { return "Light"; } }
public int LightChCount = 6;
private CamDev camDev;
/// <summary>
/// 相机控制
/// </summary>
public CamDev CamDev { get { return camDev; } }
private void InitDev()
{
axisDev = new AdvantechMotion();
ioCardDev = new AdvantechIO();
if(SysUseLight == LightDevNameEnum.CST)
lightDev = new CSTLight(LightName, LightChCount);
else
lightDev = new RseeLight(SysUseLight, LightName);
camDev = new CamDev(SysUseCam, confMgr.SysConfigParams.CamName, confMgr.SysConfigParams.CamCfgPath);
defectLib = new DefectLib();
sizeLib = new SizeLib();
forLib = new ForLib();
ifLib = new IFLib();
boardCfgParams= new BoardCfgParams();
boardCfgParams.DevEmgLogic = 1;
}
/// <summary>
/// 初始化硬件
/// </summary>
/// <returns></returns>
private bool InitAllDev()
{
bool ret = false;
InitDev();
//IO初始化
InitLog("IO板卡初始化...");
if (ioCardDev.InitBoard(MaiMuControl.Device.IOBordType.Advantech) < 0)
{
InitLog("IO板卡初始化失败", "初始化", WarningEnum.High);
return ret;
}
if(ioCardDev.OpenBoard(confMgr.SysConfigParams.IODevName, confMgr.SysConfigParams.IOCfgPath)<0)
{
InitLog("打开IO板卡失败", "初始化", WarningEnum.High);
return ret;
}
if (ioCardDev.ResetAllDO()<0)
{
InitLog("IO Reset失败", "初始化", WarningEnum.High);
return ret;
}
InitLog("初始化IO板卡成功");
//电机初始化
InitLog("运动控制板卡初始化...");
if(axisDev.InitBoard()<0)
{
InitLog("运动控制板卡初始化失败!", "初始化", WarningEnum.High);
return ret;
}
if (axisDev.OpenBoard(0, confMgr.SysConfigParams.MotionCfgPath) < 0)
{
InitLog("打开运动控制板卡失败!", "初始化", WarningEnum.High);
return ret;
}
//if (axisDev.LoadCfgFile(0, confMgr.SysConfigParams.MotionCfgPath) < 0)
//{
// InitLog("载入运动控制板卡参数失败2", "初始化", WarningEnum.High);
// return ret;
//}
if (axisDev.LoadBoardParams(0, boardCfgParams) < 0)
{
InitLog("载入运动控制板卡参数失败1", "初始化", WarningEnum.High);
return ret;
}
//光源初始化
InitLog("光源控制器初始化...");
int com_num = int.Parse(confMgr.SysConfigParams.LightCom.Remove(0, 3));
if (lightDev.InitDev(com_num, confMgr.SysConfigParams.LightComBaud) < 0)
{
AxisAllImmediateStop();
InitLog("光源控制器初始化失败!", "初始化", WarningEnum.High);
return ret;
}
InitLog("初始化光源控制器成功!");
//关闭光源
//关闭光源
for (int i = 0; i < LightChCount; i++)
{
lightDev.CloseLight(i + 1);
}
//lightDev.CloseLight((int)LightChannelEnum.CH1);
//lightDev.CloseLight((int)LightChannelEnum.CH2);
//lightDev.CloseLight((int)LightChannelEnum.CH3);
//lightDev.CloseLight((int)LightChannelEnum.CH4);
//lightDev.CloseLight((int)LightChannelEnum.CH5);
//lightDev.CloseLight((int)LightChannelEnum.CH6);
//相机初始化
InitLog("相机初始化...");
if(!camDev.InitCamera())
{
AxisAllImmediateStop();
InitLog("相机初始化失败!", "初始化", WarningEnum.High);
return ret;
}
if (!camDev.OpenCamera())
{
AxisAllImmediateStop();
InitLog("相机打开失败!", "初始化", WarningEnum.High);
return ret;
}
InitLog("初始化相机成功!");
ret = true;
return ret;
}
/// <summary>
/// 读取硬件配置
/// </summary>
private bool LoadDevConfig()
{
homeParamsX = axisDev.ReadAxisCfg(confMgr.DevConfigPath, (int)AxisName.Axis0);
homeParamsY = axisDev.ReadAxisCfg(confMgr.DevConfigPath, (int)AxisName.Axis1);
homeParamsZ = axisDev.ReadAxisCfg(confMgr.DevConfigPath, (int)AxisName.Axis2);
LightParams lightParams = new LightParams(LightName, LightChCount);
//LightChCount = 6;
//lightParams.DevName = LightName;
lightParams.ComName = confMgr.SysConfigParams.LightCom;
lightParams.Buad = confMgr.SysConfigParams.LightComBaud;
//lightParams.ChCount = LightChCount;
lightDev.WriteCfgInfo(confMgr.DevConfigPath, lightParams);
//ioCardDev.ReadCfgInfo(confMgr.DevConfigPath, "IO_1");
if ((homeParamsZ == null) || (homeParamsX == null) || (homeParamsY == null)|| !homeParamsZ.IsValid() || !homeParamsX.IsValid() || !homeParamsY.IsValid())
return false;
return true;
}
/// <summary>
/// 急停所有电机
/// </summary>
private void AxisAllImmediateStop()
{
axisDev.ImmediateStop((int)AxisName.Axis0);
axisDev.ImmediateStop((int)AxisName.Axis1);
axisDev.ImmediateStop((int)AxisName.Axis2);
}
/// <summary>
/// 减速停止
/// </summary>
private void AxisDStop()
{
axisDev.DecelStop((int)AxisName.Axis0);
axisDev.DecelStop((int)AxisName.Axis1);
axisDev.DecelStop((int)AxisName.Axis2);
}
/// <summary>
/// 获取脉冲对应的mm距离
/// </summary>
/// <param name="axis"></param>
/// <returns></returns>
public int GetMMtoPlus(AxisName axis)
{
switch (axis)
{
case AxisName.Axis0:
return HomeParamsX.MM2PulseNum;
case AxisName.Axis1:
return HomeParamsY.MM2PulseNum;
case AxisName.Axis2:
return HomeParamsZ.MM2PulseNum;
default: return 1;
}
}
/// <summary>
/// I/O指令输出
/// </summary>
/// <param name="processParam"></param>
/// <param name="isStrobe">频闪</param>
/// <param name="recover">输出sleep(recoverWaitTime)下,后恢复原信号</param>
/// <param name="recoverWaitTime">sleep 后反转</param>
public bool io_output(string tagName, JObject processParam, bool isStrobe = false, bool recover = false, int recoverWaitTime = 100)
{
bool result = false;
string[] OUT_OP_SHOW = processParam.Value<JArray>("OUT_OP_SHOW").ToObject<List<string>>().ToArray();
OUT_OP_SHOW = IODataFormatBinaryStr(OUT_OP_SHOW, true);
for (int i = 0; i < OUT_OP_SHOW.Length; i++)
{
for (int j = 0; j < OUT_OP_SHOW[i].Length; j++)
{
int jj = OUT_OP_SHOW[i].Length - j - 1;
if (OUT_OP_SHOW[i][jj] == 'L' || OUT_OP_SHOW[i][jj] == 'H')
{
if (recover)
{
if (recoverWaitTime > 0)
{
ioCardDev.WriteBitState(i, j, OUT_OP_SHOW[i][jj] == 'H');
Thread.Sleep(recoverWaitTime);
}
ioCardDev.WriteBitState(i, j, OUT_OP_SHOW[i][jj] == 'L');
}
else
{
ioCardDev.WriteBitState(i, j, OUT_OP_SHOW[i][jj] == 'H');
}
result = true;
}
}
}
return result;
}
/// <summary>
/// 多轴判断到位
/// </summary>
/// <param name="axisList"></param>
/// <returns></returns>
public bool WaitAxisDone(List<int> axisList)
{
foreach (int i in axisList)
{
if (axisDev.CheckDone(i, 60) != 0)
{
return false;
}
}
return true;
}
public double GetAxisPosValueMM(int axisNo)
{
double pos = axisDev.GetFeedbackPos(axisNo);
return pos / (double)GetMMtoPlus((AxisName)axisNo);
}
#endregion
#region
private bool _isInit;
/// <summary>
/// 是否初始化完成
/// </summary>
public bool IsInit { get { return _isInit; } }
private bool _isRuning;
/// <summary>
/// 设备正在运行
/// </summary>
public bool IsRuning { get { return _isRuning; } }
private bool _isAuto;
/// <summary>
/// 设备正在自动化流程中
/// </summary>
public bool IsAuto { get { return _isAuto; } }
#endregion
#region ++
/// <summary>
/// 登入
/// </summary>
/// <returns></returns>
public bool LoginSystem()
{
return userMgr.UserLoginDialog();
}
/// <summary>
/// 用户权限
/// </summary>
public void UserPermissiomMgr()
{
userMgr.RightManageDialog();
}
/// <summary>
/// 用户管理
/// </summary>
public void UserListMgr()
{
userMgr.UserManagerDialog();
}
#endregion
#region &&
/// <summary>
/// 系统初始化
/// </summary>
/// <returns></returns>
public bool Initial()
{
try
{
bool ret = false;
string err = "";
InitLog("系统开始初始化...");
//Thread.Sleep(200);
// 加载系统配置
InitLog("加载系统参数...");
ret = confMgr.LoadSystemConfig();
if (!ret)
{
throw new Exception("系统参数加载失败...");
}
InitLog("系统参数加载完成!");
//根据llog路径开始记录日志
statusMgr.StartLog(confMgr.SysConfigParams.LogPath);
statusMgr.GotoInitial();
//Thread.Sleep(200);
// 硬件初始化
if(!InitAllDev())
{
throw new Exception("硬件初始化失败...");
}
InitLog("硬件初始化完成!");
// 加载硬件配置
InitLog("加载硬件驱动参数...");
if (!LoadDevConfig())
{
throw new Exception("加载硬件驱动参数失败...");
}
InitLog("加载硬件驱动参数完成!");
//Thread.Sleep(200);
// 处理运行
InitLog("AI算法核心初始化...");
if (!defectLib.start())
throw new Exception("外观检测核心初始化失败...");
if (!sizeLib.start(confMgr.SysConfigParams.ImageProcessPath))
throw new Exception("尺寸检测核心初始化失败...");
InitLog("AI算法核心初始化完成");
//多轴回原
if (confMgr.SysConfigParams.OpenAutoGoHome)
{
if ((homeParamsZ != null) && (homeParamsX != null) && (homeParamsY != null))
{
axisDev.ResetAxisState((int)AxisName.Axis0);
axisDev.ResetAxisState((int)AxisName.Axis1);
axisDev.ResetAxisState((int)AxisName.Axis2);
InitLog("Z轴开始回原点...");
axisDev.BackHome((int)AxisName.Axis2, homeParamsZ);
InitLog("X轴开始回原点...");
axisDev.BackHome((int)AxisName.Axis0, homeParamsX);
InitLog("Y轴开始回原点...");
//axisDev.BackHome((int)AxisName.Axis1, homeParamsY);
//y轴使用io回原
if (!AxisYGoHome())
throw new Exception("Y轴回原报警");
}
Thread.Sleep(1000);
//判断轴是否回原成功
if (!AxisYGoHomeDone(60))
{
AxisAllImmediateStop();
throw new Exception("Y轴回原失败");
}
if (axisDev.CheckHomeDone((int)AxisName.Axis0, 60) != 0)
{
AxisAllImmediateStop();
throw new Exception("X轴回原失败");
}
if (axisDev.CheckHomeDone((int)AxisName.Axis2, 60) != 0)
{
AxisAllImmediateStop();
throw new Exception("Z轴回原失败");
}
InitLog("所有轴回原成功!");
//清空y轴发送命令和反馈位置
axisDev.SetCommandPos((int)AxisName.Axis1, 0);
axisDev.SetFeedbackPos((int)AxisName.Axis1, 0);
}
LedReady();
if (confMgr.SysConfigParams.OpenAutoGoHome)
{
InitLog("移动到上料...");
//Thread.Sleep(500);
if (!GotoLoadPos())
{
throw new Exception("移动到上料失败!");
}
}
//初始化成功
_isInit = true;
statusMgr.GotoNormalStandby();
OnInitRuning(new InitEventArgs("系统初始化完成...", this.IsInit));
Run();
return ret;
}
catch (Exception ex)
{
InitLog(ex.Message, "初始化", WarningEnum.High);
InitLog("系统初始化失败!" , "初始化", WarningEnum.High);
//statusMgr.GotoWarning(MaiMuControl.Device.WarningEnum.High, "初始化", ex.Message);
return false;
}
}
public bool InitDefectEvent()
{
defectLib.WarningEvent = (warning, msg) =>
{
Log("缺陷处理", msg, warning);
};
sizeLib.WarningEvent = (warning, msg) =>
{
Log("尺寸检测", msg, warning);
};
return true;
}
public bool InitWebServer()
{
//InitLog("开启数据服务器...");
webService.Defect_Compress_SavePath = confMgr.SysConfigParams.DefectRepairImag.SavePath;
webService.SizeBmp_Zoom_Image_SavePath = confMgr.SysConfigParams.SizeRepairImag.SavePath;
webService.LogEvent = (warning, msg) =>
{
Log("HTTP服务", msg, warning);
//OnMainRuning(new MainEventArgs("HTTP服务", msg, warning));
if(!confMgr.SysConfigParams.OpenHttpLog)
webService.LogEvent = null;
};
webService.start(confMgr.SysConfigParams.HttpServerIP, confMgr.SysConfigParams.HttpServerPort);
//InitLog("开启数据服务器完成!");
Thread.Sleep(200);
return true;
}
private void Run()
{
_mainThread = new Thread(() =>
{
MainThreadFunction();
});
_mainThread.IsBackground = true;
_mainThread.Start();
}
#endregion
#region
/// <summary>
/// 关闭
/// </summary>
public void Close()
{
_isInit = false;
_isRuning = false;
if (null != _cts)
{
_cts.Cancel();
}
if (null != _mainThread)
{
_mainThread.Join(1000);
}
webService.stop();
AxisDStop();
axisDev.SetServo((int)AxisName.Axis0, 0);
axisDev.SetServo((int)AxisName.Axis1, 0);
axisDev.SetServo((int)AxisName.Axis2, 0);
axisDev.CloseBoard();
camDev.CloseCamera();
//关闭光源
//关闭光源
for (int i = 0; i < LightChCount; i++)
{
lightDev.CloseLight(i + 1);
}
//lightDev.CloseLight((int)LightChannelEnum.CH1);
//lightDev.CloseLight((int)LightChannelEnum.CH2);
//lightDev.CloseLight((int)LightChannelEnum.CH3);
//lightDev.CloseLight((int)LightChannelEnum.CH4);
//lightDev.CloseLight((int)LightChannelEnum.CH5);
//lightDev.CloseLight((int)LightChannelEnum.CH6);
lightDev.CloseDev();
ioCardDev.ResetAllDO();
ioCardDev.CloseBoard();
}
#endregion
#region
public string SelectProduct()
{
InputFrm frm = new InputFrm(productCodeList, "请选择产品料号:");
if (frm.ShowDialog() != DialogResult.OK && string.IsNullOrWhiteSpace(frm.inputData))
return "";
//显示料号
//this.txtProductCode.Text = frm.inputData;
var model = PdtService.GetModelNav(frm.inputData);
if (model != null && model.StepInfo.ProcessList.Count > 0)
{
//名称料号显示一个就可以
return model.Code;
}
return "";
}
/// <summary>
/// 拷贝产品
/// </summary>
/// <param name="list"></param>
/// <param name="liIndex"></param>
/// <returns></returns>
public bool ProductCopy(List<Product> list, int liIndex)
{
Product newProduct = new Product()
{
Code = list[liIndex].Code + "_clone",
Name = $"{list[liIndex].Name} (克隆)",
Spec = list[liIndex].Spec,
ClassesId = list[liIndex].ClassesId,
ClassesInfo = list[liIndex].ClassesInfo,
HoleCount = list[liIndex].HoleCount,
DefectModelFile = list[liIndex].DefectModelFile,
AttachmentList = new List<Attachment>(),
BatchId = list[liIndex].BatchId,
TargetCount = list[liIndex].TargetCount,
CompleteCount = list[liIndex].CompleteCount,
BatchHistoryList = new List<BatchHistory>(),
QualifiedCriterionList = new List<QualifiedCriterion>(),
Note = list[liIndex].Note,
TensionBaseValue = list[liIndex].TensionBaseValue,
TensionUpFloatValue = list[liIndex].TensionUpFloatValue,
TensionDownFloatValue = list[liIndex].TensionDownFloatValue,
HeightBaseValue = list[liIndex].HeightBaseValue,
HeightUpFloatValue = list[liIndex].HeightUpFloatValue,
HeightDownFloatValue = list[liIndex].HeightDownFloatValue,
LineWidthBaseValue = list[liIndex].LineWidthBaseValue,
LineWidthUpFloatValue = list[liIndex].LineWidthUpFloatValue,
LineWidthDownFloatValue = list[liIndex].LineWidthDownFloatValue,
PTBaseValue = list[liIndex].PTBaseValue,
PTUpFloatValue = list[liIndex].PTUpFloatValue,
PTDownFloatValue = list[liIndex].PTDownFloatValue,
HeightBaseDec = list[liIndex].HeightBaseDec,
StepId = list[liIndex].StepId,
StepInfo = list[liIndex].StepInfo,
ProductProcessList = new List<ProductProcess>(),
ReviseStepId = list[liIndex].ReviseStepId,
ReviseStepInfo = list[liIndex].ReviseStepInfo,
ProductReviseProcessList = new List<ProductReviseProcess>(),
AssistStepId = list[liIndex].AssistStepId,
AssistStepInfo = list[liIndex].AssistStepInfo,
ProductAssistProcessList = new List<ProductAssistProcess>(),
//OrderList = new List<Order>(),
ModifyUserCode = userMgr.LoginUser.Code,
CreateUserCode = userMgr.LoginUser.Code
};
foreach (var item in list[liIndex].AttachmentList)
{
newProduct.AttachmentList.Add(new Attachment()
{
TBName = item.TBName,
Type = item.Type,
Pid = item.Pid,
Name = item.Name,
NameTimestamp = item.NameTimestamp,
ExtendName = item.ExtendName,
ModifyUserCode = userMgr.LoginUser.Code,
CreateUserCode = userMgr.LoginUser.Code
});
}
foreach (var item in list[liIndex].BatchHistoryList)
{
newProduct.BatchHistoryList.Add(new BatchHistory()
{
Pid = item.Pid,
BatchId = item.BatchId,
TargetCount = item.TargetCount,
CompleteCount = item.CompleteCount,
ModifyUserCode = userMgr.LoginUser.Code,
CreateUserCode = userMgr.LoginUser.Code
});
}
foreach (var item in list[liIndex].QualifiedCriterionList)
{
newProduct.QualifiedCriterionList.Add(new QualifiedCriterion()
{
Pid = item.Pid,
DefectCode = item.DefectCode,
Size = item.Size,
MaxDefectCount = item.MaxDefectCount,
ModifyUserCode = userMgr.LoginUser.Code,
CreateUserCode = userMgr.LoginUser.Code
});
}
foreach (var item in list[liIndex].ProductProcessList)
{
newProduct.ProductProcessList.Add(new ProductProcess()
{
Pid = item.Pid,
ProcessCode = item.ProcessCode,
ProcessParams = item.ProcessParams,
ModifyUserCode = userMgr.LoginUser.Code,
CreateUserCode = userMgr.LoginUser.Code
});
}
foreach (var item in list[liIndex].ProductReviseProcessList)
{
newProduct.ProductReviseProcessList.Add(new ProductReviseProcess()
{
Pid = item.Pid,
ProcessCode = item.ProcessCode,
ProcessParams = item.ProcessParams,
ModifyUserCode = userMgr.LoginUser.Code,
CreateUserCode = userMgr.LoginUser.Code
});
}
foreach (var item in list[liIndex].ProductAssistProcessList)
{
newProduct.ProductAssistProcessList.Add(new ProductAssistProcess()
{
Pid = item.Pid,
ProcessCode = item.ProcessCode,
ProcessParams = item.ProcessParams,
ModifyUserCode = userMgr.LoginUser.Code,
CreateUserCode = userMgr.LoginUser.Code
});
}
/*
foreach (var item in list[liIndex].OrderList)
{
newProduct.OrderList.Add(new Order()
{
ProductId = item.ProductId,
ProductInfo = item.ProductInfo,
SN = item.SN,
ModifyUserCode = Config.loginUser.Code,
CreateUserCode = Config.loginUser.Code
});
}*/
bool result = PdtService.InsertNav(newProduct);
return result;
}
/// <summary>
/// 加载产品列表
/// </summary>
public void LoadProductCodeList()
{
try
{
//productCodeList = PdtService.GetList().Select(m => m.Code).OrderBy(m => m).ToList();
productCodeList = PdtService.GetList().Select(m => m.Code).ToList();
productIdList = PdtService.GetList().Select(m => m.Id).ToList();
//string[] array = ReadSNText();
//if (array != null && array.Length > 0)
//{
// for (int i = 0; i < array.Length; i++)
// productSNList.Add(array[i]);
//}
}
catch (Exception ex)
{
//throw new Exception("加载产品料号失败:" + ex.Message);
OnMainRuning(new MainEventArgs("启动", "加载产品料号失败:" + ex.Message, WarningEnum.High));
statusMgr.GotoWarning(WarningEnum.High, "启动", "加载产品料号失败:" + ex.Message);
}
}
/// <summary>
/// 记录使用的sn
/// </summary>
/// <param name="str"></param>
public void Remind(string str)
{
string workPath = Directory.GetCurrentDirectory();
string textPath = Path.Combine(workPath, "TextRemind.txt");
try
{
if (productSNList.Count == 0 || !productSNList.Contains(str))
{
if (productSNList.Count > 20)
productSNList.RemoveAt(0);
productSNList.Add(str);
//File.AppendAllLines(textPath, new string[] { str });
}
if(productSNList.Count > 0)
{
File.WriteAllLines(textPath, productSNList);
}
}
catch
{
}
}
/// <summary>
/// 读取近期sn
/// </summary>
/// <returns></returns>
private string[] ReadSNText()
{
string workPath = Directory.GetCurrentDirectory();
string textPath = Path.Combine(workPath, "TextRemind.txt");
try
{
if (!File.Exists(textPath))
return null;
return File.ReadAllLines(textPath);
}
catch
{
return null;
}
}
#endregion
#region
private static void InitDevDic()
{
//dicDevType.Add("CodeScanner", "扫码枪");//固定为必有开始
if (!dicDevType.ContainsKey("IOCard")) dicDevType.Add("IOCard", "I/O控制");
//if (!dicDevType.ContainsKey("Tension")) dicDevType.Add("Tension", "张力测量");
//if (!dicDevType.ContainsKey("Height")) dicDevType.Add("Height", "厚度测量");
if (!dicDevType.ContainsKey("Axis")) dicDevType.Add("Axis", "滑台电机");
if (!dicDevType.ContainsKey("AxisTag")) dicDevType.Add("AxisTag", "滑台&测量");
if (!dicDevType.ContainsKey("Light")) dicDevType.Add("Light", "光源");
if (!dicDevType.ContainsKey("Scanner_GENTL")) dicDevType.Add("Scanner_GENTL", "相机拍照");
//if (!dicDevType.ContainsKey("Scanner_CC")) dicDevType.Add("Scanner_CC", "相机CC");
//if (!dicDevType.ContainsKey("SmallAxis")) dicDevType.Add("SmallAxis", "镜头电机");
if (!dicDevType.ContainsKey("Defect")) dicDevType.Add("Defect", "缺陷检测");
if (!dicDevType.ContainsKey("Size")) dicDevType.Add("Size", "尺寸测量");
if (!dicDevType.ContainsKey("For")) dicDevType.Add("For", "For循环");
if (!dicDevType.ContainsKey("If")) dicDevType.Add("If", "If条件");
}
#endregion
#region
public void CheckWebLog()
{
if (!confMgr.SysConfigParams.OpenHttpLog)
webService.LogEvent = null;
else
{
webService.LogEvent = (warning, msg) =>
{
Log("HTTP服务", msg, warning);
//OnMainRuning(new MainEventArgs("HTTP服务", msg, warning));
};
}
}
/// <summary>
/// 关闭光源移动到上料位置
/// </summary>
/// <returns></returns>
public bool GotoLoadPos()
{
bool ret = true;
//关闭光源
for (int i = 0; i < LightChCount; i++)
{
lightDev.CloseLight(i + 1);
}
//lightDev.CloseLight((int)LightChannelEnum.CH1);
//lightDev.CloseLight((int)LightChannelEnum.CH2);
//lightDev.CloseLight((int)LightChannelEnum.CH3);
//lightDev.CloseLight((int)LightChannelEnum.CH4);
//lightDev.CloseLight((int)LightChannelEnum.CH5);
//lightDev.CloseLight((int)LightChannelEnum.CH6);
VelocityCurveParams vel_z = new VelocityCurveParams(DefaultSpeed / 2, DefaultSpeed / 2, 0, DefaultSpeed / 2, 1, GetMMtoPlus(AxisName.Axis2));
axisDev.MoveAbsValue((int)AxisName.Axis2, vel_z, confMgr.LoadPoint_Z);
if (axisDev.CheckDone((int)AxisName.Axis2, 30) != 0)
return false;
VelocityCurveParams vel_x = new VelocityCurveParams(DefaultSpeed, DefaultSpeed, 0, DefaultSpeed, 1, GetMMtoPlus(AxisName.Axis0));
axisDev.MoveAbsValue((int)AxisName.Axis0, vel_x, confMgr.LoadPoint_X);
VelocityCurveParams vel_y = new VelocityCurveParams(DefaultSpeed, DefaultSpeed, 0, DefaultSpeed, 1, GetMMtoPlus(AxisName.Axis1));
axisDev.MoveAbsValue((int)AxisName.Axis1, vel_y, confMgr.LoadPoint_Y);
if (axisDev.CheckDone((int)AxisName.Axis0, 30) != 0)
return false;
if (axisDev.CheckDone((int)AxisName.Axis1, 30) != 0)
return false;
return ret;
}
/// <summary>
/// 急停设备
/// </summary>
public void EmergencyStop()
{
Log("设备", "紧急停止", WarningEnum.High);
_isAuto = false;
AxisAllImmediateStop();
}
private int GetIOPortIndex(int DIDOEnum)
{
return DIDOEnum / 8;
}
private int GetIOBitIndex(int DIDOEnum)
{
return DIDOEnum % 8;
}
/// <summary>
/// 开关照明灯
/// </summary>
/// <param name="open"></param>
public void OpenFloodlight(bool open)
{
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), open);
}
public bool RunQG(bool ack)
{
bool ret = false;
ret = ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), ack);
Thread.Sleep(500);
//ret = ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.加紧气缸), GetIOBitIndex((int)DOName.加紧气缸), ack);
return ret;
}
/// <summary>
/// 三色灯初始化
/// </summary>
public void LedReady()
{
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.绿), GetIOBitIndex((int)DOName.绿), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.绿), GetIOBitIndex((int)DOName.绿), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.绿), GetIOBitIndex((int)DOName.绿), false);
}
public void LedRun()
{
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.绿), GetIOBitIndex((int)DOName.绿), true);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.绿), GetIOBitIndex((int)DOName.绿), true);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.绿), GetIOBitIndex((int)DOName.绿), false);
}
public void LedPause()
{
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.绿), GetIOBitIndex((int)DOName.绿), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), true);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.绿), GetIOBitIndex((int)DOName.绿), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), true);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.绿), GetIOBitIndex((int)DOName.绿), false);
}
//控制黄灯闪烁
private bool Blink;
private int BlinkCnt = 0;
//控制蜂鸣间隔
private int BuzzCnt = 0;
public void LedRset(bool val)
{
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.绿), GetIOBitIndex((int)DOName.绿), false);
//ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.三色灯黄灯), GetIOBitIndex((int)DOName.三色灯黄灯), val);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.绿), GetIOBitIndex((int)DOName.绿), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), val);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.绿), GetIOBitIndex((int)DOName.绿), false);
Blink = val;
BlinkCnt = 0;
}
private bool AxisYGoHome()
{
//加入读取急停信号
AxisSignalState axisSignalState = axisDev.GetAxisState((int)AxisName.Axis1);
if(axisSignalState.EMG != GeneralElectricalLevelMode.High)
{
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.Y轴回原点), GetIOBitIndex((int)DOName.Y轴回原点), true);
return true;
}
return false;
}
private bool AxisYGoHomeDone(double timeout)
{
System.Diagnostics.Stopwatch strtime = new System.Diagnostics.Stopwatch();
strtime.Start();
do
{
//加入读取急停信号
AxisSignalState axisSignalState = axisDev.GetAxisState((int)AxisName.Axis1);
if (axisSignalState.EMG == GeneralElectricalLevelMode.High)
{
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.Y轴回原点), GetIOBitIndex((int)DOName.Y轴回原点), false);
return false;
}
//判断是否正常停止
bool sts;
ioCardDev.GetDIBitState(GetIOPortIndex((int)DIName.Y轴回原点完成), GetIOBitIndex((int)DIName.Y轴回原点完成), out sts);
if (sts)
break;
//检查是否超时
strtime.Stop();
if (strtime.ElapsedMilliseconds / 1000.0 > timeout)
{
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.Y轴回原点), GetIOBitIndex((int)DOName.Y轴回原点), false);
return false;
}
strtime.Start();
//延时
System.Threading.Thread.Sleep(20);
} while (true);
Thread.Sleep(500);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.Y轴回原点), GetIOBitIndex((int)DOName.Y轴回原点), false);
return true;
}
public bool GotoReadyPosAndIO()
{
Log("复位", "系统复位");
_isAuto = false;
CurrProcessIndex = -1;
bool ret = GotoLoadPos();
if (!ret)
{
Log("复位", "系统电机复位失败", WarningEnum.High);
return false;
}
if (!RunQG(false))
{
Log("复位", "系统IO复位失败", WarningEnum.High);
return false;
}
LedReady();
statusMgr.GotoNormalStandby();
return ret;
}
/// <summary>
/// 确认当前位置为上料位置
/// </summary>
/// <returns></returns>
private bool CheckPosIsLoadPos()
{
bool ret = false;
double x = GetAxisPosValueMM((int)AxisName.Axis0);
double y = GetAxisPosValueMM((int)AxisName.Axis1);
double z = GetAxisPosValueMM((int)AxisName.Axis2);
ret = Math.Abs(x - confMgr.LoadPoint_X) < 1;
ret = ret&Math.Abs(y - confMgr.LoadPoint_Y) < 1;
ret = ret&Math.Abs(z - confMgr.LoadPoint_Z) < 1;
return ret;
}
/// <summary>
/// 删除修复台重复sn图片
/// </summary>
private void DeleteRepairImage(string sn)
{
//删除文件
Task.Factory.StartNew(() =>
{
string dirPath = Util.CreateSubDir(confMgr.SysConfigParams.SizeRepairImag.SavePath,
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);
}
}
dirPath = Util.CreateSubDir(confMgr.SysConfigParams.DefectRepairImag.SavePath,
new List<string> { DateTime.Now.ToString("yyyyMMdd"), sn });
if (!Directory.Exists(dirPath))
{
return;
}
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>
public bool StartRun(Form fatherFrm, string productCode, string sn)
{
bool ret = true;
//Log("运行", $"启动自动检测流程---料号:{productCode},网版编码:{sn}");
//运行前清除过期图片文件
//DateTime st = DateTime.Now;
DelectPictureFile();
if(CurrProcessIndex < -1)
{
Log("运行", "流程报警中,请清除报警,复位启动", WarningEnum.Low);
return false;
}
if ((statusMgr.Status != SystemStsEnum.Standby)&&(statusMgr.Status != SystemStsEnum.Pause))
{
Log("运行", "系统非可运行状态", WarningEnum.Low);
return false;
}
//Log("启动", "移动至上料位...");
//GotoLoadPos();
if(!CheckPosIsLoadPos())
{
Log("运行", "载具不在上料位!请复位到上料位在启动!", WarningEnum.Low);
FrmDialog.ShowDialog(fatherFrm, $"载具不在上料位!请复位到上料位在启动!", "警告", false);
return false;
}
if (string.IsNullOrEmpty(productCode))
{
Log("运行", "产品料号未选择!", WarningEnum.Low);
return false;
}
string code = productCode;
//清空显示
//scannerGBmpQueue.Clear();
scannerCBmpQueue.Clear();
scannerGBmpQueue.Clear();
lstCompareFailZoomImage.Clear();
contoursAffineTrans1_Out = null;
defectBmpNum = 0;
defectBmpNumResult = 0;
//Log("调试", $"time1:{(DateTime.Now - st).Milliseconds}");
//st = DateTime.Now;
int errStep = 0;
try
{
var model = PdtService.GetModelNav(code);
if (model != null && model.StepInfo.ProcessList.Count > 0)
{
errStep = 1;
//根据产品设置动态加载外观检测模型文件
string onnxFile;
if (!string.IsNullOrWhiteSpace(model.DefectModelFile))
onnxFile = $"{ConfMgr.Instance.SysConfigParams.AIModelPath}\\{model.DefectModelFile}";
else
onnxFile = $"{ConfMgr.Instance.SysConfigParams.AIModelPath}\\default.onnx";
Classes classTemp = this.ClassesService.GetById(model.ClassesId);
defectLib.loadModelFile(onnxFile, classTemp.Name);
//输入SN
errStep = 2;
//InputFrm frm = new InputFrm(null, "请输入网版编码:");
//if (frm.ShowDialog() == DialogResult.OK && !string.IsNullOrWhiteSpace(frm.inputData))
// sn = frm.inputData;
//else
//{
// Log("运行", "输入产品编码取消,停止流程!", WarningEnum.Low);
// return false;
//}
//Log("调试", $"time2:{(DateTime.Now - st).Milliseconds}");
//st = DateTime.Now;
errStep = 3;
if (string.IsNullOrWhiteSpace(sn))
{
Log("运行", "网版编码为空!", WarningEnum.Low);
return false;
}
Log("运行", $"料号:{code},网版编码:{sn}");
//记忆
//Remind(sn);
//查询SN是否重复
var findSN = OrderService.GetModelNav(sn);
if (findSN != null)
{
Log("运行", $"网版编码:{sn}, 已经存在检测数据!");
if(FrmDialog.ShowDialog(fatherFrm, $"网版编码:{sn}, 已经存在检测数据!", "提示", true) != DialogResult.OK)
{
Log("运行", "网版编码重复测试终止运行!", WarningEnum.Low);
return false;
}
else
Log("运行", "网版编码重复测试");
//删除已有sn的修复图片
DeleteRepairImage(sn);
}
//Log("调试", $"time3:{(DateTime.Now - st).Milliseconds}");
//st = DateTime.Now;
//判断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 (OrderService.Count(exp1) >= model.TargetCount)
{
Log("运行", $"当前产品本批次检测数已达目标数量,请更换检测批次号!", WarningEnum.Low);
return false;
}
errStep = 7;
}
//Log("调试", $"time4:{(DateTime.Now - st).Milliseconds}");
//st = DateTime.Now;
//界面显示SN
model.HeightBaseDec = "";
CurrProductModel = model;
Log("运行", $"{model.Name} {model.Spec} [{model.Code}]");
OnAutoRuning(new RunEventArgs(sn, model.StepInfo.ProcessList));
forLib.clear();
ifLib.clear();
errStep = 8;
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;
AllDefectCount = 0;
SizeNGCnt = 0;
RunQG(true);
CurrProcessIndex = 0;
LedRun();
stopWatch = new Stopwatch();
_isRuning = true;
_isAuto = true;
statusMgr.GotoAuto();
errStep = 10;
//Log("调试", $"time5:{(DateTime.Now - st).Milliseconds}");
//st = DateTime.Now;
}
else
Log("运行", model != null ? $"料号{code}不存在!" : $"产品({model.Name})未配置检测流程!", WarningEnum.Low);
}
catch (Exception ex)
{
Log("运行", "程序错误-" +ex.Message + "\n", WarningEnum.High);
}
return ret;
}
public bool ReStartRun()
{
bool ret = false;
if (CurrProcessIndex >= 1 )
{
Log("启动", $"暂停 -> 继续 当前工序索引:{CurrProcessIndex + 1}");
LedRun();
_isRuning = true;
statusMgr.GotoAuto();
ret = true;
}
return ret;
}
public bool WarningShowLed(bool DisEnableBuzz)
{
bool sts = false;
if (statusMgr.Warning == WarningEnum.Normal)
{
if(statusMgr.Status == SystemStsEnum.Auto)
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.绿), GetIOBitIndex((int)DOName.绿), true);
else
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.绿), GetIOBitIndex((int)DOName.绿), false);
if (statusMgr.Status == SystemStsEnum.Pause)
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), true);
else
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
BuzzCnt = 0;
//判断黄灯是否需要闪烁调用200ms一次
if (Blink)
{
if(BlinkCnt < 3)
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), true);
else if(BlinkCnt < 6)
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
BlinkCnt++;
if (BlinkCnt == 6)
BlinkCnt = 0;
}
else
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
}
if (statusMgr.Warning == WarningEnum.Low)
{
//ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.启动按钮绿灯), GetIOBitIndex((int)DOName.启动按钮绿灯), false);
//ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.停止按钮红灯), GetIOBitIndex((int)DOName.停止按钮红灯), true);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), true);
//ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.三色灯绿灯), GetIOBitIndex((int)DOName.三色灯绿灯), false);
//sts = true;
}
if (statusMgr.Warning == WarningEnum.High)
{
sts = true;
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.绿), GetIOBitIndex((int)DOName.绿), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), true);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), true);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.绿), GetIOBitIndex((int)DOName.绿), false);
if (!DisEnableBuzz && confMgr.SysConfigParams.OpenBuzzer)
{
if(BuzzCnt < 3)
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), true);
else if (BuzzCnt < 6)
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
BuzzCnt++;
if (BuzzCnt == 6)
BuzzCnt = 0;
}
}
return sts;
}
public int ButtonIOTrg(bool DisEnabledoorSig)
{
int ret = 0;
bool sts;
if(!DisEnabledoorSig && confMgr.SysConfigParams.OpenDoor)
{
ioCardDev.GetDIBitState(GetIOPortIndex((int)DIName.), GetIOBitIndex((int)DIName.), out sts);
if ((!sts)&&(statusMgr.Status == SystemStsEnum.Auto))
{
Log("暂停", "门磁报警-门打开", WarningEnum.Low );
statusMgr.GotoPause();
ret = 2;
}
}
ioCardDev.GetDIBitState(GetIOPortIndex((int)DIName.), GetIOBitIndex((int)DIName.), out sts);
if (sts)
{
Log("暂停", "手动暂停");
statusMgr.GotoPause();
ret = 2;
}
ioCardDev.GetDIBitState(GetIOPortIndex((int)DIName.), GetIOBitIndex((int)DIName.), out sts);
if (sts)
{
ret = 3;
//if (SysMgr.Instance.StatusMgr.Status == SystemStsEnum.Warning)
//{
// Log("清除", "手动清除报警");
// if (SysMgr.Instance.IsAuto)
// SysMgr.Instance.StatusMgr.GotoPause();
// else
// SysMgr.Instance.StatusMgr.GotoNormalStandby();
//}
}
ioCardDev.GetDIBitState(GetIOPortIndex((int)DIName.), GetIOBitIndex((int)DIName.), out sts);
if (sts)
ret = 1;
return ret ;
}
/// <summary>
/// 设备硬件重新加载
/// </summary>
public void AllResetAndGoHome()
{
Log("复位", "系统硬件重置");
_isAuto = false;
_isRuning = false;
statusMgr.ClearWarning();
AxisDStop();
axisDev.CloseBoard();
ioCardDev.ResetAllDO();
ioCardDev.CloseBoard();
lightDev.CloseDev();
camDev.CloseCamera();
camDev = new CamDev(SysUseCam, confMgr.SysConfigParams.CamName, confMgr.SysConfigParams.CamCfgPath);
if (ioCardDev.InitBoard(MaiMuControl.Device.IOBordType.Advantech) < 0)
{
Log("IO板卡初始化失败", "初始化", WarningEnum.High);
return;
}
if (ioCardDev.OpenBoard(confMgr.SysConfigParams.IODevName, confMgr.SysConfigParams.IOCfgPath) < 0)
{
Log("打开IO板卡失败", "初始化", WarningEnum.High);
return;
}
if (ioCardDev.ResetAllDO() < 0)
{
Log("IO Reset失败", "初始化", WarningEnum.High);
return;
}
statusMgr.GotoInitial();
statusMgr.ClearWarning();
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), true);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), true);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.绿), GetIOBitIndex((int)DOName.绿), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.绿), GetIOBitIndex((int)DOName.绿), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.), GetIOBitIndex((int)DOName.), false);
ioCardDev.WriteBitState(GetIOPortIndex((int)DOName.绿), GetIOBitIndex((int)DOName.绿), false);
//电机初始化
if (axisDev.InitBoard() < 0)
{
Log("运动控制板卡初始化失败!", "初始化", WarningEnum.High);
return ;
}
if (axisDev.OpenBoard(0, confMgr.SysConfigParams.MotionCfgPath) < 0)
{
Log("打开运动控制板卡失败!", "初始化", WarningEnum.High);
return;
}
if (axisDev.LoadBoardParams(0, boardCfgParams) < 0)
{
Log("载入运动控制板卡参数失败1", "初始化", WarningEnum.High);
return;
}
//光源初始化
int com_num = int.Parse(confMgr.SysConfigParams.LightCom.Remove(0, 3));
if (lightDev.InitDev(com_num, confMgr.SysConfigParams.LightComBaud) < 0)
{
Log("光源控制器初始化失败!", "初始化", WarningEnum.High);
return;
}
//相机初始化
if (!camDev.InitCamera())
{
Log("相机初始化失败!", "初始化", WarningEnum.High);
return;
}
if (!camDev.OpenCamera())
{
Log("相机打开失败!", "初始化", WarningEnum.High);
return;
}
//多轴回原
if ((homeParamsZ != null) && (homeParamsX != null) && (homeParamsY != null))
{
axisDev.ResetAxisState((int)AxisName.Axis0);
axisDev.ResetAxisState((int)AxisName.Axis1);
axisDev.ResetAxisState((int)AxisName.Axis2);
Log("复位", "Z轴开始回原点...");
axisDev.BackHome((int)AxisName.Axis2, homeParamsZ);
Log("复位", "X轴开始回原点...");
axisDev.BackHome((int)AxisName.Axis0, homeParamsX);
Log("复位", "Y轴开始回原点...");
//axisDev.BackHome((int)AxisName.Axis1, homeParamsY);
//y轴使用io回原
AxisYGoHome();
}
Thread.Sleep(1000);
//判断轴是否回原成功
if (!AxisYGoHomeDone(60))
{
AxisAllImmediateStop();
Log("复位", "Y轴回原失败", WarningEnum.High);
return;
}
if (axisDev.CheckHomeDone((int)AxisName.Axis0, 60) != 0)
{
AxisAllImmediateStop();
Log("复位", "X轴回原失败", WarningEnum.High);
return;
}
if (axisDev.CheckHomeDone((int)AxisName.Axis2, 60) != 0)
{
AxisAllImmediateStop();
Log("复位", "Z轴回原失败", WarningEnum.High);
return;
}
Log("复位", "所有轴回原成功!");
//清空y轴发送命令和反馈位置
axisDev.SetCommandPos((int)AxisName.Axis1, 0);
axisDev.SetFeedbackPos((int)AxisName.Axis1, 0);
Log("复位", "移动到上料...");
LedReady();
GotoLoadPos();
//初始化成功
_isInit = true;
statusMgr.GotoNormalStandby();
}
public string GetAxisPos()
{
string posStrng = "";
double pos1 = axisDev.GetFeedbackPos((int)AxisName.Axis0);
double pos2 = axisDev.GetFeedbackPos((int)AxisName.Axis1);
double pos3 = axisDev.GetFeedbackPos((int)AxisName.Axis2);
double cmd1 = axisDev.GetCommandPos((int)AxisName.Axis0);
double cmd2 = axisDev.GetCommandPos((int)AxisName.Axis1);
double cmd3 = axisDev.GetCommandPos((int)AxisName.Axis2);
posStrng = "[命令位:" + (cmd1 / (double)GetMMtoPlus(AxisName.Axis0)).ToString("0.0000") +
" 反馈位:" + (pos1 / (double)GetMMtoPlus(AxisName.Axis0)).ToString("0.0000") + "]" +
"[命令位:" + (cmd2 / (double)GetMMtoPlus(AxisName.Axis1)).ToString("0.0000") +
" 反馈位:" + (pos2 / (double)GetMMtoPlus(AxisName.Axis1)).ToString("0.0000") + "]" +
"[命令位:" + (cmd3 / (double)GetMMtoPlus(AxisName.Axis2)).ToString("0.0000") +
" 反馈位:" + (pos3 / (double)GetMMtoPlus(AxisName.Axis2)).ToString("0.0000") + "]";
return posStrng;
}
#endregion
#region
/// <summary>
/// 中断工序运行
/// </summary>
/// <returns></returns>
private bool isBreakProcessRun()
{
return statusMgr.Status == SystemStsEnum.Pause || statusMgr.Warning == WarningEnum.High ;
}
/// <summary>
/// 后台运行主线程
/// </summary>
private void MainThreadFunction()
{
while (true)
{
try
{
if (_cts.IsCancellationRequested)
break;
if (IsRuning)
{
//暂停开始
stopWatch.Start();
do
{
CurrProcessIndex = nextProcess(CurrProductModel, CurrProcessIndex);
} while (CurrProcessIndex >= 0 && !isBreakProcessRun());
//暂停中断
stopWatch.Stop();
_isRuning = false;
}
Thread.Sleep(10);
}
catch (Exception e)
{
_isRuning = false;
Log("运行报警", "流程运行出错:" + e.Message + "\n", WarningEnum.High);
}
}
}
/// <summary>
/// 获取缺陷项阈值
/// </summary>
/// <param name="m"></param>
/// <returns></returns>
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
//全缺陷项
//foreach (var item in Enum.GetValues(typeof(DefectCodeEnum)))
//{
// var code = EnumExtension.GetEnumDescription((DefectCodeEnum)item);
// if (!dic.ContainsKey(code))
// dic.Add(code, 0);
//}
Classes classtemp = ClassesService.GetById(m.ClassesId);
ArrayList lstDefect;
if ((classtemp != null) && (classtemp.Name == "钢网"))
lstDefect = ConfMgr.GetArrayList<DefectCode2Enum>();
else
lstDefect = ConfMgr.GetArrayList<DefectCodeEnum>();
foreach (DictionaryEntry item in lstDefect)
{
string code = item.Value.ToString();
if (!dic.ContainsKey(code))
dic.Add(code, 0);
}
return dic;
}
//统计缺陷类型 [["92.7542","80.85799","99.54083","86.05363","dk","0.52"]]
public 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 "gs":
order.GSYCCount++;
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;
}
}
}
//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;
OnAutoRuning(new RunEventArgs(stepIndex));
//判断是否中断或暂停
if (isBreakProcessRun())
return stepIndex;
//开始计时
if ( model.StepInfo.StartTimeIndex > 0 && model.StepInfo.StartTimeIndex == stepIndex + 1)
stopWatch.Restart();
var 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;
Log($"{stepIndex + 1}-{processName}", $"使用产品专用配方:{jsonParams}");
}
}
//使用流程默认配方
if (jsonParams == null)
{
jsonParams = processInfo.ProcessParams;
if (jsonParams == null) throw new Exception("配方为null!!");
Log($"{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");
Log($"{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;
byte[] DIData;
ioCardDev.GetDIByteState(out DIData);
if (compareIOInput(inValue, DIData))
break;
Thread.Sleep(10);
inWaitingTime += 10;
if (IN_Waiting_Timeout > 0 && inWaitingTime >= IN_Waiting_Timeout)
{
Log($"{stepIndex + 1}-{processName}", $"输入等待超时告警!", WarningEnum.High);
return stepIndex;
}
}
Log($"{stepIndex + 1}-{processName}", $"I/O输入信号对比完成");
}
if (direction == IODirectionEnum. || direction == IODirectionEnum.)
io_output($"{stepIndex + 1}-{processName}", processParam);
#endregion
break;
case "Tension":
#region
Log($"{stepIndex + 1}-{processName}", $"忽略不支持流程!");
OnAutoRuning(new RunEventArgs(liStatocStepIndex, $"设备禁用,忽略此步骤!"));
#endregion
break;
case "Height":
#region
Log($"{stepIndex + 1}-{processName}", $"忽略不支持流程!");
OnAutoRuning(new RunEventArgs(liStatocStepIndex, $"设备禁用,忽略此步骤!"));
#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;
}
//支持多轴移动
List<int> axisList = new List<int>();
foreach (var processParamSub in processParam.Properties())
{
processParam = processParamSub.Value as JObject;
Log($"{stepIndex + 1}-{processName}", processParam.ToString());
if (!processParam.ContainsKey("Disable") || !processParam.Value<bool>("Disable"))
{
//asynRun = processParam.Value<bool>("AsynRun");//异步
int AxisIndex = processParam.Value<int>("AxisIndex");
axisList.Add(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");
Log($"{stepIndex + 1}-{processName}",
$"轴{AxisIndex}准备({(MoveMode == AxMoveMode.绝对位置 ? "" : "")})运动至{PPUValue}...");
if(axisDev.CheckDone(AxisIndex, 60) != 0)
{
Log($"{stepIndex + 1}-{processName}", $"轴{AxisIndex}到位失败!", WarningEnum.High);
return stepIndex;
}
VelocityCurveParams vel = new VelocityCurveParams(Acc, Dec, VelLow, VelHigh, MotionST, GetMMtoPlus((AxisName)AxisIndex));
int iret = 0;
if(MoveMode == AxMoveMode.)
iret = axisDev.MoveAbsValue(AxisIndex, vel, PPUValue);
else
iret = axisDev.MoveRelValue(AxisIndex, vel, PPUValue);
if (iret != 0)
{
Log($"{stepIndex + 1}-{processName}", $"轴{AxisIndex}运动失败!", WarningEnum.High);
return stepIndex;
}
}
}
//多轴同时运行后强制等待各轴完成
Log($"{stepIndex + 1}-{processName}", $"等待轴组运行完成...");
if (!WaitAxisDone(axisList))
{
Log($"{stepIndex + 1}-{processName}", $"轴到位失败!", WarningEnum.High);
return stepIndex;
}
Log($"{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");
//判断有无tag
if (order.SizeTagDataList == null)
{
Log($"{stepIndex + 1}-{processName}", $"数据提供者Tag为空", WarningEnum.High);
return stepIndex;
}
var sizeTagObj = order.SizeTagDataList.LastOrDefault(m => m.SizeTag == axisSizeTag);//用最新的last
if (sizeTagObj == null)
{
Log($"{stepIndex + 1}-{processName}", $"偏移校正轴工序找不到数据提供者Tag:{axisSizeTag}", WarningEnum.High);
return stepIndex;
}
string[] posePT = sizeTagObj.posePT.Split(',');
if (posePT.Length < useIndex + AxisIndexList.Count)
{
Log($"{stepIndex + 1}-{processName}",
$"Tag:{axisSizeTag}对应消费索引:{useIndex},Axis数量:{AxisIndexList.Count} 超出postPT:{sizeTagObj.posePT} 范围!", 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())})";
Log($"{stepIndex + 1}-{processName}", axisTagMsg);
//界面显示
OnAutoRuning(new RunEventArgs(liStatocStepIndex, axisTagMsg));
for (int i = 0; i < AxisIndexList.Count && i < TagPPUValue.Length; i++)
{
if (axisDev.CheckDone(AxisIndexList[i], 60) != 0)
{
Log($"{stepIndex + 1}-{processName}", $"轴{AxisIndexList[i]}到位失败!", WarningEnum.High);
return stepIndex;
}
VelocityCurveParams vel = new VelocityCurveParams(TagAcc, TagDec, TagVelLow, TagVelHigh, MotionST, GetMMtoPlus((AxisName)AxisIndexList[i]));
int iret = 0;
if (TagMoveMode == AxMoveMode.)
iret = axisDev.MoveAbsValue(AxisIndexList[i], vel, TagPPUValue[i]);
else
iret = axisDev.MoveRelValue(AxisIndexList[i], vel, TagPPUValue[i]);
if (iret != 0)
{
Log($"{stepIndex + 1}-{processName}", $"轴{AxisIndexList[i]}运动失败!", WarningEnum.High);
return stepIndex;
}
}
if (sizeTagObj.ConsumeStepIndex == null) sizeTagObj.ConsumeStepIndex = "";
sizeTagObj.ConsumeStepIndex += $"{stepIndex + 1}-{useIndex}, ";//消费工序ID
//多轴同时运行后强制等待各轴完成
Log($"{stepIndex + 1}-{processName}", $"等待轴组运行完成...");
if (!WaitAxisDone(AxisIndexList))
{
Log($"{stepIndex + 1}-{processName}", $"轴到位失败!", WarningEnum.High);
return stepIndex;
}
Log($"{stepIndex + 1}-{processName}", $"轴组运行完成");
#endregion
break;
case "Light":
#region
if (confMgr.SysConfigParams.DisableLight)
{
Log($"{stepIndex + 1}-{processName}", $"设备禁用,忽略此步骤!");
//界面显示
OnAutoRuning(new RunEventArgs(liStatocStepIndex, $"设备禁用,忽略此步骤!"));
break;
}
int ChannelIndex = processParam.Value<int>("ChannelIndex"); //通道
int DigitalValue = processParam.Value<int>("DigitalValue"); //亮度
int nowDiaitalValue = lightDev.GetLightDigitalValue(ChannelIndex);
Log($"{stepIndex + 1}-{processName}", $"通道{ChannelIndex}当前值:{nowDiaitalValue},准备更新值:{DigitalValue}...");
lightDev.SetLightDigitalValue(ChannelIndex, DigitalValue);
nowDiaitalValue = lightDev.GetLightDigitalValue(ChannelIndex);
Log($"{stepIndex + 1}-{processName}", $"通道{ChannelIndex}更新后当前值:{nowDiaitalValue}。");
#endregion
break;
case "Scanner_GENTL":
#region
if (confMgr.SysConfigParams.DisableCam)
{
Log($"{stepIndex + 1}-{processName}", $"设备禁用,忽略此步骤!");
//界面显示
OnAutoRuning(new RunEventArgs(liStatocStepIndex, $"设备禁用,忽略此步骤!"));
break;
}
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"); //帧率
Log($"{stepIndex + 1}-{processName}", $"相机开始采集照片...");
CamDev.SetExposure(ExposureTime);
CamDev.SetGain(Gain);
CamDev.SetResultingFrameRate(ResultingFrameRate);
DateTime dt = DateTime.Now;
CamDev.ClearImageQueue();
Acquisition acq = CamDev.Snap(1, 5000);
if (acq.GrabStatus != "GrabPass")
{
Log($"{stepIndex + 1}-{processName}", $"相机采集照片失败!", WarningEnum.High);
return stepIndex;
}
Log($"{stepIndex + 1}-{processName}", $"相机采集照片完成[" + (DateTime.Now - dt).Milliseconds.ToString() + "ms]" );
//显示
OnAutoRuning(new RunEventArgs(acq.Image));
//----缺陷队列
if (AIEngineLib == AIEngineLibEnum. || AIEngineLib == AIEngineLibEnum.)
{
var mat = CamDev.HImageToMat(acq.Image);
scannerGBmpQueue.Enqueue(new scannerGBmpLoc(mat,
GetAxisPosValueMM((int)AxisName.Axis0),
GetAxisPosValueMM((int)AxisName.Axis1)));//Dequeue
Log($"{stepIndex + 1}-{processName}", $"缺陷图像队列数量: {scannerGBmpQueue.Count}");
}
if (AIEngineLib == AIEngineLibEnum. || AIEngineLib == AIEngineLibEnum.)
{
scannerCBmpQueue.Enqueue(new scannerCBmpLoc(
acq.Image.Clone(),
GetAxisPosValueMM((int)AxisName.Axis0),
GetAxisPosValueMM((int)AxisName.Axis1)));//Dequeue
Log($"{stepIndex + 1}-{processName}", $"添加尺寸图像队列," +
$"X:{GetAxisPosValueMM((int)AxisName.Axis0)},y:{GetAxisPosValueMM((int)AxisName.Axis1)}," +
$"数量: {scannerCBmpQueue.Count}");
}
#endregion
break;
case "Scanner_CC":
#region
Log($"{stepIndex + 1}-{processName}", $"忽略不支持流程!");
OnAutoRuning(new RunEventArgs(liStatocStepIndex, $"设备禁用,忽略此步骤!"));
#endregion
break;
case "SmallAxis":
#region
Log($"{stepIndex + 1}-{processName}", $"忽略不支持流程!");
OnAutoRuning(new RunEventArgs(liStatocStepIndex, $"设备禁用,忽略此步骤!"));
#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)
{
Log($"{stepIndex + 1}-{processName}", $"尺寸检测异常,无源图像!!", WarningEnum.Low);
return stepIndex;
}
var bmpCBmpQueue = scannerCBmpQueue.Dequeue();
Log($"{stepIndex + 1}-{processName}", $"开始尺寸检测index:{sizeIndex},posX:{bmpCBmpQueue.PosX},posY:{bmpCBmpQueue.PosY},图像队列数量: {scannerCBmpQueue.Count}...");
attachmentFile = model.AttachmentList.FirstOrDefault(x => x.Type == 0);
Log($"{stepIndex + 1}-{processName}", $"尺寸检测index:{sizeIndex},{model.AttachmentList.Count}|{(attachmentFile == null ? "null" : attachmentFile.NameTimestamp + attachmentFile.ExtendName)}");
if (attachmentFile != null)
{
gbxBmpPath = confMgr.ProjectDir + $"\\{attachmentFile.NameTimestamp}";
if (!File.Exists(gbxBmpPath + attachmentFile.ExtendName))
gbxBmpPath = "";
}
if ((sizeIndex == 333 || sizeIndex == 777) && gbxBmpPath == "")
Log($"{stepIndex + 1}-{processName}", $"尺寸检测index:{sizeIndex},图纸不存在!", WarningEnum.Low);
//2023-10-27
if (useMap && (sizeIndex == 3333) && (getPosArray != null) && (getPosArray.Count() == 28) && (getPosArray[0] != 0))
Log($"{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);
SizeLib.add(new SizeTask()
{
stepIndex = stepIndex,
processName = processName,
sizeTag = sizeTag,
engineName = processParam.Value<string>("EngineName"),
Himage = bmpCBmpQueue.Himage.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)
{
//界面显示
OnAutoRuning(new RunEventArgs(liStatocStepIndex, $"index:{res.index}-{compBmpIndex}posX:{res.posX},posY:{res.posY},图像比对:{(res.CompResult ? "" : "")} "));
Log($"{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;
if(!res.CompResult)
{
//不合格
order.Qualified = false;
}
//更新比对看板 对比置零3
if (!res.CompResult)
SizeNGCnt++;
if (SizeNGCnt>0)
OnAutoRuning(new RunEventArgs(3, false, SizeNGCnt));
else
OnAutoRuning(new RunEventArgs(3, true, SizeNGCnt));
if (!res.CompResult)
{
Log($"{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 = userMgr.LoginUser.Code,
CreateUserCode = userMgr.LoginUser.Code,
});
}
//比对失败的图片 -- 用于修复台调用
Bitmap bmpCompareFailZoomImage = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(res.Zoom_Image_mat);
lstCompareFailZoomImage.Add(bmpCompareFailZoomImage);
if (confMgr.SysConfigParams.SizeRepairImag.SavePath != "" && Directory.Exists(confMgr.SysConfigParams.SizeRepairImag.SavePath))
{
string path = Util.CreateSubDir(confMgr.SysConfigParams.SizeRepairImag.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 (confMgr.SysConfigParams.SizeNGImag.SavePath != "" && Directory.Exists(confMgr.SysConfigParams.SizeNGImag.SavePath))
{
string path = Util.CreateSubDir(confMgr.SysConfigParams.SizeNGImag.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";
Log($"{res.stepIndex + 1}-{processName}", $"未通过图片保存:{path}");
if (res.Himage != null)
HOperatorSet.WriteImage(res.Himage, "bmp", 0, path);
else
API.CopyFile(res.file_path, path, false);//比.NET(File.Copy)更快
}
}
}
else
{
//不合格
order.Qualified = false;
order.CompareResult = 2;
SizeNGCnt++;
OnAutoRuning(new RunEventArgs(3, false, SizeNGCnt));
OnAutoRuning(new RunEventArgs(liStatocStepIndex, $"index:{res.index},图像比对失败!"));
Log($"{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)
{
Log($"{res.stepIndex + 1}-{processName}", $"Mark点 Index={res.index},结果记录...");
if (res.index == 333) this.contoursAffineTrans1_Out = res.ContoursAffineTrans1_Out;//不管成功失败都替换
if (res.isSucceed)
{
Thread.Sleep(100);
Log($"{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();
OnAutoRuning(new RunEventArgs(liStatocStepIndex, $"index:{res.index}Mark点:{order.MarkData} "));
Log($"{res.stepIndex + 1}-{processName}", $"Mark点 Index={res.index};合并后:{order.MarkData}");
}
else
{
OnAutoRuning(new RunEventArgs(liStatocStepIndex, $"index:{res.index}Mark点计算失败"));
Log($"{res.stepIndex + 1}-{processName}", $"Mark点计算失败index:{res.index}.", confMgr.SysConfigParams.OpenMarkErrorStop? WarningEnum.High : WarningEnum.Normal);
}
//保存
if (confMgr.SysConfigParams.SizeBigImag.SavePath != "" && Directory.Exists(confMgr.SysConfigParams.SizeBigImag.SavePath))
{
string path = Util.CreateSubDir(confMgr.SysConfigParams.SizeBigImag.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.Himage != null)
HOperatorSet.WriteImage(res.Himage, "bmp", 0, path);
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)
{
Log($"{res.stepIndex + 1}-{res.processName}", $"尺寸检测输出Tag对应posePT非法: {tagOutData}", WarningEnum.High);
return;
}
//2023-10-27
Log($"{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);
});
}
OnAutoRuning(new RunEventArgs(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}"));
Log($"{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)
{
//PT测量无
;
}
//------
if (roundIndex > 0)//1-9测量
{
//线宽测量无
;
}
//校正偏移 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;
Log($"{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.;
Log($"{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)
{
;
}
}
}
//失败
else
{
//------TEST
if (res.index > 20 && res.index < 30)
{
;
}
//------
if (roundIndex > 0)
{
;
}
OnAutoRuning(new RunEventArgs(liStatocStepIndex, $"失败:{res.resultInfo}"));
Log($"{res.stepIndex + 1}-{res.processName}", $"尺寸检测失败index:{res.index}:{res.resultInfo}");
}
//保存
if (confMgr.SysConfigParams.SizeBigImag.SavePath != "" && Directory.Exists(confMgr.SysConfigParams.SizeBigImag.SavePath))
{
string path = Util.CreateSubDir(confMgr.SysConfigParams.SizeBigImag.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.Himage != null)
HOperatorSet.WriteImage(res.Himage, "bmp", 0, path);
else
API.CopyFile(res.file_path, path, false);//比.NET(File.Copy)更快
}
}
}
catch (Exception ex)
{
Log($"{res.stepIndex + 1}-{res.processName}", $"尺寸检测回调处理异常 index:{res.index}ex={ex.Message}");
}
endEvent.Set();//roundIndex成功或失败线程返回
//---
if (res.Himage != null)
{
res.Himage.Dispose();
res.Himage = null;
}
else
{
API.DeleteFile(res.file_path);
}
}
});
//需等上面异步回调中的相对偏移校正完成再继续
if (!asynRun || sizeIndex % 10 == 0)
{
if (!endEvent.WaitOne(60000))
Log($"{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)
{
Log($"{stepIndex + 1}-{processName}", $"缺陷检测异常,无源图像!!", WarningEnum.Low);
return stepIndex;
}
var bmpLoc = scannerGBmpQueue.Dequeue();
Log($"{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 = ConfMgr.Instance.ProjectDir + $"\\{attachmentFile.NameTimestamp}";
if (!File.Exists(gbxBmpPath + attachmentFile.ExtendName)) gbxBmpPath = "";
}
Log($"{stepIndex + 1}-{processName}", $"图纸路径:{gbxBmpPath}");
defectLib.add(new DefectTask()
{
stepIndex = stepIndex,
processName = processName,
drawingPagePath = gbxBmpPath,
index = defectBmpNum++,
bmp = bmpLoc.bmp.Clone(),
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)
{
//界面显示
OnAutoRuning(new RunEventArgs(liStatocStepIndex,
$"源图索引:{res.index},缺陷数:{res.defectCount},处理时间(ms):{string.Join("->", res.stopwatch.Select(i => i.ToString()).ToArray())}"));
Log($"{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显示小图 (含统计缺陷类型数量)
AllDefectCount += res.informationList.Count;
showDefectSmallBmps(res.bmps_tag, res.bmps_cut, res.Xmm, res.Ymm, res.informationList);
if (res.defectInfor2RestorationDeskPage != null && res.defectInfor2RestorationDeskPage.Count > 0)
{
Log($"{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 = UserMgr.LoginUser.Code,
CreateUserCode = UserMgr.LoginUser.Code,
});
}
//保存原始大图
if (confMgr.SysConfigParams.DefectBigImag.SavePath != "" && Directory.Exists(confMgr.SysConfigParams.DefectBigImag.SavePath))
{
path = Util.CreateSubDir(confMgr.SysConfigParams.DefectBigImag.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}";
OpenCvSharp.Extensions.BitmapConverter.ToBitmap(res.bmp).Save(path + ".bmp", ImageFormat.Bmp);
File.WriteAllText(path + ".json", JsonConvert.SerializeObject(res.informationList));
}
//保存小图
if (confMgr.SysConfigParams.DefectSmallImag.SavePath != "" && Directory.Exists(confMgr.SysConfigParams.DefectSmallImag.SavePath))
{
path = Util.CreateSubDir(confMgr.SysConfigParams.DefectSmallImag.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 (confMgr.SysConfigParams.DefectRepairImag.SavePath != "" && Directory.Exists(confMgr.SysConfigParams.DefectRepairImag.SavePath))
{
path = Util.CreateSubDir(confMgr.SysConfigParams.DefectRepairImag.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}";
OpenCvSharp.Extensions.BitmapConverter.ToBitmap(res.bmpCompress).Save(path + ".bmp", ImageFormat.Bmp);
File.WriteAllText(path + ".json", JsonConvert.SerializeObject(res.defectInfor2RestorationDesk));
}
}
else//没有缺陷
{
if (confMgr.SysConfigParams.SaveAllImg && confMgr.SysConfigParams.DefectBigImag.SavePath != "" && Directory.Exists(confMgr.SysConfigParams.DefectBigImag.SavePath))
{
path = Util.CreateSubDir(confMgr.SysConfigParams.DefectBigImag.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}";
OpenCvSharp.Extensions.BitmapConverter.ToBitmap(res.bmp).Save(path + ".bmp", ImageFormat.Bmp);
}
}
}
else
{
OnAutoRuning(new RunEventArgs(liStatocStepIndex, $"失败:{res.resultInfo}"));
Log($"{res.stepIndex + 1}-{res.processName}", $"缺陷检测失败:{res.resultInfo}");
//暂停 这里不能暂停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)
{
Log($"{stepIndex + 1}-{processName}", $"For死循环", WarningEnum.High);
return stepIndex;
}
if (!forLib.dicData.ContainsKey(UniqueId))
forLib.dicData.Add(UniqueId, 0);
//
int Num = forLib.dicData[UniqueId];
Num++;
if (Num <= LimitNum)
{
if (Num == LimitNum)
{
OnAutoRuning(new RunEventArgs(liStatocStepIndex, $"第[{Num}/{LimitNum}]次,循环完成"));
Log($"{stepIndex + 1}-{processName}", $"第[{Num}/{LimitNum}]次,循环完成。");
}
else
{
OnAutoRuning(new RunEventArgs(liStatocStepIndex, $"第[{Num}/{LimitNum}]次"));
Log($"{stepIndex + 1}-{processName}", $"第[{Num}/{LimitNum}]次跳转到步骤[{GotoStepIndex}]...");
stepIndex = GotoStepIndex - 2;
}
forLib.dicData[UniqueId] = Num;
}
else
{
OnAutoRuning(new RunEventArgs(liStatocStepIndex, $"已失效不执行"));
Log($"{stepIndex + 1}-{processName}", $"本循环已失效不执行!");
}
//达到limit重置0
if (forLib.dicData[UniqueId] >= LimitNum && Reset)
{
forLib.dicData[UniqueId] = 0;
OnAutoRuning(new RunEventArgs(liStatocStepIndex, $"第[0/{LimitNum}]次"));
Log($"{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)
{
Log($"{stepIndex + 1}-{processName}", $"If死循环不可自我跳转", WarningEnum.High);
return stepIndex;
}
//
if (!ifLib.dicData.ContainsKey(UniqueId_if))
ifLib.dicData.Add(UniqueId_if, 0);
//
int Num_if = ifLib.dicData[UniqueId_if];
Num_if++;
if (Num_if <= LimitNum_if)
{
if (Num_if == LimitNum_if)
{
OnAutoRuning(new RunEventArgs(liStatocStepIndex, $"第[{Num_if}/{LimitNum_if}]次,跳转至[{GotoStepIndex_if}]"));
Log($"{stepIndex + 1}-{processName}", $"计数器[{Num_if}/{LimitNum_if}],跳转至步骤[{GotoStepIndex_if}]...");
stepIndex = GotoStepIndex_if - 2;
}
else
{
OnAutoRuning(new RunEventArgs(liStatocStepIndex, $"第[{Num_if}/{LimitNum_if}]次,不跳转"));
Log($"{stepIndex + 1}-{processName}", $"计数器[{Num_if}/{LimitNum_if}],不跳转。");
}
//
ifLib.dicData[UniqueId_if] = Num_if;
}
else
{
OnAutoRuning(new RunEventArgs(liStatocStepIndex, $"已失效不执行"));
Log($"{stepIndex + 1}-{processName}", $"本IF已失效不执行。");
}
//达到limit重置0
if (ifLib.dicData[UniqueId_if] >= LimitNum_if && Reset_if)
{
ifLib.dicData[UniqueId_if] = 0;
OnAutoRuning(new RunEventArgs(liStatocStepIndex, $"第[0/{LimitNum_if}]次"));
Log($"{stepIndex + 1}-{processName}", $"计数器已重置。");
}
#endregion
break;
default:
Log($"{stepIndex + 1}-{processName}", $"未知工序:{processInfo.ProcessCode}", WarningEnum.High);
return stepIndex;
}
if (sleepLater > 0) Thread.Sleep((int)sleepLater);
}
//============结束,判断是否自动下料
if (stepIndex == processList.Count - 1)
{
Log("下料", "产品测试完成,移动到下料位");
bool ret = GotoLoadPos();
if (!ret)
{
Log("下料", "系统电机复位失败", WarningEnum.High);
}
if (!RunQG(false))
{
Log("下料", "系统IO复位失败", WarningEnum.High);
}
Log("结果", "产品测试完成,等待测试结果...");
//等待缺陷图显示完成
while (defectBmpNum != defectBmpNumResult)
Thread.Sleep(100);
//判断是否合格
DefectCodeEnum defectCode;
DefectCode2Enum defectCode2;
string defectNames = "";
//if (model.QualifiedCriterionList != null && model.QualifiedCriterionList.Count > 0)
//{
// int itemDefectCount;
// foreach (var item in model.QualifiedCriterionList)
// {
// Classes classtemp = ClassesService.GetById(model.ClassesId);
// if ((classtemp != null) && (classtemp.Name == "钢网"))
// {
// defectCode2 = EnumExtension.Convert2Enum<DefectCode2Enum>(item.DefectCode);
// itemDefectCount = getDefectCountFromCode(order, defectCode2);
// if (item.MaxDefectCount > -1 && itemDefectCount > item.MaxDefectCount)
// {
// order.Qualified = false;
// defectNames += $"{EnumExtension.GetEnumDescription(defectCode2)}({itemDefectCount}),";
// }
// }
// else
// {
// defectCode = EnumExtension.Convert2Enum<DefectCodeEnum>(item.DefectCode);
// itemDefectCount = getDefectCountFromCode(order, defectCode);
// if (item.MaxDefectCount > -1 && itemDefectCount > item.MaxDefectCount)
// {
// order.Qualified = false;
// defectNames += $"{EnumExtension.GetEnumDescription(defectCode)}({itemDefectCount}),";
// }
// }
// }
//}
//else
{
Log("结果", "结果判断");
int itemDefectCount;
bool isGetQua = false;
Classes classtemp = ClassesService.GetById(model.ClassesId);
if ((classtemp != null) && (classtemp.Name == "钢网"))
{
Log("结果", $"类别判断:{classtemp.Name}");
for (int enumcnt = 0; enumcnt < 3; enumcnt++)
{
isGetQua = false;
//判断是否是过滤项
if (model.QualifiedCriterionList != null && model.QualifiedCriterionList.Count > 0)
{
foreach (var item in model.QualifiedCriterionList)
{
defectCode2 = EnumExtension.Convert2Enum<DefectCode2Enum>(item.DefectCode);
//是过滤
if (defectCode2 == (DefectCode2Enum)enumcnt)
{
isGetQua = true;
itemDefectCount = getDefectCountFromCode(order, defectCode2);
if (item.MaxDefectCount > -1 && itemDefectCount > item.MaxDefectCount)
{
order.Qualified = false;
defectNames += $"{EnumExtension.GetEnumDescription(defectCode2)}({itemDefectCount}),";
}
}
}
}
if (!isGetQua)
{
itemDefectCount = getDefectCountFromCode(order, (DefectCode2Enum)enumcnt);
if (itemDefectCount > 0)
{
order.Qualified = false;
defectNames += $"{EnumExtension.GetEnumDescription((DefectCode2Enum)enumcnt)}({itemDefectCount}),";
}
}
}
}
else
{
if (classtemp != null)
Log("结果", $"类别判断:{classtemp.Name}");
else
Log("结果", $"类别默认");
for (int enumcnt = 0; enumcnt < 12; enumcnt++)
{
isGetQua = false;
//判断是否是过滤项
if (model.QualifiedCriterionList != null && model.QualifiedCriterionList.Count > 0)
{
foreach (var item in model.QualifiedCriterionList)
{
defectCode = EnumExtension.Convert2Enum<DefectCodeEnum>(item.DefectCode);
//是过滤
if (defectCode == (DefectCodeEnum)enumcnt)
{
isGetQua = true;
itemDefectCount = getDefectCountFromCode(order, defectCode);
if (item.MaxDefectCount > -1 && itemDefectCount > item.MaxDefectCount)
{
order.Qualified = false;
defectNames += $"{EnumExtension.GetEnumDescription(defectCode)}({itemDefectCount}),";
}
}
}
}
if (!isGetQua)
{
itemDefectCount = getDefectCountFromCode(order, (DefectCodeEnum)enumcnt);
if (itemDefectCount > 0)
{
order.Qualified = false;
defectNames += $"{EnumExtension.GetEnumDescription((DefectCodeEnum)enumcnt)}({itemDefectCount}),";
}
}
}
}
}
stopWatch.Stop();
long timeLen = stopWatch.ElapsedMilliseconds / 1000;
OnAutoRuning(new RunEventArgs(4, defectNames == "",0, defectNames));
OnAutoRuning(new RunEventArgs(timeLen));
//界面显示
order.TimeLen = timeLen;
order.DefectCount = AllDefectCount;
order.Succeed = true;
order.ModifyUserCode = order.CreateUserCode = userMgr.LoginUser.Code;
order.Abnormalities = "";//无异常
order.RepairCode = "";//无修复人员
//如SN检测已存在先删除
var oldSNOrder = OrderService.GetFirst(m => m.SN == order.SN);
if (oldSNOrder != null)
{
Log("删除记录", $"删除上一重复SN检测记录:SN={oldSNOrder.SN}, Date={oldSNOrder.CreateTime}");
OrderService.DelNav(oldSNOrder);
}
if (!OrderService.InsertNav(order))//导航插入
Log("保存失败", $"保存生产记录失败!", WarningEnum.Low);
//更新本批次检测数量
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 = OrderService.Count(expOrder);
}
//以主键为条件更新CompleteCount单列值
PdtService.Update(it => new Product() { CompleteCount = CurrProductModel.CompleteCount }, it => it.Id == CurrProductModel.Id);
Log("完成", $"用时 {order.TimeLen} 秒");
_isAuto = false;
OnAutoRuning(new RunEventArgs(_isAuto));
//GotoReadyPosAndIO();
statusMgr.ClearWarning();
LedReady();
statusMgr.GotoNormalStandby();
CurrProcessIndex = -1;
return -1;
}
else //继续
{
return ++stepIndex;
}
}
catch (Exception ex)
{
Log("工序", $"[{stepIndex + 1}] Err:" + ex.Message + "\n" + ex.StackTrace, WarningEnum.High);
return -2;
}
}
/// <summary>
/// 根据缺陷code获取缺陷数量
/// </summary>
/// <param name="order"></param>
/// <param name="defectCodeEnum"></param>
/// <returns></returns>
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 int getDefectCountFromCode(Order order, DefectCode2Enum defectCodeEnum)
{
switch (defectCodeEnum)
{
case DefectCode2Enum.gs:
return order.GSYCCount;
case DefectCode2Enum.zw:
return order.ZWCount;
default:
return 0;
}
}
#endregion
#region
#region
public void DelectPictureFile()
{
//删除文件
Task.Factory.StartNew(() =>
{
//图片
if (confMgr.SysConfigParams.DefectBigImag.AutoDelete)
statusMgr.DeleteFiles(confMgr.SysConfigParams.DefectBigImag.SavePath, confMgr.SysConfigParams.DefectBigImag.AutoDeleteDays, true);
if (confMgr.SysConfigParams.DefectSmallImag.AutoDelete)
statusMgr.DeleteFiles(confMgr.SysConfigParams.DefectSmallImag.SavePath, confMgr.SysConfigParams.DefectSmallImag.AutoDeleteDays, true);
if (confMgr.SysConfigParams.DefectRepairImag.AutoDelete)
statusMgr.DeleteFiles(confMgr.SysConfigParams.DefectRepairImag.SavePath, confMgr.SysConfigParams.DefectRepairImag.AutoDeleteDays, true);
if (confMgr.SysConfigParams.SizeBigImag.AutoDelete)
statusMgr.DeleteFiles(confMgr.SysConfigParams.SizeBigImag.SavePath, confMgr.SysConfigParams.SizeBigImag.AutoDeleteDays, true);
if (confMgr.SysConfigParams.SizeNGImag.AutoDelete)
statusMgr.DeleteFiles(confMgr.SysConfigParams.SizeNGImag.SavePath, confMgr.SysConfigParams.SizeNGImag.AutoDeleteDays, true);
if (confMgr.SysConfigParams.SizeRepairImag.AutoDelete)
statusMgr.DeleteFiles(confMgr.SysConfigParams.SizeRepairImag.SavePath, confMgr.SysConfigParams.SizeRepairImag.AutoDeleteDays, true);
//日志
if (confMgr.SysConfigParams.AutoDeleteLog)
statusMgr.DeleteFiles(confMgr.SysConfigParams.LogPath, confMgr.SysConfigParams.AutoDeleteLogData, true);
});
}
#endregion
#endregion
#region
/// <summary>
/// 初始化回调
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public delegate void InitEventHandler(Object sender, InitEventArgs e);
public event InitEventHandler InitRuning;
protected virtual void OnInitRuning(InitEventArgs e)
{
if (null != InitRuning)
{
InitRuning(this, e);
}
}
/// <summary>
/// 流程回调
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public delegate void RunEventHandler(Object sender, RunEventArgs e);
public event RunEventHandler AutoRuning;
protected virtual void OnAutoRuning(RunEventArgs e)
{
if (null != AutoRuning)
{
AutoRuning(this, e);
}
}
/// <summary>
/// 显图回调
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public delegate void ImgEventHandler(Object sender, ImgEventArgs e);
public event ImgEventHandler AutoShowImg;
protected virtual void OnAutoShowImg(ImgEventArgs e)
{
if (null != AutoShowImg)
{
AutoShowImg(this, e);
}
}
/// <summary>
/// 主窗体回调
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public delegate void MainEventHandler(Object sender, MainEventArgs e);
public event MainEventHandler MainRuning;
protected virtual void OnMainRuning(MainEventArgs e)
{
if (null != MainRuning)
{
MainRuning(this, e);
}
}
private void showDefectSmallBmps(Bitmap[] bmps, Mat[] bmps_cut, double Xmm, double Ymm, List<Dictionary<int, List<string>[]>> info)
{
OnAutoShowImg(new ImgEventArgs(bmps, bmps_cut, Xmm, Ymm, info));
}
#endregion
#region
public static void showRowNum_onDataGrid_RowPostPaint(DataGridView dgv, object sender, DataGridViewRowPostPaintEventArgs e)
{
Rectangle rectangle = new Rectangle(e.RowBounds.Location.X, e.RowBounds.Location.Y, dgv.RowHeadersWidth - 4, e.RowBounds.Height);
TextRenderer.DrawText(e.Graphics, (e.RowIndex + 1).ToString(), dgv.RowHeadersDefaultCellStyle.Font, rectangle, dgv.RowHeadersDefaultCellStyle.ForeColor, TextFormatFlags.VerticalCenter | TextFormatFlags.Right);
}
/// <summary>
/// IO二进制数据格式化到8位 XXXX10X0
/// </summary>
/// <param name="datas"></param>
/// <returns></returns>
public static string[] IODataFormatBinaryStr(string[] datas, bool clone, char defaultPadChar = 'X')
{
string[] datas2 = new string[datas.Length];
for (int i = 0; i < datas.Length; i++)
{
if (clone)
{
datas2[i] = datas[i].Replace(" ", "");
if (datas2[i].Length > 8)
datas2[i] = datas2[i].Substring(datas2[i].Length - 8);
else if (datas2[i].Length < 8)
datas2[i] = datas2[i].PadLeft(8, defaultPadChar);
}
else
{
datas[i] = datas[i].Replace(" ", "");
if (datas[i].Length > 8)
datas[i] = datas[i].Substring(datas[i].Length - 8);
else if (datas[i].Length < 8)
datas[i] = datas[i].PadLeft(8, defaultPadChar);
datas2 = datas;
}
}
return datas2;
}
/// <summary>
///
/// </summary>
/// <param name="op_show_list">[XXHL XXXX,XXXX XXXX,...]</param>
/// <param name="currIoDatas">[byte,byte,byte,byte]</param>
/// <returns></returns>
public static bool compareIOInput(string[] op_show_list, byte[] currIoDatas)
{
int isok = 0;//1-true 2-false
string IN_OP_SHOW;
for (int i = 0; i < currIoDatas.Length; i++)
{
IN_OP_SHOW = op_show_list[i].Replace(" ", "").PadLeft(8, 'X');
if (IN_OP_SHOW.IndexOf('H') < 0 && IN_OP_SHOW.IndexOf('L') < 0)
continue;
for (int j = 7; j >= 0; j--)
{
byte bit = (byte)(1 << 7 - j);
if (IN_OP_SHOW[j] == 'H')
{
if ((bit & currIoDatas[i]) > 0)
isok = 1;
else
{
isok = 2;
break;
}
}
else if (IN_OP_SHOW[j] == 'L')
{
if ((currIoDatas[i] ^ (currIoDatas[i] | bit)) > 0)
isok = 1;
else
{
isok = 2;
break;
}
}
}
//已经不符
if (isok == 2) break;
}
//
return isok == 1;
}
#endregion
#region
public static bool CheckDisk(IWin32Window owner, int max = 10)
{
string path = ConfMgr.Instance.SysConfigParams.DefectBigImag.SavePath;
string volume = path.Substring(0, path.IndexOf(':'));
long freespace = DiskAPI.GetHardDiskSpace(volume);
if (freespace < max)
{
string tip = $"当前{volume}硬盘容量:{freespace}GB小于{max}GB。注意清理";
FrmDialog.ShowDialog(owner, tip, "警告", true);
return false;
}
return true;
}
#endregion
}
#region
/// <summary>
/// 流程事件
/// </summary>
public class RunEventArgs : EventArgs
{
private int _cmd;
public int Cmd { get { return _cmd; } }
private string _sn;
public string SN { get { return _sn; } }
private List<StepProcess> _stepProcesses;
public List<StepProcess> StepProcessesList { get { return _stepProcesses; } }
private int _stepIndex;
public int StepIndex { get { return _stepIndex; } }
private string _mesg;
public string Mesg { get { return _mesg; } }
private bool _compareResult;
public bool CompareResult { get { return _compareResult; } }
private string _resultStr;
public string ResultStr { get { return _resultStr; } }
private long _time;
public long Time { get { return _time; } }
private long _cnt;
public long Cnt { get { return _cnt; } }
public RunEventArgs(string sn, List<StepProcess> list)
{
this._cmd = 0;
this._sn = sn;
this._stepProcesses = list;
}
public RunEventArgs(int stepIndex)
{
this._cmd = 1;
this._stepIndex = stepIndex;
}
public RunEventArgs(int stepIndex, string mesg)
{
this._cmd = 2;
this._stepIndex = stepIndex;
_mesg = mesg;
}
public RunEventArgs(int cmd, bool rel, int cnt, string str = "")
{
this._cmd = cmd;
this._compareResult = rel;
this._cnt = cnt;
this._resultStr = str;
}
public RunEventArgs(long time )
{
this._cmd = 7;
this._time = time;
}
private HObject _pic;
public HObject Pic { get { return _pic; } }
public RunEventArgs(HObject pic)
{
this._cmd = 6;
this._pic = pic.Clone();
}
private bool _over;
public bool Over { get { return _over; } }
public RunEventArgs(bool ov)
{
this._cmd = 10;
this._over = ov;
}
}
/// <summary>
/// 显图事件
/// </summary>
public class ImgEventArgs : EventArgs
{
private Bitmap[] _bmps;
public Bitmap[] Bitmaps { get { return _bmps; } }
private Mat[] _bmps_cut;
public Mat[] Bmps_cut { get { return _bmps_cut; } }
private double _x;
public double X { get { return _x; } }
private double _y;
public double Y { get { return _y; } }
private List<Dictionary<int, List<string>[]>> _info;
public List<Dictionary<int, List<string>[]>> Info
{
get { return _info; }
}
public ImgEventArgs(Bitmap[] bmps, Mat[] bmps_cut, double Xmm, double Ymm, List<Dictionary<int, List<string>[]>> info)
{
this._bmps = new Bitmap[bmps.Length];
for (int i = 0; i < bmps.Length; i++)
{
this._bmps[i] = (Bitmap)bmps[i].Clone();
}
this._bmps_cut = new Mat[bmps_cut.Length];
for (int i = 0; i < bmps_cut.Length; i++)
{
this._bmps_cut[i] = bmps_cut[i].Clone();
}
this._x = Xmm;
this._y = Ymm;
this._info = info;
}
}
/// <summary>
/// 主窗体事件
/// </summary>
public class MainEventArgs : EventArgs
{
private string _tag;
public string Tag { get { return _tag; } }
private string _message;
public string Message { get { return _message; } }
private int _showIndex;
public int ShowIndex { get { return _showIndex; } }
private WarningEnum _warning;
public WarningEnum Warning { get { return _warning; } }
public MainEventArgs(int index)
{
this._showIndex = index;
}
public MainEventArgs(int index, string message)
{
this._message = message;
this._showIndex = index;
}
public MainEventArgs(string tag, string message, WarningEnum warning = WarningEnum.Normal)
{
this._tag = tag;
this._message = message;
this._showIndex = 0;
this._warning = warning;
}
}
/// <summary>
/// 初始化事件
/// </summary>
public class InitEventArgs : EventArgs
{
private string _message;
public string Message { get { return _message; } }
private bool _isInitialized;
public bool IsInitialized { get { return _isInitialized; } }
public InitEventArgs()
{
}
public InitEventArgs(string message, bool isInitialized = false)
{
this._message = message;
this._isInitialized = isInitialized;
}
}
#endregion
}