using Advantech.Motion; using AssistClient.Device; using AssistClient.Utils; using Models; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using OpenCvSharp; using SqlSugar; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Imaging; using System.Dynamic; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using Yolo5; using static AssistClient.Device.SizeLib; using Point = System.Drawing.Point; using Size = System.Drawing.Size; namespace AssistClient { public partial class FrmMain : Form { #region pic缩放变量 private double ratio = 1; // 图片的起始显示比例 private double ratioStep = 0.1; private Size pic_size; private int xPos; private int yPos; #endregion private bool bExitApp = false; private Service.ProductService svcProduct = new Service.ProductService(); private Service.OrderService svcOrder = new Service.OrderService(); private DevContainer devContainer = new DevContainer(); private Queue scannerCBmpQueue = new Queue(); private int sizeBmpNum = 0, sizeBmpNumResult = 0; private string SN = ""; private int OrderId = 0; private JArray currProductMarkList = null; private int currDefectIndex = 0; private List defectList = new List(); private Dictionary defectBmpsDir = new Dictionary(); private Dictionary>> defectInfoDir = new Dictionary>>(); private object myLock = new object(); private WarningEnum warningLevel;//警告等级 private CurrentPTEnum currentPT;//当前点位 private CurrentStateEnum currentState;//当前状态 /// /// 当前流程ID,暂停/继续时使用 /// private int currProcessIndex = -1; private Models.Product currProductModel = null;//当前产品 private System.Timers.Timer timer = new System.Timers.Timer(); Yolo_Class yolo = new Yolo_Class(); private class scannerCBmpLoc { public scannerCBmpLoc(string path, double posX, double posY) { Path = path; PosX = posX; PosY = posY; } public scannerCBmpLoc(Bitmap bmp, double posX, double posY) { BMP = bmp; PosX = posX; PosY = posY; } public Bitmap BMP { get; private set; } public string Path { get; private set; } public double PosX { get; private set; } public double PosY { get; private set; } } public FrmMain() { InitializeComponent(); this.tsbtnCloseDev.Visible = false; this.dgvProcess.AutoGenerateColumns = false; //显示行号与列宽度自动调整 dgvProcess.RowHeadersVisible = true; dgvProcess.RowHeadersWidth = 30; dgvProcess.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing; //dgvProcess.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders;//数据量过百绑定太变 dgvProcess.RowPostPaint += (sender, e) =>//序号列头 { Utils.Util.showRowNum_onDataGrid_RowPostPaint(this.dgvProcess, sender, e); }; for (int i = 0; i < dgvProcess.Columns.Count; i++)//禁止点击列头排序 dgvProcess.Columns[i].SortMode = DataGridViewColumnSortMode.NotSortable; //模糊查询,Append自动填充 this.cbxSN.AutoCompleteMode = AutoCompleteMode.SuggestAppend; this.cbxSN.AutoCompleteSource = AutoCompleteSource.ListItems; } private void FrmMain_Load(object sender, EventArgs e) { this.tsbtnPause.Left = this.tsbtnGoDownPT.Left = this.gpbZAxis.Right + 10; } private void FrmMain_FormClosing(object sender, FormClosingEventArgs e) { if (devContainer.state) { MessageBox.Show("请先停止设备后才能关闭程序!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning); e.Cancel = true; return; } if (!bExitApp && MessageBox.Show($"确认退出?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) { e.Cancel = true; return; } } private void FrmMain_FormClosed(object sender, FormClosedEventArgs e) { Application.Exit(); System.GC.Collect(); System.Environment.Exit(0); } #region 菜单 private void 设备调试ToolStripMenuItem_Click(object sender, EventArgs e) { if (devContainer.state) { MessageBox.Show("请先停止设备,再进行设备调试!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } FrmDebug3 frm = new FrmDebug3(); frm.ShowDialog(); } private void tsMenuPTSetting_Click(object sender, EventArgs e) { if (devContainer.state) { MessageBox.Show("请先停止设备,再进行设置!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } FrmPTSetting from = new FrmPTSetting(); from.ShowDialog(); } private void tsMenuCmdSetting_Click(object sender, EventArgs e) { if (devContainer.state) { MessageBox.Show("请先停止设备,再进行设置!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } FrmCMDProcess from = new FrmCMDProcess(); from.ShowDialog(); } private void tsMenuSysSetting_Click(object sender, EventArgs e) { FrmSysSetting frmSetting = new FrmSysSetting(); frmSetting.ShowDialog(); } #endregion #region 图片缩放控制 private void reloadPic(Bitmap bmp, List> defectInfor2RepairTable, DefectStruct defectInfo) { //绘框 if (defectInfor2RepairTable != null && defectInfo != null) { AddTextEvent("更新图片", $"打标:MainX={defectInfo.MainX},MainY={defectInfo.MainY},CurrIndex={defectInfo.CurrIndex},RepairTable={JsonConvert.SerializeObject(defectInfor2RepairTable)}", warningLevel); Mat mat = OpenCvSharp.Extensions.BitmapConverter.ToMat(bmp); mat = yolo.RepairTableDrawRec(defectInfor2RepairTable, defectInfo.MainX, defectInfo.MainY, defectInfo.CurrIndex, mat); bmp = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat); } else AddTextEvent("更新图片", "无需打标!", warningLevel); var newSize = Util.getNewSize(splitContainer2.Panel1.ClientSize, new Size(bmp.Size.Width*100, bmp.Size.Height*100)); this.pnlPic.Size = newSize; if (this.pnlPic.Width < splitContainer2.Panel1.ClientSize.Width) this.pnlPic.Left = (splitContainer2.Panel1.ClientSize.Width - this.pnlPic.Width) / 2; if (this.pnlPic.Height < splitContainer2.Panel1.ClientSize.Height) this.pnlPic.Top = (splitContainer2.Panel1.ClientSize.Height - this.pnlPic.Height) / 2; ratio = 1.0;// 图片的起始显示比例 Size size = bmp.Size; //this.pnlPic.ClientSize = new Size(this.pnlPic.ClientSize.Width, // (int)(this.pnlPic.ClientSize.Width * (size.Height * 1.0f / size.Width))); this.pictureBox1.Size = this.pnlPic.ClientSize; this.pictureBox1.Location = new Point(0, 0); this.pictureBox1.Image = bmp;//del pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; //2023-12-22 之前工程师写的,存在bug,屏蔽 pictureBox1.MouseWheel += new MouseEventHandler(pictureBox1_MouseWheel); pictureBox1.MouseMove += pictureBox1_MouseMove; pictureBox1.MouseDown += pictureBox1_MouseDown; this.ActiveControl = this.pictureBox1; // 设置焦点 pic_size = this.pnlPic.ClientSize; } private void pictureBox1_MouseWheel(object sender, MouseEventArgs e) { //Point pictureBoxPoint = this.PointToClient(Cursor.Position); ////this.Text = $"{e.X}:{e.Y}; {pictureBoxPoint.X}:{pictureBoxPoint.Y}; {pictureBox1.Left}:{pictureBox1.Top}; " + //// $"{this.pictureBox1.Width}:{this.pictureBox1.Height}; {this.Width}:{this.Height}; " + //// $"Cursor:{Cursor.Position.X}:{Cursor.Position.Y}"; //if (e.Delta > 0) //{ // ratio += ratioStep; // if (ratio > 100) // 放大上限 // ratio = 100; // else // { // int x = (int)(pictureBox1.Left - e.X * (e.X * 1.0d / pictureBox1.Width * ratioStep) + 0.5); // int y = (int)(pictureBox1.Top - e.Y * (e.Y * 1.0d / pictureBox1.Height * ratioStep) + 0.5); // //this.Text = $"{pictureBox1.Width}-{pic_size.Width};{ratio},{pictureBox1.Left}-{e.X}* 比例:{e.X*1.0d/pictureBox1.Width}={e.X}/{pictureBox1.Width} * {(ratioStep)}={x} | " + // // $"{pictureBox1.Top}-{e.Y}* {e.Y * 1.0f / pictureBox1.Height * (ratio - 1.0d)}={y}"; // this.changePictureBoxSize(new Point(x, y), ratio); // } //} //else if (ratio - ratioStep >= 1) //{ // ratio -= ratioStep; // //if (ratio < 0.1) // 放大下限 // // ratio = 0.1; // //else // int x = (int)(pictureBox1.Left + e.X * (e.X * 1.0d / pictureBox1.Width * ratioStep) + 0.5); // int y = (int)(pictureBox1.Top + e.Y * (e.Y * 1.0d / pictureBox1.Height * ratioStep) + 0.5); // this.changePictureBoxSize(new Point(x, y), ratio); //} } private void changePictureBoxSize(Point location, double ratio) { //var picSize = pictureBox1.Size; //picSize.Width = Convert.ToInt32(picSize.Width * ratio); //picSize.Height = Convert.ToInt32(picSize.Height * ratio); //pictureBox1.Size = picSize; //if (location.X > 0) location.X = 0; //if (location.Y > 0) location.Y = 0; //if (picSize.Width + location.X < this.pnlPic.ClientSize.Width) location.X = -(picSize.Width - this.pnlPic.ClientSize.Width); //if (picSize.Height + location.Y < this.pnlPic.ClientSize.Height) location.Y = -(picSize.Height - this.pnlPic.ClientSize.Height); ////Point location = new Point(); ////location.X = (this.ClientSize.Width - this.pictureBox1.Width) / 2; ////location.Y = (this.ClientSize.Height - this.pictureBox1.Height) / 2; //this.pictureBox1.Location = location; } private void pictureBox1_MouseMove(object sender, MouseEventArgs e) { //try //{ // // 鼠标按下拖拽图片 // if (e.Button == MouseButtons.Left) // { // this.Text = $"{e.X}:{e.Y};{xPos}:{yPos}"; // // 限制拖拽出框 // if (pictureBox1.Width > this.pnlPic.ClientSize.Width // || pictureBox1.Height > this.pnlPic.ClientSize.Height) // { // int moveX = e.X - xPos; // int moveY = e.Y - yPos; // if ((pictureBox1.Left + moveX) <= 0 // && (pictureBox1.Top + moveY) <= 0 // && (pictureBox1.Right + moveX) >= this.pnlPic.ClientSize.Width // && (pictureBox1.Bottom + moveY) >= this.pnlPic.ClientSize.Height) // { // pictureBox1.Left += moveX;//设置x坐标. // pictureBox1.Top += moveY;//设置y坐标. // } // } // } //} //catch (Exception dd) //{ // MessageBox.Show(dd.Message); //} } private void pictureBox1_MouseDown(object sender, MouseEventArgs e) { //xPos = e.X;//当前x坐标. //yPos = e.Y;//当前y坐标. } #endregion #region 中断命令Fun private Thread threadProcess; /// /// 启动 /// private void startCommand() { if (!devContainer.state || warningLevel != WarningEnum.Normal || currentState != CurrentStateEnum.等待启动) return; if (currentPT == CurrentPTEnum.MakeTag) { AddTextEvent("启动", "打标未结束,非可启动状态!", warningLevel); return; } if (!devContainer.devAxis.isReady()) { AddTextEvent("启动", "轴状态异常,不可启动!", warningLevel); return; } if (!devContainer.devAxis.IsReset) { AddTextEvent("启动", "轴需先进行复位操作!", WarningEnum.High); return; } devContainer.io_output(CMDName.启动按钮); //devContainer.io_output(CMDName.绿灯输出); //devContainer.io_output(CMDName.暂停按钮, false, true, 0); //devContainer.io_output(CMDName.红灯输出, false, true, 0); //devContainer.io_output(CMDName.黄灯输出, false, true, 0); //暂停-》继续 if (currProcessIndex >= 0 && currentPT == CurrentPTEnum.Moving && currentState == CurrentStateEnum.等待启动) { AddTextEvent("启动", $"暂停 -> 继续 当前工序索引:{currProcessIndex + 1}"); threadProcess = new System.Threading.Thread(() => { int nextStepId = currProcessIndex; do { currentState = CurrentStateEnum.运行中; nextStepId = nextProcess(currProductModel, nextStepId); } while (nextStepId >= 0 && !isBreakProcessRun()); //nextProcess(currProductModel, currProcessIndex); }); threadProcess.IsBackground = true; threadProcess.Start(); this.setButtonEnabled(this.tsbtnPause, true); this.setButtonEnabled(this.tsbtnStopNow, true); } else//开始/重新开始 { //校正从复位-》运行,不会新启动 resetUIValue(); AddTextEvent("启动", "移动至上料位..."); Task.Run(() => { loadOrderSNList(); });//加载SN gotoUpPT(); this.Invoke(new System.Action(() => { //新开始 runStep(); })); this.setButtonEnabled(this.tsbtnPause, false); this.setButtonEnabled(this.tsbtnStopNow, false); } this.setButtonEnabled(this.tsbtnStart, false); this.setButtonEnabled(this.tsbtnReset, false); this.setButtonEnabled(this.tsbtnGoDownPT, false); } /// /// 暂停 /// /// 是否响蜂鸣 private void pauseCommand(bool buzzer = false) { //devContainer.io_output(CMDName.暂停按钮); //if (buzzer) //{ // devContainer.io_output(CMDName.红灯输出); // devContainer.io_output(CMDName.蜂鸣器输出); //} //else // devContainer.io_output(CMDName.黄灯输出); devContainer.io_output(CMDName.启动按钮, false, true, 0); //devContainer.io_output(CMDName.绿灯输出, false, true, 0); this.setButtonEnabled(this.tsbtnWarning, true); this.setButtonEnabled(this.tsbtnGoDownPT, false); this.setButtonEnabled(this.tsbtnStart, false); this.setButtonEnabled(this.tsbtnPause, false); this.setButtonEnabled(this.tsbtnStopNow, false); this.setButtonEnabled(this.tsbtnReset, false); AddTextEvent("暂停", $"当前工序索引:{currProcessIndex + 1}", WarningEnum.Low); } /// /// 急停 /// private void stopNowCommand() { if (!devContainer.state) { this.setButtonEnabled(this.tsbtnStopNow, false); return; } //devContainer.io_output(CMDName.Y轴复位输出, false, true, 0); //devContainer.io_output(CMDName.红灯输出); //if (!this.disableBuzzer) devContainer.io_output(CMDName.蜂鸣器输出); //devContainer.io_output(CMDName.暂停按钮, false, true, 0); //devContainer.io_output(CMDName.黄灯输出, false, true, 0); devContainer.io_output(CMDName.启动按钮, false, true, 0); //devContainer.io_output(CMDName.绿灯输出, false, true, 0); this.setButtonEnabled(this.tsbtnWarning, true); this.setButtonEnabled(this.tsbtnGoDownPT, false); this.setButtonEnabled(this.tsbtnStart, false); this.setButtonEnabled(this.tsbtnPause, false); this.setButtonEnabled(this.tsbtnStopNow, false); this.setButtonEnabled(this.tsbtnReset, false); if(currentState== CurrentStateEnum.运行中) AddTextEvent("急停", $"当前工序索引:{currProcessIndex + 1}", WarningEnum.High); else AddTextEvent("急停", $"已急停,请人工处理。", WarningEnum.High); } private bool reseting = false; private void resetCommand() { currentState = CurrentStateEnum.等待复位; warningLevel = WarningEnum.Normal; currentPT = CurrentPTEnum.InitPT; this.Invoke(new System.Action(() => { this.tsbtnWarning.Enabled = this.tsbtnGoDownPT.Enabled = this.tsbtnStart.Enabled = this.tsbtnStopNow.Enabled = this.tsbtnPause.Enabled = this.tsbtnReset.Enabled = this.gpbXYAxis.Enabled = gpbZAxis.Enabled = false; })); try { if (devContainer.state && !reseting) { reseting = true; resetUIValue(); AddTextEvent("复位", $"设备复位中..."); this.setButtonEnabled(this.tsbtnReset, false); if ((AxisState)devContainer.devAxis.AxState[0] == AxisState.STA_AX_EXT_JOG) devContainer.devAxis.closeJogMode(0);//关闭jog时自动停止 if ((AxisState)devContainer.devAxis.AxState[1] == AxisState.STA_AX_EXT_JOG) devContainer.devAxis.closeJogMode(1);//关闭jog时自动停止 // I/O reset后,输出默认状态 AddTextEvent("复位", $"I/O复位中..."); if (!devContainer.devIOCard.reset()) { AddTextEvent("复位", "I/O板卡复位失败!", WarningEnum.High); return; } if (!devContainer.io_output(CMDName.IO默认输出)) { //AddTextEvent("复位", "I/O板卡复位默认值失败!", WarningEnum.High); //return; } //板卡复位输出灯 //devContainer.io_output(CMDName.复位按钮); devContainer.io_output(CMDName.复位按钮, true);//闪 //goto ORG AddTextEvent("复位", $"轴正在回原点..."); devContainer.devAxis.closeJogMode(); devContainer.devAxis.resetAxisState(-1);//reset state //AddTextEvent("复位", $"重置轴状态..."); for (int i = 0; i < Config.Axis_HomeMode.Length; i++) { //到起始位速度使用回HOME速度 devContainer.devAxis.setAxisVelParam((double)Config.Axis_HomeVelLow[i], (double)Config.Axis_HomeVelHigh[i], (double)Config.Axis_HomeAcc[i], (double)Config.Axis_HomeDec[i], i); //devContainer.devAxis.setAxisVelParam(40000,200000,5000000, 5000000,i,true); devContainer.devAxis.home(i, (uint)Config.Axis_HomeMode[i], (uint)Config.Axis_HomeDir[i]); } AddTextEvent("复位", $"等待轴状态完成..."); while (!devContainer.devAxis.isReady()) { if (!devContainer.state || currentState != CurrentStateEnum.等待复位) { AddTextEvent("复位", $"当前状态:" + ((CurrentStateEnum)currentState).ToString()); return; } //AddTextEvent("复位", $"轴0状态:"+ ((AxisState)devContainer.devAxis.AxState[0]).ToString()); //AddTextEvent("复位", $"轴1状态:" + ((AxisState)devContainer.devAxis.AxState[1]).ToString()); //AddTextEvent("复位", $"轴2状态:" + ((AxisState)devContainer.devAxis.AxState[2]).ToString()); //AddTextEvent("复位", $"轴3状态:" + ((AxisState)devContainer.devAxis.AxState[3]).ToString()); Thread.Sleep(1000); //Application.DoEvents(); } // if (devContainer.devAxis.isError()) throw new Exception("轴回原点失败!"); // //goto InitPT AddTextEvent("复位", $"轴回原点完成,回到初始位..."); JArray arrPT = Config.joPTSetting.Value("initPT"); for (int i = 0; i < arrPT.Count; i++) { if (!devContainer.state || currentState != CurrentStateEnum.等待复位) return; AddTextEvent($"复位", $"轴{i}准备运动至初始位:{(double)arrPT[i]}(当前轴状态:{((AxisState)devContainer.devAxis.AxState[i]).ToString()})..."); devContainer.devAxis.move_ptp(i, (double)arrPT[i], AxMoveMode.MODE1_Abs); } while (!devContainer.devAxis.isReady()) { if (!devContainer.state || warningLevel != WarningEnum.Normal) return; Thread.Sleep(100); //Application.DoEvents(); } if (devContainer.devAxis.isError()) throw new Exception("轴移动至初始位失败!"); // this.setButtonEnabled(this.tsbtnReset, true); this.setButtonEnabled(this.tsbtnStart, true); this.setButtonEnabled(this.tsbtnStopNow, true); this.setButtonEnabled(this.tsbtnPause, false); this.setButtonEnabled(this.tsbtnGoDownPT, false); this.setButtonEnabled(this.tsbtnWarning, false); this.setButtonEnabled(this.cbxSN, false); this.Invoke(new System.Action(() => {//根据UI上是否勾选打开激光 chkLaser_CheckedChanged(null, null); })); //devContainer.io_output(CMDName.复位按钮, false, true, 0);//熄灭 devContainer.io_output(CMDName.复位按钮);//长亮 currentPT = CurrentPTEnum.InitPT; currentState = CurrentStateEnum.等待启动; AddTextEvent("复位", $"复位完成。"); } else { AddTextEvent("复位", "非可复位状态,请先停止后再复位!", WarningEnum.High); } } catch (Exception ex) { AddTextEvent("复位", "复位失败 Err:" + ex.Message, WarningEnum.High); warning(WarningEnum.High, true); } finally { reseting = false; } } /// /// 上料 /// private void gotoUpPT() { try { JArray arrPT = Config.joPTSetting.Value("upPT"); for (int i = 0; i < arrPT.Count; i++) { if (!devContainer.state || warningLevel != WarningEnum.Normal) return; AddTextEvent($"上料", $"轴{i}准备运动至上料位:{(double)arrPT[i]}(当前轴状态:{((AxisState)devContainer.devAxis.AxState[i]).ToString()})..."); devContainer.devAxis.move_ptp(i, (double)arrPT[i], AxMoveMode.MODE1_Abs); } while (!devContainer.devAxis.isReady()) { if (!devContainer.state || warningLevel != WarningEnum.Normal) return; Thread.Sleep(100); } if (devContainer.devAxis.isError()) throw new Exception("轴移动至上料位失败!"); // currentPT = CurrentPTEnum.UpPT; currentState = CurrentStateEnum.等待扫码; this.setButtonEnabled(cbxSN, true); AddTextEvent($"上料", "到达上料位!"); } catch (Exception ex) { AddTextEvent("上料", "上料初始失败 Err:" + ex.Message, WarningEnum.High); warning(WarningEnum.High); } } /// /// 下料(暂当完成) /// private void gotoDownPT() { try { AddTextEvent("下料", "检测状态..."); if (!devContainer.state || warningLevel != WarningEnum.Normal) { AddTextEvent("下料失败", "轴状态异常!", WarningEnum.Low); return; } AddTextEvent("下料", "开始下料!"); if (!devContainer.devAxis.isReady()) { AddTextEvent("下料失败", "轴状态异常!", WarningEnum.Low); return; } if (currentState != CurrentStateEnum.打标中 && currentState != CurrentStateEnum.等待启动 && currentState != CurrentStateEnum.自动流程结束) { AddTextEvent($"下料", $"非可下料状态:{currentState.ToString()}"); return; } currentState = CurrentStateEnum.下料中; JArray arrPT = Config.joPTSetting.Value("downPT"); for (int i = 0; i < arrPT.Count; i++) { if (!devContainer.state || warningLevel != WarningEnum.Normal || currentState != CurrentStateEnum.下料中) return; AddTextEvent($"下料", $"轴{i}准备运动至下料位:{(double)arrPT[i]}(当前轴状态:{((AxisState)devContainer.devAxis.AxState[i]).ToString()})..."); devContainer.devAxis.move_ptp(i, (double)arrPT[i], AxMoveMode.MODE1_Abs); } while (!devContainer.devAxis.isReady()) { if (!devContainer.state || warningLevel != WarningEnum.Normal || currentState != CurrentStateEnum.下料中) return; Thread.Sleep(100); } if (devContainer.devAxis.isError()) throw new Exception("轴移动至下料位失败!"); // currentPT = CurrentPTEnum.DownPT; currentState = CurrentStateEnum.等待启动; devContainer.io_output(CMDName.启动按钮, false, true, 0); devContainer.devLight.setDigitalValue(1, 0);//关闭上光源 devContainer.devLight.setDigitalValue(2, 0);//关闭下光源 this.Invoke(new System.Action(() => { this.chkLaser.Checked = false; this.gpbXYAxis.Enabled = gpbZAxis.Enabled = false; })); setButtonEnabled(tsbtnStart, true); setButtonEnabled(tsbtnGoDownPT, false); AddTextEvent($"下料", "下料完成!"); //更新指定列 //2023-10-31 加入异常情况 FrmRepairInfo frmInfo = new FrmRepairInfo(); DialogResult dr = frmInfo.ShowDialog(); if (svcOrder.Update(it => new Order() { State = dr == DialogResult.OK? 10 :5 , Abnormalities = frmInfo.RepairInfo, RepairCode = Config.loginUser.Code }, it => it.Id == OrderId)) AddTextEvent($"检测结束", $"保存检测结果成功。"); else AddTextEvent($"检测结束", $"保存检测结果失败!",WarningEnum.High); } catch (Exception ex) { AddTextEvent("下料", "下料失败 Err:" + ex.Message, WarningEnum.High); warning(WarningEnum.High); } } private void openLowerLight()//下光源 { var value = devContainer.devLight.getDigitalValue(2); devContainer.devLight.setDigitalValue(2, value == 0 ? 255 : 0); } private void setButtonEnabled(ToolStripButton button, bool Enabled) { this.Invoke(new System.Action(() => { button.Enabled = Enabled; })); } private void setButtonEnabled(ToolStripMenuItem button, bool Enabled) { this.Invoke(new System.Action(() => { button.Enabled = Enabled; })); } private void setButtonEnabled(Control button, bool Enabled) { this.Invoke(new System.Action(() => { button.Enabled = Enabled; })); } #endregion #region 自动流程 nextProcess /// /// 中断工序运行 /// /// private bool isBreakProcessRun() { return warningLevel != WarningEnum.Normal || currentState != CurrentStateEnum.运行中; } private void runStep() { sizeBmpNum = sizeBmpNumResult = 0; AddTextEvent("启动", "等待网版编码扫码..."); if (devContainer.devCodeScanner != null) { devContainer.devCodeScanner.stop(); devContainer.devCodeScanner = null; } devContainer.devCodeScanner = new CodeScannerDev(); if (!devContainer.devCodeScanner.start()) { AddTextEvent("扫码枪", "扫码枪初始化失败!"); return; } devContainer.devCodeScanner.ScanerEvent = (code) => { if (devContainer.devCodeScanner.isLock ||!devContainer.state || currentState != CurrentStateEnum.等待扫码 || string.IsNullOrWhiteSpace(code) ) return; devContainer.devCodeScanner.isLock = true; Thread threadtest = new System.Threading.Thread(() => { try { //注:需要重复输入SN时不能在此释放 //devContainer.devCodeScanner.stop(); //devContainer.devCodeScanner = null; // AddTextEvent("扫码枪", $"开始读取网版编码:{code} 数据..."); var modOrder = svcOrder.GetModelNav(code);//from sn //AddTextEvent("扫码枪", $"读取网版编码:{code}DB数据完成"); string modeState = ""; if (modOrder == null) AddTextEvent("扫码枪", $"网版编码{code}不存在!"); if (modOrder.State == 5) { modeState = $"网版编码{code}已被检测!"; AddTextEvent("扫码枪", $"网版编码{code}已被检测!"); loadOrderSNList(); } else if (modOrder.State == 10) { modeState = $"网版编码{code}已被检测, 并且异常!"; AddTextEvent("扫码枪", $"网版编码{code}已被检测, 并且异常!"); loadOrderSNList(); } if(!string.IsNullOrEmpty(modeState)) { if(DialogResult.No == MessageBox.Show(modeState + "是否重新检测!", "网版已被检测", MessageBoxButtons.YesNo, MessageBoxIcon.Information)) { return; } } //2023-10-20 //else if (modOrder.ProductInfo == null) if (modOrder.ProductInfo == null) AddTextEvent("扫码枪", $"网版编码:{code}对应产品信息已不存在!"); else if (modOrder.DefectCount < 1) AddTextEvent("扫码枪", $"网版编码:{code}没有缺陷!"); //else if (string.IsNullOrWhiteSpace(modOrder.MarkData)) // AddTextEvent("扫码枪", $"产品(网版编码:{code})在主机台未保存原始Mark点!"); else if (modOrder.ProductInfo.AssistStepInfo == null || modOrder.ProductInfo.AssistStepInfo.ProcessList.Count < 1) AddTextEvent("扫码枪", $"产品({modOrder.ProductInfo.Name})未配置检测流程!"); else { if (string.IsNullOrWhiteSpace(modOrder.MarkData)) { AddTextEvent("扫码枪", $"产品(网版编码:{code})在主机台未保存原始Mark点!"); modOrder.MarkData = "[0,0,0,0,0,0,0,0]"; } else AddTextEvent("主机台", $"主机台Mark数据:{modOrder.MarkData}"); currProductMarkList = JArray.Parse(modOrder.MarkData); if (currProductMarkList.Count < 8) { AddTextEvent("主机台", $"产品(网版编码:{code})在主机台原始Mark点数量错误!"); return; } //异步读取 JObject parm = new JObject() { {"date",modOrder.CreateTime.ToString("yyyyMMdd") }, {"sn",code } }; Task.Run(() => loadDefectInfo(parm)); // devContainer.devCodeScanner.stop(); devContainer.devCodeScanner = null; currentState = CurrentStateEnum.运行中; currentPT = CurrentPTEnum.Moving; currProductModel = modOrder.ProductInfo; AddTextEvent("扫码枪", $"网版编码:{code}({currProductModel.Name} {currProductModel.Spec} [{currProductModel.Code}])"); this.Invoke(new System.Action(() => { this.cbxSN.Enabled = false; this.txtBatchId.Text = modOrder.BatchId.ToString(); this.txtProductName.Text = currProductModel.Name; this.txtProductCode.Text = currProductModel.Code; this.txtCreateTime.Text = modOrder.CreateTime.ToString("yyyy-MM-dd HH:mm"); //this.dgvProcess.DataSource = new BindingSource(currProductModel.StepInfo.ProcessList, null); devContainer.libFor.clear(); devContainer.libIF.clear(); })); // this.SN = code; this.OrderId = modOrder.Id; this.setButtonEnabled(this.tsbtnPause, true); this.setButtonEnabled(this.tsbtnStopNow, true); devContainer.devLight.setDigitalValue(2, 255);//下光源 int nextStepId = 0; do { nextStepId = nextProcess(currProductModel, nextStepId); } while (nextStepId >= 0 && !isBreakProcessRun()); } } catch (Exception ex) { AddTextEvent("扫码枪", $"读取网版编码信息失败:{ex.Message}"); } finally { if (devContainer.devCodeScanner != null) devContainer.devCodeScanner.isLock = false; } }); threadtest.IsBackground = true; threadtest.Start(); }; } private void loadDefectInfo(object parm) { try { JObject req = (JObject)parm; currDefectIndex = 0; defectList.Clear(); defectInfoDir.Clear(); defectBmpsDir.Clear(); //从主机台取缺陷文件名列表和JSON数组 var obj = WebApi.getDefectFromSN(req); if (obj.Value("code") != 200) throw new Exception(obj.Value("data")); // var defectInfo = obj.Value("data"); //文件名列表(主机台已对文件名排序,这里不需再排序(主机台按各自index进行的排序,比对在缺陷文件名后面) if (defectInfo.Count < 1) throw new Exception("主机台缺陷文件已不存在!"); //string date = req.Value("date"); //string sn = req.Value("sn"); getDefectBmpList(req, defectInfo); } catch (Exception ex) { AddTextEvent("网络访问",$"{ex.Message}",WarningEnum.High); warning(WarningEnum.High); } } /// /// 通过文件名列表取各文件名对应BMP /// /// /// 文件名列表 private void getDefectBmpList(JObject req, JObject defectInfo) { int liStep = 0; try { #region 这里转换绑定没实际用处,只是为了提前显示列表 foreach (var kv in defectInfo) { defectInfoDir.Add(kv.Key, JsonConvert.DeserializeObject>>(kv.Value.ToString())); // //["4","3.9","-0.8","dk","0.39"],["index","X","Y","缺陷类型","缺陷的置信度"] JArray arr = kv.Value as JArray;//二维数组 AddTextEvent("主机台", $"缺陷大项:{kv.Key},含小项:{arr.Count}."); foreach (JArray arr2 in arr) { var obj = new DefectStruct(); obj.Key = kv.Key; obj.Index = Convert.ToInt32(arr2[0].ToString()); obj.X = Convert.ToDouble(arr2[1].ToString()); obj.Y = Convert.ToDouble(arr2[2].ToString()); obj.DefectName = Config.getDefectName(arr2[3].ToString()); obj.DefectCC = Convert.ToDouble(arr2[4].ToString()); defectList.Add(obj); } } this.Invoke(new System.Action(() => { //注:这样绑定List中的对象必需得用{get;set;}方式定义属性,否则单独格为空内容 AddTextEvent("主机台", $"准备显示缺陷列表,共{defectList.Count}项."); this.dgvProcess.DataSource = new BindingSource(defectList, null); AddTextEvent("主机台", $"显示缺陷列表完成."); this.gpbDefectList.Text = $"缺陷明细({defectList.Count}条)"; //2023-11-1 图纸对比缺陷标红 for (int i = 0; i < defectList.Count; i++) { string defName = (string)this.dgvProcess.Rows[i].Cells["colDefectName"].Value; if ((defName == Config.getDefectName("ds"))||((defName == Config.getDefectName("yx")))) this.dgvProcess.Rows[i].DefaultCellStyle.BackColor = Color.Red; } })); #endregion req.Add("file_name", ""); liStep = 1; bool first = true; int index = 1; foreach (var kv in defectInfo) { req["file_name"] = kv.Key; var obj = WebApi.getDefectBmpBase64(req); if (!devContainer.state || warningLevel == WarningEnum.High || (currentState != CurrentStateEnum.运行中 && currentState != CurrentStateEnum.暂停 && currentState != CurrentStateEnum.等待启动 && currentState != CurrentStateEnum.打标中)) return; if (obj.Value("code") != 200) throw new Exception(obj.Value("data")); Bitmap bmp = new Bitmap(new MemoryStream(Convert.FromBase64String(obj.Value("data")))); defectBmpsDir.Add(kv.Key, bmp); AddTextEvent("网络访问", $"已读取第{index++}/{defectInfo.Count}张缺陷图片;"); if (first) { first = false; this.Invoke(new System.Action(() => { this.reloadPic(bmp,null,null); pictureBox1.Tag = kv.Key; })); } } } catch (Exception ex) { if (liStep == 0) { AddTextEvent("网络访问", $"解析主机缺陷报文失败:{ex.Message}",WarningEnum.High); warning(WarningEnum.High); } else AddTextEvent("网络访问", $"读取主机台缺陷Bmp图片失败:{ex.Message}"); } } private void convert2LocXY() { //AddTextEvent($"缺陷项", $"转换缺陷项坐标值..."); // public string Key; //public string Key0;//index //public string Key1;//X //public string Key2;//Y //public string Key3;//缺陷类型 //public string Key4;//缺陷的置信度 currDefectIndex = 0; defectList.Clear(); double X, Y; int MainIndex; foreach (var item in defectInfoDir) { //Key : Defect_SN{order.SN}_I{res.index}_X{res.Xmm}_Y{res.Ymm}_C{res.defectCount} string[] str = item.Key.Split('_'); MainIndex = Convert.ToInt32(str[2].Substring(1)); X = Convert.ToDouble(str[3].Substring(1)); Y = Convert.ToDouble(str[4].Substring(1)); AddTextEvent("主机台", $"转换前,缺陷大项:{item.Key},含小项:{item.Value.Count}."); var arr = yolo.ImageXY2RepairTable(item.Value, X, Y, Config.SizeRepairTablePath); AddTextEvent("主机台", $"转换后,缺陷大项:{item.Key},含小项:{arr.Count}."); int i = 0; foreach (var arr2 in arr) { var obj = new DefectStruct(); obj.Key = item.Key; obj.CurrIndex = i++; obj.MainIndex = MainIndex; obj.MainX = X; obj.MainY = Y; obj.Index = Convert.ToInt32(arr2[0].ToString()); obj.X = Convert.ToDouble(arr2[1].ToString()); obj.Y = Convert.ToDouble(arr2[2].ToString()); obj.DefectName = Config.getDefectName(arr2[3].ToString()); obj.DefectCC = Convert.ToDouble(arr2[4].ToString()); defectList.Add(obj); } } this.Invoke(new System.Action(() => { this.dgvProcess.DataSource = null; //注:这样绑定List中的对象必需得用{get;set;}方式定义属性,否则单独格为空内容 this.dgvProcess.DataSource = new BindingSource(defectList, null); this.gpbDefectList.Text = $"缺陷明细({defectList.Count}条)"; })); gotoDefctListIndex(currDefectIndex); } private void gotoDefctListIndex(int index,int preIndex=-1) { try { AddTextEvent($"缺陷项", $"移至缺陷项:{index + 1}..."); this.Invoke(new System.Action(() => { string key = defectList[index].Key; if (defectBmpsDir.ContainsKey(key)) { if (pictureBox1.Tag == null || pictureBox1.Tag.ToString() != key) { //reloadPic(defectBmpsDir[key], defectInfoDir[key], defectList[index]); pictureBox1.Tag = key; } reloadPic(defectBmpsDir[key], defectInfoDir[key], defectList[index]); } else AddTextEvent($"缺陷项", $"缺陷图:{defectList[index].Key}还未传输完成!"); if (preIndex > -1) this.dgvProcess.Rows[preIndex].DefaultCellStyle.BackColor = Color.White; this.dgvProcess.Rows[index].DefaultCellStyle.BackColor = Color.LightGreen; this.dgvProcess.Rows[index].Selected = true; this.dgvProcess.CurrentCell = this.dgvProcess.Rows[index].Cells["colResult"]; this.dgvProcess.Rows[index].Cells["colResult"].Value = "已检"; })); if ((defectList[index].X <= 0) || (defectList[index].Y <= 0)) { AddTextEvent($"缺陷项", $"移动报错,当前缺陷项({index + 1})坐标:X{defectList[index].X},Y{defectList[index].Y}", WarningEnum.Low); return; } while (!devContainer.devAxis.isReady(0)) Thread.Sleep(100); devContainer.devAxis.move_ptp(0, defectList[index].X, AxMoveMode.MODE1_Abs); while (!devContainer.devAxis.isReady(1)) Thread.Sleep(100); devContainer.devAxis.move_ptp(1, defectList[index].Y, AxMoveMode.MODE1_Abs); AddTextEvent($"缺陷项", $"移动完成,当前缺陷项({index + 1})坐标:X{defectList[index].X},Y{defectList[index].Y}"); } catch (Exception ex) { AddTextEvent("缺陷项", "轴移动失败:" + ex.Message, WarningEnum.High); warning(WarningEnum.High, true); } } private void gotoNextPic() { if (currDefectIndex>= defectList.Count-1) return; this.Invoke(new System.Action(() => { for(int i= currDefectIndex+1;i< defectList.Count; i++) { if (this.pictureBox1.Tag == null || this.pictureBox1.Tag.ToString() != defectList[i].Key) { AddTextEvent($"缺陷项", $"移至下张图:{i+1}..."); int preIndex = currDefectIndex; currDefectIndex = i; gotoDefctListIndex(currDefectIndex, preIndex); return; } } })); } private void gotoPrePic() { if (currDefectIndex < 1) return; this.Invoke(new System.Action(() => { if (this.pictureBox1.Tag == null) return; for (int i = currDefectIndex-1; i >=0; i--) { if (this.pictureBox1.Tag.ToString() != defectList[i].Key) { AddTextEvent($"缺陷项", $"移至上张图:{i + 1}..."); int preIndex = currDefectIndex; currDefectIndex = i; gotoDefctListIndex(currDefectIndex, preIndex); return; } } })); } private class DefectStruct { //Defect_{order.SN}_{res.index}_X{res.Xmm}_Y{res.Ymm} public string Key { get; set; } public int CurrIndex { get; set; }//当前缺陷在本大图中的索引0-n public int MainIndex { get; set; }//大图 public double MainX { get; set; }//大图X 大相机拍照时原始X,Y轴坐标 public double MainY { get; set; }//大图X //["4","3.9","-0.8","dk","0.39"],["index","X","Y","缺陷类型","缺陷的置信度"] public int Index { get; set; } public double X { get; set; } public double Y { get; set; } public string DefectName { get; set; }//缺陷类型 public double DefectCC { get; set; }//缺陷的置信度 //2023-10-30 修复情况 public string Restoratory { get; set; } } private double[] convert(JArray data) { double[] result = new double[data.Count]; for (int i = 0; i < data.Count; i++) result[i]=Convert.ToDouble(data[i]); return result; } /// /// 工序循环 /// /// /// 0-n /// 大于等于0正常工序; -1:结束 -2:异常 private int nextProcess(Models.Product model, int stepIndex) { try { //记录当前index this.currProcessIndex = stepIndex; //this.Invoke(new System.Action(() => //{ // try // { // this.dgvProcess.Rows[stepIndex].Selected = true; // dgvProcess.CurrentCell = dgvProcess.Rows[stepIndex].Cells[1]; // } // catch { } //})); lock (myLock) { if (isBreakProcessRun()) return stepIndex; } var processList = model.AssistStepInfo.ProcessList; var processInfo = processList[stepIndex]; string processName = processInfo.ProcessName; //AddTextEvent($"{stepIndex + 1}-{processName}", $"工序开始..."); string jsonParams = null;//配方 if (model.ProductProcessList != null && model.ProductProcessList.Count > 0)//使用产品配方 { ProductProcess productProcessParams = model.ProductProcessList.First(m => m.ProcessCode == processInfo.ProcessCode); if (productProcessParams != null) { jsonParams = productProcessParams.ProcessParams; AddTextEvent($"{stepIndex + 1}-{processName}", $"使用产品专用配方:{jsonParams}"); } } if (jsonParams == null)//使用流程默认配方 { jsonParams = processInfo.ProcessParams; AddTextEvent($"{stepIndex + 1}-{processName}", $"使用流程默认配方:{jsonParams}"); } // JObject processParam = JObject.Parse(jsonParams); if (!processParam.ContainsKey("Disable") || !processParam.Value("Disable")) { AutoResetEvent endEvent; uint sleepPre = processParam.Value("SleepPre"); uint sleepLater = processParam.Value("SleepLater"); if (sleepPre > 0) Thread.Sleep((int)sleepPre); double limitThresholdVal, lowerThresholdVal; //======Switch 工序类型 int liStatocStepIndex = stepIndex; switch (processInfo.ProcessCode) { case "IOCard": #region var direction = (IODirectionEnum)processParam.Value("Direction"); if (direction == IODirectionEnum.输入 || direction == IODirectionEnum.输入输出) { uint IN_Waiting_Timeout = processParam.Value("IN_Waiting_Timeout"); AddTextEvent($"{stepIndex + 1}-{processName}", $"等待I/O输入信号{(IN_Waiting_Timeout > 0 ? $"(超时时长: {IN_Waiting_Timeout})" : "...")}"); string[] inValue = processParam.Value("IN_OP_SHOW").ToObject>().ToArray(); uint inWaitingTime = 0; while (true) { if (isBreakProcessRun()) return stepIndex; if (Util.compareIOInput(inValue, devContainer.devIOCard.DIData)) break; Thread.Sleep(10); inWaitingTime += 10; if (IN_Waiting_Timeout > 0 && inWaitingTime >= IN_Waiting_Timeout) { AddTextEvent($"{stepIndex + 1}-{processName}", $"输入等待超时告警!", WarningEnum.High); warning(WarningEnum.Low);//暂停 return stepIndex; } } AddTextEvent($"{stepIndex + 1}-{processName}", $"I/O输入信号对比完成!"); } if (direction == IODirectionEnum.输出 || direction == IODirectionEnum.输入输出) devContainer.io_output($"{stepIndex + 1}-{processName}", processParam); #endregion break; case "Axis": #region bool asynRun = processParam.Value("AsynRun");//异步 int AxisIndex = processParam.Value("AxisIndex"); int DeviceType = processParam.Value("DeviceType"); double VelLow = processParam.Value("VelLow"); double VelHigh = processParam.Value("VelHigh"); double Acc = processParam.Value("Acc"); double Dec = processParam.Value("Dec"); AxMoveMode MoveMode = (AxMoveMode)processParam.Value("MoveMode");//绝对位置 double PPUValue = processParam.Value("Value"); AddTextEvent($"{stepIndex + 1}-{processName}", $"轴{AxisIndex}准备({(MoveMode == AxMoveMode.MODE1_Abs ? "绝对" : "相对")})运动至{PPUValue}(当前轴状态:{((AxisState)devContainer.devAxis.AxState[AxisIndex]).ToString()})..."); ////移动Axis前等待厚度传感器收回 //if (!Config.SkipHeight) //{ // while (devContainer.devHeight.getHeight() < (double)Math.Abs(Config.HeightDev_SafeValue)) // { // if (isBreakProcessRun()) // return stepIndex; // Thread.Sleep(10); // } //} while (!devContainer.devAxis.isReady(AxisIndex)) { Thread.Sleep(100); if (isBreakProcessRun()) return stepIndex; } devContainer.devAxis.setAxisVelParam(VelLow, VelHigh, Acc, Dec, AxisIndex); if (!devContainer.devAxis.move_ptp(AxisIndex, PPUValue, MoveMode)) { AddTextEvent($"{stepIndex + 1}-{processName}", $"轴{AxisIndex}运动失败!", WarningEnum.Low); warning(WarningEnum.Low);//终止 return stepIndex; } AddTextEvent($"{stepIndex + 1}-{processName}", $"等待轴{AxisIndex}运行完成..."); while (!asynRun && !devContainer.devAxis.isReady(AxisIndex)) { Thread.Sleep(100); if (isBreakProcessRun()) { currProcessIndex = stepIndex + 1; return stepIndex; } } AddTextEvent($"{stepIndex + 1}-{processName}", $"轴{AxisIndex}运行完成,当前命令位置:{devContainer.devAxis.getCmdPos_mm(AxisIndex)},反馈位置:{devContainer.devAxis.getActualPos_mm(AxisIndex)}"); #endregion break; case "Light": #region if (Config.SkipLight) { AddTextEvent($"{stepIndex + 1}-{processName}", $"设备禁用,忽略此步骤!"); //setDgvContentCol(liStatocStepIndex, $"设备禁用,忽略此步骤!"); break; } int ChannelIndex = processParam.Value("ChannelIndex"); //通道 int DigitalValue = processParam.Value("DigitalValue"); //亮度 int nowDiaitalValue = devContainer.devLight.getDigitalValue(ChannelIndex); AddTextEvent($"{stepIndex + 1}-{processName}", $"通道{ChannelIndex}当前值:{nowDiaitalValue},准备更新值:{DigitalValue}..."); devContainer.devLight.setDigitalValue(ChannelIndex, DigitalValue); nowDiaitalValue = devContainer.devLight.getDigitalValue(ChannelIndex); AddTextEvent($"{stepIndex + 1}-{processName}", $"通道{ChannelIndex}更新后当前值:{nowDiaitalValue}。"); #endregion break; case "Scanner_CC": #region if (Config.SkipScannerCC) { AddTextEvent($"{stepIndex + 1}-{processName}", $"设备禁用,忽略此步骤!"); //setDgvContentCol(liStatocStepIndex, $"设备禁用,忽略此步骤!"); break; } while (!devContainer.devAxis.isReady())//因启用轴异步功能,使用前需等待 { Thread.Sleep(100); if (isBreakProcessRun()) { //currProcessIndex = stepIndex;//本工序没执行,step不变 return stepIndex; } } float ExposureTimeCC = processParam.Value("ExposureTime"); //曝光 float GainCC = processParam.Value("Gain"); //增益 float ResultingFrameRateCC = processParam.Value("ResultingFrameRate"); //帧率 AddTextEvent($"{stepIndex + 1}-{processName}", $"相机开始采集照片..."); devContainer.devScannerCC.setParam(ExposureTimeCC, GainCC, ResultingFrameRateCC); AddTextEvent($"{stepIndex + 1}-{processName}", $"相机参数设置完成。"); AutoResetEvent endEventCC = new AutoResetEvent(false); //devContainer.devScannerCC.ScanEvent = (num, bmp2) => //{ // AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片完成."); // scannerCBmpQueue.Enqueue(bmp2, // devContainer.devAxis.getActualPos_mm(0), // devContainer.devAxis.getActualPos_mm(1)) // endEventCC.Set();//线程返回 //}; devContainer.devScannerCC.ScanEventPath += new System.Action((num, path2) => { AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片完成."); scannerCBmpQueue.Enqueue(new scannerCBmpLoc(path2, devContainer.devAxis.getActualPos_mm(0), devContainer.devAxis.getActualPos_mm(1)));//Dequeue AddTextEvent($"{stepIndex + 1}-{processName}", $"图像队列数量: {scannerCBmpQueue.Count}"); endEventCC.Set();//线程返回 }); if (!devContainer.devScannerCC.scan(1))//软触发拍照 { devContainer.devScannerCC.ScanEventPath = null; AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片失败!", WarningEnum.Low); warning(WarningEnum.Low);//终止 return stepIndex; } if (!endEventCC.WaitOne(5000)) { devContainer.devScannerCC.ScanEventPath = null; AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片超时!", WarningEnum.Low); warning(WarningEnum.Low);//终止 return stepIndex; } devContainer.devScannerCC.ScanEventPath = null; #endregion break; case "Size": #region limitThresholdVal = processParam.Value("LimitThresholdVal"); lowerThresholdVal = processParam.Value("LowerThresholdVal"); int sizeIndex = processParam.Value("Index"); double xPos = 0; double yPos = 0; if (scannerCBmpQueue.Count < 1) { AddTextEvent($"{stepIndex + 1}-{processName}", $"尺寸检测异常,无源图像!!", WarningEnum.Low); warning(WarningEnum.Low);//暂停 return stepIndex; } var bmpCBmpQueue = scannerCBmpQueue.Dequeue(); AddTextEvent($"{stepIndex + 1}-{processName}", $"开始尺寸检测,index:{sizeIndex},图像队列数量: {scannerCBmpQueue.Count}..."); //需要偏移校正,index=0时不能异步 endEvent = new AutoResetEvent(false); sizeBmpNum++; devContainer.libSize.add(new SizeTask() { index = sizeIndex, stepIndex = stepIndex,//仅供回调时用 engineName = processParam.Value("EngineName"), bmp = bmpCBmpQueue.BMP,//bmp/file_path二选一,优先bmp file_path = bmpCBmpQueue.Path, posX = bmpCBmpQueue.PosX, posY = bmpCBmpQueue.PosY, MarkPointList= convert(currProductMarkList), finishEvent = (res) => { if(res.isSucceed) { AddTextEvent($"{stepIndex + 1}-{processName}", $"尺寸检测完成,index:{res.index}。"); } else { //setDgvContentCol(liStatocStepIndex, $"失败:{res.resultInfo}"); AddTextEvent($"{res.stepIndex + 1}-{processName}", $"尺寸检测失败index:{res.index}:{res.resultInfo}"); //warning(WarningEnum.Low);//暂停 这里不能暂停,stepIndex和scannerBmpQueue队列也不对了 } sizeBmpNumResult++; string sizeSavePath = Config.SizeBmp_Path + "\\" + DateTime.Now.ToString("yyyyMMdd") + "\\"; if (!Directory.Exists(sizeSavePath)) Directory.CreateDirectory(sizeSavePath); sizeSavePath += $"SN{this.SN}_I{res.index}_X{res.posX}_Y{res.posY}.bmp"; if (res.bmp != null) { res.bmp.Save(sizeSavePath,ImageFormat.Bmp); res.bmp.Dispose(); res.bmp = null; } else { //File.Copy(res.file_path, defectFileName + ".bmp", true); API.CopyFile(res.file_path, sizeSavePath, false);//更快 File.Delete(res.file_path); } } }); #endregion break; case "For": #region long UniqueId = processParam.Value("UniqueId"); int GotoStepIndex = processParam.Value("GotoStepIndex");//1-n int LimitNum = processParam.Value("LimitNum");//1-n bool Reset = processParam.Value("Reset"); if (GotoStepIndex - 1 == stepIndex) { AddTextEvent($"{stepIndex + 1}-{processName}", $"For死循环!!!"); warning(WarningEnum.High); return stepIndex; } if (!devContainer.libFor.dicData.ContainsKey(UniqueId)) devContainer.libFor.dicData.Add(UniqueId, 0); // int Num = devContainer.libFor.dicData[UniqueId]; Num++; if (Num <= LimitNum) { if (Num == LimitNum) { //setDgvContentCol(liStatocStepIndex, $"第[{Num}/{LimitNum}]次,循环完成"); AddTextEvent($"{stepIndex + 1}-{processName}", $"第[{Num}/{LimitNum}]次,循环完成。"); } else { //setDgvContentCol(liStatocStepIndex, $"第[{Num}/{LimitNum}]次"); AddTextEvent($"{stepIndex + 1}-{processName}", $"第[{Num}/{LimitNum}]次跳转到步骤[{GotoStepIndex}]..."); stepIndex = GotoStepIndex - 2; } devContainer.libFor.dicData[UniqueId] = Num; } else { //setDgvContentCol(liStatocStepIndex, $"已失效不执行"); AddTextEvent($"{stepIndex + 1}-{processName}", $"本循环已失效不执行!"); } //达到limit重置0 if (devContainer.libFor.dicData[UniqueId] >= LimitNum && Reset) { devContainer.libFor.dicData[UniqueId] = 0; //setDgvContentCol(liStatocStepIndex, $"第[0/{LimitNum}]次"); AddTextEvent($"{stepIndex + 1}-{processName}", $"计数器已重置。"); } #endregion break; case "If": #region long UniqueId_if = processParam.Value("UniqueId"); int GotoStepIndex_if = processParam.Value("GotoStepIndex");//1-n int LimitNum_if = processParam.Value("LimitNum");//1-n bool Reset_if = processParam.Value("Reset"); if (GotoStepIndex_if - 1 == stepIndex) { AddTextEvent($"{stepIndex + 1}-{processName}", $"If死循环,不可自我跳转!!!"); warning(WarningEnum.High); return stepIndex; } // if (!devContainer.libIF.dicData.ContainsKey(UniqueId_if)) devContainer.libIF.dicData.Add(UniqueId_if, 0); // int Num_if = devContainer.libIF.dicData[UniqueId_if]; Num_if++; if (Num_if <= LimitNum_if) { if (Num_if == LimitNum_if) { //setDgvContentCol(liStatocStepIndex, $"第[{Num_if}/{LimitNum_if}]次,跳转至[{GotoStepIndex_if}]"); AddTextEvent($"{stepIndex + 1}-{processName}", $"计数器[{Num_if}/{LimitNum_if}],跳转至步骤[{GotoStepIndex_if}]..."); stepIndex = GotoStepIndex_if - 2; } else { //setDgvContentCol(liStatocStepIndex, $"第[{Num_if}/{LimitNum_if}]次,不跳转"); AddTextEvent($"{stepIndex + 1}-{processName}", $"计数器[{Num_if}/{LimitNum_if}],不跳转。"); } // devContainer.libIF.dicData[UniqueId_if] = Num_if; } else { //setDgvContentCol(liStatocStepIndex, $"已失效不执行"); AddTextEvent($"{stepIndex + 1}-{processName}", $"本IF已失效不执行。"); } //达到limit重置0 if (devContainer.libIF.dicData[UniqueId_if] >= LimitNum_if && Reset_if) { devContainer.libIF.dicData[UniqueId_if] = 0; //setDgvContentCol(liStatocStepIndex, $"第[0/{LimitNum_if}]次"); AddTextEvent($"{stepIndex + 1}-{processName}", $"计数器已重置。"); } #endregion break; default: AddTextEvent($"{stepIndex + 1}-{processName}", $"未知工序:{processInfo.ProcessCode}"); warning(WarningEnum.High); return stepIndex; } if (sleepLater > 0) Thread.Sleep((int)sleepLater); } //============结束,判断是否自动下料 if (stepIndex == processList.Count - 1) { setButtonEnabled(tsbtnPause, false);//后面手动模式暂停无意义 //等待Mark图处理完成 while (sizeBmpNum != sizeBmpNumResult) Thread.Sleep(100); // this.Invoke(new System.Action(() => { this.chkLaser.Checked = true; this.gpbXYAxis.Enabled = gpbZAxis.Enabled = true; })); AddTextEvent("完成", $"Mark点计算工序结束,开始转换主机台缺陷坐标..."); convert2LocXY(); AddTextEvent("完成", $"开始进行人工修复..."); currentPT = CurrentPTEnum.MakeTag; currentState = CurrentStateEnum.打标中; setButtonEnabled(tsbtnGoDownPT, true); setButtonEnabled(tsbtnReset, true); //== currProcessIndex = -1; return -1; } else //继续 { return ++stepIndex; //return nextProcess(model, ++stepIndex); } } catch (Exception ex) { if (devContainer.devAxis.isError()) { AddTextEvent("工序", $"[{stepIndex}] Err:" + ex.Message); warning(WarningEnum.High); } else { AddTextEvent("工序", $"[{stepIndex}] Err:" + ex.Message); warning(WarningEnum.Low); } return -2; } } #endregion #region Fun /// /// 全局中断 /// private void globalBreakEvent(int portIndex, byte data) { AddTextEvent("中断命令", $"{portIndex}-HEX:{Convert.ToString(data, 16)}"); if (compareIOInput(CMDName.启动按钮) && this.tsbtnStart.Enabled) startCommand(); else if (compareIOInput(CMDName.暂停按钮) && this.tsbtnPause.Enabled) warning(WarningEnum.Low, false); else if (compareIOInput(CMDName.完成下料) && this.tsbtnGoDownPT.Enabled) gotoDownPT(); else if (compareIOInput(CMDName.下光源按钮)) openLowerLight(); else if (compareIOInput(CMDName.上一张图) && currentState == CurrentStateEnum.打标中 && currDefectIndex > 0) gotoPrePic(); else if (compareIOInput(CMDName.下一张图) && currentState == CurrentStateEnum.打标中 && currDefectIndex < defectList.Count - 1) gotoNextPic(); else if (compareIOInput(CMDName.上一缺陷) && currentState == CurrentStateEnum.打标中 && currDefectIndex > 0) gotoDefctListIndex(--currDefectIndex, currDefectIndex + 1); else if (compareIOInput(CMDName.下一缺陷) && currentState == CurrentStateEnum.打标中 && currDefectIndex < defectList.Count - 1) gotoDefctListIndex(++currDefectIndex, currDefectIndex - 1); else if (compareIOInput(CMDName.复位按钮) && this.tsbtnReset.Enabled) resetCommand(); // if (devContainer.state && warningLevel == WarningEnum.Normal && currentState == CurrentStateEnum.打标中 && currentPT == CurrentPTEnum.MakeTag) { int axisIndex = 0; bool isJog_axis = (AxisState)devContainer.devAxis.AxState[axisIndex] == AxisState.STA_AX_EXT_JOG; if(!handleJog(axisIndex, CMDName.手柄左移,1) && !handleJog(axisIndex, CMDName.手柄右移,0)) { if (isJog_axis) { AddTextEvent("中断命令", $"轴{axisIndex}关闭JOG模式!"); devContainer.devAxis.closeJogMode(axisIndex);//关闭jog时自动停止 } } axisIndex = 1; isJog_axis = (AxisState)devContainer.devAxis.AxState[axisIndex] == AxisState.STA_AX_EXT_JOG; if (!handleJog(axisIndex, CMDName.手柄前移,0) && !handleJog(axisIndex, CMDName.手柄后移,1)) { if (isJog_axis) { AddTextEvent("中断命令", $"轴{axisIndex}关闭JOG模式!"); devContainer.devAxis.closeJogMode(axisIndex);//关闭jog时自动停止 } } } } private bool compareIOInput(CMDName key) { JObject joJson = Config.CMDProcess[key]; IODirectionEnum direction = (IODirectionEnum)joJson.Value("Direction"); if (direction == IODirectionEnum.输入 || direction == IODirectionEnum.输入输出) { return Util.compareIOInput( joJson.Value("IN_OP_SHOW").ToObject>().ToArray(), devContainer.devIOCard.DIData); } return false; } private bool handleJog(int axisIndex,CMDName cmd,ushort dir) { if (compareIOInput(cmd) && currentState == CurrentStateEnum.打标中) { AddTextEvent("中断命令", $"{cmd.ToString()}:开"); devContainer.devAxis.openJogMode(axisIndex); devContainer.devAxis.setAxisVelParam((double)Config.Axis_JogVelLow[axisIndex], (double)Config.Axis_JogVelLow[axisIndex], (double)Config.Axis_JogVelLow[axisIndex], (double)Config.Axis_JogVelLow[axisIndex], axisIndex, true); devContainer.devAxis.jog(axisIndex, dir);//jog move return true; } return false; } /// /// 报警,只响应low,high /// private void warning(WarningEnum level, bool buzzer = true) { if (level == WarningEnum.Normal) return; lock (myLock) warningLevel = level; if (level == WarningEnum.Low)//暂停 { currentState = CurrentStateEnum.暂停; pauseCommand(buzzer); } else if (level == WarningEnum.High)//急停 { currentState = CurrentStateEnum.急停; devContainer.devAxis.stopNow(); stopNowCommand(); } //启用报警消除按钮 setButtonEnabled(tsbtnWarning, true); } private void resetUIValue() { currProcessIndex = -1; currProductModel = null; currProductMarkList = null; scannerCBmpQueue.Clear(); defectBmpsDir.Clear(); this.Invoke(new System.Action(() => { cbxSN.Enabled = false; cbxSN.Text = txtProductCode.Text = txtProductName.Text = txtBatchId.Text = txtBatchId.Text = txtCreateTime.Text = ""; this.gpbDefectList.Text = $"缺陷明细"; this.dgvProcess.DataSource = null; this.lstLog.Items.Clear(); this.pictureBox1.Image = null; pictureBox1.Refresh(); })); } private void delDirFiles(string dirPath) { try { var files = Directory.EnumerateFiles(dirPath, "*.bmp", SearchOption.TopDirectoryOnly); foreach (string file in files) API.DeleteFile(file); } catch (Exception ex) { } } public delegate void AddTextDelegate(string tag, string msg, WarningEnum level); /// /// 异步输出日志 /// /// 模板标识 /// 内容 /// private void AddTextEvent(string tag, string msg, WarningEnum level = WarningEnum.Normal) { try { if (InvokeRequired) { Invoke(new AddTextDelegate(AddTextEvent), new object[] { tag, msg, level }); } else { if (tag != null && tag != "") tag = $" - [{tag}]"; var now = DateTime.Now; msg = now.ToString("HH:mm:ss fff") + tag + " - " + msg; //cont = MyHelper.subString(cont, 300); //写日志,warn和error日志直接写 writeLog(now, level, msg); // //if (type > 0) // cont = $"{cont}"; msg = (level == WarningEnum.Normal ? "B" : level == WarningEnum.Low ? "Y" : "R") + msg; this.Invoke(new System.Action(() => { if (this.lstLog.Items.Count > 1000) this.lstLog.Items.Clear(); lstLog.Items.Insert(0, msg); })); //日志滚动 //lstLog.SelectedIndex = lstLog.Items.Count - 1; } } catch (Exception ex) { //MessageBox.Show("AddTextEvent ex=(" + ex.Message + ")", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, 0); } } private void lstLog_DrawItem(object sender, DrawItemEventArgs e) { e.DrawBackground(); if (e.Index < 0) return; string str = lstLog.Items[e.Index].ToString(); e.Graphics.DrawString(str.Substring(1), e.Font, new SolidBrush(str[0] == 'R' ? Color.Red : (str[0] == 'Y' ? Color.Orange : Color.Black)), e.Bounds); } private void writeLog(DateTime now, WarningEnum level, string text) { string directory = Config.LogPath + "\\" + DateTime.Now.ToString("yyyyMM") + "\\"; //if (type == 0) directory = Application.StartupPath + "\\Log\\Info\\"; //else if (type == 1) directory = Application.StartupPath + "\\Log\\Warn\\"; //else directory = Application.StartupPath + "\\Log\\Error\\"; if (!System.IO.Directory.Exists(directory)) System.IO.Directory.CreateDirectory(directory); File.AppendAllText(directory + now.ToString("yyyyMMdd") + ".log", text + "\r\n"); } #endregion private void tsbtnOpenDev_Click(object sender, EventArgs e) { Config.LoadAllConfig(); if(string.IsNullOrWhiteSpace(Config.DBConStr)|| string.IsNullOrWhiteSpace(Config.ServerIP)) { AddTextEvent("设备启动", "启动失败,请先设置数据库和主机台通讯地址!",WarningEnum.High); return; } //设置程序最小/大线程池 // Get the current settings. int minWorker, minIOC; ThreadPool.GetMinThreads(out minWorker, out minIOC); ThreadPool.SetMinThreads(25, minIOC); //ThreadPool.SetMaxThreads(256, 256); this.tsbtnOpenDev.Enabled = false; scannerCBmpQueue.Clear(); //scannerCBmpIndex = 0; this.resetUIValue(); currentState = CurrentStateEnum.等待复位; warningLevel = WarningEnum.Normal; currentPT = CurrentPTEnum.InitPT; this.tsbtnWarning.Enabled = this.tsbtnGoDownPT.Enabled = this.tsbtnStart.Enabled = this.tsbtnStopNow.Enabled = this.tsbtnPause.Enabled = this.tsbtnReset.Enabled = this.gpbXYAxis.Enabled = gpbZAxis.Enabled = false; //后台线程回调事件 devContainer.StateChange = (state, msg) => { if (state) { //全局中断 devContainer.devIOCard.INEvent = globalBreakEvent; devContainer.OutDebugEvent = (tag, debugInfo) => { AddTextEvent(tag, debugInfo); }; // AddTextEvent("设备启动", "请先进行复位操作!"); this.Invoke(new System.Action(() => { this.tsbtnReset.Enabled = true; tsbtnWarning.Enabled = this.tsbtnStart.Enabled = this.tsbtnGoDownPT.Enabled = this.tsbtnPause.Enabled = this.tsbtnStopNow.Enabled = false; this.chkLaser.Enabled = true; this.tsbtnOpenDev.Enabled = true; this.tsbtnOpenDev.Visible = false; this.tsbtnCloseDev.Visible = true; })); timer.Elapsed += Timer_Elapsed; timer.Interval = 500; timer.Start(); } else { AddTextEvent("设备启动", $"启动失败,{msg}", WarningEnum.High); this.Invoke(new System.Action(() => { this.chkLaser.Enabled = false; this.tsbtnOpenDev.Enabled = true; this.tsbtnOpenDev.Visible = true; this.tsbtnCloseDev.Visible = false; })); } }; devContainer.WarningEvent = (level, msg) => { AddTextEvent("设备事件", msg, level); if (level == WarningEnum.High) warning(level, true); }; AddTextEvent("设备启动", "启动"); devContainer.start(IntPtr.Zero, IntPtr.Zero); } private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { this.Invoke(new System.Action(() => { this.tsAxisState.Text = $"[命令位:{devContainer.devAxis.CmdPos[0]} 反馈位:{devContainer.devAxis.ActualPos[0]} ({((AxisState)devContainer.devAxis.AxState[0]).ToString()})] | " + $"[命令位:{devContainer.devAxis.CmdPos[1]} 反馈位:{devContainer.devAxis.ActualPos[1]} ({((AxisState)devContainer.devAxis.AxState[1]).ToString()})] | " + $"[命令位:{devContainer.devAxis.CmdPos[2]} 反馈位:{devContainer.devAxis.ActualPos[2]} ({((AxisState)devContainer.devAxis.AxState[2]).ToString()})] | " + $"[命令位:{devContainer.devAxis.CmdPos[3]} 反馈位:{devContainer.devAxis.ActualPos[3]} ({((AxisState)devContainer.devAxis.AxState[3]).ToString()})] | "; })); } private void tsbtnCloseDev_Click(object sender, EventArgs e) { AddTextEvent("设备停止", $"设备停止..."); this.tsbtnOpenDev.Visible = true; this.tsbtnCloseDev.Visible = false; this.chkLaser.Enabled = false; this.tsbtnReset.Enabled = tsbtnWarning.Enabled = this.tsbtnStart.Enabled = this.tsbtnGoDownPT.Enabled = this.tsbtnPause.Enabled = this.tsbtnStopNow.Enabled = this.gpbXYAxis.Enabled = this.gpbZAxis.Enabled = false; if (devContainer.state) { devContainer.devIOCard.reset(); devContainer.io_output(CMDName.IO默认输出); } timer.Stop(); devContainer.stop(); } private void dgvProcess_CellDoubleClick(object sender, DataGridViewCellEventArgs e) { if (e.RowIndex < 0 || !devContainer.state || currentState != CurrentStateEnum.打标中) return; int preIndex = currDefectIndex; currDefectIndex = e.RowIndex; gotoDefctListIndex(currDefectIndex, preIndex); } private void 流程管理ToolStripMenuItem_Click(object sender, EventArgs e) { if (devContainer.state) { MessageBox.Show("请先停止设备,再进行流程修改!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } FrmStepList frm = new FrmStepList(); frm.ShowDialog(); } private void 产品管理ToolStripMenuItem_Click(object sender, EventArgs e) { //if (devContainer.state) //{ // MessageBox.Show("请先停止设备,再进行产品修改!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning); // return; //} FrmProductList frm = new FrmProductList(); frm.ShowDialog(); } private void loadOrderSNList() { try { //ConditionalType: 0-等于 3-大于等于 5-小于等于 6-IN "CSharpTypeName":"int" JArray domainList =new JArray(); domainList.Add(new JObject() { {"FieldName","State" }, {"FieldValue",0 },//0-初始; 5-已检测 {"ConditionalType",0 }, }); domainList.Add(new JObject() { {"FieldName","DefectCount" }, {"FieldValue",1 }, {"ConditionalType",3 }, }); domainList.Add(new JObject() { {"FieldName","CreateTime" }, {"FieldValue",DateTime.Now.AddDays(-1) }, {"ConditionalType",3 }, }); var list = svcOrder.GetList("Order", "SN", domainList.ToString(), "SN DESC"); List snList = new List(); foreach(var item in list) snList.Add(item.ToList().Select(m => m.Value.ToString()).ToArray()[0]); this.Invoke(new System.Action(() => { this.cbxSN.Text = ""; this.cbxSN.Items.Clear(); this.cbxSN.Items.AddRange(snList.ToArray()); })); } catch (Exception ex) { AddTextEvent("启动", "加载已检测网版编码失败:" + ex.Message, WarningEnum.Low); } } private void splitContainer1_SizeChanged(object sender, EventArgs e) { this.gpbProductInfo.Width = this.gpbDefectList.Width = splitContainer1.Panel2.Width-10; this.gpbProductInfo.Top = this.splitContainer1.ClientSize.Height- this.gpbProductInfo.Height; this.gpbDefectList.Height = this.gpbProductInfo.Top-10; this.cbxSN.Width= this.txtProductCode.Width = this.txtProductName.Width = this.txtBatchId.Width = this.txtCreateTime.Width = this.gpbProductInfo.Width- this.cbxSN.Left-5; //this.dgvProcess.Width = gpbDefectList.Width - 10; //this.dgvProcess.Height = this.splitContainer1.ClientSize.Height - this.gpbProductInfo.Height; // } private void splitContainer2_SizeChanged(object sender, EventArgs e) { this.tsbtnPause.Left = this.tsbtnGoDownPT.Left = this.splitContainer1.SplitterDistance- this.tsbtnPause.Width - 10; this.gpbZAxis.Left = this.tsbtnPause.Left - this.gpbZAxis.Width-10; this.gpbXYAxis.Left = this.gpbZAxis.Left - this.gpbXYAxis.Width - 10; this.gpbLog.Width = this.gpbXYAxis.Left - 10; this.splitContainer2.SplitterDistance = this.ClientRectangle.Height - gpbLog.Height - 10; } private void tsbtnReset_Click(object sender, EventArgs e) { Task.Run(() => this.resetCommand()); } private void tsbtnStart_Click(object sender, EventArgs e) { Task.Run(() => this.startCommand()); } private void tsbtnPause_Click(object sender, EventArgs e) { warning(WarningEnum.Low, false); } private void tsbtnGoDownPT_Click(object sender, EventArgs e) { AddTextEvent("下料", "准备下料。。。"); // Task.Run(() => this.gotoDownPT()); gotoDownPT(); } private void tsbtnWarning_Click(object sender, EventArgs e) { //if (warningLevel == WarningEnum.Normal) //{ // tsbtnWarning.Enabled = false; // return; //} //重置AXIS状态 devContainer.devAxis.resetAxisState(); if (!devContainer.devAxis.isReady()) { AddTextEvent("解除报警", "轴状态未恢复,解除报警失败!", warningLevel); return; } if (devContainer.devAxis.isError()) { AddTextEvent("解除报警", "轴IO状态异常,解除报警失败!", warningLevel); return; } //if (!this.disableDoorSensor && compareIOInput(CMDName.门磁告警输入)) //{ // AddTextEvent("解除报警", "门磁告警未清除 ,解除报警失败!", warningLevel); // return; //} //if (!this.disableDoorSensor && compareIOInput(CMDName.喷墨告警输入)) //{ // AddTextEvent("解除报警", "喷墨告警输入未清除 ,解除报警失败!", warningLevel); // return; //} ////关闭蜂鸣器 //devContainer.io_output(CMDName.蜂鸣器输出, false, true, 0); //devContainer.io_output(CMDName.红灯输出, false, true, 0); //devContainer.io_output(CMDName.复位按钮, false, true, 0); if (warningLevel == WarningEnum.High) { AddTextEvent("解除报警", "急停告警已解除,但必需进行复位操作!", warningLevel); currentState = CurrentStateEnum.等待复位; this.tsbtnReset.Enabled = true; tsbtnWarning.Enabled = this.tsbtnStart.Enabled = this.tsbtnGoDownPT.Enabled = this.tsbtnPause.Enabled = this.tsbtnStopNow.Enabled = false; } else { //devContainer.io_output(CMDName.黄灯输出); AddTextEvent("解除报警", "告警已解除,请继续选择下一步操作!", warningLevel); if (currentPT == CurrentPTEnum.MakeTag) currentState = CurrentStateEnum.打标中; else currentState = CurrentStateEnum.等待启动; tsbtnWarning.Enabled = false; this.tsbtnStart.Enabled = this.tsbtnGoDownPT.Enabled = true; this.tsbtnReset.Enabled = this.tsbtnPause.Enabled = this.tsbtnStopNow.Enabled = true; } warningLevel = WarningEnum.Normal; } private void 测试ToolStripMenuItem_Click(object sender, EventArgs e) { //devContainer.start(IntPtr.Zero, IntPtr.Zero); //devContainer.state = true; //currentState = CurrentStateEnum.等待扫码; //cbxSN.Enabled = true; //runStep(); //Bitmap bmp = (Bitmap)Bitmap.FromFile(Application.StartupPath + "\\test.bmp"); //AddTextEvent("", $"{this.splitContainer1.Width},{this.pnlPic.Width},bmp:{bmp.Width}"); //pnlPic.BackColor = Color.Red; //reloadPic(bmp); //for (int i = 0; i < 100; i++) // this.dgvProcess.Rows.Add(i, i, i, i, i, i, i, i, i, i, i); //this.dgvProcess.Rows[1].DefaultCellStyle.BackColor = Color.LightGreen; //loadOrderSNList(); } private void btnFront_MouseDown(object sender, MouseEventArgs e) { if (devContainer.state && currentState == CurrentStateEnum.打标中) { ushort dir; int axisIndex; PictureBox btn = sender as PictureBox; switch (btn.Name) { case "btnFront": dir = 1; axisIndex = 1; break; case "btnBack": dir = 0; axisIndex = 1; break; case "btnLeft": dir = 1; axisIndex = 0; break; case "btnRight": dir = 0; axisIndex = 0; break; case "btnZUp": dir = 0; axisIndex = 2; break; case "btnZDown": dir = 1; axisIndex = 2; break; default: return; } // devContainer.devAxis.openJogMode(axisIndex); devContainer.devAxis.setAxisVelParam((double)Config.Axis_JogVelLow[axisIndex], (double)Config.Axis_JogVelLow[axisIndex], (double)Config.Axis_JogVelLow[axisIndex], (double)Config.Axis_JogVelLow[axisIndex], axisIndex, true); devContainer.devAxis.jog(axisIndex, dir);//jog move } } private void btnFront_MouseUp(object sender, MouseEventArgs e) { devContainer.devAxis.closeJogMode(); } private void chkLaser_CheckedChanged(object sender, EventArgs e) { if (!devContainer.state) return; if(chkLaser.Checked) devContainer.io_output(CMDName.激光灯输出); else devContainer.io_output(CMDName.激光灯输出, false, true, 0); } private void tsbtnLog_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(Config.LogPath)) return; string lsPath = (Config.LogPath + "\\" + DateTime.Now.ToString("yyyyMM") + "\\").Replace("\\\\", "\\"); if (!Directory.Exists(lsPath)) Directory.CreateDirectory(lsPath); System.Diagnostics.Process.Start("explorer.exe", lsPath); } private void FrmMain_KeyUp(object sender, KeyEventArgs e) { //AddTextEvent("KEY",e.KeyCode.ToString()); switch (e.KeyCode) { //case Keys.Left://上一张图 // if (devContainer.state && currentState == CurrentStateEnum.打标中 && currDefectIndex > 0) // gotoPrePic(); // break; case Keys.F:// Keys.Right://下一张图 if (devContainer.state && currentState == CurrentStateEnum.打标中 && currDefectIndex < defectList.Count - 1) gotoNextPic(); break; case Keys.K://Keys.Up://上一缺陷 if (devContainer.state && currentState == CurrentStateEnum.打标中 && currDefectIndex > 0) gotoDefctListIndex(--currDefectIndex, currDefectIndex+1); break; case Keys.P://Keys.Down://下一缺陷 if (devContainer.state && currentState == CurrentStateEnum.打标中 && currDefectIndex < defectList.Count - 1) gotoDefctListIndex(++currDefectIndex, currDefectIndex-1); break; } } private void 关于ToolStripMenuItem_Click(object sender, EventArgs e) { } private void cbxSN_KeyUp(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { if (currentState != CurrentStateEnum.等待扫码) return; string sn = this.cbxSN.Text.Trim(); if (string.IsNullOrWhiteSpace(sn)) return; //FrmInput frm = new FrmInput(productCodeList, "请选择产品编码:"); //if (frm.ShowDialog() != DialogResult.OK && string.IsNullOrWhiteSpace(frm.inputData)) // return; Task.Factory.StartNew(() => { devContainer.devCodeScanner.ScanerEvent?.Invoke(sn); }); } } private void tsbtnGoDownPT_Click_1(object sender, EventArgs e) { AddTextEvent("下料", "准备下料。。。"); // Task.Run(() => this.gotoDownPT()); gotoDownPT(); } private void cbxSN_KeyPress(object sender, KeyPressEventArgs e) { //if (e.KeyChar == (char)Keys.Enter) //{ // if (currentState != CurrentStateEnum.等待扫码) return; // string sn = this.cbxSN.Text.Trim(); // if (string.IsNullOrWhiteSpace(sn)) // return; // //FrmInput frm = new FrmInput(productCodeList, "请选择产品编码:"); // //if (frm.ShowDialog() != DialogResult.OK && string.IsNullOrWhiteSpace(frm.inputData)) // // return; // Task.Factory.StartNew(() => // { // devContainer.devCodeScanner.ScanerEvent?.Invoke(sn); // }); //} } } }