版博士V2.0程序
Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 

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