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

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