3414 lines
167 KiB
C#
3414 lines
167 KiB
C#
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=0成功或失败线程返回
|
||
//---
|
||
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
|
||
}
|