Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 

2277 строки
109 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. //2024-03-05 将尺寸未通过排到最前
  945. for (int i = (defectList.Count - 1); i >=0 ; i--)
  946. {
  947. if (defectList[i].DefectName == Config.getDefectName("wtg"))
  948. {
  949. defectList.Insert(0, defectList[i]);
  950. defectList.RemoveAt(i + 1);
  951. }
  952. }
  953. this.Invoke(new System.Action(() =>
  954. {
  955. this.dgvProcess.DataSource = null;
  956. //注:这样绑定List中的对象必需得用{get;set;}方式定义属性,否则单独格为空内容
  957. this.dgvProcess.DataSource = new BindingSource(defectList, null);
  958. this.gpbDefectList.Text = $"缺陷明细({defectList.Count}条)";
  959. }));
  960. gotoDefctListIndex(currDefectIndex);
  961. }
  962. private void gotoDefctListIndex(int index,int preIndex=-1)
  963. {
  964. try
  965. {
  966. AddTextEvent($"缺陷项", $"移至缺陷项:{index + 1}...");
  967. this.Invoke(new System.Action(() =>
  968. {
  969. string key = defectList[index].Key;
  970. if (defectBmpsDir.ContainsKey(key))
  971. {
  972. if (pictureBox1.Tag == null || pictureBox1.Tag.ToString() != key)
  973. {
  974. //reloadPic(defectBmpsDir[key], defectInfoDir[key], defectList[index]);
  975. pictureBox1.Tag = key;
  976. }
  977. reloadPic(defectBmpsDir[key], defectInfoDir[key], defectList[index]);
  978. }
  979. else
  980. AddTextEvent($"缺陷项", $"缺陷图:{defectList[index].Key}还未传输完成!");
  981. if (preIndex > -1)
  982. this.dgvProcess.Rows[preIndex].DefaultCellStyle.BackColor = Color.White;
  983. this.dgvProcess.Rows[index].DefaultCellStyle.BackColor = Color.LightGreen;
  984. this.dgvProcess.Rows[index].Selected = true;
  985. this.dgvProcess.CurrentCell = this.dgvProcess.Rows[index].Cells["colResult"];
  986. this.dgvProcess.Rows[index].Cells["colResult"].Value = "已检";
  987. }));
  988. if ((defectList[index].X <= 0) || (defectList[index].Y <= 0))
  989. {
  990. AddTextEvent($"缺陷项", $"移动报错,当前缺陷项({index + 1})坐标:X{defectList[index].X},Y{defectList[index].Y}", WarningEnum.Low);
  991. return;
  992. }
  993. while (!devContainer.devAxis.isReady(0)) Thread.Sleep(100);
  994. devContainer.devAxis.move_ptp(0, defectList[index].X, AxMoveMode.MODE1_Abs);
  995. while (!devContainer.devAxis.isReady(1)) Thread.Sleep(100);
  996. devContainer.devAxis.move_ptp(1, defectList[index].Y, AxMoveMode.MODE1_Abs);
  997. AddTextEvent($"缺陷项", $"移动完成,当前缺陷项({index + 1})坐标:X{defectList[index].X},Y{defectList[index].Y}");
  998. }
  999. catch (Exception ex)
  1000. {
  1001. AddTextEvent("缺陷项", "轴移动失败:" + ex.Message, WarningEnum.High);
  1002. warning(WarningEnum.High, true);
  1003. }
  1004. }
  1005. private void gotoNextPic()
  1006. {
  1007. if (currDefectIndex>= defectList.Count-1) return;
  1008. this.Invoke(new System.Action(() =>
  1009. {
  1010. for(int i= currDefectIndex+1;i< defectList.Count; i++)
  1011. {
  1012. if (this.pictureBox1.Tag == null || this.pictureBox1.Tag.ToString() != defectList[i].Key)
  1013. {
  1014. AddTextEvent($"缺陷项", $"移至下张图:{i+1}...");
  1015. int preIndex = currDefectIndex;
  1016. currDefectIndex = i;
  1017. gotoDefctListIndex(currDefectIndex, preIndex);
  1018. return;
  1019. }
  1020. }
  1021. }));
  1022. }
  1023. private void gotoPrePic()
  1024. {
  1025. if (currDefectIndex < 1) return;
  1026. this.Invoke(new System.Action(() =>
  1027. {
  1028. if (this.pictureBox1.Tag == null) return;
  1029. for (int i = currDefectIndex-1; i >=0; i--)
  1030. {
  1031. if (this.pictureBox1.Tag.ToString() != defectList[i].Key)
  1032. {
  1033. AddTextEvent($"缺陷项", $"移至上张图:{i + 1}...");
  1034. int preIndex = currDefectIndex;
  1035. currDefectIndex = i;
  1036. gotoDefctListIndex(currDefectIndex, preIndex);
  1037. return;
  1038. }
  1039. }
  1040. }));
  1041. }
  1042. private class DefectStruct
  1043. {
  1044. //Defect_{order.SN}_{res.index}_X{res.Xmm}_Y{res.Ymm}
  1045. public string Key { get; set; }
  1046. public int CurrIndex { get; set; }//当前缺陷在本大图中的索引0-n
  1047. public int MainIndex { get; set; }//大图
  1048. public double MainX { get; set; }//大图X 大相机拍照时原始X,Y轴坐标
  1049. public double MainY { get; set; }//大图X
  1050. //["4","3.9","-0.8","dk","0.39"],["index","X","Y","缺陷类型","缺陷的置信度"]
  1051. public int Index { get; set; }
  1052. public double X { get; set; }
  1053. public double Y { get; set; }
  1054. public string DefectName { get; set; }//缺陷类型
  1055. public double DefectCC { get; set; }//缺陷的置信度
  1056. //2023-10-30 修复情况
  1057. public string Restoratory { get; set; }
  1058. }
  1059. private double[] convert(JArray data)
  1060. {
  1061. double[] result = new double[data.Count];
  1062. for (int i = 0; i < data.Count; i++)
  1063. result[i]=Convert.ToDouble(data[i]);
  1064. return result;
  1065. }
  1066. /// <summary>
  1067. /// 工序循环
  1068. /// </summary>
  1069. /// <param name="model"></param>
  1070. /// <param name="stepIndex">0-n</param>
  1071. /// <returns>大于等于0正常工序; -1:结束 -2:异常</returns>
  1072. private int nextProcess(Models.Product model, int stepIndex)
  1073. {
  1074. try
  1075. {
  1076. //记录当前index
  1077. this.currProcessIndex = stepIndex;
  1078. //this.Invoke(new System.Action(() =>
  1079. //{
  1080. // try
  1081. // {
  1082. // this.dgvProcess.Rows[stepIndex].Selected = true;
  1083. // dgvProcess.CurrentCell = dgvProcess.Rows[stepIndex].Cells[1];
  1084. // }
  1085. // catch { }
  1086. //}));
  1087. lock (myLock)
  1088. {
  1089. if (isBreakProcessRun())
  1090. return stepIndex;
  1091. }
  1092. var processList = model.AssistStepInfo.ProcessList;
  1093. var processInfo = processList[stepIndex];
  1094. string processName = processInfo.ProcessName;
  1095. //AddTextEvent($"{stepIndex + 1}-{processName}", $"工序开始...");
  1096. string jsonParams = null;//配方
  1097. if (model.ProductProcessList != null && model.ProductProcessList.Count > 0)//使用产品配方
  1098. {
  1099. ProductProcess productProcessParams = model.ProductProcessList.First(m => m.ProcessCode == processInfo.ProcessCode);
  1100. if (productProcessParams != null)
  1101. {
  1102. jsonParams = productProcessParams.ProcessParams;
  1103. AddTextEvent($"{stepIndex + 1}-{processName}", $"使用产品专用配方:{jsonParams}");
  1104. }
  1105. }
  1106. if (jsonParams == null)//使用流程默认配方
  1107. {
  1108. jsonParams = processInfo.ProcessParams;
  1109. AddTextEvent($"{stepIndex + 1}-{processName}", $"使用流程默认配方:{jsonParams}");
  1110. }
  1111. //
  1112. JObject processParam = JObject.Parse(jsonParams);
  1113. if (!processParam.ContainsKey("Disable") || !processParam.Value<bool>("Disable"))
  1114. {
  1115. AutoResetEvent endEvent;
  1116. uint sleepPre = processParam.Value<uint>("SleepPre");
  1117. uint sleepLater = processParam.Value<uint>("SleepLater");
  1118. if (sleepPre > 0)
  1119. Thread.Sleep((int)sleepPre);
  1120. double limitThresholdVal, lowerThresholdVal;
  1121. //======Switch 工序类型
  1122. int liStatocStepIndex = stepIndex;
  1123. switch (processInfo.ProcessCode)
  1124. {
  1125. case "IOCard":
  1126. #region
  1127. var direction = (IODirectionEnum)processParam.Value<int>("Direction");
  1128. if (direction == IODirectionEnum.输入 || direction == IODirectionEnum.输入输出)
  1129. {
  1130. uint IN_Waiting_Timeout = processParam.Value<uint>("IN_Waiting_Timeout");
  1131. AddTextEvent($"{stepIndex + 1}-{processName}", $"等待I/O输入信号{(IN_Waiting_Timeout > 0 ? $"(超时时长: {IN_Waiting_Timeout})" : "...")}");
  1132. string[] inValue = processParam.Value<JArray>("IN_OP_SHOW").ToObject<List<string>>().ToArray();
  1133. uint inWaitingTime = 0;
  1134. while (true)
  1135. {
  1136. if (isBreakProcessRun())
  1137. return stepIndex;
  1138. if (Util.compareIOInput(inValue, devContainer.devIOCard.DIData))
  1139. break;
  1140. Thread.Sleep(10);
  1141. inWaitingTime += 10;
  1142. if (IN_Waiting_Timeout > 0 && inWaitingTime >= IN_Waiting_Timeout)
  1143. {
  1144. AddTextEvent($"{stepIndex + 1}-{processName}", $"输入等待超时告警!", WarningEnum.High);
  1145. warning(WarningEnum.Low);//暂停
  1146. return stepIndex;
  1147. }
  1148. }
  1149. AddTextEvent($"{stepIndex + 1}-{processName}", $"I/O输入信号对比完成!");
  1150. }
  1151. if (direction == IODirectionEnum.输出 || direction == IODirectionEnum.输入输出)
  1152. devContainer.io_output($"{stepIndex + 1}-{processName}", processParam);
  1153. #endregion
  1154. break;
  1155. case "Axis":
  1156. #region
  1157. bool asynRun = processParam.Value<bool>("AsynRun");//异步
  1158. int AxisIndex = processParam.Value<int>("AxisIndex");
  1159. int DeviceType = processParam.Value<int>("DeviceType");
  1160. double VelLow = processParam.Value<double>("VelLow");
  1161. double VelHigh = processParam.Value<double>("VelHigh");
  1162. double Acc = processParam.Value<double>("Acc");
  1163. double Dec = processParam.Value<double>("Dec");
  1164. AxMoveMode MoveMode = (AxMoveMode)processParam.Value<int>("MoveMode");//绝对位置
  1165. double PPUValue = processParam.Value<double>("Value");
  1166. AddTextEvent($"{stepIndex + 1}-{processName}", $"轴{AxisIndex}准备({(MoveMode == AxMoveMode.MODE1_Abs ? "绝对" : "相对")})运动至{PPUValue}(当前轴状态:{((AxisState)devContainer.devAxis.AxState[AxisIndex]).ToString()})...");
  1167. ////移动Axis前等待厚度传感器收回
  1168. //if (!Config.SkipHeight)
  1169. //{
  1170. // while (devContainer.devHeight.getHeight() < (double)Math.Abs(Config.HeightDev_SafeValue))
  1171. // {
  1172. // if (isBreakProcessRun())
  1173. // return stepIndex;
  1174. // Thread.Sleep(10);
  1175. // }
  1176. //}
  1177. while (!devContainer.devAxis.isReady(AxisIndex))
  1178. {
  1179. Thread.Sleep(100);
  1180. if (isBreakProcessRun())
  1181. return stepIndex;
  1182. }
  1183. devContainer.devAxis.setAxisVelParam(VelLow, VelHigh, Acc, Dec, AxisIndex);
  1184. if (!devContainer.devAxis.move_ptp(AxisIndex, PPUValue, MoveMode))
  1185. {
  1186. AddTextEvent($"{stepIndex + 1}-{processName}", $"轴{AxisIndex}运动失败!", WarningEnum.Low);
  1187. warning(WarningEnum.Low);//终止
  1188. return stepIndex;
  1189. }
  1190. AddTextEvent($"{stepIndex + 1}-{processName}", $"等待轴{AxisIndex}运行完成...");
  1191. while (!asynRun && !devContainer.devAxis.isReady(AxisIndex))
  1192. {
  1193. Thread.Sleep(100);
  1194. if (isBreakProcessRun())
  1195. {
  1196. currProcessIndex = stepIndex + 1;
  1197. return stepIndex;
  1198. }
  1199. }
  1200. AddTextEvent($"{stepIndex + 1}-{processName}", $"轴{AxisIndex}运行完成,当前命令位置:{devContainer.devAxis.getCmdPos_mm(AxisIndex)},反馈位置:{devContainer.devAxis.getActualPos_mm(AxisIndex)}");
  1201. #endregion
  1202. break;
  1203. case "Light":
  1204. #region
  1205. if (Config.SkipLight)
  1206. {
  1207. AddTextEvent($"{stepIndex + 1}-{processName}", $"设备禁用,忽略此步骤!");
  1208. //setDgvContentCol(liStatocStepIndex, $"设备禁用,忽略此步骤!");
  1209. break;
  1210. }
  1211. int ChannelIndex = processParam.Value<int>("ChannelIndex"); //通道
  1212. int DigitalValue = processParam.Value<int>("DigitalValue"); //亮度
  1213. int nowDiaitalValue = devContainer.devLight.getDigitalValue(ChannelIndex);
  1214. AddTextEvent($"{stepIndex + 1}-{processName}", $"通道{ChannelIndex}当前值:{nowDiaitalValue},准备更新值:{DigitalValue}...");
  1215. devContainer.devLight.setDigitalValue(ChannelIndex, DigitalValue);
  1216. nowDiaitalValue = devContainer.devLight.getDigitalValue(ChannelIndex);
  1217. AddTextEvent($"{stepIndex + 1}-{processName}", $"通道{ChannelIndex}更新后当前值:{nowDiaitalValue}。");
  1218. #endregion
  1219. break;
  1220. case "Scanner_CC":
  1221. #region
  1222. if (Config.SkipScannerCC)
  1223. {
  1224. AddTextEvent($"{stepIndex + 1}-{processName}", $"设备禁用,忽略此步骤!");
  1225. //setDgvContentCol(liStatocStepIndex, $"设备禁用,忽略此步骤!");
  1226. break;
  1227. }
  1228. while (!devContainer.devAxis.isReady())//因启用轴异步功能,使用前需等待
  1229. {
  1230. Thread.Sleep(100);
  1231. if (isBreakProcessRun())
  1232. {
  1233. //currProcessIndex = stepIndex;//本工序没执行,step不变
  1234. return stepIndex;
  1235. }
  1236. }
  1237. float ExposureTimeCC = processParam.Value<float>("ExposureTime"); //曝光
  1238. float GainCC = processParam.Value<float>("Gain"); //增益
  1239. float ResultingFrameRateCC = processParam.Value<float>("ResultingFrameRate"); //帧率
  1240. AddTextEvent($"{stepIndex + 1}-{processName}", $"相机开始采集照片...");
  1241. devContainer.devScannerCC.setParam(ExposureTimeCC, GainCC, ResultingFrameRateCC);
  1242. AddTextEvent($"{stepIndex + 1}-{processName}", $"相机参数设置完成。");
  1243. AutoResetEvent endEventCC = new AutoResetEvent(false);
  1244. //devContainer.devScannerCC.ScanEvent = (num, bmp2) =>
  1245. //{
  1246. // AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片完成.");
  1247. // scannerCBmpQueue.Enqueue(bmp2,
  1248. // devContainer.devAxis.getActualPos_mm(0),
  1249. // devContainer.devAxis.getActualPos_mm(1))
  1250. // endEventCC.Set();//线程返回
  1251. //};
  1252. devContainer.devScannerCC.ScanEventPath += new System.Action<int, string>((num, path2) =>
  1253. {
  1254. AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片完成.");
  1255. scannerCBmpQueue.Enqueue(new scannerCBmpLoc(path2,
  1256. devContainer.devAxis.getActualPos_mm(0),
  1257. devContainer.devAxis.getActualPos_mm(1)));//Dequeue
  1258. AddTextEvent($"{stepIndex + 1}-{processName}", $"图像队列数量: {scannerCBmpQueue.Count}");
  1259. endEventCC.Set();//线程返回
  1260. });
  1261. if (!devContainer.devScannerCC.scan(1))//软触发拍照
  1262. {
  1263. devContainer.devScannerCC.ScanEventPath = null;
  1264. AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片失败!", WarningEnum.Low);
  1265. warning(WarningEnum.Low);//终止
  1266. return stepIndex;
  1267. }
  1268. if (!endEventCC.WaitOne(5000))
  1269. {
  1270. devContainer.devScannerCC.ScanEventPath = null;
  1271. AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片超时!", WarningEnum.Low);
  1272. warning(WarningEnum.Low);//终止
  1273. return stepIndex;
  1274. }
  1275. devContainer.devScannerCC.ScanEventPath = null;
  1276. #endregion
  1277. break;
  1278. case "Size":
  1279. #region
  1280. limitThresholdVal = processParam.Value<double>("LimitThresholdVal");
  1281. lowerThresholdVal = processParam.Value<double>("LowerThresholdVal");
  1282. int sizeIndex = processParam.Value<int>("Index");
  1283. double xPos = 0;
  1284. double yPos = 0;
  1285. if (scannerCBmpQueue.Count < 1)
  1286. {
  1287. AddTextEvent($"{stepIndex + 1}-{processName}", $"尺寸检测异常,无源图像!!", WarningEnum.Low);
  1288. warning(WarningEnum.Low);//暂停
  1289. return stepIndex;
  1290. }
  1291. var bmpCBmpQueue = scannerCBmpQueue.Dequeue();
  1292. AddTextEvent($"{stepIndex + 1}-{processName}", $"开始尺寸检测,index:{sizeIndex},图像队列数量: {scannerCBmpQueue.Count}...");
  1293. //需要偏移校正,index=0时不能异步
  1294. endEvent = new AutoResetEvent(false);
  1295. sizeBmpNum++;
  1296. devContainer.libSize.add(new SizeTask()
  1297. {
  1298. index = sizeIndex,
  1299. stepIndex = stepIndex,//仅供回调时用
  1300. engineName = processParam.Value<string>("EngineName"),
  1301. bmp = bmpCBmpQueue.BMP,//bmp/file_path二选一,优先bmp
  1302. file_path = bmpCBmpQueue.Path,
  1303. posX = bmpCBmpQueue.PosX,
  1304. posY = bmpCBmpQueue.PosY,
  1305. MarkPointList= convert(currProductMarkList),
  1306. finishEvent = (res) =>
  1307. {
  1308. if(res.isSucceed)
  1309. {
  1310. AddTextEvent($"{stepIndex + 1}-{processName}", $"尺寸检测完成,index:{res.index}。");
  1311. }
  1312. else
  1313. {
  1314. //setDgvContentCol(liStatocStepIndex, $"失败:{res.resultInfo}");
  1315. AddTextEvent($"{res.stepIndex + 1}-{processName}", $"尺寸检测失败index:{res.index}:{res.resultInfo}");
  1316. //warning(WarningEnum.Low);//暂停 这里不能暂停,stepIndex和scannerBmpQueue队列也不对了
  1317. }
  1318. sizeBmpNumResult++;
  1319. string sizeSavePath = Config.SizeBmp_Path + "\\" + DateTime.Now.ToString("yyyyMMdd") + "\\";
  1320. if (!Directory.Exists(sizeSavePath))
  1321. Directory.CreateDirectory(sizeSavePath);
  1322. sizeSavePath += $"SN{this.SN}_I{res.index}_X{res.posX}_Y{res.posY}.bmp";
  1323. if (res.bmp != null)
  1324. {
  1325. res.bmp.Save(sizeSavePath,ImageFormat.Bmp);
  1326. res.bmp.Dispose();
  1327. res.bmp = null;
  1328. }
  1329. else
  1330. {
  1331. //File.Copy(res.file_path, defectFileName + ".bmp", true);
  1332. API.CopyFile(res.file_path, sizeSavePath, false);//更快
  1333. File.Delete(res.file_path);
  1334. }
  1335. }
  1336. });
  1337. #endregion
  1338. break;
  1339. case "For":
  1340. #region
  1341. long UniqueId = processParam.Value<long>("UniqueId");
  1342. int GotoStepIndex = processParam.Value<int>("GotoStepIndex");//1-n
  1343. int LimitNum = processParam.Value<int>("LimitNum");//1-n
  1344. bool Reset = processParam.Value<bool>("Reset");
  1345. if (GotoStepIndex - 1 == stepIndex)
  1346. {
  1347. AddTextEvent($"{stepIndex + 1}-{processName}", $"For死循环!!!");
  1348. warning(WarningEnum.High);
  1349. return stepIndex;
  1350. }
  1351. if (!devContainer.libFor.dicData.ContainsKey(UniqueId))
  1352. devContainer.libFor.dicData.Add(UniqueId, 0);
  1353. //
  1354. int Num = devContainer.libFor.dicData[UniqueId];
  1355. Num++;
  1356. if (Num <= LimitNum)
  1357. {
  1358. if (Num == LimitNum)
  1359. {
  1360. //setDgvContentCol(liStatocStepIndex, $"第[{Num}/{LimitNum}]次,循环完成");
  1361. AddTextEvent($"{stepIndex + 1}-{processName}", $"第[{Num}/{LimitNum}]次,循环完成。");
  1362. }
  1363. else
  1364. {
  1365. //setDgvContentCol(liStatocStepIndex, $"第[{Num}/{LimitNum}]次");
  1366. AddTextEvent($"{stepIndex + 1}-{processName}", $"第[{Num}/{LimitNum}]次跳转到步骤[{GotoStepIndex}]...");
  1367. stepIndex = GotoStepIndex - 2;
  1368. }
  1369. devContainer.libFor.dicData[UniqueId] = Num;
  1370. }
  1371. else
  1372. {
  1373. //setDgvContentCol(liStatocStepIndex, $"已失效不执行");
  1374. AddTextEvent($"{stepIndex + 1}-{processName}", $"本循环已失效不执行!");
  1375. }
  1376. //达到limit重置0
  1377. if (devContainer.libFor.dicData[UniqueId] >= LimitNum && Reset)
  1378. {
  1379. devContainer.libFor.dicData[UniqueId] = 0;
  1380. //setDgvContentCol(liStatocStepIndex, $"第[0/{LimitNum}]次");
  1381. AddTextEvent($"{stepIndex + 1}-{processName}", $"计数器已重置。");
  1382. }
  1383. #endregion
  1384. break;
  1385. case "If":
  1386. #region
  1387. long UniqueId_if = processParam.Value<long>("UniqueId");
  1388. int GotoStepIndex_if = processParam.Value<int>("GotoStepIndex");//1-n
  1389. int LimitNum_if = processParam.Value<int>("LimitNum");//1-n
  1390. bool Reset_if = processParam.Value<bool>("Reset");
  1391. if (GotoStepIndex_if - 1 == stepIndex)
  1392. {
  1393. AddTextEvent($"{stepIndex + 1}-{processName}", $"If死循环,不可自我跳转!!!");
  1394. warning(WarningEnum.High);
  1395. return stepIndex;
  1396. }
  1397. //
  1398. if (!devContainer.libIF.dicData.ContainsKey(UniqueId_if))
  1399. devContainer.libIF.dicData.Add(UniqueId_if, 0);
  1400. //
  1401. int Num_if = devContainer.libIF.dicData[UniqueId_if];
  1402. Num_if++;
  1403. if (Num_if <= LimitNum_if)
  1404. {
  1405. if (Num_if == LimitNum_if)
  1406. {
  1407. //setDgvContentCol(liStatocStepIndex, $"第[{Num_if}/{LimitNum_if}]次,跳转至[{GotoStepIndex_if}]");
  1408. AddTextEvent($"{stepIndex + 1}-{processName}", $"计数器[{Num_if}/{LimitNum_if}],跳转至步骤[{GotoStepIndex_if}]...");
  1409. stepIndex = GotoStepIndex_if - 2;
  1410. }
  1411. else
  1412. {
  1413. //setDgvContentCol(liStatocStepIndex, $"第[{Num_if}/{LimitNum_if}]次,不跳转");
  1414. AddTextEvent($"{stepIndex + 1}-{processName}", $"计数器[{Num_if}/{LimitNum_if}],不跳转。");
  1415. }
  1416. //
  1417. devContainer.libIF.dicData[UniqueId_if] = Num_if;
  1418. }
  1419. else
  1420. {
  1421. //setDgvContentCol(liStatocStepIndex, $"已失效不执行");
  1422. AddTextEvent($"{stepIndex + 1}-{processName}", $"本IF已失效不执行。");
  1423. }
  1424. //达到limit重置0
  1425. if (devContainer.libIF.dicData[UniqueId_if] >= LimitNum_if && Reset_if)
  1426. {
  1427. devContainer.libIF.dicData[UniqueId_if] = 0;
  1428. //setDgvContentCol(liStatocStepIndex, $"第[0/{LimitNum_if}]次");
  1429. AddTextEvent($"{stepIndex + 1}-{processName}", $"计数器已重置。");
  1430. }
  1431. #endregion
  1432. break;
  1433. default:
  1434. AddTextEvent($"{stepIndex + 1}-{processName}", $"未知工序:{processInfo.ProcessCode}");
  1435. warning(WarningEnum.High);
  1436. return stepIndex;
  1437. }
  1438. if (sleepLater > 0) Thread.Sleep((int)sleepLater);
  1439. }
  1440. //============结束,判断是否自动下料
  1441. if (stepIndex == processList.Count - 1)
  1442. {
  1443. setButtonEnabled(tsbtnPause, false);//后面手动模式暂停无意义
  1444. //等待Mark图处理完成
  1445. while (sizeBmpNum != sizeBmpNumResult)
  1446. Thread.Sleep(100);
  1447. //
  1448. this.Invoke(new System.Action(() =>
  1449. {
  1450. this.chkLaser.Checked = true;
  1451. this.gpbXYAxis.Enabled = gpbZAxis.Enabled = true;
  1452. }));
  1453. AddTextEvent("完成", $"Mark点计算工序结束,开始转换主机台缺陷坐标...");
  1454. convert2LocXY();
  1455. AddTextEvent("完成", $"开始进行人工修复...");
  1456. currentPT = CurrentPTEnum.MakeTag;
  1457. currentState = CurrentStateEnum.打标中;
  1458. setButtonEnabled(tsbtnGoDownPT, true);
  1459. setButtonEnabled(tsbtnReset, true);
  1460. //==
  1461. currProcessIndex = -1;
  1462. return -1;
  1463. }
  1464. else //继续
  1465. {
  1466. return ++stepIndex;
  1467. //return nextProcess(model, ++stepIndex);
  1468. }
  1469. }
  1470. catch (Exception ex)
  1471. {
  1472. if (devContainer.devAxis.isError())
  1473. {
  1474. AddTextEvent("工序", $"[{stepIndex}] Err:" + ex.Message);
  1475. warning(WarningEnum.High);
  1476. }
  1477. else
  1478. {
  1479. AddTextEvent("工序", $"[{stepIndex}] Err:" + ex.Message);
  1480. warning(WarningEnum.Low);
  1481. }
  1482. return -2;
  1483. }
  1484. }
  1485. #endregion
  1486. #region Fun
  1487. /// <summary>
  1488. /// 全局中断
  1489. /// </summary>
  1490. private void globalBreakEvent(int portIndex, byte data)
  1491. {
  1492. AddTextEvent("中断命令", $"{portIndex}-HEX:{Convert.ToString(data, 16)}");
  1493. if (compareIOInput(CMDName.启动按钮) && this.tsbtnStart.Enabled)
  1494. {
  1495. AddTextEvent("中断命令", $"启动-按钮");
  1496. startCommand();
  1497. AddTextEvent("中断命令", $"启动-完成");
  1498. }
  1499. else if (compareIOInput(CMDName.暂停按钮) && this.tsbtnPause.Enabled)
  1500. {
  1501. AddTextEvent("中断命令", $"暂停-按钮");
  1502. warning(WarningEnum.Low, false);
  1503. AddTextEvent("中断命令", $"暂停-完成");
  1504. }
  1505. else if (compareIOInput(CMDName.完成下料) && this.tsbtnGoDownPT.Enabled)
  1506. {
  1507. AddTextEvent("中断命令", $"完成-按钮");
  1508. gotoDownPT();
  1509. AddTextEvent("中断命令", $"完成-完成");
  1510. }
  1511. else if (compareIOInput(CMDName.下光源按钮))
  1512. {
  1513. AddTextEvent("中断命令", $"下光源-按钮");
  1514. openLowerLight();
  1515. AddTextEvent("中断命令", $"下光源-完成");
  1516. }
  1517. else if (compareIOInput(CMDName.上一张图) && currentState == CurrentStateEnum.打标中 && currDefectIndex > 0)
  1518. {
  1519. AddTextEvent("中断命令", $"上一张图-按钮");
  1520. gotoPrePic();
  1521. AddTextEvent("中断命令", $"上一张图-完成");
  1522. }
  1523. else if (compareIOInput(CMDName.下一张图) && currentState == CurrentStateEnum.打标中 && currDefectIndex < defectList.Count - 1)
  1524. {
  1525. AddTextEvent("中断命令", $"下一张图-按钮");
  1526. gotoNextPic();
  1527. AddTextEvent("中断命令", $"下一张图-完成");
  1528. }
  1529. else if (compareIOInput(CMDName.上一缺陷) && currentState == CurrentStateEnum.打标中 && currDefectIndex > 0)
  1530. {
  1531. AddTextEvent("中断命令", $"上一缺陷-按钮");
  1532. gotoDefctListIndex(--currDefectIndex, currDefectIndex + 1);
  1533. AddTextEvent("中断命令", $"上一缺陷-完成");
  1534. }
  1535. else if (compareIOInput(CMDName.下一缺陷) && currentState == CurrentStateEnum.打标中 && currDefectIndex < defectList.Count - 1)
  1536. {
  1537. AddTextEvent("中断命令", $"下一缺陷-按钮");
  1538. gotoDefctListIndex(++currDefectIndex, currDefectIndex - 1);
  1539. AddTextEvent("中断命令", $"下一缺陷-完成");
  1540. }
  1541. else if (compareIOInput(CMDName.复位按钮) && this.tsbtnReset.Enabled)
  1542. {
  1543. AddTextEvent("中断命令", $"复位-按钮");
  1544. resetCommand();
  1545. AddTextEvent("中断命令", $"复位-完成");
  1546. }
  1547. //
  1548. if (devContainer.state && warningLevel == WarningEnum.Normal
  1549. && currentState == CurrentStateEnum.打标中 && currentPT == CurrentPTEnum.MakeTag)
  1550. {
  1551. int axisIndex = 0;
  1552. bool isJog_axis = (AxisState)devContainer.devAxis.AxState[axisIndex] == AxisState.STA_AX_EXT_JOG;
  1553. if(!handleJog(axisIndex, CMDName.手柄左移,1) && !handleJog(axisIndex, CMDName.手柄右移,0))
  1554. {
  1555. if (isJog_axis)
  1556. {
  1557. AddTextEvent("中断命令", $"轴{axisIndex}关闭JOG模式!");
  1558. devContainer.devAxis.closeJogMode(axisIndex);//关闭jog时自动停止
  1559. }
  1560. }
  1561. axisIndex = 1;
  1562. isJog_axis = (AxisState)devContainer.devAxis.AxState[axisIndex] == AxisState.STA_AX_EXT_JOG;
  1563. if (!handleJog(axisIndex, CMDName.手柄前移,0) && !handleJog(axisIndex, CMDName.手柄后移,1))
  1564. {
  1565. if (isJog_axis)
  1566. {
  1567. AddTextEvent("中断命令", $"轴{axisIndex}关闭JOG模式!");
  1568. devContainer.devAxis.closeJogMode(axisIndex);//关闭jog时自动停止
  1569. }
  1570. }
  1571. }
  1572. }
  1573. private bool compareIOInput(CMDName key)
  1574. {
  1575. JObject joJson = Config.CMDProcess[key];
  1576. IODirectionEnum direction = (IODirectionEnum)joJson.Value<int>("Direction");
  1577. if (direction == IODirectionEnum.输入 || direction == IODirectionEnum.输入输出)
  1578. {
  1579. return Util.compareIOInput(
  1580. joJson.Value<JArray>("IN_OP_SHOW").ToObject<List<string>>().ToArray(),
  1581. devContainer.devIOCard.DIData);
  1582. }
  1583. return false;
  1584. }
  1585. private bool handleJog(int axisIndex,CMDName cmd,ushort dir)
  1586. {
  1587. if (compareIOInput(cmd) && currentState == CurrentStateEnum.打标中)
  1588. {
  1589. AddTextEvent("中断命令", $"{cmd.ToString()}:开");
  1590. devContainer.devAxis.openJogMode(axisIndex);
  1591. devContainer.devAxis.setAxisVelParam((double)Config.Axis_JogVelLow[axisIndex], (double)Config.Axis_JogVelLow[axisIndex],
  1592. (double)Config.Axis_JogVelLow[axisIndex], (double)Config.Axis_JogVelLow[axisIndex], axisIndex, true);
  1593. devContainer.devAxis.jog(axisIndex, dir);//jog move
  1594. return true;
  1595. }
  1596. return false;
  1597. }
  1598. /// <summary>
  1599. /// 报警,只响应low,high
  1600. /// </summary>
  1601. private void warning(WarningEnum level, bool buzzer = true)
  1602. {
  1603. if (level == WarningEnum.Normal)
  1604. return;
  1605. lock (myLock)
  1606. warningLevel = level;
  1607. if (level == WarningEnum.Low)//暂停
  1608. {
  1609. currentState = CurrentStateEnum.暂停;
  1610. pauseCommand(buzzer);
  1611. }
  1612. else if (level == WarningEnum.High)//急停
  1613. {
  1614. currentState = CurrentStateEnum.急停;
  1615. devContainer.devAxis.stopNow();
  1616. stopNowCommand();
  1617. }
  1618. //启用报警消除按钮
  1619. setButtonEnabled(tsbtnWarning, true);
  1620. }
  1621. private void resetUIValue()
  1622. {
  1623. currProcessIndex = -1;
  1624. currProductModel = null;
  1625. currProductMarkList = null;
  1626. scannerCBmpQueue.Clear();
  1627. defectBmpsDir.Clear();
  1628. this.Invoke(new System.Action(() =>
  1629. {
  1630. cbxSN.Enabled = false;
  1631. cbxSN.Text = txtProductCode.Text = txtProductName.Text = txtBatchId.Text =
  1632. txtBatchId.Text = txtCreateTime.Text = "";
  1633. this.gpbDefectList.Text = $"缺陷明细";
  1634. this.dgvProcess.DataSource = null;
  1635. this.lstLog.Items.Clear();
  1636. this.pictureBox1.Image = null;
  1637. pictureBox1.Refresh();
  1638. }));
  1639. }
  1640. private void delDirFiles(string dirPath)
  1641. {
  1642. try
  1643. {
  1644. var files = Directory.EnumerateFiles(dirPath, "*.bmp", SearchOption.TopDirectoryOnly);
  1645. foreach (string file in files)
  1646. API.DeleteFile(file);
  1647. }
  1648. catch (Exception ex)
  1649. {
  1650. }
  1651. }
  1652. public delegate void AddTextDelegate(string tag, string msg, WarningEnum level);
  1653. /// <summary>
  1654. /// 异步输出日志
  1655. /// </summary>
  1656. /// <param name="tag">模板标识</param>
  1657. /// <param name="msg">内容</param>
  1658. /// <param name="type"></param>
  1659. private void AddTextEvent(string tag, string msg, WarningEnum level = WarningEnum.Normal)
  1660. {
  1661. try
  1662. {
  1663. if (InvokeRequired)
  1664. {
  1665. Invoke(new AddTextDelegate(AddTextEvent), new object[]
  1666. {
  1667. tag,
  1668. msg,
  1669. level
  1670. });
  1671. }
  1672. else
  1673. {
  1674. if (tag != null && tag != "")
  1675. tag = $" - [{tag}]";
  1676. var now = DateTime.Now;
  1677. msg = now.ToString("HH:mm:ss fff") + tag + " - " + msg;
  1678. //cont = MyHelper.subString(cont, 300);
  1679. //写日志,warn和error日志直接写
  1680. writeLog(now, level, msg);
  1681. //
  1682. //if (type > 0)
  1683. // cont = $"<color=\"{(type == 1 ? "Yellow" : "Red")}\">{cont}</color>";
  1684. msg = (level == WarningEnum.Normal ? "B" : level == WarningEnum.Low ? "Y" : "R") + msg;
  1685. this.Invoke(new System.Action(() =>
  1686. {
  1687. if (this.lstLog.Items.Count > 1000)
  1688. this.lstLog.Items.Clear();
  1689. lstLog.Items.Insert(0, msg);
  1690. }));
  1691. //日志滚动
  1692. //lstLog.SelectedIndex = lstLog.Items.Count - 1;
  1693. }
  1694. }
  1695. catch (Exception ex)
  1696. {
  1697. //MessageBox.Show("AddTextEvent ex=(" + ex.Message + ")", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, 0);
  1698. }
  1699. }
  1700. private void lstLog_DrawItem(object sender, DrawItemEventArgs e)
  1701. {
  1702. e.DrawBackground();
  1703. if (e.Index < 0) return;
  1704. string str = lstLog.Items[e.Index].ToString();
  1705. e.Graphics.DrawString(str.Substring(1), e.Font,
  1706. new SolidBrush(str[0] == 'R' ? Color.Red : (str[0] == 'Y' ? Color.Orange : Color.Black)),
  1707. e.Bounds);
  1708. }
  1709. private void writeLog(DateTime now, WarningEnum level, string text)
  1710. {
  1711. string directory = Config.LogPath + "\\" + DateTime.Now.ToString("yyyyMM") + "\\";
  1712. //if (type == 0) directory = Application.StartupPath + "\\Log\\Info\\";
  1713. //else if (type == 1) directory = Application.StartupPath + "\\Log\\Warn\\";
  1714. //else directory = Application.StartupPath + "\\Log\\Error\\";
  1715. if (!System.IO.Directory.Exists(directory))
  1716. System.IO.Directory.CreateDirectory(directory);
  1717. File.AppendAllText(directory + now.ToString("yyyyMMdd") + ".log", text + "\r\n");
  1718. }
  1719. #endregion
  1720. private void tsbtnOpenDev_Click(object sender, EventArgs e)
  1721. {
  1722. Config.LoadAllConfig();
  1723. if(string.IsNullOrWhiteSpace(Config.DBConStr)|| string.IsNullOrWhiteSpace(Config.ServerIP))
  1724. {
  1725. AddTextEvent("设备启动", "启动失败,请先设置数据库和主机台通讯地址!",WarningEnum.High);
  1726. return;
  1727. }
  1728. //设置程序最小/大线程池
  1729. // Get the current settings.
  1730. int minWorker, minIOC;
  1731. ThreadPool.GetMinThreads(out minWorker, out minIOC);
  1732. ThreadPool.SetMinThreads(25, minIOC);
  1733. //ThreadPool.SetMaxThreads(256, 256);
  1734. this.tsbtnOpenDev.Enabled = false;
  1735. scannerCBmpQueue.Clear();
  1736. //scannerCBmpIndex = 0;
  1737. this.resetUIValue();
  1738. currentState = CurrentStateEnum.等待复位;
  1739. warningLevel = WarningEnum.Normal;
  1740. currentPT = CurrentPTEnum.InitPT;
  1741. this.tsbtnWarning.Enabled = this.tsbtnGoDownPT.Enabled = this.tsbtnStart.Enabled
  1742. = this.tsbtnStopNow.Enabled = this.tsbtnPause.Enabled = this.tsbtnReset.Enabled
  1743. = this.gpbXYAxis.Enabled = gpbZAxis.Enabled = false;
  1744. //后台线程回调事件
  1745. devContainer.StateChange = (state, msg) =>
  1746. {
  1747. if (state)
  1748. {
  1749. //全局中断
  1750. devContainer.devIOCard.INEvent = globalBreakEvent;
  1751. devContainer.OutDebugEvent = (tag, debugInfo) =>
  1752. {
  1753. AddTextEvent(tag, debugInfo);
  1754. };
  1755. //
  1756. AddTextEvent("设备启动", "请先进行复位操作!");
  1757. this.Invoke(new System.Action(() =>
  1758. {
  1759. this.tsbtnReset.Enabled = true;
  1760. tsbtnWarning.Enabled = this.tsbtnStart.Enabled = this.tsbtnGoDownPT.Enabled
  1761. = this.tsbtnPause.Enabled = this.tsbtnStopNow.Enabled = false;
  1762. this.chkLaser.Enabled = true;
  1763. this.tsbtnOpenDev.Enabled = true;
  1764. this.tsbtnOpenDev.Visible = false;
  1765. this.tsbtnCloseDev.Visible = true;
  1766. }));
  1767. timer.Elapsed += Timer_Elapsed;
  1768. timer.Interval = 500;
  1769. timer.Start();
  1770. }
  1771. else
  1772. {
  1773. AddTextEvent("设备启动", $"启动失败,{msg}", WarningEnum.High);
  1774. this.Invoke(new System.Action(() =>
  1775. {
  1776. this.chkLaser.Enabled = false;
  1777. this.tsbtnOpenDev.Enabled = true;
  1778. this.tsbtnOpenDev.Visible = true;
  1779. this.tsbtnCloseDev.Visible = false;
  1780. }));
  1781. }
  1782. };
  1783. devContainer.WarningEvent = (level, msg) =>
  1784. {
  1785. AddTextEvent("设备事件", msg, level);
  1786. if (level == WarningEnum.High)
  1787. warning(level, true);
  1788. };
  1789. AddTextEvent("设备启动", "启动");
  1790. devContainer.start(IntPtr.Zero, IntPtr.Zero);
  1791. }
  1792. private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
  1793. {
  1794. this.Invoke(new System.Action(() =>
  1795. {
  1796. this.tsAxisState.Text = $"[命令位:{devContainer.devAxis.CmdPos[0]} 反馈位:{devContainer.devAxis.ActualPos[0]} ({((AxisState)devContainer.devAxis.AxState[0]).ToString()})] | " +
  1797. $"[命令位:{devContainer.devAxis.CmdPos[1]} 反馈位:{devContainer.devAxis.ActualPos[1]} ({((AxisState)devContainer.devAxis.AxState[1]).ToString()})] | " +
  1798. $"[命令位:{devContainer.devAxis.CmdPos[2]} 反馈位:{devContainer.devAxis.ActualPos[2]} ({((AxisState)devContainer.devAxis.AxState[2]).ToString()})] | " +
  1799. $"[命令位:{devContainer.devAxis.CmdPos[3]} 反馈位:{devContainer.devAxis.ActualPos[3]} ({((AxisState)devContainer.devAxis.AxState[3]).ToString()})] | ";
  1800. }));
  1801. }
  1802. private void tsbtnCloseDev_Click(object sender, EventArgs e)
  1803. {
  1804. AddTextEvent("设备停止", $"设备停止...");
  1805. this.tsbtnOpenDev.Visible = true;
  1806. this.tsbtnCloseDev.Visible = false;
  1807. this.chkLaser.Enabled = false;
  1808. this.tsbtnReset.Enabled = tsbtnWarning.Enabled = this.tsbtnStart.Enabled = this.tsbtnGoDownPT.Enabled
  1809. = this.tsbtnPause.Enabled = this.tsbtnStopNow.Enabled
  1810. = this.gpbXYAxis.Enabled = this.gpbZAxis.Enabled = false;
  1811. if (devContainer.state)
  1812. {
  1813. devContainer.devIOCard.reset();
  1814. devContainer.io_output(CMDName.IO默认输出);
  1815. }
  1816. timer.Stop();
  1817. devContainer.stop();
  1818. }
  1819. private void dgvProcess_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
  1820. {
  1821. if (e.RowIndex < 0 || !devContainer.state || currentState != CurrentStateEnum.打标中)
  1822. return;
  1823. int preIndex = currDefectIndex;
  1824. currDefectIndex = e.RowIndex;
  1825. gotoDefctListIndex(currDefectIndex, preIndex);
  1826. }
  1827. private void 流程管理ToolStripMenuItem_Click(object sender, EventArgs e)
  1828. {
  1829. if (devContainer.state)
  1830. {
  1831. MessageBox.Show("请先停止设备,再进行流程修改!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  1832. return;
  1833. }
  1834. FrmStepList frm = new FrmStepList();
  1835. frm.ShowDialog();
  1836. }
  1837. private void 产品管理ToolStripMenuItem_Click(object sender, EventArgs e)
  1838. {
  1839. //if (devContainer.state)
  1840. //{
  1841. // MessageBox.Show("请先停止设备,再进行产品修改!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  1842. // return;
  1843. //}
  1844. FrmProductList frm = new FrmProductList();
  1845. frm.ShowDialog();
  1846. }
  1847. private void loadOrderSNList()
  1848. {
  1849. try
  1850. {
  1851. //ConditionalType: 0-等于 3-大于等于 5-小于等于 6-IN "CSharpTypeName":"int"
  1852. JArray domainList =new JArray();
  1853. domainList.Add(new JObject()
  1854. {
  1855. {"FieldName","State" },
  1856. {"FieldValue",0 },//0-初始; 5-已检测
  1857. {"ConditionalType",0 },
  1858. });
  1859. domainList.Add(new JObject()
  1860. {
  1861. {"FieldName","DefectCount" },
  1862. {"FieldValue",1 },
  1863. {"ConditionalType",3 },
  1864. });
  1865. domainList.Add(new JObject()
  1866. {
  1867. {"FieldName","CreateTime" },
  1868. {"FieldValue",DateTime.Now.AddDays(-1) },
  1869. {"ConditionalType",3 },
  1870. });
  1871. var list = svcOrder.GetList("Order", "SN", domainList.ToString(), "SN DESC");
  1872. List<string> snList = new List<string>();
  1873. foreach(var item in list)
  1874. snList.Add(item.ToList().Select(m => m.Value.ToString()).ToArray()[0]);
  1875. this.Invoke(new System.Action(() =>
  1876. {
  1877. this.cbxSN.Text = "";
  1878. this.cbxSN.Items.Clear();
  1879. this.cbxSN.Items.AddRange(snList.ToArray());
  1880. }));
  1881. }
  1882. catch (Exception ex)
  1883. {
  1884. AddTextEvent("启动", "加载已检测网版编码失败:" + ex.Message, WarningEnum.Low);
  1885. }
  1886. }
  1887. private void splitContainer1_SizeChanged(object sender, EventArgs e)
  1888. {
  1889. this.gpbProductInfo.Width = this.gpbDefectList.Width = splitContainer1.Panel2.Width-10;
  1890. this.gpbProductInfo.Top = this.splitContainer1.ClientSize.Height- this.gpbProductInfo.Height;
  1891. this.gpbDefectList.Height = this.gpbProductInfo.Top-10;
  1892. this.cbxSN.Width= this.txtProductCode.Width = this.txtProductName.Width
  1893. = this.txtBatchId.Width = this.txtCreateTime.Width = this.gpbProductInfo.Width- this.cbxSN.Left-5;
  1894. //this.dgvProcess.Width = gpbDefectList.Width - 10;
  1895. //this.dgvProcess.Height = this.splitContainer1.ClientSize.Height - this.gpbProductInfo.Height;
  1896. //
  1897. }
  1898. private void splitContainer2_SizeChanged(object sender, EventArgs e)
  1899. {
  1900. this.tsbtnPause.Left = this.tsbtnGoDownPT.Left = this.splitContainer1.SplitterDistance- this.tsbtnPause.Width - 10;
  1901. this.gpbZAxis.Left = this.tsbtnPause.Left - this.gpbZAxis.Width-10;
  1902. this.gpbXYAxis.Left = this.gpbZAxis.Left - this.gpbXYAxis.Width - 10;
  1903. this.gpbLog.Width = this.gpbXYAxis.Left - 10;
  1904. this.splitContainer2.SplitterDistance = this.ClientRectangle.Height - gpbLog.Height - 10;
  1905. }
  1906. private void tsbtnReset_Click(object sender, EventArgs e)
  1907. {
  1908. Task.Run(() => this.resetCommand());
  1909. }
  1910. private void tsbtnStart_Click(object sender, EventArgs e)
  1911. {
  1912. Task.Run(() => this.startCommand());
  1913. }
  1914. private void tsbtnPause_Click(object sender, EventArgs e)
  1915. {
  1916. warning(WarningEnum.Low, false);
  1917. }
  1918. private void tsbtnGoDownPT_Click(object sender, EventArgs e)
  1919. {
  1920. AddTextEvent("下料", "准备下料。。。");
  1921. // Task.Run(() => this.gotoDownPT());
  1922. gotoDownPT();
  1923. }
  1924. private void tsbtnWarning_Click(object sender, EventArgs e)
  1925. {
  1926. //if (warningLevel == WarningEnum.Normal)
  1927. //{
  1928. // tsbtnWarning.Enabled = false;
  1929. // return;
  1930. //}
  1931. //重置AXIS状态
  1932. devContainer.devAxis.resetAxisState();
  1933. if (!devContainer.devAxis.isReady())
  1934. {
  1935. AddTextEvent("解除报警", "轴状态未恢复,解除报警失败!", warningLevel);
  1936. return;
  1937. }
  1938. if (devContainer.devAxis.isError())
  1939. {
  1940. AddTextEvent("解除报警", "轴IO状态异常,解除报警失败!", warningLevel);
  1941. return;
  1942. }
  1943. //if (!this.disableDoorSensor && compareIOInput(CMDName.门磁告警输入))
  1944. //{
  1945. // AddTextEvent("解除报警", "门磁告警未清除 ,解除报警失败!", warningLevel);
  1946. // return;
  1947. //}
  1948. //if (!this.disableDoorSensor && compareIOInput(CMDName.喷墨告警输入))
  1949. //{
  1950. // AddTextEvent("解除报警", "喷墨告警输入未清除 ,解除报警失败!", warningLevel);
  1951. // return;
  1952. //}
  1953. ////关闭蜂鸣器
  1954. //devContainer.io_output(CMDName.蜂鸣器输出, false, true, 0);
  1955. //devContainer.io_output(CMDName.红灯输出, false, true, 0);
  1956. //devContainer.io_output(CMDName.复位按钮, false, true, 0);
  1957. if (warningLevel == WarningEnum.High)
  1958. {
  1959. AddTextEvent("解除报警", "急停告警已解除,但必需进行复位操作!", warningLevel);
  1960. currentState = CurrentStateEnum.等待复位;
  1961. this.tsbtnReset.Enabled = true;
  1962. tsbtnWarning.Enabled = this.tsbtnStart.Enabled = this.tsbtnGoDownPT.Enabled
  1963. = this.tsbtnPause.Enabled = this.tsbtnStopNow.Enabled = false;
  1964. }
  1965. else
  1966. {
  1967. //devContainer.io_output(CMDName.黄灯输出);
  1968. AddTextEvent("解除报警", "告警已解除,请继续选择下一步操作!", warningLevel);
  1969. if (currentPT == CurrentPTEnum.MakeTag)
  1970. currentState = CurrentStateEnum.打标中;
  1971. else
  1972. currentState = CurrentStateEnum.等待启动;
  1973. tsbtnWarning.Enabled = false;
  1974. this.tsbtnStart.Enabled = this.tsbtnGoDownPT.Enabled = true;
  1975. this.tsbtnReset.Enabled = this.tsbtnPause.Enabled = this.tsbtnStopNow.Enabled = true;
  1976. }
  1977. warningLevel = WarningEnum.Normal;
  1978. }
  1979. private void 测试ToolStripMenuItem_Click(object sender, EventArgs e)
  1980. {
  1981. //devContainer.start(IntPtr.Zero, IntPtr.Zero);
  1982. //devContainer.state = true;
  1983. //currentState = CurrentStateEnum.等待扫码;
  1984. //cbxSN.Enabled = true;
  1985. //runStep();
  1986. //Bitmap bmp = (Bitmap)Bitmap.FromFile(Application.StartupPath + "\\test.bmp");
  1987. //AddTextEvent("", $"{this.splitContainer1.Width},{this.pnlPic.Width},bmp:{bmp.Width}");
  1988. //pnlPic.BackColor = Color.Red;
  1989. //reloadPic(bmp);
  1990. //for (int i = 0; i < 100; i++)
  1991. // this.dgvProcess.Rows.Add(i, i, i, i, i, i, i, i, i, i, i);
  1992. //this.dgvProcess.Rows[1].DefaultCellStyle.BackColor = Color.LightGreen;
  1993. //loadOrderSNList();
  1994. }
  1995. private void btnFront_MouseDown(object sender, MouseEventArgs e)
  1996. {
  1997. if (devContainer.state && currentState == CurrentStateEnum.打标中)
  1998. {
  1999. ushort dir;
  2000. int axisIndex;
  2001. PictureBox btn = sender as PictureBox;
  2002. switch (btn.Name)
  2003. {
  2004. case "btnFront":
  2005. dir = 1;
  2006. axisIndex = 1;
  2007. break;
  2008. case "btnBack":
  2009. dir = 0;
  2010. axisIndex = 1;
  2011. break;
  2012. case "btnLeft":
  2013. dir = 1;
  2014. axisIndex = 0;
  2015. break;
  2016. case "btnRight":
  2017. dir = 0;
  2018. axisIndex = 0;
  2019. break;
  2020. case "btnZUp":
  2021. dir = 0;
  2022. axisIndex = 2;
  2023. break;
  2024. case "btnZDown":
  2025. dir = 1;
  2026. axisIndex = 2;
  2027. break;
  2028. default:
  2029. return;
  2030. }
  2031. //
  2032. devContainer.devAxis.openJogMode(axisIndex);
  2033. devContainer.devAxis.setAxisVelParam((double)Config.Axis_JogVelLow[axisIndex], (double)Config.Axis_JogVelLow[axisIndex],
  2034. (double)Config.Axis_JogVelLow[axisIndex], (double)Config.Axis_JogVelLow[axisIndex], axisIndex, true);
  2035. devContainer.devAxis.jog(axisIndex, dir);//jog move
  2036. }
  2037. }
  2038. private void btnFront_MouseUp(object sender, MouseEventArgs e)
  2039. {
  2040. devContainer.devAxis.closeJogMode();
  2041. }
  2042. private void chkLaser_CheckedChanged(object sender, EventArgs e)
  2043. {
  2044. if (!devContainer.state) return;
  2045. if(chkLaser.Checked)
  2046. devContainer.io_output(CMDName.激光灯输出);
  2047. else
  2048. devContainer.io_output(CMDName.激光灯输出, false, true, 0);
  2049. }
  2050. private void tsbtnLog_Click(object sender, EventArgs e)
  2051. {
  2052. if (string.IsNullOrWhiteSpace(Config.LogPath)) return;
  2053. string lsPath = (Config.LogPath + "\\" + DateTime.Now.ToString("yyyyMM") + "\\").Replace("\\\\", "\\");
  2054. if (!Directory.Exists(lsPath))
  2055. Directory.CreateDirectory(lsPath);
  2056. System.Diagnostics.Process.Start("explorer.exe", lsPath);
  2057. }
  2058. private void FrmMain_KeyUp(object sender, KeyEventArgs e)
  2059. {
  2060. //AddTextEvent("KEY",e.KeyCode.ToString());
  2061. switch (e.KeyCode)
  2062. {
  2063. //case Keys.Left://上一张图
  2064. // if (devContainer.state && currentState == CurrentStateEnum.打标中 && currDefectIndex > 0)
  2065. // gotoPrePic();
  2066. // break;
  2067. case Keys.F:// Keys.Right://下一张图
  2068. if (devContainer.state && currentState == CurrentStateEnum.打标中 && currDefectIndex < defectList.Count - 1)
  2069. gotoNextPic();
  2070. break;
  2071. case Keys.K://Keys.Up://上一缺陷
  2072. if (devContainer.state && currentState == CurrentStateEnum.打标中 && currDefectIndex > 0)
  2073. gotoDefctListIndex(--currDefectIndex, currDefectIndex+1);
  2074. break;
  2075. case Keys.P://Keys.Down://下一缺陷
  2076. if (devContainer.state && currentState == CurrentStateEnum.打标中 && currDefectIndex < defectList.Count - 1)
  2077. gotoDefctListIndex(++currDefectIndex, currDefectIndex-1);
  2078. break;
  2079. }
  2080. }
  2081. private void 关于ToolStripMenuItem_Click(object sender, EventArgs e)
  2082. {
  2083. }
  2084. private void cbxSN_KeyUp(object sender, KeyEventArgs e)
  2085. {
  2086. if (e.KeyCode == Keys.Enter)
  2087. {
  2088. if (currentState != CurrentStateEnum.等待扫码) return;
  2089. string sn = this.cbxSN.Text.Trim();
  2090. if (string.IsNullOrWhiteSpace(sn))
  2091. return;
  2092. //FrmInput frm = new FrmInput(productCodeList, "请选择产品编码:");
  2093. //if (frm.ShowDialog() != DialogResult.OK && string.IsNullOrWhiteSpace(frm.inputData))
  2094. // return;
  2095. Task.Factory.StartNew(() =>
  2096. {
  2097. devContainer.devCodeScanner.ScanerEvent?.Invoke(sn);
  2098. });
  2099. }
  2100. }
  2101. private void tsbtnGoDownPT_Click_1(object sender, EventArgs e)
  2102. {
  2103. AddTextEvent("下料", "准备下料。。。");
  2104. // Task.Run(() => this.gotoDownPT());
  2105. gotoDownPT();
  2106. }
  2107. private void cbxSN_KeyPress(object sender, KeyPressEventArgs e)
  2108. {
  2109. //if (e.KeyChar == (char)Keys.Enter)
  2110. //{
  2111. // if (currentState != CurrentStateEnum.等待扫码) return;
  2112. // string sn = this.cbxSN.Text.Trim();
  2113. // if (string.IsNullOrWhiteSpace(sn))
  2114. // return;
  2115. // //FrmInput frm = new FrmInput(productCodeList, "请选择产品编码:");
  2116. // //if (frm.ShowDialog() != DialogResult.OK && string.IsNullOrWhiteSpace(frm.inputData))
  2117. // // return;
  2118. // Task.Factory.StartNew(() =>
  2119. // {
  2120. // devContainer.devCodeScanner.ScanerEvent?.Invoke(sn);
  2121. // });
  2122. //}
  2123. }
  2124. }
  2125. }