版博士V2.0程序
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 

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