You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

2232 lines
107 KiB

  1. using Advantech.Motion;
  2. using AssistClient.Device;
  3. using AssistClient.Utils;
  4. using Models;
  5. using Newtonsoft.Json;
  6. using Newtonsoft.Json.Linq;
  7. using OpenCvSharp;
  8. using SqlSugar;
  9. using System;
  10. using System.Collections.Generic;
  11. using System.ComponentModel;
  12. using System.Data;
  13. using System.Drawing;
  14. using System.Drawing.Imaging;
  15. using System.Dynamic;
  16. using System.IO;
  17. using System.Linq;
  18. using System.Text;
  19. using System.Threading;
  20. using System.Threading.Tasks;
  21. using System.Windows.Forms;
  22. using Yolo5;
  23. using static AssistClient.Device.SizeLib;
  24. using Point = System.Drawing.Point;
  25. using Size = System.Drawing.Size;
  26. namespace AssistClient
  27. {
  28. public partial class FrmMain : Form
  29. {
  30. #region pic缩放变量
  31. private double ratio = 1; // 图片的起始显示比例
  32. private double ratioStep = 0.1;
  33. private Size pic_size;
  34. private int xPos;
  35. private int yPos;
  36. #endregion
  37. private bool bExitApp = false;
  38. private Service.ProductService svcProduct = new Service.ProductService();
  39. private Service.OrderService svcOrder = new Service.OrderService();
  40. private DevContainer devContainer = new DevContainer();
  41. private Queue<scannerCBmpLoc> scannerCBmpQueue = new Queue<scannerCBmpLoc>();
  42. private int sizeBmpNum = 0, sizeBmpNumResult = 0;
  43. private string SN = "";
  44. private int OrderId = 0;
  45. private JArray currProductMarkList = null;
  46. private int currDefectIndex = 0;
  47. private List<DefectStruct> defectList = new List<DefectStruct>();
  48. private Dictionary<string, Bitmap> defectBmpsDir = new Dictionary<string, Bitmap>();
  49. private Dictionary<string, List<List<string>>> defectInfoDir = new Dictionary<string, List<List<string>>>();
  50. private object myLock = new object();
  51. private WarningEnum warningLevel;//警告等级
  52. private CurrentPTEnum currentPT;//当前点位
  53. private CurrentStateEnum currentState;//当前状态
  54. /// <summary>
  55. /// 当前流程ID,暂停/继续时使用
  56. /// </summary>
  57. private int currProcessIndex = -1;
  58. private Models.Product currProductModel = null;//当前产品
  59. private System.Timers.Timer timer = new System.Timers.Timer();
  60. Yolo_Class yolo = new Yolo_Class();
  61. private class scannerCBmpLoc
  62. {
  63. public scannerCBmpLoc(string path, double posX, double posY)
  64. {
  65. Path = path;
  66. PosX = posX;
  67. PosY = posY;
  68. }
  69. public scannerCBmpLoc(Bitmap bmp, double posX, double posY)
  70. {
  71. BMP = bmp;
  72. PosX = posX;
  73. PosY = posY;
  74. }
  75. public Bitmap BMP { get; private set; }
  76. public string Path { get; private set; }
  77. public double PosX { get; private set; }
  78. public double PosY { get; private set; }
  79. }
  80. public FrmMain()
  81. {
  82. InitializeComponent();
  83. this.tsbtnCloseDev.Visible = false;
  84. this.dgvProcess.AutoGenerateColumns = false;
  85. //显示行号与列宽度自动调整
  86. dgvProcess.RowHeadersVisible = true;
  87. dgvProcess.RowHeadersWidth = 30;
  88. dgvProcess.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
  89. //dgvProcess.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders;//数据量过百绑定太变
  90. dgvProcess.RowPostPaint += (sender, e) =>//序号列头
  91. {
  92. Utils.Util.showRowNum_onDataGrid_RowPostPaint(this.dgvProcess, sender, e);
  93. };
  94. for (int i = 0; i < dgvProcess.Columns.Count; i++)//禁止点击列头排序
  95. dgvProcess.Columns[i].SortMode = DataGridViewColumnSortMode.NotSortable;
  96. //模糊查询,Append自动填充
  97. this.cbxSN.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
  98. this.cbxSN.AutoCompleteSource = AutoCompleteSource.ListItems;
  99. }
  100. private void FrmMain_Load(object sender, EventArgs e)
  101. {
  102. this.tsbtnPause.Left = this.tsbtnGoDownPT.Left = this.gpbZAxis.Right + 10;
  103. }
  104. private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
  105. {
  106. if (devContainer.state)
  107. {
  108. MessageBox.Show("请先停止设备后才能关闭程序!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  109. e.Cancel = true;
  110. return;
  111. }
  112. if (!bExitApp && MessageBox.Show($"确认退出?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
  113. {
  114. e.Cancel = true;
  115. return;
  116. }
  117. }
  118. private void FrmMain_FormClosed(object sender, FormClosedEventArgs e)
  119. {
  120. Application.Exit();
  121. System.GC.Collect();
  122. System.Environment.Exit(0);
  123. }
  124. #region 菜单
  125. private void 设备调试ToolStripMenuItem_Click(object sender, EventArgs e)
  126. {
  127. if (devContainer.state)
  128. {
  129. MessageBox.Show("请先停止设备,再进行设备调试!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  130. return;
  131. }
  132. FrmDebug3 frm = new FrmDebug3();
  133. frm.ShowDialog();
  134. }
  135. private void tsMenuPTSetting_Click(object sender, EventArgs e)
  136. {
  137. if (devContainer.state)
  138. {
  139. MessageBox.Show("请先停止设备,再进行设置!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  140. return;
  141. }
  142. FrmPTSetting from = new FrmPTSetting();
  143. from.ShowDialog();
  144. }
  145. private void tsMenuCmdSetting_Click(object sender, EventArgs e)
  146. {
  147. if (devContainer.state)
  148. {
  149. MessageBox.Show("请先停止设备,再进行设置!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  150. return;
  151. }
  152. FrmCMDProcess from = new FrmCMDProcess();
  153. from.ShowDialog();
  154. }
  155. private void tsMenuSysSetting_Click(object sender, EventArgs e)
  156. {
  157. FrmSysSetting frmSetting = new FrmSysSetting();
  158. frmSetting.ShowDialog();
  159. }
  160. #endregion
  161. #region 图片缩放控制
  162. private void reloadPic(Bitmap bmp, List<List<string>> defectInfor2RepairTable, DefectStruct defectInfo)
  163. {
  164. //绘框
  165. if (defectInfor2RepairTable != null && defectInfo != null)
  166. {
  167. AddTextEvent("更新图片", $"打标:MainX={defectInfo.MainX},MainY={defectInfo.MainY},CurrIndex={defectInfo.CurrIndex},RepairTable={JsonConvert.SerializeObject(defectInfor2RepairTable)}", warningLevel);
  168. Mat mat = OpenCvSharp.Extensions.BitmapConverter.ToMat(bmp);
  169. mat = yolo.RepairTableDrawRec(defectInfor2RepairTable, defectInfo.MainX, defectInfo.MainY, defectInfo.CurrIndex, mat);
  170. bmp = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat);
  171. }
  172. else
  173. AddTextEvent("更新图片", "无需打标!", warningLevel);
  174. var newSize = Util.getNewSize(splitContainer2.Panel1.ClientSize, new Size(bmp.Size.Width*100, bmp.Size.Height*100));
  175. this.pnlPic.Size = newSize;
  176. if (this.pnlPic.Width < splitContainer2.Panel1.ClientSize.Width)
  177. this.pnlPic.Left = (splitContainer2.Panel1.ClientSize.Width - this.pnlPic.Width) / 2;
  178. if (this.pnlPic.Height < splitContainer2.Panel1.ClientSize.Height)
  179. this.pnlPic.Top = (splitContainer2.Panel1.ClientSize.Height - this.pnlPic.Height) / 2;
  180. ratio = 1.0;// 图片的起始显示比例
  181. Size size = bmp.Size;
  182. //this.pnlPic.ClientSize = new Size(this.pnlPic.ClientSize.Width,
  183. // (int)(this.pnlPic.ClientSize.Width * (size.Height * 1.0f / size.Width)));
  184. this.pictureBox1.Size = this.pnlPic.ClientSize;
  185. this.pictureBox1.Location = new Point(0, 0);
  186. this.pictureBox1.Image = bmp;//del
  187. pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
  188. //2023-12-22 之前工程师写的,存在bug,屏蔽
  189. pictureBox1.MouseWheel += new MouseEventHandler(pictureBox1_MouseWheel);
  190. pictureBox1.MouseMove += pictureBox1_MouseMove;
  191. pictureBox1.MouseDown += pictureBox1_MouseDown;
  192. this.ActiveControl = this.pictureBox1; // 设置焦点
  193. pic_size = this.pnlPic.ClientSize;
  194. }
  195. private void pictureBox1_MouseWheel(object sender, MouseEventArgs e)
  196. {
  197. //Point pictureBoxPoint = this.PointToClient(Cursor.Position);
  198. ////this.Text = $"{e.X}:{e.Y}; {pictureBoxPoint.X}:{pictureBoxPoint.Y}; {pictureBox1.Left}:{pictureBox1.Top}; " +
  199. //// $"{this.pictureBox1.Width}:{this.pictureBox1.Height}; {this.Width}:{this.Height}; " +
  200. //// $"Cursor:{Cursor.Position.X}:{Cursor.Position.Y}";
  201. //if (e.Delta > 0)
  202. //{
  203. // ratio += ratioStep;
  204. // if (ratio > 100) // 放大上限
  205. // ratio = 100;
  206. // else
  207. // {
  208. // int x = (int)(pictureBox1.Left - e.X * (e.X * 1.0d / pictureBox1.Width * ratioStep) + 0.5);
  209. // int y = (int)(pictureBox1.Top - e.Y * (e.Y * 1.0d / pictureBox1.Height * ratioStep) + 0.5);
  210. // //this.Text = $"{pictureBox1.Width}-{pic_size.Width};{ratio},{pictureBox1.Left}-{e.X}* 比例:{e.X*1.0d/pictureBox1.Width}={e.X}/{pictureBox1.Width} * {(ratioStep)}={x} | " +
  211. // // $"{pictureBox1.Top}-{e.Y}* {e.Y * 1.0f / pictureBox1.Height * (ratio - 1.0d)}={y}";
  212. // this.changePictureBoxSize(new Point(x, y), ratio);
  213. // }
  214. //}
  215. //else if (ratio - ratioStep >= 1)
  216. //{
  217. // ratio -= ratioStep;
  218. // //if (ratio < 0.1) // 放大下限
  219. // // ratio = 0.1;
  220. // //else
  221. // int x = (int)(pictureBox1.Left + e.X * (e.X * 1.0d / pictureBox1.Width * ratioStep) + 0.5);
  222. // int y = (int)(pictureBox1.Top + e.Y * (e.Y * 1.0d / pictureBox1.Height * ratioStep) + 0.5);
  223. // this.changePictureBoxSize(new Point(x, y), ratio);
  224. //}
  225. }
  226. private void changePictureBoxSize(Point location, double ratio)
  227. {
  228. //var picSize = pictureBox1.Size;
  229. //picSize.Width = Convert.ToInt32(picSize.Width * ratio);
  230. //picSize.Height = Convert.ToInt32(picSize.Height * ratio);
  231. //pictureBox1.Size = picSize;
  232. //if (location.X > 0) location.X = 0;
  233. //if (location.Y > 0) location.Y = 0;
  234. //if (picSize.Width + location.X < this.pnlPic.ClientSize.Width) location.X = -(picSize.Width - this.pnlPic.ClientSize.Width);
  235. //if (picSize.Height + location.Y < this.pnlPic.ClientSize.Height) location.Y = -(picSize.Height - this.pnlPic.ClientSize.Height);
  236. ////Point location = new Point();
  237. ////location.X = (this.ClientSize.Width - this.pictureBox1.Width) / 2;
  238. ////location.Y = (this.ClientSize.Height - this.pictureBox1.Height) / 2;
  239. //this.pictureBox1.Location = location;
  240. }
  241. private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
  242. {
  243. //try
  244. //{
  245. // // 鼠标按下拖拽图片
  246. // if (e.Button == MouseButtons.Left)
  247. // {
  248. // this.Text = $"{e.X}:{e.Y};{xPos}:{yPos}";
  249. // // 限制拖拽出框
  250. // if (pictureBox1.Width > this.pnlPic.ClientSize.Width
  251. // || pictureBox1.Height > this.pnlPic.ClientSize.Height)
  252. // {
  253. // int moveX = e.X - xPos;
  254. // int moveY = e.Y - yPos;
  255. // if ((pictureBox1.Left + moveX) <= 0
  256. // && (pictureBox1.Top + moveY) <= 0
  257. // && (pictureBox1.Right + moveX) >= this.pnlPic.ClientSize.Width
  258. // && (pictureBox1.Bottom + moveY) >= this.pnlPic.ClientSize.Height)
  259. // {
  260. // pictureBox1.Left += moveX;//设置x坐标.
  261. // pictureBox1.Top += moveY;//设置y坐标.
  262. // }
  263. // }
  264. // }
  265. //}
  266. //catch (Exception dd)
  267. //{
  268. // MessageBox.Show(dd.Message);
  269. //}
  270. }
  271. private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
  272. {
  273. //xPos = e.X;//当前x坐标.
  274. //yPos = e.Y;//当前y坐标.
  275. }
  276. #endregion
  277. #region 中断命令Fun
  278. private Thread threadProcess;
  279. /// <summary>
  280. /// 启动
  281. /// </summary>
  282. private void startCommand()
  283. {
  284. if (!devContainer.state || warningLevel != WarningEnum.Normal || currentState != CurrentStateEnum.等待启动)
  285. return;
  286. if (currentPT == CurrentPTEnum.MakeTag)
  287. {
  288. AddTextEvent("启动", "打标未结束,非可启动状态!", warningLevel);
  289. return;
  290. }
  291. if (!devContainer.devAxis.isReady())
  292. {
  293. AddTextEvent("启动", "轴状态异常,不可启动!", warningLevel);
  294. return;
  295. }
  296. if (!devContainer.devAxis.IsReset)
  297. {
  298. AddTextEvent("启动", "轴需先进行复位操作!", WarningEnum.High);
  299. return;
  300. }
  301. devContainer.io_output(CMDName.启动按钮);
  302. //devContainer.io_output(CMDName.绿灯输出);
  303. //devContainer.io_output(CMDName.暂停按钮, false, true, 0);
  304. //devContainer.io_output(CMDName.红灯输出, false, true, 0);
  305. //devContainer.io_output(CMDName.黄灯输出, false, true, 0);
  306. //暂停-》继续
  307. if (currProcessIndex >= 0 && currentPT == CurrentPTEnum.Moving && currentState == CurrentStateEnum.等待启动)
  308. {
  309. AddTextEvent("启动", $"暂停 -> 继续 当前工序索引:{currProcessIndex + 1}");
  310. threadProcess = new System.Threading.Thread(() =>
  311. {
  312. int nextStepId = currProcessIndex;
  313. do
  314. {
  315. currentState = CurrentStateEnum.运行中;
  316. nextStepId = nextProcess(currProductModel, nextStepId);
  317. } while (nextStepId >= 0 && !isBreakProcessRun());
  318. //nextProcess(currProductModel, currProcessIndex);
  319. });
  320. threadProcess.IsBackground = true;
  321. threadProcess.Start();
  322. this.setButtonEnabled(this.tsbtnPause, true);
  323. this.setButtonEnabled(this.tsbtnStopNow, true);
  324. }
  325. else//开始/重新开始
  326. {
  327. //校正从复位-》运行,不会新启动
  328. resetUIValue();
  329. AddTextEvent("启动", "移动至上料位...");
  330. Task.Run(() => { loadOrderSNList(); });//加载SN
  331. gotoUpPT();
  332. this.Invoke(new System.Action(() =>
  333. {
  334. //新开始
  335. runStep();
  336. }));
  337. this.setButtonEnabled(this.tsbtnPause, false);
  338. this.setButtonEnabled(this.tsbtnStopNow, false);
  339. }
  340. this.setButtonEnabled(this.tsbtnStart, false);
  341. this.setButtonEnabled(this.tsbtnReset, false);
  342. this.setButtonEnabled(this.tsbtnGoDownPT, false);
  343. }
  344. /// <summary>
  345. /// 暂停
  346. /// </summary>
  347. /// <param name="buzzer">是否响蜂鸣</param>
  348. private void pauseCommand(bool buzzer = false)
  349. {
  350. //devContainer.io_output(CMDName.暂停按钮);
  351. //if (buzzer)
  352. //{
  353. // devContainer.io_output(CMDName.红灯输出);
  354. // devContainer.io_output(CMDName.蜂鸣器输出);
  355. //}
  356. //else
  357. // devContainer.io_output(CMDName.黄灯输出);
  358. devContainer.io_output(CMDName.启动按钮, false, true, 0);
  359. //devContainer.io_output(CMDName.绿灯输出, false, true, 0);
  360. this.setButtonEnabled(this.tsbtnWarning, true);
  361. this.setButtonEnabled(this.tsbtnGoDownPT, false);
  362. this.setButtonEnabled(this.tsbtnStart, false);
  363. this.setButtonEnabled(this.tsbtnPause, false);
  364. this.setButtonEnabled(this.tsbtnStopNow, false);
  365. this.setButtonEnabled(this.tsbtnReset, false);
  366. AddTextEvent("暂停", $"当前工序索引:{currProcessIndex + 1}", WarningEnum.Low);
  367. }
  368. /// <summary>
  369. /// 急停
  370. /// </summary>
  371. private void stopNowCommand()
  372. {
  373. if (!devContainer.state)
  374. {
  375. this.setButtonEnabled(this.tsbtnStopNow, false);
  376. return;
  377. }
  378. //devContainer.io_output(CMDName.Y轴复位输出, false, true, 0);
  379. //devContainer.io_output(CMDName.红灯输出);
  380. //if (!this.disableBuzzer) devContainer.io_output(CMDName.蜂鸣器输出);
  381. //devContainer.io_output(CMDName.暂停按钮, false, true, 0);
  382. //devContainer.io_output(CMDName.黄灯输出, false, true, 0);
  383. devContainer.io_output(CMDName.启动按钮, false, true, 0);
  384. //devContainer.io_output(CMDName.绿灯输出, false, true, 0);
  385. this.setButtonEnabled(this.tsbtnWarning, true);
  386. this.setButtonEnabled(this.tsbtnGoDownPT, false);
  387. this.setButtonEnabled(this.tsbtnStart, false);
  388. this.setButtonEnabled(this.tsbtnPause, false);
  389. this.setButtonEnabled(this.tsbtnStopNow, false);
  390. this.setButtonEnabled(this.tsbtnReset, false);
  391. if(currentState== CurrentStateEnum.运行中)
  392. AddTextEvent("急停", $"当前工序索引:{currProcessIndex + 1}", WarningEnum.High);
  393. else
  394. AddTextEvent("急停", $"已急停,请人工处理。", WarningEnum.High);
  395. }
  396. private bool reseting = false;
  397. private void resetCommand()
  398. {
  399. currentState = CurrentStateEnum.等待复位;
  400. warningLevel = WarningEnum.Normal;
  401. currentPT = CurrentPTEnum.InitPT;
  402. this.Invoke(new System.Action(() =>
  403. {
  404. this.tsbtnWarning.Enabled = this.tsbtnGoDownPT.Enabled = this.tsbtnStart.Enabled
  405. = this.tsbtnStopNow.Enabled = this.tsbtnPause.Enabled = this.tsbtnReset.Enabled
  406. = this.gpbXYAxis.Enabled = gpbZAxis.Enabled = false;
  407. }));
  408. try
  409. {
  410. if (devContainer.state && !reseting)
  411. {
  412. reseting = true;
  413. resetUIValue();
  414. AddTextEvent("复位", $"设备复位中...");
  415. this.setButtonEnabled(this.tsbtnReset, false);
  416. if ((AxisState)devContainer.devAxis.AxState[0] == AxisState.STA_AX_EXT_JOG) devContainer.devAxis.closeJogMode(0);//关闭jog时自动停止
  417. if ((AxisState)devContainer.devAxis.AxState[1] == AxisState.STA_AX_EXT_JOG) devContainer.devAxis.closeJogMode(1);//关闭jog时自动停止
  418. // I/O reset后,输出默认状态
  419. AddTextEvent("复位", $"I/O复位中...");
  420. if (!devContainer.devIOCard.reset())
  421. {
  422. AddTextEvent("复位", "I/O板卡复位失败!", WarningEnum.High);
  423. return;
  424. }
  425. if (!devContainer.io_output(CMDName.IO默认输出))
  426. {
  427. //AddTextEvent("复位", "I/O板卡复位默认值失败!", WarningEnum.High);
  428. //return;
  429. }
  430. //板卡复位输出灯
  431. //devContainer.io_output(CMDName.复位按钮);
  432. devContainer.io_output(CMDName.复位按钮, true);//闪
  433. //goto ORG
  434. AddTextEvent("复位", $"轴正在回原点...");
  435. devContainer.devAxis.closeJogMode();
  436. devContainer.devAxis.resetAxisState(-1);//reset state
  437. //AddTextEvent("复位", $"重置轴状态...");
  438. for (int i = 0; i < Config.Axis_HomeMode.Length; i++)
  439. {
  440. //到起始位速度使用回HOME速度
  441. devContainer.devAxis.setAxisVelParam((double)Config.Axis_HomeVelLow[i], (double)Config.Axis_HomeVelHigh[i],
  442. (double)Config.Axis_HomeAcc[i], (double)Config.Axis_HomeDec[i], i);
  443. //devContainer.devAxis.setAxisVelParam(40000,200000,5000000, 5000000,i,true);
  444. devContainer.devAxis.home(i, (uint)Config.Axis_HomeMode[i], (uint)Config.Axis_HomeDir[i]);
  445. }
  446. AddTextEvent("复位", $"等待轴状态完成...");
  447. while (!devContainer.devAxis.isReady())
  448. {
  449. if (!devContainer.state || currentState != CurrentStateEnum.等待复位)
  450. {
  451. AddTextEvent("复位", $"当前状态:" + ((CurrentStateEnum)currentState).ToString());
  452. return;
  453. }
  454. //AddTextEvent("复位", $"轴0状态:"+ ((AxisState)devContainer.devAxis.AxState[0]).ToString());
  455. //AddTextEvent("复位", $"轴1状态:" + ((AxisState)devContainer.devAxis.AxState[1]).ToString());
  456. //AddTextEvent("复位", $"轴2状态:" + ((AxisState)devContainer.devAxis.AxState[2]).ToString());
  457. //AddTextEvent("复位", $"轴3状态:" + ((AxisState)devContainer.devAxis.AxState[3]).ToString());
  458. Thread.Sleep(1000);
  459. //Application.DoEvents();
  460. }
  461. //
  462. if (devContainer.devAxis.isError())
  463. throw new Exception("轴回原点失败!");
  464. //
  465. //goto InitPT
  466. AddTextEvent("复位", $"轴回原点完成,回到初始位...");
  467. JArray arrPT = Config.joPTSetting.Value<JArray>("initPT");
  468. for (int i = 0; i < arrPT.Count; i++)
  469. {
  470. if (!devContainer.state || currentState != CurrentStateEnum.等待复位)
  471. return;
  472. AddTextEvent($"复位", $"轴{i}准备运动至初始位:{(double)arrPT[i]}(当前轴状态:{((AxisState)devContainer.devAxis.AxState[i]).ToString()})...");
  473. devContainer.devAxis.move_ptp(i, (double)arrPT[i], AxMoveMode.MODE1_Abs);
  474. }
  475. while (!devContainer.devAxis.isReady())
  476. {
  477. if (!devContainer.state || warningLevel != WarningEnum.Normal)
  478. return;
  479. Thread.Sleep(100);
  480. //Application.DoEvents();
  481. }
  482. if (devContainer.devAxis.isError())
  483. throw new Exception("轴移动至初始位失败!");
  484. //
  485. this.setButtonEnabled(this.tsbtnReset, true);
  486. this.setButtonEnabled(this.tsbtnStart, true);
  487. this.setButtonEnabled(this.tsbtnStopNow, true);
  488. this.setButtonEnabled(this.tsbtnPause, false);
  489. this.setButtonEnabled(this.tsbtnGoDownPT, false);
  490. this.setButtonEnabled(this.tsbtnWarning, false);
  491. this.setButtonEnabled(this.cbxSN, false);
  492. this.Invoke(new System.Action(() =>
  493. {//根据UI上是否勾选打开激光
  494. chkLaser_CheckedChanged(null, null);
  495. }));
  496. //devContainer.io_output(CMDName.复位按钮, false, true, 0);//熄灭
  497. devContainer.io_output(CMDName.复位按钮);//长亮
  498. currentPT = CurrentPTEnum.InitPT;
  499. currentState = CurrentStateEnum.等待启动;
  500. AddTextEvent("复位", $"复位完成。");
  501. }
  502. else
  503. {
  504. AddTextEvent("复位", "非可复位状态,请先停止后再复位!", WarningEnum.High);
  505. }
  506. }
  507. catch (Exception ex)
  508. {
  509. AddTextEvent("复位", "复位失败 Err:" + ex.Message, WarningEnum.High);
  510. warning(WarningEnum.High, true);
  511. }
  512. finally
  513. {
  514. reseting = false;
  515. }
  516. }
  517. /// <summary>
  518. /// 上料
  519. /// </summary>
  520. private void gotoUpPT()
  521. {
  522. try
  523. {
  524. JArray arrPT = Config.joPTSetting.Value<JArray>("upPT");
  525. for (int i = 0; i < arrPT.Count; i++)
  526. {
  527. if (!devContainer.state || warningLevel != WarningEnum.Normal)
  528. return;
  529. AddTextEvent($"上料", $"轴{i}准备运动至上料位:{(double)arrPT[i]}(当前轴状态:{((AxisState)devContainer.devAxis.AxState[i]).ToString()})...");
  530. devContainer.devAxis.move_ptp(i, (double)arrPT[i], AxMoveMode.MODE1_Abs);
  531. }
  532. while (!devContainer.devAxis.isReady())
  533. {
  534. if (!devContainer.state || warningLevel != WarningEnum.Normal)
  535. return;
  536. Thread.Sleep(100);
  537. }
  538. if (devContainer.devAxis.isError())
  539. throw new Exception("轴移动至上料位失败!");
  540. //
  541. currentPT = CurrentPTEnum.UpPT;
  542. currentState = CurrentStateEnum.等待扫码;
  543. this.setButtonEnabled(cbxSN, true);
  544. AddTextEvent($"上料", "到达上料位!");
  545. }
  546. catch (Exception ex)
  547. {
  548. AddTextEvent("上料", "上料初始失败 Err:" + ex.Message, WarningEnum.High);
  549. warning(WarningEnum.High);
  550. }
  551. }
  552. /// <summary>
  553. /// 下料(暂当完成)
  554. /// </summary>
  555. private void gotoDownPT()
  556. {
  557. try
  558. {
  559. AddTextEvent("下料", "检测状态...");
  560. if (!devContainer.state || warningLevel != WarningEnum.Normal)
  561. {
  562. AddTextEvent("下料失败", "轴状态异常!", WarningEnum.Low);
  563. return;
  564. }
  565. AddTextEvent("下料", "开始下料!");
  566. if (!devContainer.devAxis.isReady())
  567. {
  568. AddTextEvent("下料失败", "轴状态异常!", WarningEnum.Low);
  569. return;
  570. }
  571. if (currentState != CurrentStateEnum.打标中 && currentState != CurrentStateEnum.等待启动 && currentState != CurrentStateEnum.自动流程结束)
  572. {
  573. AddTextEvent($"下料", $"非可下料状态:{currentState.ToString()}");
  574. return;
  575. }
  576. currentState = CurrentStateEnum.下料中;
  577. JArray arrPT = Config.joPTSetting.Value<JArray>("downPT");
  578. for (int i = 0; i < arrPT.Count; i++)
  579. {
  580. if (!devContainer.state || warningLevel != WarningEnum.Normal || currentState != CurrentStateEnum.下料中)
  581. return;
  582. AddTextEvent($"下料", $"轴{i}准备运动至下料位:{(double)arrPT[i]}(当前轴状态:{((AxisState)devContainer.devAxis.AxState[i]).ToString()})...");
  583. devContainer.devAxis.move_ptp(i, (double)arrPT[i], AxMoveMode.MODE1_Abs);
  584. }
  585. while (!devContainer.devAxis.isReady())
  586. {
  587. if (!devContainer.state || warningLevel != WarningEnum.Normal || currentState != CurrentStateEnum.下料中)
  588. return;
  589. Thread.Sleep(100);
  590. }
  591. if (devContainer.devAxis.isError())
  592. throw new Exception("轴移动至下料位失败!");
  593. //
  594. currentPT = CurrentPTEnum.DownPT;
  595. currentState = CurrentStateEnum.等待启动;
  596. devContainer.io_output(CMDName.启动按钮, false, true, 0);
  597. devContainer.devLight.setDigitalValue(1, 0);//关闭上光源
  598. devContainer.devLight.setDigitalValue(2, 0);//关闭下光源
  599. this.Invoke(new System.Action(() =>
  600. {
  601. this.chkLaser.Checked = false;
  602. this.gpbXYAxis.Enabled = gpbZAxis.Enabled = false;
  603. }));
  604. setButtonEnabled(tsbtnStart, true);
  605. setButtonEnabled(tsbtnGoDownPT, false);
  606. AddTextEvent($"下料", "下料完成!");
  607. //更新指定列
  608. //2023-10-31 加入异常情况
  609. FrmRepairInfo frmInfo = new FrmRepairInfo();
  610. DialogResult dr = frmInfo.ShowDialog();
  611. if (svcOrder.Update(it => new Order() {
  612. State = dr == DialogResult.OK? 10 :5 ,
  613. Abnormalities = frmInfo.RepairInfo,
  614. RepairCode = Config.loginUser.Code
  615. }, it => it.Id == OrderId))
  616. AddTextEvent($"检测结束", $"保存检测结果成功。");
  617. else
  618. AddTextEvent($"检测结束", $"保存检测结果失败!",WarningEnum.High);
  619. }
  620. catch (Exception ex)
  621. {
  622. AddTextEvent("下料", "下料失败 Err:" + ex.Message, WarningEnum.High);
  623. warning(WarningEnum.High);
  624. }
  625. }
  626. private void openLowerLight()//下光源
  627. {
  628. var value = devContainer.devLight.getDigitalValue(2);
  629. devContainer.devLight.setDigitalValue(2, value == 0 ? 255 : 0);
  630. }
  631. private void setButtonEnabled(ToolStripButton button, bool Enabled)
  632. {
  633. this.Invoke(new System.Action(() =>
  634. {
  635. button.Enabled = Enabled;
  636. }));
  637. }
  638. private void setButtonEnabled(ToolStripMenuItem button, bool Enabled)
  639. {
  640. this.Invoke(new System.Action(() =>
  641. {
  642. button.Enabled = Enabled;
  643. }));
  644. }
  645. private void setButtonEnabled(Control button, bool Enabled)
  646. {
  647. this.Invoke(new System.Action(() =>
  648. {
  649. button.Enabled = Enabled;
  650. }));
  651. }
  652. #endregion
  653. #region 自动流程 nextProcess
  654. /// <summary>
  655. /// 中断工序运行
  656. /// </summary>
  657. /// <returns></returns>
  658. private bool isBreakProcessRun()
  659. {
  660. return warningLevel != WarningEnum.Normal || currentState != CurrentStateEnum.运行中;
  661. }
  662. private void runStep()
  663. {
  664. sizeBmpNum = sizeBmpNumResult = 0;
  665. AddTextEvent("启动", "等待网版编码扫码...");
  666. if (devContainer.devCodeScanner != null)
  667. {
  668. devContainer.devCodeScanner.stop();
  669. devContainer.devCodeScanner = null;
  670. }
  671. devContainer.devCodeScanner = new CodeScannerDev();
  672. if (!devContainer.devCodeScanner.start())
  673. {
  674. AddTextEvent("扫码枪", "扫码枪初始化失败!");
  675. return;
  676. }
  677. devContainer.devCodeScanner.ScanerEvent = (code) =>
  678. {
  679. if (devContainer.devCodeScanner.isLock ||!devContainer.state
  680. || currentState != CurrentStateEnum.等待扫码 || string.IsNullOrWhiteSpace(code) )
  681. return;
  682. devContainer.devCodeScanner.isLock = true;
  683. Thread threadtest = new System.Threading.Thread(() =>
  684. {
  685. try
  686. {
  687. //注:需要重复输入SN时不能在此释放
  688. //devContainer.devCodeScanner.stop();
  689. //devContainer.devCodeScanner = null;
  690. //
  691. AddTextEvent("扫码枪", $"开始读取网版编码:{code} 数据...");
  692. var modOrder = svcOrder.GetModelNav(code);//from sn
  693. //AddTextEvent("扫码枪", $"读取网版编码:{code}DB数据完成");
  694. string modeState = "";
  695. if (modOrder == null)
  696. AddTextEvent("扫码枪", $"网版编码{code}不存在!");
  697. if (modOrder.State == 5)
  698. {
  699. modeState = $"网版编码{code}已被检测!";
  700. AddTextEvent("扫码枪", $"网版编码{code}已被检测!");
  701. loadOrderSNList();
  702. }
  703. else if (modOrder.State == 10)
  704. {
  705. modeState = $"网版编码{code}已被检测, 并且异常!";
  706. AddTextEvent("扫码枪", $"网版编码{code}已被检测, 并且异常!");
  707. loadOrderSNList();
  708. }
  709. if(!string.IsNullOrEmpty(modeState))
  710. {
  711. if(DialogResult.No == MessageBox.Show(modeState + "是否重新检测!", "网版已被检测", MessageBoxButtons.YesNo, MessageBoxIcon.Information))
  712. {
  713. return;
  714. }
  715. }
  716. //2023-10-20
  717. //else if (modOrder.ProductInfo == null)
  718. if (modOrder.ProductInfo == null)
  719. AddTextEvent("扫码枪", $"网版编码:{code}对应产品信息已不存在!");
  720. else if (modOrder.DefectCount < 1)
  721. AddTextEvent("扫码枪", $"网版编码:{code}没有缺陷!");
  722. //else if (string.IsNullOrWhiteSpace(modOrder.MarkData))
  723. // AddTextEvent("扫码枪", $"产品(网版编码:{code})在主机台未保存原始Mark点!");
  724. else if (modOrder.ProductInfo.AssistStepInfo == null
  725. || modOrder.ProductInfo.AssistStepInfo.ProcessList.Count < 1)
  726. AddTextEvent("扫码枪", $"产品({modOrder.ProductInfo.Name})未配置检测流程!");
  727. else
  728. {
  729. if (string.IsNullOrWhiteSpace(modOrder.MarkData))
  730. {
  731. AddTextEvent("扫码枪", $"产品(网版编码:{code})在主机台未保存原始Mark点!");
  732. modOrder.MarkData = "[0,0,0,0,0,0,0,0]";
  733. }
  734. else
  735. AddTextEvent("主机台", $"主机台Mark数据:{modOrder.MarkData}");
  736. currProductMarkList = JArray.Parse(modOrder.MarkData);
  737. if (currProductMarkList.Count < 8)
  738. {
  739. AddTextEvent("主机台", $"产品(网版编码:{code})在主机台原始Mark点数量错误!");
  740. return;
  741. }
  742. //异步读取
  743. JObject parm = new JObject()
  744. {
  745. {"date",modOrder.CreateTime.ToString("yyyyMMdd") },
  746. {"sn",code }
  747. };
  748. Task.Run(() => loadDefectInfo(parm));
  749. //
  750. devContainer.devCodeScanner.stop();
  751. devContainer.devCodeScanner = null;
  752. currentState = CurrentStateEnum.运行中;
  753. currentPT = CurrentPTEnum.Moving;
  754. currProductModel = modOrder.ProductInfo;
  755. AddTextEvent("扫码枪", $"网版编码:{code}({currProductModel.Name} {currProductModel.Spec} [{currProductModel.Code}])");
  756. this.Invoke(new System.Action(() =>
  757. {
  758. this.cbxSN.Enabled = false;
  759. this.txtBatchId.Text = modOrder.BatchId.ToString();
  760. this.txtProductName.Text = currProductModel.Name;
  761. this.txtProductCode.Text = currProductModel.Code;
  762. this.txtCreateTime.Text = modOrder.CreateTime.ToString("yyyy-MM-dd HH:mm");
  763. //this.dgvProcess.DataSource = new BindingSource(currProductModel.StepInfo.ProcessList, null);
  764. devContainer.libFor.clear();
  765. devContainer.libIF.clear();
  766. }));
  767. //
  768. this.SN = code;
  769. this.OrderId = modOrder.Id;
  770. this.setButtonEnabled(this.tsbtnPause, true);
  771. this.setButtonEnabled(this.tsbtnStopNow, true);
  772. devContainer.devLight.setDigitalValue(2, 255);//下光源
  773. int nextStepId = 0;
  774. do
  775. {
  776. nextStepId = nextProcess(currProductModel, nextStepId);
  777. } while (nextStepId >= 0 && !isBreakProcessRun());
  778. }
  779. }
  780. catch (Exception ex)
  781. {
  782. AddTextEvent("扫码枪", $"读取网版编码信息失败:{ex.Message}");
  783. }
  784. finally
  785. {
  786. if (devContainer.devCodeScanner != null)
  787. devContainer.devCodeScanner.isLock = false;
  788. }
  789. });
  790. threadtest.IsBackground = true;
  791. threadtest.Start();
  792. };
  793. }
  794. private void loadDefectInfo(object parm)
  795. {
  796. try
  797. {
  798. JObject req = (JObject)parm;
  799. currDefectIndex = 0;
  800. defectList.Clear();
  801. defectInfoDir.Clear();
  802. defectBmpsDir.Clear();
  803. //从主机台取缺陷文件名列表和JSON数组
  804. var obj = WebApi.getDefectFromSN(req);
  805. if (obj.Value<int>("code") != 200)
  806. throw new Exception(obj.Value<string>("data"));
  807. //
  808. var defectInfo = obj.Value<JObject>("data"); //文件名列表(主机台已对文件名排序,这里不需再排序(主机台按各自index进行的排序,比对在缺陷文件名后面)
  809. if (defectInfo.Count < 1)
  810. throw new Exception("主机台缺陷文件已不存在!");
  811. //string date = req.Value<string>("date");
  812. //string sn = req.Value<string>("sn");
  813. getDefectBmpList(req, defectInfo);
  814. }
  815. catch (Exception ex)
  816. {
  817. AddTextEvent("网络访问",$"{ex.Message}",WarningEnum.High);
  818. warning(WarningEnum.High);
  819. }
  820. }
  821. /// <summary>
  822. /// 通过文件名列表取各文件名对应BMP
  823. /// </summary>
  824. /// <param name="req"></param>
  825. /// <param name="defectInfo">文件名列表</param>
  826. private void getDefectBmpList(JObject req, JObject defectInfo)
  827. {
  828. int liStep = 0;
  829. try
  830. {
  831. #region 这里转换绑定没实际用处,只是为了提前显示列表
  832. foreach (var kv in defectInfo)
  833. {
  834. defectInfoDir.Add(kv.Key, JsonConvert.DeserializeObject<List<List<string>>>(kv.Value.ToString()));
  835. //
  836. //["4","3.9","-0.8","dk","0.39"],["index","X","Y","缺陷类型","缺陷的置信度"]
  837. JArray arr = kv.Value as JArray;//二维数组
  838. AddTextEvent("主机台", $"缺陷大项:{kv.Key},含小项:{arr.Count}.");
  839. foreach (JArray arr2 in arr) {
  840. var obj = new DefectStruct();
  841. obj.Key = kv.Key;
  842. obj.Index = Convert.ToInt32(arr2[0].ToString());
  843. obj.X = Convert.ToDouble(arr2[1].ToString());
  844. obj.Y = Convert.ToDouble(arr2[2].ToString());
  845. obj.DefectName = Config.getDefectName(arr2[3].ToString());
  846. obj.DefectCC = Convert.ToDouble(arr2[4].ToString());
  847. defectList.Add(obj);
  848. }
  849. }
  850. this.Invoke(new System.Action(() =>
  851. {
  852. //注:这样绑定List中的对象必需得用{get;set;}方式定义属性,否则单独格为空内容
  853. AddTextEvent("主机台", $"准备显示缺陷列表,共{defectList.Count}项.");
  854. this.dgvProcess.DataSource = new BindingSource(defectList, null);
  855. AddTextEvent("主机台", $"显示缺陷列表完成.");
  856. this.gpbDefectList.Text = $"缺陷明细({defectList.Count}条)";
  857. //2023-11-1 图纸对比缺陷标红
  858. for (int i = 0; i < defectList.Count; i++)
  859. {
  860. string defName = (string)this.dgvProcess.Rows[i].Cells["colDefectName"].Value;
  861. if ((defName == Config.getDefectName("ds"))||((defName == Config.getDefectName("yx"))))
  862. this.dgvProcess.Rows[i].DefaultCellStyle.BackColor = Color.Red;
  863. }
  864. }));
  865. #endregion
  866. req.Add("file_name", "");
  867. liStep = 1;
  868. bool first = true;
  869. int index = 1;
  870. foreach (var kv in defectInfo)
  871. {
  872. req["file_name"] = kv.Key;
  873. var obj = WebApi.getDefectBmpBase64(req);
  874. if (!devContainer.state || warningLevel == WarningEnum.High ||
  875. (currentState != CurrentStateEnum.运行中 && currentState != CurrentStateEnum.暂停 && currentState != CurrentStateEnum.等待启动 && currentState != CurrentStateEnum.打标中))
  876. return;
  877. if (obj.Value<int>("code") != 200)
  878. throw new Exception(obj.Value<string>("data"));
  879. Bitmap bmp = new Bitmap(new MemoryStream(Convert.FromBase64String(obj.Value<string>("data"))));
  880. defectBmpsDir.Add(kv.Key, bmp);
  881. AddTextEvent("网络访问", $"已读取第{index++}/{defectInfo.Count}张缺陷图片;");
  882. if (first)
  883. {
  884. first = false;
  885. this.Invoke(new System.Action(() =>
  886. {
  887. this.reloadPic(bmp,null,null);
  888. pictureBox1.Tag = kv.Key;
  889. }));
  890. }
  891. }
  892. }
  893. catch (Exception ex)
  894. {
  895. if (liStep == 0)
  896. {
  897. AddTextEvent("网络访问", $"解析主机缺陷报文失败:{ex.Message}",WarningEnum.High);
  898. warning(WarningEnum.High);
  899. }
  900. else
  901. AddTextEvent("网络访问", $"读取主机台缺陷Bmp图片失败:{ex.Message}");
  902. }
  903. }
  904. private void convert2LocXY()
  905. {
  906. //AddTextEvent($"缺陷项", $"转换缺陷项坐标值...");
  907. // public string Key;
  908. //public string Key0;//index
  909. //public string Key1;//X
  910. //public string Key2;//Y
  911. //public string Key3;//缺陷类型
  912. //public string Key4;//缺陷的置信度
  913. currDefectIndex = 0;
  914. defectList.Clear();
  915. double X, Y;
  916. int MainIndex;
  917. foreach (var item in defectInfoDir)
  918. {
  919. //Key : Defect_SN{order.SN}_I{res.index}_X{res.Xmm}_Y{res.Ymm}_C{res.defectCount}
  920. string[] str = item.Key.Split('_');
  921. MainIndex = Convert.ToInt32(str[2].Substring(1));
  922. X = Convert.ToDouble(str[3].Substring(1));
  923. Y = Convert.ToDouble(str[4].Substring(1));
  924. AddTextEvent("主机台", $"转换前,缺陷大项:{item.Key},含小项:{item.Value.Count}.");
  925. var arr = yolo.ImageXY2RepairTable(item.Value, X, Y, Config.SizeRepairTablePath);
  926. AddTextEvent("主机台", $"转换后,缺陷大项:{item.Key},含小项:{arr.Count}.");
  927. int i = 0;
  928. foreach (var arr2 in arr)
  929. {
  930. var obj = new DefectStruct();
  931. obj.Key = item.Key;
  932. obj.CurrIndex = i++;
  933. obj.MainIndex = MainIndex;
  934. obj.MainX = X;
  935. obj.MainY = Y;
  936. obj.Index = Convert.ToInt32(arr2[0].ToString());
  937. obj.X = Convert.ToDouble(arr2[1].ToString());
  938. obj.Y = Convert.ToDouble(arr2[2].ToString());
  939. obj.DefectName = Config.getDefectName(arr2[3].ToString());
  940. obj.DefectCC = Convert.ToDouble(arr2[4].ToString());
  941. defectList.Add(obj);
  942. }
  943. }
  944. this.Invoke(new System.Action(() =>
  945. {
  946. this.dgvProcess.DataSource = null;
  947. //注:这样绑定List中的对象必需得用{get;set;}方式定义属性,否则单独格为空内容
  948. this.dgvProcess.DataSource = new BindingSource(defectList, null);
  949. this.gpbDefectList.Text = $"缺陷明细({defectList.Count}条)";
  950. }));
  951. gotoDefctListIndex(currDefectIndex);
  952. }
  953. private void gotoDefctListIndex(int index,int preIndex=-1)
  954. {
  955. try
  956. {
  957. AddTextEvent($"缺陷项", $"移至缺陷项:{index + 1}...");
  958. this.Invoke(new System.Action(() =>
  959. {
  960. string key = defectList[index].Key;
  961. if (defectBmpsDir.ContainsKey(key))
  962. {
  963. if (pictureBox1.Tag == null || pictureBox1.Tag.ToString() != key)
  964. {
  965. //reloadPic(defectBmpsDir[key], defectInfoDir[key], defectList[index]);
  966. pictureBox1.Tag = key;
  967. }
  968. reloadPic(defectBmpsDir[key], defectInfoDir[key], defectList[index]);
  969. }
  970. else
  971. AddTextEvent($"缺陷项", $"缺陷图:{defectList[index].Key}还未传输完成!");
  972. if (preIndex > -1)
  973. this.dgvProcess.Rows[preIndex].DefaultCellStyle.BackColor = Color.White;
  974. this.dgvProcess.Rows[index].DefaultCellStyle.BackColor = Color.LightGreen;
  975. this.dgvProcess.Rows[index].Selected = true;
  976. this.dgvProcess.CurrentCell = this.dgvProcess.Rows[index].Cells["colResult"];
  977. this.dgvProcess.Rows[index].Cells["colResult"].Value = "已检";
  978. }));
  979. if ((defectList[index].X <= 0) || (defectList[index].Y <= 0))
  980. {
  981. AddTextEvent($"缺陷项", $"移动报错,当前缺陷项({index + 1})坐标:X{defectList[index].X},Y{defectList[index].Y}", WarningEnum.Low);
  982. return;
  983. }
  984. while (!devContainer.devAxis.isReady(0)) Thread.Sleep(100);
  985. devContainer.devAxis.move_ptp(0, defectList[index].X, AxMoveMode.MODE1_Abs);
  986. while (!devContainer.devAxis.isReady(1)) Thread.Sleep(100);
  987. devContainer.devAxis.move_ptp(1, defectList[index].Y, AxMoveMode.MODE1_Abs);
  988. AddTextEvent($"缺陷项", $"移动完成,当前缺陷项({index + 1})坐标:X{defectList[index].X},Y{defectList[index].Y}");
  989. }
  990. catch (Exception ex)
  991. {
  992. AddTextEvent("缺陷项", "轴移动失败:" + ex.Message, WarningEnum.High);
  993. warning(WarningEnum.High, true);
  994. }
  995. }
  996. private void gotoNextPic()
  997. {
  998. if (currDefectIndex>= defectList.Count-1) return;
  999. this.Invoke(new System.Action(() =>
  1000. {
  1001. for(int i= currDefectIndex+1;i< defectList.Count; i++)
  1002. {
  1003. if (this.pictureBox1.Tag == null || this.pictureBox1.Tag.ToString() != defectList[i].Key)
  1004. {
  1005. AddTextEvent($"缺陷项", $"移至下张图:{i+1}...");
  1006. int preIndex = currDefectIndex;
  1007. currDefectIndex = i;
  1008. gotoDefctListIndex(currDefectIndex, preIndex);
  1009. return;
  1010. }
  1011. }
  1012. }));
  1013. }
  1014. private void gotoPrePic()
  1015. {
  1016. if (currDefectIndex < 1) return;
  1017. this.Invoke(new System.Action(() =>
  1018. {
  1019. if (this.pictureBox1.Tag == null) return;
  1020. for (int i = currDefectIndex-1; i >=0; i--)
  1021. {
  1022. if (this.pictureBox1.Tag.ToString() != defectList[i].Key)
  1023. {
  1024. AddTextEvent($"缺陷项", $"移至上张图:{i + 1}...");
  1025. int preIndex = currDefectIndex;
  1026. currDefectIndex = i;
  1027. gotoDefctListIndex(currDefectIndex, preIndex);
  1028. return;
  1029. }
  1030. }
  1031. }));
  1032. }
  1033. private class DefectStruct
  1034. {
  1035. //Defect_{order.SN}_{res.index}_X{res.Xmm}_Y{res.Ymm}
  1036. public string Key { get; set; }
  1037. public int CurrIndex { get; set; }//当前缺陷在本大图中的索引0-n
  1038. public int MainIndex { get; set; }//大图
  1039. public double MainX { get; set; }//大图X 大相机拍照时原始X,Y轴坐标
  1040. public double MainY { get; set; }//大图X
  1041. //["4","3.9","-0.8","dk","0.39"],["index","X","Y","缺陷类型","缺陷的置信度"]
  1042. public int Index { get; set; }
  1043. public double X { get; set; }
  1044. public double Y { get; set; }
  1045. public string DefectName { get; set; }//缺陷类型
  1046. public double DefectCC { get; set; }//缺陷的置信度
  1047. //2023-10-30 修复情况
  1048. public string Restoratory { get; set; }
  1049. }
  1050. private double[] convert(JArray data)
  1051. {
  1052. double[] result = new double[data.Count];
  1053. for (int i = 0; i < data.Count; i++)
  1054. result[i]=Convert.ToDouble(data[i]);
  1055. return result;
  1056. }
  1057. /// <summary>
  1058. /// 工序循环
  1059. /// </summary>
  1060. /// <param name="model"></param>
  1061. /// <param name="stepIndex">0-n</param>
  1062. /// <returns>大于等于0正常工序; -1:结束 -2:异常</returns>
  1063. private int nextProcess(Models.Product model, int stepIndex)
  1064. {
  1065. try
  1066. {
  1067. //记录当前index
  1068. this.currProcessIndex = stepIndex;
  1069. //this.Invoke(new System.Action(() =>
  1070. //{
  1071. // try
  1072. // {
  1073. // this.dgvProcess.Rows[stepIndex].Selected = true;
  1074. // dgvProcess.CurrentCell = dgvProcess.Rows[stepIndex].Cells[1];
  1075. // }
  1076. // catch { }
  1077. //}));
  1078. lock (myLock)
  1079. {
  1080. if (isBreakProcessRun())
  1081. return stepIndex;
  1082. }
  1083. var processList = model.AssistStepInfo.ProcessList;
  1084. var processInfo = processList[stepIndex];
  1085. string processName = processInfo.ProcessName;
  1086. //AddTextEvent($"{stepIndex + 1}-{processName}", $"工序开始...");
  1087. string jsonParams = null;//配方
  1088. if (model.ProductProcessList != null && model.ProductProcessList.Count > 0)//使用产品配方
  1089. {
  1090. ProductProcess productProcessParams = model.ProductProcessList.First(m => m.ProcessCode == processInfo.ProcessCode);
  1091. if (productProcessParams != null)
  1092. {
  1093. jsonParams = productProcessParams.ProcessParams;
  1094. AddTextEvent($"{stepIndex + 1}-{processName}", $"使用产品专用配方:{jsonParams}");
  1095. }
  1096. }
  1097. if (jsonParams == null)//使用流程默认配方
  1098. {
  1099. jsonParams = processInfo.ProcessParams;
  1100. AddTextEvent($"{stepIndex + 1}-{processName}", $"使用流程默认配方:{jsonParams}");
  1101. }
  1102. //
  1103. JObject processParam = JObject.Parse(jsonParams);
  1104. if (!processParam.ContainsKey("Disable") || !processParam.Value<bool>("Disable"))
  1105. {
  1106. AutoResetEvent endEvent;
  1107. uint sleepPre = processParam.Value<uint>("SleepPre");
  1108. uint sleepLater = processParam.Value<uint>("SleepLater");
  1109. if (sleepPre > 0)
  1110. Thread.Sleep((int)sleepPre);
  1111. double limitThresholdVal, lowerThresholdVal;
  1112. //======Switch 工序类型
  1113. int liStatocStepIndex = stepIndex;
  1114. switch (processInfo.ProcessCode)
  1115. {
  1116. case "IOCard":
  1117. #region
  1118. var direction = (IODirectionEnum)processParam.Value<int>("Direction");
  1119. if (direction == IODirectionEnum.输入 || direction == IODirectionEnum.输入输出)
  1120. {
  1121. uint IN_Waiting_Timeout = processParam.Value<uint>("IN_Waiting_Timeout");
  1122. AddTextEvent($"{stepIndex + 1}-{processName}", $"等待I/O输入信号{(IN_Waiting_Timeout > 0 ? $"(超时时长: {IN_Waiting_Timeout})" : "...")}");
  1123. string[] inValue = processParam.Value<JArray>("IN_OP_SHOW").ToObject<List<string>>().ToArray();
  1124. uint inWaitingTime = 0;
  1125. while (true)
  1126. {
  1127. if (isBreakProcessRun())
  1128. return stepIndex;
  1129. if (Util.compareIOInput(inValue, devContainer.devIOCard.DIData))
  1130. break;
  1131. Thread.Sleep(10);
  1132. inWaitingTime += 10;
  1133. if (IN_Waiting_Timeout > 0 && inWaitingTime >= IN_Waiting_Timeout)
  1134. {
  1135. AddTextEvent($"{stepIndex + 1}-{processName}", $"输入等待超时告警!", WarningEnum.High);
  1136. warning(WarningEnum.Low);//暂停
  1137. return stepIndex;
  1138. }
  1139. }
  1140. AddTextEvent($"{stepIndex + 1}-{processName}", $"I/O输入信号对比完成!");
  1141. }
  1142. if (direction == IODirectionEnum.输出 || direction == IODirectionEnum.输入输出)
  1143. devContainer.io_output($"{stepIndex + 1}-{processName}", processParam);
  1144. #endregion
  1145. break;
  1146. case "Axis":
  1147. #region
  1148. bool asynRun = processParam.Value<bool>("AsynRun");//异步
  1149. int AxisIndex = processParam.Value<int>("AxisIndex");
  1150. int DeviceType = processParam.Value<int>("DeviceType");
  1151. double VelLow = processParam.Value<double>("VelLow");
  1152. double VelHigh = processParam.Value<double>("VelHigh");
  1153. double Acc = processParam.Value<double>("Acc");
  1154. double Dec = processParam.Value<double>("Dec");
  1155. AxMoveMode MoveMode = (AxMoveMode)processParam.Value<int>("MoveMode");//绝对位置
  1156. double PPUValue = processParam.Value<double>("Value");
  1157. AddTextEvent($"{stepIndex + 1}-{processName}", $"轴{AxisIndex}准备({(MoveMode == AxMoveMode.MODE1_Abs ? "绝对" : "相对")})运动至{PPUValue}(当前轴状态:{((AxisState)devContainer.devAxis.AxState[AxisIndex]).ToString()})...");
  1158. ////移动Axis前等待厚度传感器收回
  1159. //if (!Config.SkipHeight)
  1160. //{
  1161. // while (devContainer.devHeight.getHeight() < (double)Math.Abs(Config.HeightDev_SafeValue))
  1162. // {
  1163. // if (isBreakProcessRun())
  1164. // return stepIndex;
  1165. // Thread.Sleep(10);
  1166. // }
  1167. //}
  1168. while (!devContainer.devAxis.isReady(AxisIndex))
  1169. {
  1170. Thread.Sleep(100);
  1171. if (isBreakProcessRun())
  1172. return stepIndex;
  1173. }
  1174. devContainer.devAxis.setAxisVelParam(VelLow, VelHigh, Acc, Dec, AxisIndex);
  1175. if (!devContainer.devAxis.move_ptp(AxisIndex, PPUValue, MoveMode))
  1176. {
  1177. AddTextEvent($"{stepIndex + 1}-{processName}", $"轴{AxisIndex}运动失败!", WarningEnum.Low);
  1178. warning(WarningEnum.Low);//终止
  1179. return stepIndex;
  1180. }
  1181. AddTextEvent($"{stepIndex + 1}-{processName}", $"等待轴{AxisIndex}运行完成...");
  1182. while (!asynRun && !devContainer.devAxis.isReady(AxisIndex))
  1183. {
  1184. Thread.Sleep(100);
  1185. if (isBreakProcessRun())
  1186. {
  1187. currProcessIndex = stepIndex + 1;
  1188. return stepIndex;
  1189. }
  1190. }
  1191. AddTextEvent($"{stepIndex + 1}-{processName}", $"轴{AxisIndex}运行完成,当前命令位置:{devContainer.devAxis.getCmdPos_mm(AxisIndex)},反馈位置:{devContainer.devAxis.getActualPos_mm(AxisIndex)}");
  1192. #endregion
  1193. break;
  1194. case "Light":
  1195. #region
  1196. if (Config.SkipLight)
  1197. {
  1198. AddTextEvent($"{stepIndex + 1}-{processName}", $"设备禁用,忽略此步骤!");
  1199. //setDgvContentCol(liStatocStepIndex, $"设备禁用,忽略此步骤!");
  1200. break;
  1201. }
  1202. int ChannelIndex = processParam.Value<int>("ChannelIndex"); //通道
  1203. int DigitalValue = processParam.Value<int>("DigitalValue"); //亮度
  1204. int nowDiaitalValue = devContainer.devLight.getDigitalValue(ChannelIndex);
  1205. AddTextEvent($"{stepIndex + 1}-{processName}", $"通道{ChannelIndex}当前值:{nowDiaitalValue},准备更新值:{DigitalValue}...");
  1206. devContainer.devLight.setDigitalValue(ChannelIndex, DigitalValue);
  1207. nowDiaitalValue = devContainer.devLight.getDigitalValue(ChannelIndex);
  1208. AddTextEvent($"{stepIndex + 1}-{processName}", $"通道{ChannelIndex}更新后当前值:{nowDiaitalValue}。");
  1209. #endregion
  1210. break;
  1211. case "Scanner_CC":
  1212. #region
  1213. if (Config.SkipScannerCC)
  1214. {
  1215. AddTextEvent($"{stepIndex + 1}-{processName}", $"设备禁用,忽略此步骤!");
  1216. //setDgvContentCol(liStatocStepIndex, $"设备禁用,忽略此步骤!");
  1217. break;
  1218. }
  1219. while (!devContainer.devAxis.isReady())//因启用轴异步功能,使用前需等待
  1220. {
  1221. Thread.Sleep(100);
  1222. if (isBreakProcessRun())
  1223. {
  1224. //currProcessIndex = stepIndex;//本工序没执行,step不变
  1225. return stepIndex;
  1226. }
  1227. }
  1228. float ExposureTimeCC = processParam.Value<float>("ExposureTime"); //曝光
  1229. float GainCC = processParam.Value<float>("Gain"); //增益
  1230. float ResultingFrameRateCC = processParam.Value<float>("ResultingFrameRate"); //帧率
  1231. AddTextEvent($"{stepIndex + 1}-{processName}", $"相机开始采集照片...");
  1232. devContainer.devScannerCC.setParam(ExposureTimeCC, GainCC, ResultingFrameRateCC);
  1233. AddTextEvent($"{stepIndex + 1}-{processName}", $"相机参数设置完成。");
  1234. AutoResetEvent endEventCC = new AutoResetEvent(false);
  1235. //devContainer.devScannerCC.ScanEvent = (num, bmp2) =>
  1236. //{
  1237. // AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片完成.");
  1238. // scannerCBmpQueue.Enqueue(bmp2,
  1239. // devContainer.devAxis.getActualPos_mm(0),
  1240. // devContainer.devAxis.getActualPos_mm(1))
  1241. // endEventCC.Set();//线程返回
  1242. //};
  1243. devContainer.devScannerCC.ScanEventPath += new System.Action<int, string>((num, path2) =>
  1244. {
  1245. AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片完成.");
  1246. scannerCBmpQueue.Enqueue(new scannerCBmpLoc(path2,
  1247. devContainer.devAxis.getActualPos_mm(0),
  1248. devContainer.devAxis.getActualPos_mm(1)));//Dequeue
  1249. AddTextEvent($"{stepIndex + 1}-{processName}", $"图像队列数量: {scannerCBmpQueue.Count}");
  1250. endEventCC.Set();//线程返回
  1251. });
  1252. if (!devContainer.devScannerCC.scan(1))//软触发拍照
  1253. {
  1254. devContainer.devScannerCC.ScanEventPath = null;
  1255. AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片失败!", WarningEnum.Low);
  1256. warning(WarningEnum.Low);//终止
  1257. return stepIndex;
  1258. }
  1259. if (!endEventCC.WaitOne(5000))
  1260. {
  1261. devContainer.devScannerCC.ScanEventPath = null;
  1262. AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片超时!", WarningEnum.Low);
  1263. warning(WarningEnum.Low);//终止
  1264. return stepIndex;
  1265. }
  1266. devContainer.devScannerCC.ScanEventPath = null;
  1267. #endregion
  1268. break;
  1269. case "Size":
  1270. #region
  1271. limitThresholdVal = processParam.Value<double>("LimitThresholdVal");
  1272. lowerThresholdVal = processParam.Value<double>("LowerThresholdVal");
  1273. int sizeIndex = processParam.Value<int>("Index");
  1274. double xPos = 0;
  1275. double yPos = 0;
  1276. if (scannerCBmpQueue.Count < 1)
  1277. {
  1278. AddTextEvent($"{stepIndex + 1}-{processName}", $"尺寸检测异常,无源图像!!", WarningEnum.Low);
  1279. warning(WarningEnum.Low);//暂停
  1280. return stepIndex;
  1281. }
  1282. var bmpCBmpQueue = scannerCBmpQueue.Dequeue();
  1283. AddTextEvent($"{stepIndex + 1}-{processName}", $"开始尺寸检测,index:{sizeIndex},图像队列数量: {scannerCBmpQueue.Count}...");
  1284. //需要偏移校正,index=0时不能异步
  1285. endEvent = new AutoResetEvent(false);
  1286. sizeBmpNum++;
  1287. devContainer.libSize.add(new SizeTask()
  1288. {
  1289. index = sizeIndex,
  1290. stepIndex = stepIndex,//仅供回调时用
  1291. engineName = processParam.Value<string>("EngineName"),
  1292. bmp = bmpCBmpQueue.BMP,//bmp/file_path二选一,优先bmp
  1293. file_path = bmpCBmpQueue.Path,
  1294. posX = bmpCBmpQueue.PosX,
  1295. posY = bmpCBmpQueue.PosY,
  1296. MarkPointList= convert(currProductMarkList),
  1297. finishEvent = (res) =>
  1298. {
  1299. if(res.isSucceed)
  1300. {
  1301. AddTextEvent($"{stepIndex + 1}-{processName}", $"尺寸检测完成,index:{res.index}。");
  1302. }
  1303. else
  1304. {
  1305. //setDgvContentCol(liStatocStepIndex, $"失败:{res.resultInfo}");
  1306. AddTextEvent($"{res.stepIndex + 1}-{processName}", $"尺寸检测失败index:{res.index}:{res.resultInfo}");
  1307. //warning(WarningEnum.Low);//暂停 这里不能暂停,stepIndex和scannerBmpQueue队列也不对了
  1308. }
  1309. sizeBmpNumResult++;
  1310. string sizeSavePath = Config.SizeBmp_Path + "\\" + DateTime.Now.ToString("yyyyMMdd") + "\\";
  1311. if (!Directory.Exists(sizeSavePath))
  1312. Directory.CreateDirectory(sizeSavePath);
  1313. sizeSavePath += $"SN{this.SN}_I{res.index}_X{res.posX}_Y{res.posY}.bmp";
  1314. if (res.bmp != null)
  1315. {
  1316. res.bmp.Save(sizeSavePath,ImageFormat.Bmp);
  1317. res.bmp.Dispose();
  1318. res.bmp = null;
  1319. }
  1320. else
  1321. {
  1322. //File.Copy(res.file_path, defectFileName + ".bmp", true);
  1323. API.CopyFile(res.file_path, sizeSavePath, false);//更快
  1324. File.Delete(res.file_path);
  1325. }
  1326. }
  1327. });
  1328. #endregion
  1329. break;
  1330. case "For":
  1331. #region
  1332. long UniqueId = processParam.Value<long>("UniqueId");
  1333. int GotoStepIndex = processParam.Value<int>("GotoStepIndex");//1-n
  1334. int LimitNum = processParam.Value<int>("LimitNum");//1-n
  1335. bool Reset = processParam.Value<bool>("Reset");
  1336. if (GotoStepIndex - 1 == stepIndex)
  1337. {
  1338. AddTextEvent($"{stepIndex + 1}-{processName}", $"For死循环!!!");
  1339. warning(WarningEnum.High);
  1340. return stepIndex;
  1341. }
  1342. if (!devContainer.libFor.dicData.ContainsKey(UniqueId))
  1343. devContainer.libFor.dicData.Add(UniqueId, 0);
  1344. //
  1345. int Num = devContainer.libFor.dicData[UniqueId];
  1346. Num++;
  1347. if (Num <= LimitNum)
  1348. {
  1349. if (Num == LimitNum)
  1350. {
  1351. //setDgvContentCol(liStatocStepIndex, $"第[{Num}/{LimitNum}]次,循环完成");
  1352. AddTextEvent($"{stepIndex + 1}-{processName}", $"第[{Num}/{LimitNum}]次,循环完成。");
  1353. }
  1354. else
  1355. {
  1356. //setDgvContentCol(liStatocStepIndex, $"第[{Num}/{LimitNum}]次");
  1357. AddTextEvent($"{stepIndex + 1}-{processName}", $"第[{Num}/{LimitNum}]次跳转到步骤[{GotoStepIndex}]...");
  1358. stepIndex = GotoStepIndex - 2;
  1359. }
  1360. devContainer.libFor.dicData[UniqueId] = Num;
  1361. }
  1362. else
  1363. {
  1364. //setDgvContentCol(liStatocStepIndex, $"已失效不执行");
  1365. AddTextEvent($"{stepIndex + 1}-{processName}", $"本循环已失效不执行!");
  1366. }
  1367. //达到limit重置0
  1368. if (devContainer.libFor.dicData[UniqueId] >= LimitNum && Reset)
  1369. {
  1370. devContainer.libFor.dicData[UniqueId] = 0;
  1371. //setDgvContentCol(liStatocStepIndex, $"第[0/{LimitNum}]次");
  1372. AddTextEvent($"{stepIndex + 1}-{processName}", $"计数器已重置。");
  1373. }
  1374. #endregion
  1375. break;
  1376. case "If":
  1377. #region
  1378. long UniqueId_if = processParam.Value<long>("UniqueId");
  1379. int GotoStepIndex_if = processParam.Value<int>("GotoStepIndex");//1-n
  1380. int LimitNum_if = processParam.Value<int>("LimitNum");//1-n
  1381. bool Reset_if = processParam.Value<bool>("Reset");
  1382. if (GotoStepIndex_if - 1 == stepIndex)
  1383. {
  1384. AddTextEvent($"{stepIndex + 1}-{processName}", $"If死循环,不可自我跳转!!!");
  1385. warning(WarningEnum.High);
  1386. return stepIndex;
  1387. }
  1388. //
  1389. if (!devContainer.libIF.dicData.ContainsKey(UniqueId_if))
  1390. devContainer.libIF.dicData.Add(UniqueId_if, 0);
  1391. //
  1392. int Num_if = devContainer.libIF.dicData[UniqueId_if];
  1393. Num_if++;
  1394. if (Num_if <= LimitNum_if)
  1395. {
  1396. if (Num_if == LimitNum_if)
  1397. {
  1398. //setDgvContentCol(liStatocStepIndex, $"第[{Num_if}/{LimitNum_if}]次,跳转至[{GotoStepIndex_if}]");
  1399. AddTextEvent($"{stepIndex + 1}-{processName}", $"计数器[{Num_if}/{LimitNum_if}],跳转至步骤[{GotoStepIndex_if}]...");
  1400. stepIndex = GotoStepIndex_if - 2;
  1401. }
  1402. else
  1403. {
  1404. //setDgvContentCol(liStatocStepIndex, $"第[{Num_if}/{LimitNum_if}]次,不跳转");
  1405. AddTextEvent($"{stepIndex + 1}-{processName}", $"计数器[{Num_if}/{LimitNum_if}],不跳转。");
  1406. }
  1407. //
  1408. devContainer.libIF.dicData[UniqueId_if] = Num_if;
  1409. }
  1410. else
  1411. {
  1412. //setDgvContentCol(liStatocStepIndex, $"已失效不执行");
  1413. AddTextEvent($"{stepIndex + 1}-{processName}", $"本IF已失效不执行。");
  1414. }
  1415. //达到limit重置0
  1416. if (devContainer.libIF.dicData[UniqueId_if] >= LimitNum_if && Reset_if)
  1417. {
  1418. devContainer.libIF.dicData[UniqueId_if] = 0;
  1419. //setDgvContentCol(liStatocStepIndex, $"第[0/{LimitNum_if}]次");
  1420. AddTextEvent($"{stepIndex + 1}-{processName}", $"计数器已重置。");
  1421. }
  1422. #endregion
  1423. break;
  1424. default:
  1425. AddTextEvent($"{stepIndex + 1}-{processName}", $"未知工序:{processInfo.ProcessCode}");
  1426. warning(WarningEnum.High);
  1427. return stepIndex;
  1428. }
  1429. if (sleepLater > 0) Thread.Sleep((int)sleepLater);
  1430. }
  1431. //============结束,判断是否自动下料
  1432. if (stepIndex == processList.Count - 1)
  1433. {
  1434. setButtonEnabled(tsbtnPause, false);//后面手动模式暂停无意义
  1435. //等待Mark图处理完成
  1436. while (sizeBmpNum != sizeBmpNumResult)
  1437. Thread.Sleep(100);
  1438. //
  1439. this.Invoke(new System.Action(() =>
  1440. {
  1441. this.chkLaser.Checked = true;
  1442. this.gpbXYAxis.Enabled = gpbZAxis.Enabled = true;
  1443. }));
  1444. AddTextEvent("完成", $"Mark点计算工序结束,开始转换主机台缺陷坐标...");
  1445. convert2LocXY();
  1446. AddTextEvent("完成", $"开始进行人工修复...");
  1447. currentPT = CurrentPTEnum.MakeTag;
  1448. currentState = CurrentStateEnum.打标中;
  1449. setButtonEnabled(tsbtnGoDownPT, true);
  1450. setButtonEnabled(tsbtnReset, true);
  1451. //==
  1452. currProcessIndex = -1;
  1453. return -1;
  1454. }
  1455. else //继续
  1456. {
  1457. return ++stepIndex;
  1458. //return nextProcess(model, ++stepIndex);
  1459. }
  1460. }
  1461. catch (Exception ex)
  1462. {
  1463. if (devContainer.devAxis.isError())
  1464. {
  1465. AddTextEvent("工序", $"[{stepIndex}] Err:" + ex.Message);
  1466. warning(WarningEnum.High);
  1467. }
  1468. else
  1469. {
  1470. AddTextEvent("工序", $"[{stepIndex}] Err:" + ex.Message);
  1471. warning(WarningEnum.Low);
  1472. }
  1473. return -2;
  1474. }
  1475. }
  1476. #endregion
  1477. #region Fun
  1478. /// <summary>
  1479. /// 全局中断
  1480. /// </summary>
  1481. private void globalBreakEvent(int portIndex, byte data)
  1482. {
  1483. AddTextEvent("中断命令", $"{portIndex}-HEX:{Convert.ToString(data, 16)}");
  1484. if (compareIOInput(CMDName.启动按钮) && this.tsbtnStart.Enabled)
  1485. startCommand();
  1486. else if (compareIOInput(CMDName.暂停按钮) && this.tsbtnPause.Enabled)
  1487. warning(WarningEnum.Low, false);
  1488. else if (compareIOInput(CMDName.完成下料) && this.tsbtnGoDownPT.Enabled)
  1489. gotoDownPT();
  1490. else if (compareIOInput(CMDName.下光源按钮))
  1491. openLowerLight();
  1492. else if (compareIOInput(CMDName.上一张图) && currentState == CurrentStateEnum.打标中 && currDefectIndex > 0)
  1493. gotoPrePic();
  1494. else if (compareIOInput(CMDName.下一张图) && currentState == CurrentStateEnum.打标中 && currDefectIndex < defectList.Count - 1)
  1495. gotoNextPic();
  1496. else if (compareIOInput(CMDName.上一缺陷) && currentState == CurrentStateEnum.打标中 && currDefectIndex > 0)
  1497. gotoDefctListIndex(--currDefectIndex, currDefectIndex + 1);
  1498. else if (compareIOInput(CMDName.下一缺陷) && currentState == CurrentStateEnum.打标中 && currDefectIndex < defectList.Count - 1)
  1499. gotoDefctListIndex(++currDefectIndex, currDefectIndex - 1);
  1500. else if (compareIOInput(CMDName.复位按钮) && this.tsbtnReset.Enabled)
  1501. resetCommand();
  1502. //
  1503. if (devContainer.state && warningLevel == WarningEnum.Normal
  1504. && currentState == CurrentStateEnum.打标中 && currentPT == CurrentPTEnum.MakeTag)
  1505. {
  1506. int axisIndex = 0;
  1507. bool isJog_axis = (AxisState)devContainer.devAxis.AxState[axisIndex] == AxisState.STA_AX_EXT_JOG;
  1508. if(!handleJog(axisIndex, CMDName.手柄左移,1) && !handleJog(axisIndex, CMDName.手柄右移,0))
  1509. {
  1510. if (isJog_axis)
  1511. {
  1512. AddTextEvent("中断命令", $"轴{axisIndex}关闭JOG模式!");
  1513. devContainer.devAxis.closeJogMode(axisIndex);//关闭jog时自动停止
  1514. }
  1515. }
  1516. axisIndex = 1;
  1517. isJog_axis = (AxisState)devContainer.devAxis.AxState[axisIndex] == AxisState.STA_AX_EXT_JOG;
  1518. if (!handleJog(axisIndex, CMDName.手柄前移,0) && !handleJog(axisIndex, CMDName.手柄后移,1))
  1519. {
  1520. if (isJog_axis)
  1521. {
  1522. AddTextEvent("中断命令", $"轴{axisIndex}关闭JOG模式!");
  1523. devContainer.devAxis.closeJogMode(axisIndex);//关闭jog时自动停止
  1524. }
  1525. }
  1526. }
  1527. }
  1528. private bool compareIOInput(CMDName key)
  1529. {
  1530. JObject joJson = Config.CMDProcess[key];
  1531. IODirectionEnum direction = (IODirectionEnum)joJson.Value<int>("Direction");
  1532. if (direction == IODirectionEnum.输入 || direction == IODirectionEnum.输入输出)
  1533. {
  1534. return Util.compareIOInput(
  1535. joJson.Value<JArray>("IN_OP_SHOW").ToObject<List<string>>().ToArray(),
  1536. devContainer.devIOCard.DIData);
  1537. }
  1538. return false;
  1539. }
  1540. private bool handleJog(int axisIndex,CMDName cmd,ushort dir)
  1541. {
  1542. if (compareIOInput(cmd) && currentState == CurrentStateEnum.打标中)
  1543. {
  1544. AddTextEvent("中断命令", $"{cmd.ToString()}:开");
  1545. devContainer.devAxis.openJogMode(axisIndex);
  1546. devContainer.devAxis.setAxisVelParam((double)Config.Axis_JogVelLow[axisIndex], (double)Config.Axis_JogVelLow[axisIndex],
  1547. (double)Config.Axis_JogVelLow[axisIndex], (double)Config.Axis_JogVelLow[axisIndex], axisIndex, true);
  1548. devContainer.devAxis.jog(axisIndex, dir);//jog move
  1549. return true;
  1550. }
  1551. return false;
  1552. }
  1553. /// <summary>
  1554. /// 报警,只响应low,high
  1555. /// </summary>
  1556. private void warning(WarningEnum level, bool buzzer = true)
  1557. {
  1558. if (level == WarningEnum.Normal)
  1559. return;
  1560. lock (myLock)
  1561. warningLevel = level;
  1562. if (level == WarningEnum.Low)//暂停
  1563. {
  1564. currentState = CurrentStateEnum.暂停;
  1565. pauseCommand(buzzer);
  1566. }
  1567. else if (level == WarningEnum.High)//急停
  1568. {
  1569. currentState = CurrentStateEnum.急停;
  1570. devContainer.devAxis.stopNow();
  1571. stopNowCommand();
  1572. }
  1573. //启用报警消除按钮
  1574. setButtonEnabled(tsbtnWarning, true);
  1575. }
  1576. private void resetUIValue()
  1577. {
  1578. currProcessIndex = -1;
  1579. currProductModel = null;
  1580. currProductMarkList = null;
  1581. scannerCBmpQueue.Clear();
  1582. defectBmpsDir.Clear();
  1583. this.Invoke(new System.Action(() =>
  1584. {
  1585. cbxSN.Enabled = false;
  1586. cbxSN.Text = txtProductCode.Text = txtProductName.Text = txtBatchId.Text =
  1587. txtBatchId.Text = txtCreateTime.Text = "";
  1588. this.gpbDefectList.Text = $"缺陷明细";
  1589. this.dgvProcess.DataSource = null;
  1590. this.lstLog.Items.Clear();
  1591. this.pictureBox1.Image = null;
  1592. pictureBox1.Refresh();
  1593. }));
  1594. }
  1595. private void delDirFiles(string dirPath)
  1596. {
  1597. try
  1598. {
  1599. var files = Directory.EnumerateFiles(dirPath, "*.bmp", SearchOption.TopDirectoryOnly);
  1600. foreach (string file in files)
  1601. API.DeleteFile(file);
  1602. }
  1603. catch (Exception ex)
  1604. {
  1605. }
  1606. }
  1607. public delegate void AddTextDelegate(string tag, string msg, WarningEnum level);
  1608. /// <summary>
  1609. /// 异步输出日志
  1610. /// </summary>
  1611. /// <param name="tag">模板标识</param>
  1612. /// <param name="msg">内容</param>
  1613. /// <param name="type"></param>
  1614. private void AddTextEvent(string tag, string msg, WarningEnum level = WarningEnum.Normal)
  1615. {
  1616. try
  1617. {
  1618. if (InvokeRequired)
  1619. {
  1620. Invoke(new AddTextDelegate(AddTextEvent), new object[]
  1621. {
  1622. tag,
  1623. msg,
  1624. level
  1625. });
  1626. }
  1627. else
  1628. {
  1629. if (tag != null && tag != "")
  1630. tag = $" - [{tag}]";
  1631. var now = DateTime.Now;
  1632. msg = now.ToString("HH:mm:ss fff") + tag + " - " + msg;
  1633. //cont = MyHelper.subString(cont, 300);
  1634. //写日志,warn和error日志直接写
  1635. writeLog(now, level, msg);
  1636. //
  1637. //if (type > 0)
  1638. // cont = $"<color=\"{(type == 1 ? "Yellow" : "Red")}\">{cont}</color>";
  1639. msg = (level == WarningEnum.Normal ? "B" : level == WarningEnum.Low ? "Y" : "R") + msg;
  1640. this.Invoke(new System.Action(() =>
  1641. {
  1642. if (this.lstLog.Items.Count > 1000)
  1643. this.lstLog.Items.Clear();
  1644. lstLog.Items.Insert(0, msg);
  1645. }));
  1646. //日志滚动
  1647. //lstLog.SelectedIndex = lstLog.Items.Count - 1;
  1648. }
  1649. }
  1650. catch (Exception ex)
  1651. {
  1652. //MessageBox.Show("AddTextEvent ex=(" + ex.Message + ")", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, 0);
  1653. }
  1654. }
  1655. private void lstLog_DrawItem(object sender, DrawItemEventArgs e)
  1656. {
  1657. e.DrawBackground();
  1658. if (e.Index < 0) return;
  1659. string str = lstLog.Items[e.Index].ToString();
  1660. e.Graphics.DrawString(str.Substring(1), e.Font,
  1661. new SolidBrush(str[0] == 'R' ? Color.Red : (str[0] == 'Y' ? Color.Orange : Color.Black)),
  1662. e.Bounds);
  1663. }
  1664. private void writeLog(DateTime now, WarningEnum level, string text)
  1665. {
  1666. string directory = Config.LogPath + "\\" + DateTime.Now.ToString("yyyyMM") + "\\";
  1667. //if (type == 0) directory = Application.StartupPath + "\\Log\\Info\\";
  1668. //else if (type == 1) directory = Application.StartupPath + "\\Log\\Warn\\";
  1669. //else directory = Application.StartupPath + "\\Log\\Error\\";
  1670. if (!System.IO.Directory.Exists(directory))
  1671. System.IO.Directory.CreateDirectory(directory);
  1672. File.AppendAllText(directory + now.ToString("yyyyMMdd") + ".log", text + "\r\n");
  1673. }
  1674. #endregion
  1675. private void tsbtnOpenDev_Click(object sender, EventArgs e)
  1676. {
  1677. Config.LoadAllConfig();
  1678. if(string.IsNullOrWhiteSpace(Config.DBConStr)|| string.IsNullOrWhiteSpace(Config.ServerIP))
  1679. {
  1680. AddTextEvent("设备启动", "启动失败,请先设置数据库和主机台通讯地址!",WarningEnum.High);
  1681. return;
  1682. }
  1683. //设置程序最小/大线程池
  1684. // Get the current settings.
  1685. int minWorker, minIOC;
  1686. ThreadPool.GetMinThreads(out minWorker, out minIOC);
  1687. ThreadPool.SetMinThreads(25, minIOC);
  1688. //ThreadPool.SetMaxThreads(256, 256);
  1689. this.tsbtnOpenDev.Enabled = false;
  1690. scannerCBmpQueue.Clear();
  1691. //scannerCBmpIndex = 0;
  1692. this.resetUIValue();
  1693. currentState = CurrentStateEnum.等待复位;
  1694. warningLevel = WarningEnum.Normal;
  1695. currentPT = CurrentPTEnum.InitPT;
  1696. this.tsbtnWarning.Enabled = this.tsbtnGoDownPT.Enabled = this.tsbtnStart.Enabled
  1697. = this.tsbtnStopNow.Enabled = this.tsbtnPause.Enabled = this.tsbtnReset.Enabled
  1698. = this.gpbXYAxis.Enabled = gpbZAxis.Enabled = false;
  1699. //后台线程回调事件
  1700. devContainer.StateChange = (state, msg) =>
  1701. {
  1702. if (state)
  1703. {
  1704. //全局中断
  1705. devContainer.devIOCard.INEvent = globalBreakEvent;
  1706. devContainer.OutDebugEvent = (tag, debugInfo) =>
  1707. {
  1708. AddTextEvent(tag, debugInfo);
  1709. };
  1710. //
  1711. AddTextEvent("设备启动", "请先进行复位操作!");
  1712. this.Invoke(new System.Action(() =>
  1713. {
  1714. this.tsbtnReset.Enabled = true;
  1715. tsbtnWarning.Enabled = this.tsbtnStart.Enabled = this.tsbtnGoDownPT.Enabled
  1716. = this.tsbtnPause.Enabled = this.tsbtnStopNow.Enabled = false;
  1717. this.chkLaser.Enabled = true;
  1718. this.tsbtnOpenDev.Enabled = true;
  1719. this.tsbtnOpenDev.Visible = false;
  1720. this.tsbtnCloseDev.Visible = true;
  1721. }));
  1722. timer.Elapsed += Timer_Elapsed;
  1723. timer.Interval = 500;
  1724. timer.Start();
  1725. }
  1726. else
  1727. {
  1728. AddTextEvent("设备启动", $"启动失败,{msg}", WarningEnum.High);
  1729. this.Invoke(new System.Action(() =>
  1730. {
  1731. this.chkLaser.Enabled = false;
  1732. this.tsbtnOpenDev.Enabled = true;
  1733. this.tsbtnOpenDev.Visible = true;
  1734. this.tsbtnCloseDev.Visible = false;
  1735. }));
  1736. }
  1737. };
  1738. devContainer.WarningEvent = (level, msg) =>
  1739. {
  1740. AddTextEvent("设备事件", msg, level);
  1741. if (level == WarningEnum.High)
  1742. warning(level, true);
  1743. };
  1744. AddTextEvent("设备启动", "启动");
  1745. devContainer.start(IntPtr.Zero, IntPtr.Zero);
  1746. }
  1747. private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
  1748. {
  1749. this.Invoke(new System.Action(() =>
  1750. {
  1751. this.tsAxisState.Text = $"[命令位:{devContainer.devAxis.CmdPos[0]} 反馈位:{devContainer.devAxis.ActualPos[0]} ({((AxisState)devContainer.devAxis.AxState[0]).ToString()})] | " +
  1752. $"[命令位:{devContainer.devAxis.CmdPos[1]} 反馈位:{devContainer.devAxis.ActualPos[1]} ({((AxisState)devContainer.devAxis.AxState[1]).ToString()})] | " +
  1753. $"[命令位:{devContainer.devAxis.CmdPos[2]} 反馈位:{devContainer.devAxis.ActualPos[2]} ({((AxisState)devContainer.devAxis.AxState[2]).ToString()})] | " +
  1754. $"[命令位:{devContainer.devAxis.CmdPos[3]} 反馈位:{devContainer.devAxis.ActualPos[3]} ({((AxisState)devContainer.devAxis.AxState[3]).ToString()})] | ";
  1755. }));
  1756. }
  1757. private void tsbtnCloseDev_Click(object sender, EventArgs e)
  1758. {
  1759. AddTextEvent("设备停止", $"设备停止...");
  1760. this.tsbtnOpenDev.Visible = true;
  1761. this.tsbtnCloseDev.Visible = false;
  1762. this.chkLaser.Enabled = false;
  1763. this.tsbtnReset.Enabled = tsbtnWarning.Enabled = this.tsbtnStart.Enabled = this.tsbtnGoDownPT.Enabled
  1764. = this.tsbtnPause.Enabled = this.tsbtnStopNow.Enabled
  1765. = this.gpbXYAxis.Enabled = this.gpbZAxis.Enabled = false;
  1766. if (devContainer.state)
  1767. {
  1768. devContainer.devIOCard.reset();
  1769. devContainer.io_output(CMDName.IO默认输出);
  1770. }
  1771. timer.Stop();
  1772. devContainer.stop();
  1773. }
  1774. private void dgvProcess_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
  1775. {
  1776. if (e.RowIndex < 0 || !devContainer.state || currentState != CurrentStateEnum.打标中)
  1777. return;
  1778. int preIndex = currDefectIndex;
  1779. currDefectIndex = e.RowIndex;
  1780. gotoDefctListIndex(currDefectIndex, preIndex);
  1781. }
  1782. private void 流程管理ToolStripMenuItem_Click(object sender, EventArgs e)
  1783. {
  1784. if (devContainer.state)
  1785. {
  1786. MessageBox.Show("请先停止设备,再进行流程修改!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  1787. return;
  1788. }
  1789. FrmStepList frm = new FrmStepList();
  1790. frm.ShowDialog();
  1791. }
  1792. private void 产品管理ToolStripMenuItem_Click(object sender, EventArgs e)
  1793. {
  1794. //if (devContainer.state)
  1795. //{
  1796. // MessageBox.Show("请先停止设备,再进行产品修改!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  1797. // return;
  1798. //}
  1799. FrmProductList frm = new FrmProductList();
  1800. frm.ShowDialog();
  1801. }
  1802. private void loadOrderSNList()
  1803. {
  1804. try
  1805. {
  1806. //ConditionalType: 0-等于 3-大于等于 5-小于等于 6-IN "CSharpTypeName":"int"
  1807. JArray domainList =new JArray();
  1808. domainList.Add(new JObject()
  1809. {
  1810. {"FieldName","State" },
  1811. {"FieldValue",0 },//0-初始; 5-已检测
  1812. {"ConditionalType",0 },
  1813. });
  1814. domainList.Add(new JObject()
  1815. {
  1816. {"FieldName","DefectCount" },
  1817. {"FieldValue",1 },
  1818. {"ConditionalType",3 },
  1819. });
  1820. domainList.Add(new JObject()
  1821. {
  1822. {"FieldName","CreateTime" },
  1823. {"FieldValue",DateTime.Now.AddDays(-1) },
  1824. {"ConditionalType",3 },
  1825. });
  1826. var list = svcOrder.GetList("Order", "SN", domainList.ToString(), "SN DESC");
  1827. List<string> snList = new List<string>();
  1828. foreach(var item in list)
  1829. snList.Add(item.ToList().Select(m => m.Value.ToString()).ToArray()[0]);
  1830. this.Invoke(new System.Action(() =>
  1831. {
  1832. this.cbxSN.Text = "";
  1833. this.cbxSN.Items.Clear();
  1834. this.cbxSN.Items.AddRange(snList.ToArray());
  1835. }));
  1836. }
  1837. catch (Exception ex)
  1838. {
  1839. AddTextEvent("启动", "加载已检测网版编码失败:" + ex.Message, WarningEnum.Low);
  1840. }
  1841. }
  1842. private void splitContainer1_SizeChanged(object sender, EventArgs e)
  1843. {
  1844. this.gpbProductInfo.Width = this.gpbDefectList.Width = splitContainer1.Panel2.Width-10;
  1845. this.gpbProductInfo.Top = this.splitContainer1.ClientSize.Height- this.gpbProductInfo.Height;
  1846. this.gpbDefectList.Height = this.gpbProductInfo.Top-10;
  1847. this.cbxSN.Width= this.txtProductCode.Width = this.txtProductName.Width
  1848. = this.txtBatchId.Width = this.txtCreateTime.Width = this.gpbProductInfo.Width- this.cbxSN.Left-5;
  1849. //this.dgvProcess.Width = gpbDefectList.Width - 10;
  1850. //this.dgvProcess.Height = this.splitContainer1.ClientSize.Height - this.gpbProductInfo.Height;
  1851. //
  1852. }
  1853. private void splitContainer2_SizeChanged(object sender, EventArgs e)
  1854. {
  1855. this.tsbtnPause.Left = this.tsbtnGoDownPT.Left = this.splitContainer1.SplitterDistance- this.tsbtnPause.Width - 10;
  1856. this.gpbZAxis.Left = this.tsbtnPause.Left - this.gpbZAxis.Width-10;
  1857. this.gpbXYAxis.Left = this.gpbZAxis.Left - this.gpbXYAxis.Width - 10;
  1858. this.gpbLog.Width = this.gpbXYAxis.Left - 10;
  1859. this.splitContainer2.SplitterDistance = this.ClientRectangle.Height - gpbLog.Height - 10;
  1860. }
  1861. private void tsbtnReset_Click(object sender, EventArgs e)
  1862. {
  1863. Task.Run(() => this.resetCommand());
  1864. }
  1865. private void tsbtnStart_Click(object sender, EventArgs e)
  1866. {
  1867. Task.Run(() => this.startCommand());
  1868. }
  1869. private void tsbtnPause_Click(object sender, EventArgs e)
  1870. {
  1871. warning(WarningEnum.Low, false);
  1872. }
  1873. private void tsbtnGoDownPT_Click(object sender, EventArgs e)
  1874. {
  1875. AddTextEvent("下料", "准备下料。。。");
  1876. // Task.Run(() => this.gotoDownPT());
  1877. gotoDownPT();
  1878. }
  1879. private void tsbtnWarning_Click(object sender, EventArgs e)
  1880. {
  1881. //if (warningLevel == WarningEnum.Normal)
  1882. //{
  1883. // tsbtnWarning.Enabled = false;
  1884. // return;
  1885. //}
  1886. //重置AXIS状态
  1887. devContainer.devAxis.resetAxisState();
  1888. if (!devContainer.devAxis.isReady())
  1889. {
  1890. AddTextEvent("解除报警", "轴状态未恢复,解除报警失败!", warningLevel);
  1891. return;
  1892. }
  1893. if (devContainer.devAxis.isError())
  1894. {
  1895. AddTextEvent("解除报警", "轴IO状态异常,解除报警失败!", warningLevel);
  1896. return;
  1897. }
  1898. //if (!this.disableDoorSensor && compareIOInput(CMDName.门磁告警输入))
  1899. //{
  1900. // AddTextEvent("解除报警", "门磁告警未清除 ,解除报警失败!", warningLevel);
  1901. // return;
  1902. //}
  1903. //if (!this.disableDoorSensor && compareIOInput(CMDName.喷墨告警输入))
  1904. //{
  1905. // AddTextEvent("解除报警", "喷墨告警输入未清除 ,解除报警失败!", warningLevel);
  1906. // return;
  1907. //}
  1908. ////关闭蜂鸣器
  1909. //devContainer.io_output(CMDName.蜂鸣器输出, false, true, 0);
  1910. //devContainer.io_output(CMDName.红灯输出, false, true, 0);
  1911. //devContainer.io_output(CMDName.复位按钮, false, true, 0);
  1912. if (warningLevel == WarningEnum.High)
  1913. {
  1914. AddTextEvent("解除报警", "急停告警已解除,但必需进行复位操作!", warningLevel);
  1915. currentState = CurrentStateEnum.等待复位;
  1916. this.tsbtnReset.Enabled = true;
  1917. tsbtnWarning.Enabled = this.tsbtnStart.Enabled = this.tsbtnGoDownPT.Enabled
  1918. = this.tsbtnPause.Enabled = this.tsbtnStopNow.Enabled = false;
  1919. }
  1920. else
  1921. {
  1922. //devContainer.io_output(CMDName.黄灯输出);
  1923. AddTextEvent("解除报警", "告警已解除,请继续选择下一步操作!", warningLevel);
  1924. if (currentPT == CurrentPTEnum.MakeTag)
  1925. currentState = CurrentStateEnum.打标中;
  1926. else
  1927. currentState = CurrentStateEnum.等待启动;
  1928. tsbtnWarning.Enabled = false;
  1929. this.tsbtnStart.Enabled = this.tsbtnGoDownPT.Enabled = true;
  1930. this.tsbtnReset.Enabled = this.tsbtnPause.Enabled = this.tsbtnStopNow.Enabled = true;
  1931. }
  1932. warningLevel = WarningEnum.Normal;
  1933. }
  1934. private void 测试ToolStripMenuItem_Click(object sender, EventArgs e)
  1935. {
  1936. //devContainer.start(IntPtr.Zero, IntPtr.Zero);
  1937. //devContainer.state = true;
  1938. //currentState = CurrentStateEnum.等待扫码;
  1939. //cbxSN.Enabled = true;
  1940. //runStep();
  1941. //Bitmap bmp = (Bitmap)Bitmap.FromFile(Application.StartupPath + "\\test.bmp");
  1942. //AddTextEvent("", $"{this.splitContainer1.Width},{this.pnlPic.Width},bmp:{bmp.Width}");
  1943. //pnlPic.BackColor = Color.Red;
  1944. //reloadPic(bmp);
  1945. //for (int i = 0; i < 100; i++)
  1946. // this.dgvProcess.Rows.Add(i, i, i, i, i, i, i, i, i, i, i);
  1947. //this.dgvProcess.Rows[1].DefaultCellStyle.BackColor = Color.LightGreen;
  1948. //loadOrderSNList();
  1949. }
  1950. private void btnFront_MouseDown(object sender, MouseEventArgs e)
  1951. {
  1952. if (devContainer.state && currentState == CurrentStateEnum.打标中)
  1953. {
  1954. ushort dir;
  1955. int axisIndex;
  1956. PictureBox btn = sender as PictureBox;
  1957. switch (btn.Name)
  1958. {
  1959. case "btnFront":
  1960. dir = 1;
  1961. axisIndex = 1;
  1962. break;
  1963. case "btnBack":
  1964. dir = 0;
  1965. axisIndex = 1;
  1966. break;
  1967. case "btnLeft":
  1968. dir = 1;
  1969. axisIndex = 0;
  1970. break;
  1971. case "btnRight":
  1972. dir = 0;
  1973. axisIndex = 0;
  1974. break;
  1975. case "btnZUp":
  1976. dir = 0;
  1977. axisIndex = 2;
  1978. break;
  1979. case "btnZDown":
  1980. dir = 1;
  1981. axisIndex = 2;
  1982. break;
  1983. default:
  1984. return;
  1985. }
  1986. //
  1987. devContainer.devAxis.openJogMode(axisIndex);
  1988. devContainer.devAxis.setAxisVelParam((double)Config.Axis_JogVelLow[axisIndex], (double)Config.Axis_JogVelLow[axisIndex],
  1989. (double)Config.Axis_JogVelLow[axisIndex], (double)Config.Axis_JogVelLow[axisIndex], axisIndex, true);
  1990. devContainer.devAxis.jog(axisIndex, dir);//jog move
  1991. }
  1992. }
  1993. private void btnFront_MouseUp(object sender, MouseEventArgs e)
  1994. {
  1995. devContainer.devAxis.closeJogMode();
  1996. }
  1997. private void chkLaser_CheckedChanged(object sender, EventArgs e)
  1998. {
  1999. if (!devContainer.state) return;
  2000. if(chkLaser.Checked)
  2001. devContainer.io_output(CMDName.激光灯输出);
  2002. else
  2003. devContainer.io_output(CMDName.激光灯输出, false, true, 0);
  2004. }
  2005. private void tsbtnLog_Click(object sender, EventArgs e)
  2006. {
  2007. if (string.IsNullOrWhiteSpace(Config.LogPath)) return;
  2008. string lsPath = (Config.LogPath + "\\" + DateTime.Now.ToString("yyyyMM") + "\\").Replace("\\\\", "\\");
  2009. if (!Directory.Exists(lsPath))
  2010. Directory.CreateDirectory(lsPath);
  2011. System.Diagnostics.Process.Start("explorer.exe", lsPath);
  2012. }
  2013. private void FrmMain_KeyUp(object sender, KeyEventArgs e)
  2014. {
  2015. //AddTextEvent("KEY",e.KeyCode.ToString());
  2016. switch (e.KeyCode)
  2017. {
  2018. //case Keys.Left://上一张图
  2019. // if (devContainer.state && currentState == CurrentStateEnum.打标中 && currDefectIndex > 0)
  2020. // gotoPrePic();
  2021. // break;
  2022. case Keys.F:// Keys.Right://下一张图
  2023. if (devContainer.state && currentState == CurrentStateEnum.打标中 && currDefectIndex < defectList.Count - 1)
  2024. gotoNextPic();
  2025. break;
  2026. case Keys.K://Keys.Up://上一缺陷
  2027. if (devContainer.state && currentState == CurrentStateEnum.打标中 && currDefectIndex > 0)
  2028. gotoDefctListIndex(--currDefectIndex, currDefectIndex+1);
  2029. break;
  2030. case Keys.P://Keys.Down://下一缺陷
  2031. if (devContainer.state && currentState == CurrentStateEnum.打标中 && currDefectIndex < defectList.Count - 1)
  2032. gotoDefctListIndex(++currDefectIndex, currDefectIndex-1);
  2033. break;
  2034. }
  2035. }
  2036. private void 关于ToolStripMenuItem_Click(object sender, EventArgs e)
  2037. {
  2038. }
  2039. private void cbxSN_KeyUp(object sender, KeyEventArgs e)
  2040. {
  2041. if (e.KeyCode == Keys.Enter)
  2042. {
  2043. if (currentState != CurrentStateEnum.等待扫码) return;
  2044. string sn = this.cbxSN.Text.Trim();
  2045. if (string.IsNullOrWhiteSpace(sn))
  2046. return;
  2047. //FrmInput frm = new FrmInput(productCodeList, "请选择产品编码:");
  2048. //if (frm.ShowDialog() != DialogResult.OK && string.IsNullOrWhiteSpace(frm.inputData))
  2049. // return;
  2050. Task.Factory.StartNew(() =>
  2051. {
  2052. devContainer.devCodeScanner.ScanerEvent?.Invoke(sn);
  2053. });
  2054. }
  2055. }
  2056. private void tsbtnGoDownPT_Click_1(object sender, EventArgs e)
  2057. {
  2058. AddTextEvent("下料", "准备下料。。。");
  2059. // Task.Run(() => this.gotoDownPT());
  2060. gotoDownPT();
  2061. }
  2062. private void cbxSN_KeyPress(object sender, KeyPressEventArgs e)
  2063. {
  2064. //if (e.KeyChar == (char)Keys.Enter)
  2065. //{
  2066. // if (currentState != CurrentStateEnum.等待扫码) return;
  2067. // string sn = this.cbxSN.Text.Trim();
  2068. // if (string.IsNullOrWhiteSpace(sn))
  2069. // return;
  2070. // //FrmInput frm = new FrmInput(productCodeList, "请选择产品编码:");
  2071. // //if (frm.ShowDialog() != DialogResult.OK && string.IsNullOrWhiteSpace(frm.inputData))
  2072. // // return;
  2073. // Task.Factory.StartNew(() =>
  2074. // {
  2075. // devContainer.devCodeScanner.ScanerEvent?.Invoke(sn);
  2076. // });
  2077. //}
  2078. }
  2079. }
  2080. }