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.
 
 
 
 
 

3720 lines
200 KiB

  1. using Advantech.Motion;
  2. using HalconDotNet;
  3. using Microsoft.VisualBasic;
  4. using Models;
  5. using Newtonsoft.Json;
  6. using Newtonsoft.Json.Linq;
  7. using OpenCvSharp;
  8. using ProductionControl.Device;
  9. using ProductionControl.UI;
  10. using ProductionControl.Utils;
  11. using SqlSugar;
  12. using System;
  13. using System.Collections;
  14. using System.Collections.Generic;
  15. using System.ComponentModel;
  16. using System.Data;
  17. using System.Diagnostics;
  18. using System.Drawing;
  19. using System.Drawing.Imaging;
  20. using System.IO;
  21. using System.Linq;
  22. using System.Security.Cryptography;
  23. using System.Text;
  24. using System.Threading;
  25. using System.Threading.Tasks;
  26. using System.Web.Routing;
  27. using System.Windows.Forms;
  28. using static ProductionControl.Device.AxisDev;
  29. using static ProductionControl.Device.DefectLib;
  30. using static ProductionControl.Device.SizeLib;
  31. namespace ProductionControl
  32. {
  33. public partial class FrmMain : Form
  34. {
  35. WebService webService = new WebService();
  36. private List<string> productCodeList = new List<string>();
  37. private DevContainer devContainer = new DevContainer();
  38. private Service.ProductService svcProduct = new Service.ProductService();
  39. private Service.OrderService svcOrder = new Service.OrderService();
  40. private bool bExitApp = false;
  41. //禁用蜂鸣器,门磁
  42. private bool disableBuzzer, disableDoorSensor;
  43. //线宽,张力,厚度,PT
  44. private List<double> lstTension = new List<double>();
  45. private List<double> lstHeight = new List<double>();
  46. private List<double> lstLineWidth = new List<double>();
  47. private List<double> lstPT = new List<double>();
  48. private Queue<scannerGBmpLoc> scannerGBmpQueue = new Queue<scannerGBmpLoc>();
  49. private Queue<scannerCBmpLoc> scannerCBmpQueue = new Queue<scannerCBmpLoc>();
  50. //private int scannerCBmpIndex = 0;//scannerCBmpQueue中使用当前项的计数器
  51. private int compBmpIndex = 0;//比对777图的索引
  52. private int defectBmpNum = 0;
  53. private int defectBmpNumResult = 0;
  54. /// <summary>
  55. /// 比对失败的图片
  56. /// </summary>
  57. private List<Bitmap> lstCompareFailZoomImage = new List<Bitmap>();
  58. private object myLock=new object();
  59. private WarningEnum warningLevel;//警告等级
  60. private CurrentPTEnum currentPT;//当前点位
  61. private CurrentStateEnum currentState;//当前状态
  62. /// <summary>
  63. /// 当前流程ID,暂停/继续时使用
  64. /// </summary>
  65. private int currProcessIndex = -1;
  66. private Models.Product currProductModel = null;//当前产品
  67. private bool autoMakeTagRuning = false;
  68. private bool isProductRevise = false;
  69. //产品-厚度base校正点位索引
  70. private int ProductPT_HeightBaseNum = 0;
  71. private Stopwatch stopWatch = new Stopwatch();
  72. private Order order = new Order();
  73. //--333输出变量供后面多个777使用
  74. public HObject contoursAffineTrans1_Out;
  75. private System.Timers.Timer timer = new System.Timers.Timer();
  76. private class scannerGBmpLoc
  77. {
  78. public scannerGBmpLoc(Mat mat, double xmm, double ymm)
  79. {
  80. bmp = mat;
  81. Xmm = xmm;
  82. Ymm = ymm;
  83. }
  84. public Mat bmp { get; private set; }
  85. public double Xmm { get; private set; }
  86. public double Ymm { get; private set; }
  87. }
  88. private class scannerCBmpLoc
  89. {
  90. public scannerCBmpLoc(string path, double posX, double posY)
  91. {
  92. Path = path;
  93. PosX=posX;
  94. PosY=posY;
  95. }
  96. public scannerCBmpLoc(Bitmap bmp, double posX, double posY)
  97. {
  98. BMP = bmp;
  99. PosX = posX;
  100. PosY = posY;
  101. }
  102. public Bitmap BMP { get; private set; }
  103. public string Path { get; private set; }
  104. public double PosX { get; private set; }
  105. public double PosY { get; private set; }
  106. }
  107. public FrmMain()
  108. {
  109. InitializeComponent();
  110. this.dgvProcess.AutoGenerateColumns = false;
  111. this.tsbtnCloseDev.Visible = false;
  112. this.tsslLoginInfo.Text = $"操作员:{Config.loginUser.Code}({Config.loginUser.Name})";
  113. this.tsslLoginTime.Text = $" 登录时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm")}";
  114. //显示行号与列宽度自动调整
  115. dgvProcess.RowHeadersVisible = true;
  116. dgvProcess.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders;
  117. dgvProcess.RowPostPaint += (sender, e) =>
  118. {
  119. Utils.Util.showRowNum_onDataGrid_RowPostPaint(this.dgvProcess, sender, e);
  120. };
  121. checkCustomerVer();
  122. }
  123. private void checkCustomerVer()
  124. {
  125. //if(Config.CustomerVer=="A")
  126. // this.tsMenuOrderProduct.Visible = false;
  127. }
  128. private void FrmMian_Load(object sender, EventArgs e)
  129. {
  130. if (Config.loginUser.RoleInfo.Code!="admin")
  131. checkRoleRight();
  132. loadProductCodeList();
  133. this.statusStrip1.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.HorizontalStackWithOverflow;
  134. this.tsslLoginTime.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;
  135. this.tsslLoginInfo.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;
  136. this.tsAxisState.Text = "";
  137. //
  138. webService.LogEvent = (warning, msg) =>
  139. {
  140. AddTextEvent("HTTP服务", msg, warning);
  141. webService.LogEvent = null;
  142. };
  143. webService.start();
  144. //读取硬盘剩余空间
  145. Config.CheckDisk();
  146. }
  147. private void loadProductCodeList()
  148. {
  149. try
  150. {
  151. productCodeList = svcProduct.GetList().Select(m => m.Code).OrderBy(m=>m).ToList();
  152. }
  153. catch(Exception ex)
  154. {
  155. AddTextEvent("启动", "加载产品料号失败:" + ex.Message,WarningEnum.High);
  156. }
  157. }
  158. private void checkRoleRight()
  159. {
  160. this.流程管理ToolStripMenuItem.Enabled = (Config.loginUser.RoleInfo.RightList.FirstOrDefault(m => m.Code == "Step") != null);
  161. this.产品管理ToolStripMenuItem.Enabled = (Config.loginUser.RoleInfo.RightList.FirstOrDefault(m => m.Code == "Product") != null);
  162. this.设备调试ToolStripMenuItem.Enabled = (Config.loginUser.RoleInfo.RightList.FirstOrDefault(m => m.Code == "Debug") != null);
  163. //this.tsMenuOrderQuery.Enabled = (Config.loginUser.RoleInfo.RightList.FirstOrDefault(m => m.Code == "Order") != null);
  164. //this.tsMenuStatistics.Enabled = (Config.loginUser.RoleInfo.RightList.FirstOrDefault(m => m.Code == "Statistics") != null);
  165. this.角色管理ToolStripMenuItem.Enabled = (Config.loginUser.RoleInfo.RightList.FirstOrDefault(m => m.Code == "Role") != null);
  166. this.用户管理ToolStripMenuItem.Enabled = (Config.loginUser.RoleInfo.RightList.FirstOrDefault(m => m.Code == "User") != null);
  167. this.tsbtnProductRevise.Enabled = (Config.loginUser.RoleInfo.RightList.FirstOrDefault(m => m.Code == "HeightBase") != null);
  168. this.tsMenuSysSetting.Enabled = (Config.loginUser.RoleInfo.RightList.FirstOrDefault(m => m.Code == "SysSetting") != null);
  169. this.tsMenuCmdSetting.Enabled = (Config.loginUser.RoleInfo.RightList.FirstOrDefault(m => m.Code == "CmdSetting") != null);
  170. this.tsMenuPTSetting.Enabled = (Config.loginUser.RoleInfo.RightList.FirstOrDefault(m => m.Code == "PTSetting") != null);
  171. }
  172. private void txtProductName_KeyPress(object sender, KeyPressEventArgs e)
  173. {
  174. //if (e.KeyChar == '\r' && devContainer.state && currentState == CurrentStateEnum.ScanBarcode)// && currentPT== CurrentPTEnum.UpPT )
  175. //{
  176. // runStep();
  177. //}
  178. }
  179. /// <summary>
  180. /// 删除修复台重复sn图片
  181. /// </summary>
  182. private void DeleteRepairImage(string sn)
  183. {
  184. List<string> imagePath = new List<string>
  185. {
  186. Config.Defect_SavePath,
  187. Config.Defect_Small_SavePath,
  188. Config.Defect_Compress_SavePath,
  189. Config.SizeBmp_Zoom_Image_SavePath,
  190. Config.SizeBmp_SavePath,
  191. Config.SizeBmp_Compare_SavePath
  192. };
  193. //删除文件
  194. //Task.Factory.StartNew(() =>
  195. //{
  196. for (int i = 0; i < imagePath.Count; i++)
  197. {
  198. string dirPath = Util.createSubDir(imagePath[i],
  199. new List<string> { DateTime.Now.ToString("yyyyMMdd"), sn });
  200. if (!Directory.Exists(dirPath))
  201. {
  202. return;
  203. }
  204. string[] array = Directory.GetFiles(dirPath);
  205. foreach (string text in array)
  206. {
  207. try
  208. {
  209. API.OutputDebugString("清除文件:" + text + "...");
  210. File.Delete(text);
  211. }
  212. catch (Exception ex)
  213. {
  214. API.OutputDebugString("Ex1:" + ex.Message);
  215. }
  216. }
  217. }
  218. //});
  219. }
  220. //后台线程运行
  221. /// <summary>
  222. /// 中断工序运行
  223. /// </summary>
  224. /// <returns></returns>
  225. private bool isBreakProcessRun()
  226. {
  227. return warningLevel != WarningEnum.Normal || currentState != CurrentStateEnum.运行中;
  228. }
  229. private void runStep()
  230. {
  231. compBmpIndex = defectBmpNum = defectBmpNumResult = 0;
  232. AddTextEvent("启动", "等待扫码枪扫码...");
  233. if (devContainer.devCodeScanner != null)
  234. {
  235. devContainer.devCodeScanner.stop();
  236. devContainer.devCodeScanner = null;
  237. }
  238. devContainer.devCodeScanner = new CodeScannerDev();
  239. if (!devContainer.devCodeScanner.start())
  240. {
  241. AddTextEvent("扫码枪", "扫码枪初始化失败!");
  242. return;
  243. }
  244. //2023-12-06 无输入料号防呆
  245. if(string.IsNullOrEmpty(this.txtProductCode.Text))
  246. {
  247. AddTextEvent("料号", "未选择料号!");
  248. return;
  249. }
  250. //2023-10-20 不使用扫码枪事件处理
  251. //devContainer.devCodeScanner.ScanerEvent = (code) =>
  252. string code = this.txtProductCode.Text;
  253. {
  254. if (!devContainer.state || currentState != CurrentStateEnum.等待扫码 || string.IsNullOrWhiteSpace(code))
  255. return;
  256. //
  257. scannerGBmpQueue.Clear();
  258. scannerCBmpQueue.Clear();
  259. lstCompareFailZoomImage.Clear();
  260. contoursAffineTrans1_Out = null;
  261. Thread threadtest = new System.Threading.Thread(() =>
  262. {
  263. int errStep = 0;
  264. try
  265. {
  266. var model = svcProduct.GetModelNav(code);
  267. if (model != null && model.StepInfo.ProcessList.Count > 0)
  268. {
  269. errStep = 1;
  270. //根据产品设置动态加载外观检测模型文件
  271. string onnxFile;
  272. if (!string.IsNullOrWhiteSpace(model.DefectModelFile))
  273. onnxFile = $"{Application.StartupPath}\\onnxFiles\\{model.DefectModelFile}";
  274. else
  275. onnxFile = $"{Application.StartupPath}\\onnxFiles\\default.onnx";
  276. devContainer.libDefect.loadModelFile(onnxFile);
  277. //
  278. errStep = 2;
  279. string sn = "";
  280. AutoResetEvent waitEvent = new AutoResetEvent(false);
  281. this.Invoke(new System.Action(() =>
  282. {
  283. FrmInput frm = new FrmInput(null, "请输入网版编码:");
  284. if (frm.ShowDialog() == DialogResult.OK && !string.IsNullOrWhiteSpace(frm.inputData))
  285. sn = frm.inputData;
  286. waitEvent.Set();
  287. }));
  288. errStep = 3;
  289. waitEvent.WaitOne();
  290. if (string.IsNullOrWhiteSpace(sn))
  291. {
  292. AddTextEvent("扫码枪", $"料号{code}未输入网版编码,流程中止!");
  293. return;
  294. }
  295. AddTextEvent("扫码枪", $"料号:{code},网版编码:{sn}");
  296. //是否闪退需观察
  297. errStep = 4;
  298. devContainer.devCodeScanner.stop();
  299. devContainer.devCodeScanner = null;
  300. errStep = 5;
  301. //删除重复sn用于修复台的图片
  302. AddTextEvent("扫码枪", $"删除{sn}重复用于修复台的图片...");
  303. DeleteRepairImage(sn);
  304. //判断SN数量是否达到批次上限
  305. //创建表达式
  306. if (!string.IsNullOrWhiteSpace(model.BatchId) && model.TargetCount > 0)
  307. {
  308. var exp1 = Expressionable.Create<Order>()
  309. .And(m => m.ProductId == model.Id)
  310. .And(m => m.BatchId == model.BatchId)
  311. .And(m => m.SN != sn)
  312. .ToExpression();//注意 这一句 不能少
  313. errStep = 6;
  314. if (svcOrder.Count(exp1) >= model.TargetCount)
  315. {
  316. AddTextEvent("扫码枪", $"当前产品本批次检测数已达目标数量,请更换检测批次号!");
  317. return;
  318. }
  319. errStep = 7;
  320. }
  321. //
  322. this.Invoke(new System.Action(() =>
  323. {
  324. this.txtProductSN.Text = sn;
  325. }));
  326. //
  327. model.HeightBaseDec = "";
  328. currentState = CurrentStateEnum.运行中;
  329. currentPT = CurrentPTEnum.Moving;
  330. currProductModel = model;
  331. AddTextEvent("扫码枪", $"{model.Name} {model.Spec} [{model.Code}]");
  332. this.Invoke(new System.Action(() =>
  333. {
  334. this.txtProductCode.Text = model.Code;
  335. this.txtProductName.Text = model.Name;
  336. this.dgvProcess.DataSource = new BindingSource(model.StepInfo.ProcessList, null);
  337. devContainer.libFor.clear();
  338. devContainer.libIF.clear();
  339. tsbtnSizeTag.Enabled = tsbtnSizeImage.Enabled = tsbtnDefectImage.Enabled = true;
  340. }));
  341. errStep = 8;
  342. //
  343. ProductPT_HeightBaseNum = 0;
  344. this.setButtonEnabled(this.tsbtnPause, true);
  345. this.setButtonEnabled(this.tsbtnStopNow, true);
  346. order = new Order();
  347. order.Qualified = true;//默认合格,中间有一项指标不合格则改为false
  348. order.ProductId = currProductModel.Id;
  349. order.StepId = (int)currProductModel.StepId;
  350. order.SN = sn;
  351. order.BatchId = currProductModel.BatchId;
  352. errStep = 9;
  353. int nextStepId = 0;
  354. do
  355. {
  356. nextStepId = nextProcess(model, nextStepId);
  357. } while (nextStepId >= 0 && !isBreakProcessRun());
  358. errStep = 10;
  359. }
  360. else
  361. AddTextEvent("扫码枪", model != null ? $"料号{code}不存在!" : $"产品({model.Name})未配置检测流程!");
  362. }
  363. catch (Exception ex)
  364. {
  365. //AddTextEvent("扫码后", $"errcode({errStep}):" + ex.Message);//会有空对象引用,但不知哪里报的
  366. //warning(WarningEnum.High);
  367. }
  368. });
  369. threadtest.IsBackground = true;
  370. threadtest.Start();
  371. };
  372. }
  373. //model.Type=1 系统校正
  374. /// <summary>
  375. ///
  376. /// </summary>
  377. /// <param name="model"></param>
  378. /// <param name="stepIndex">0-n</param>
  379. /// <returns>大于等于0正常工序; -1:结束 -2:异常</returns>
  380. private int nextProcess(Models.Product model, int stepIndex)
  381. {
  382. try
  383. {
  384. //记录当前index
  385. this.currProcessIndex = stepIndex;
  386. this.Invoke(new System.Action(() =>
  387. {
  388. try
  389. {
  390. this.dgvProcess.Rows[stepIndex].Selected = true;
  391. dgvProcess.CurrentCell = dgvProcess.Rows[stepIndex].Cells[1];
  392. }
  393. catch { }
  394. }));
  395. lock (myLock)
  396. {
  397. if (isBreakProcessRun())
  398. return stepIndex;
  399. }
  400. //开始计时
  401. if(!isProductRevise && model.StepInfo.StartTimeIndex>0 && model.StepInfo.StartTimeIndex==stepIndex+1)
  402. stopWatch.Restart();
  403. var processList = isProductRevise ? model.ReviseStepInfo.ProcessList : model.StepInfo.ProcessList;
  404. var processInfo = processList[stepIndex];
  405. string processName = processInfo.ProcessName;
  406. //AddTextEvent($"{stepIndex + 1}-{processName}", $"工序开始...");
  407. string jsonParams = null;//配方
  408. if (model.ProductProcessList != null && model.ProductProcessList.Count > 0)//使用产品配方
  409. {
  410. ProductProcess productProcessParams = model.ProductProcessList.First(m => m.ProcessCode == processInfo.ProcessCode);
  411. if (productProcessParams != null)
  412. {
  413. jsonParams = productProcessParams.ProcessParams;
  414. AddTextEvent($"{stepIndex + 1}-{processName}", $"使用产品专用配方:{jsonParams}");
  415. }
  416. }
  417. if (jsonParams == null)//使用流程默认配方
  418. {
  419. jsonParams = processInfo.ProcessParams;
  420. if (jsonParams == null) throw new Exception("配方为null!!");
  421. AddTextEvent($"{stepIndex + 1}-{processName}", $"使用流程默认配方:{jsonParams}");
  422. }
  423. //
  424. JObject processParam = JObject.Parse(jsonParams);
  425. if (!processParam.ContainsKey("Disable") || !processParam.Value<bool>("Disable"))
  426. {
  427. AutoResetEvent endEvent;
  428. uint sleepPre = processParam.Value<uint>("SleepPre");
  429. uint sleepLater = processParam.Value<uint>("SleepLater");
  430. if (sleepPre > 0)
  431. Thread.Sleep((int)sleepPre);
  432. double limitThresholdVal, lowerThresholdVal; //张力,厚度,Size,Defect
  433. //======Switch 工序类型
  434. bool asynRun;
  435. string gbxBmpPath = "";
  436. Models.Attachment attachmentFile;
  437. int liStatocStepIndex = stepIndex;
  438. switch (processInfo.ProcessCode)
  439. {
  440. case "IOCard":
  441. #region
  442. var direction = (IODirectionEnum)processParam.Value<int>("Direction");
  443. if (direction == IODirectionEnum.输入 || direction == IODirectionEnum.输入输出)
  444. {
  445. uint IN_Waiting_Timeout = processParam.Value<uint>("IN_Waiting_Timeout");
  446. AddTextEvent($"{stepIndex + 1}-{processName}", $"等待I/O输入信号{(IN_Waiting_Timeout > 0 ? $"(超时时长: {IN_Waiting_Timeout})" : "...")}");
  447. string[] inValue = processParam.Value<JArray>("IN_OP_SHOW").ToObject<List<string>>().ToArray();
  448. uint inWaitingTime = 0;
  449. while (true)
  450. {
  451. if (isBreakProcessRun())
  452. return stepIndex;
  453. if (Util.compareIOInput(inValue, devContainer.devIOCard.DIData))
  454. break;
  455. Thread.Sleep(10);
  456. inWaitingTime += 10;
  457. if (IN_Waiting_Timeout>0 && inWaitingTime >= IN_Waiting_Timeout)
  458. {
  459. AddTextEvent($"{stepIndex + 1}-{processName}", $"输入等待超时告警!", WarningEnum.High);
  460. warning(WarningEnum.Low);//暂停
  461. return stepIndex;
  462. }
  463. }
  464. AddTextEvent($"{stepIndex + 1}-{processName}", $"I/O输入信号对比完成!");
  465. }
  466. if (direction == IODirectionEnum.输出 || direction == IODirectionEnum.输入输出)
  467. devContainer.io_output($"{stepIndex + 1}-{processName}", processParam);
  468. #endregion
  469. break;
  470. case "Tension":
  471. #region
  472. //limitThresholdVal = processParam.Value<double>("LimitThresholdVal");
  473. //lowerThresholdVal = processParam.Value<double>("LowerThresholdVal");
  474. //double tensionValue = 0;
  475. //int timeoutTension = 0;
  476. //do
  477. //{
  478. // tensionValue = devContainer.devTension.getValue();
  479. // setDgvContentCol(liStatocStepIndex, $"张力值:{tensionValue}");
  480. // Thread.Sleep(10);
  481. // timeoutTension += 10;
  482. // if (tensionValue <= 0 && timeoutTension >= 600)//3秒超时
  483. // {
  484. // AddTextEvent($"{stepIndex + 1}-{processName}", $"张力测量失败,确认设备是否正常!", WarningEnum.High);
  485. // warning(WarningEnum.Low);//暂停
  486. // devContainer.io_output(CMDName.张力读取结束输出);
  487. // currProcessIndex--;
  488. // return stepIndex;
  489. // }
  490. //} while (tensionValue <= 0);
  491. //devContainer.io_output(CMDName.张力读取结束输出);
  492. //lstTension.Add(tensionValue);
  493. //updateTensionValue(model.TensionBaseValue+model.TensionUpFloatValue,model.TensionBaseValue-model.TensionDownFloatValue);
  494. //if (limitThresholdVal > 0 && tensionValue >= limitThresholdVal)
  495. //{
  496. // AddTextEvent($"{stepIndex + 1}-{processName}", $"读取数据:{tensionValue},达到上限阀值:{limitThresholdVal},进行下料...", WarningEnum.Low);
  497. // currProcessIndex = stepIndex + 1;
  498. // warning(WarningEnum.Low);//暂停
  499. // return stepIndex;
  500. //}
  501. //else if (lowerThresholdVal > 0 && tensionValue < lowerThresholdVal)
  502. //{
  503. // AddTextEvent($"{stepIndex + 1}-{processName}", $"读取数据:{tensionValue},达到下限阀值:{lowerThresholdVal},进行下料...", WarningEnum.Low);
  504. // currProcessIndex = stepIndex + 1;
  505. // warning(WarningEnum.Low);//暂停
  506. // return stepIndex;
  507. //}
  508. //AddTextEvent($"{stepIndex + 1}-{processName}", $"读取数据:{tensionValue}");
  509. #endregion
  510. break;
  511. case "Height":
  512. #region
  513. if (Config.SkipHeight)
  514. {
  515. AddTextEvent($"{stepIndex + 1}-{processName}", $"设备禁用,忽略此步骤!");
  516. setDgvContentCol(liStatocStepIndex, $"设备禁用,忽略此步骤!");
  517. break;
  518. }
  519. while (!devContainer.devAxis.isReady())//因启用轴异步功能,使用前需等待
  520. {
  521. Thread.Sleep(100);
  522. if (isBreakProcessRun())
  523. {
  524. //currProcessIndex = stepIndex;//本工序没执行,step不变
  525. return stepIndex;
  526. }
  527. }
  528. limitThresholdVal = processParam.Value<double>("LimitThresholdVal");
  529. lowerThresholdVal = processParam.Value<double>("LowerThresholdVal");
  530. bool IsRevise = processParam.Value<bool>("IsRevise");
  531. double relBaseValue = processParam.Value<double>("RelBaseValue"); //配方中相对偏移值
  532. var heightValue = devContainer.devHeight.getHeight();
  533. heightValue = Math.Round(heightValue, 2);//保留2位小数
  534. File.AppendAllText(Application.StartupPath + "\\厚度测量记录.txt", heightValue+"\r\n");//TEMP
  535. if (!IsRevise && heightValue < 0)
  536. {
  537. AddTextEvent($"{stepIndex + 1}-{processName}", $"读取数据:{heightValue},异常数据,终止任务!", WarningEnum.Low);
  538. warning(WarningEnum.Low);//暂停
  539. return stepIndex;
  540. }
  541. //厚度Base校正
  542. if (isProductRevise)
  543. {
  544. setDgvContentCol(liStatocStepIndex, $"厚度值:{heightValue}");
  545. model.HeightBaseDec += heightValue + ";";
  546. AddTextEvent($"{stepIndex + 1}-{processName}", $"读取数据:{heightValue}");
  547. }
  548. else if (IsRevise)
  549. {
  550. var reviseHeight = heightValue + relBaseValue;
  551. model.HeightBaseDec += reviseHeight + ";";
  552. setDgvContentCol(liStatocStepIndex, $"base值:{reviseHeight} = 厚度值:{heightValue}+偏移值:{relBaseValue}");
  553. AddTextEvent($"{stepIndex + 1}-{processName}", $"base值:{reviseHeight} = 厚度值:{heightValue}+偏移值:{relBaseValue},校正索引队列:{model.HeightBaseDec}");
  554. }
  555. else
  556. {
  557. AddTextEvent($"{stepIndex + 1}-{processName}", $"读取数据:{heightValue},base值:{model.HeightBaseDec},偏移值:{relBaseValue},当前base索引:{ProductPT_HeightBaseNum}");
  558. double heightDev = 0;
  559. var heightDev_BaseList=model.HeightBaseDec.Split(new char[] {';',','});
  560. if (heightDev_BaseList.Count() > ProductPT_HeightBaseNum && heightDev_BaseList[ProductPT_HeightBaseNum].Trim() != "")
  561. heightDev = Convert.ToDouble(heightDev_BaseList[ProductPT_HeightBaseNum].Trim());
  562. ProductPT_HeightBaseNum++;
  563. double heightValue2 =Math.Abs(heightDev - heightValue ) + relBaseValue;
  564. heightValue2 = Math.Round(heightValue2, 2);
  565. setDgvContentCol(liStatocStepIndex, $"厚度值:{heightValue2}");
  566. lstHeight.Add(heightValue2);
  567. updateHeightValue(model.HeightBaseValue + model.HeightUpFloatValue, model.HeightBaseValue - model.HeightDownFloatValue);
  568. if (limitThresholdVal > 0 && heightValue2 >= limitThresholdVal)
  569. {
  570. AddTextEvent($"{stepIndex + 1}-{processName}", $"读取数据:{heightValue2},达到上限阀值:{limitThresholdVal},进行下料...", WarningEnum.Low);
  571. currProcessIndex = stepIndex + 1;
  572. warning(WarningEnum.Low);//终止
  573. return stepIndex;
  574. }
  575. else if (lowerThresholdVal > 0 && heightValue2 < lowerThresholdVal)
  576. {
  577. AddTextEvent($"{stepIndex + 1}-{processName}", $"读取数据:{heightValue2},达到下限阀值:{lowerThresholdVal},进行下料...", WarningEnum.Low);
  578. currProcessIndex = stepIndex + 1;
  579. warning(WarningEnum.Low);//终止
  580. return stepIndex;
  581. }
  582. AddTextEvent($"{stepIndex + 1}-{processName}", $"厚度值:{heightValue2} (Base值:{heightDev} - 读取数据:{heightValue} + 偏移值:{relBaseValue})");
  583. }
  584. #endregion
  585. break;
  586. case "Axis":
  587. #region 多轴后遗留问题:暂停后再启动不知哪几个轴已执行
  588. JObject processParamTmp = new JObject();
  589. //兼容旧版单轴
  590. if (!processParam.ContainsKey("0") && !processParam.ContainsKey("1") && !processParam.ContainsKey("2") && !processParam.ContainsKey("3"))
  591. {
  592. processParam.Add("Enable", true);
  593. processParamTmp.Add(processParam.Value<int>("AxisIndex").ToString(), processParam);
  594. processParam = processParamTmp;
  595. }
  596. //-
  597. foreach (var processParamSub in processParam.Properties())
  598. {
  599. processParam = processParamSub.Value as JObject;
  600. AddTextEvent($"{stepIndex + 1}-{processName}", processParam.ToString());
  601. if (!processParam.ContainsKey("Disable") || !processParam.Value<bool>("Disable"))
  602. {
  603. //asynRun = processParam.Value<bool>("AsynRun");//异步
  604. int AxisIndex = processParam.Value<int>("AxisIndex");
  605. int DeviceType = processParam.Value<int>("DeviceType");
  606. double VelLow = processParam.Value<double>("VelLow");
  607. double VelHigh = processParam.Value<double>("VelHigh");
  608. double Acc = processParam.Value<double>("Acc");
  609. double Dec = processParam.Value<double>("Dec");
  610. AxMoveMode MoveMode = (AxMoveMode)processParam.Value<int>("MoveMode");//绝对位置
  611. double PPUValue = processParam.Value<double>("Value");
  612. AddTextEvent($"{stepIndex + 1}-{processName}", $"轴{AxisIndex}准备({(MoveMode == AxMoveMode.绝对位置 ? "绝对" : "相对")})运动至{PPUValue}(当前轴状态:{((AxisState)devContainer.devAxis.AxState[AxisIndex]).ToString()})...");
  613. //移动Axis前等待厚度传感器收回
  614. if (!Config.SkipHeight)
  615. {
  616. while (devContainer.devHeight.getHeight() < (double)Math.Abs(Config.HeightDev_SafeValue))
  617. {
  618. if (isBreakProcessRun())
  619. return stepIndex;
  620. Thread.Sleep(10);
  621. }
  622. }
  623. while (!devContainer.devAxis.isReady(AxisIndex))
  624. {
  625. Thread.Sleep(100);
  626. if (isBreakProcessRun())
  627. return stepIndex;
  628. }
  629. devContainer.devAxis.setAxisVelParam(VelLow, VelHigh, Acc, Dec, AxisIndex);
  630. if (!devContainer.devAxis.move_ptp(AxisIndex, PPUValue, MoveMode))
  631. {
  632. AddTextEvent($"{stepIndex + 1}-{processName}", $"轴{AxisIndex}运动失败!", WarningEnum.Low);
  633. warning(WarningEnum.Low);//终止
  634. return stepIndex;
  635. }
  636. //多轴运行自动使用异步,全部执行后强制等待各轴完成 asynRun属性已无用
  637. //AddTextEvent($"{stepIndex + 1}-{processName}", $"等待轴{AxisIndex}运行完成...");
  638. //while (!asynRun && !devContainer.devAxis.isReady(AxisIndex))
  639. //{
  640. // Thread.Sleep(100);
  641. // if (isBreakProcessRun())
  642. // {
  643. // currProcessIndex = stepIndex + 1;
  644. // return stepIndex;
  645. // }
  646. //}
  647. //if (devContainer.devAxis.isReady(AxisIndex))
  648. // AddTextEvent($"{stepIndex + 1}-{processName}", $"轴{AxisIndex}运行完成,当前命令位置:{devContainer.devAxis.getCmdPos_mm(AxisIndex)},反馈位置:{devContainer.devAxis.getActualPos_mm(AxisIndex)}");
  649. }
  650. }
  651. //多轴同时运行后强制等待各轴完成
  652. AddTextEvent($"{stepIndex + 1}-{processName}", $"等待轴组运行完成...");
  653. while (!devContainer.devAxis.isReady())
  654. {
  655. Thread.Sleep(100);
  656. if (isBreakProcessRun())
  657. {
  658. currProcessIndex = stepIndex + 1;
  659. return stepIndex;
  660. }
  661. }
  662. AddTextEvent($"{stepIndex + 1}-{processName}", $"轴组运行完成。");
  663. #endregion
  664. break;
  665. case "AxisTag":
  666. #region
  667. //asynRun = processParam.Value<bool>("AsynRun");//异步
  668. string axisSizeTag= processParam.Value<string>("SizeTag");
  669. int useIndex = processParam.Value<int>("UseIndex");//消费posePT中的索引
  670. AxMoveMode TagMoveMode = (AxMoveMode)processParam.Value<int>("MoveMode");//绝对位置
  671. var AxisIndexList = processParam.Value<JArray>("AxisIndexList").ToObject<List<int>>();
  672. double TagVelLow = processParam.Value<double>("VelLow");
  673. double TagVelHigh = processParam.Value<double>("VelHigh");
  674. double TagAcc = processParam.Value<double>("Acc");
  675. double TagDec = processParam.Value<double>("Dec");
  676. var sizeTagObj = order.SizeTagDataList.LastOrDefault(m => m.SizeTag == axisSizeTag);//用最新的last
  677. if (sizeTagObj == null)
  678. {
  679. AddTextEvent($"{stepIndex + 1}-{processName}", $"偏移校正轴工序找不到数据提供者Tag:{axisSizeTag}!", WarningEnum.High);
  680. warning(WarningEnum.High);
  681. return stepIndex;
  682. }
  683. string[] posePT= sizeTagObj.posePT.Split(',');
  684. if(posePT.Length < useIndex+ AxisIndexList.Count)
  685. {
  686. AddTextEvent($"{stepIndex + 1}-{processName}", $"Tag:{axisSizeTag}对应消费索引:{useIndex},Axis数量:{AxisIndexList.Count} 超出postPT:{sizeTagObj.posePT} 范围!", WarningEnum.High);
  687. warning(WarningEnum.High);
  688. return stepIndex;
  689. }
  690. double[] TagPPUValue = new double[AxisIndexList.Count];
  691. for (int i = 0; i < AxisIndexList.Count; i++)
  692. TagPPUValue[i] = double.Parse(posePT[useIndex + i]);
  693. string axisTagMsg = $"消费Tag:{axisSizeTag},索引:{useIndex}, 轴:{string.Join(",", AxisIndexList.ToList())},数据:{(TagMoveMode== AxMoveMode.绝对位置 ? "绝对" : "相对")}({string.Join(",", TagPPUValue.ToList())})";
  694. AddTextEvent($"{stepIndex + 1}-{processName}", axisTagMsg);
  695. setDgvContentCol(liStatocStepIndex, axisTagMsg);
  696. //移动Axis前等待厚度传感器收回
  697. if (!Config.SkipHeight)
  698. {
  699. while (devContainer.devHeight.getHeight() < (double)Math.Abs(Config.HeightDev_SafeValue))
  700. {
  701. if (isBreakProcessRun())
  702. return stepIndex; //如果是相对位置,这里返回会有问题
  703. Thread.Sleep(10);
  704. }
  705. }
  706. for (int i = 0; i < AxisIndexList.Count && i < TagPPUValue.Length; i++)
  707. {
  708. while (!devContainer.devAxis.isReady(AxisIndexList[i]))
  709. {
  710. Thread.Sleep(100);
  711. if (isBreakProcessRun())
  712. return stepIndex;
  713. }
  714. devContainer.devAxis.setAxisVelParam(TagVelLow, TagVelHigh, TagAcc, TagDec, AxisIndexList[i]);
  715. if (!devContainer.devAxis.move_ptp(AxisIndexList[i], TagPPUValue[i], TagMoveMode))
  716. {
  717. AddTextEvent($"{stepIndex + 1}-{processName}", $"轴{AxisIndexList[i]}运动失败!", WarningEnum.Low);
  718. warning(WarningEnum.Low);//终止
  719. return stepIndex;//如果是相对位置,这里返回会有问题
  720. }
  721. //AddTextEvent($"{stepIndex + 1}-{processName}", $"等待轴{AxisIndexList[i]}运行完成...");
  722. //while (!asynRun && !devContainer.devAxis.isReady(AxisIndexList[i]))
  723. //{
  724. // Thread.Sleep(100);
  725. // if (isBreakProcessRun())
  726. // {
  727. // currProcessIndex = stepIndex + 1;
  728. // return stepIndex;//如果是相对位置,这里返回会有问题
  729. // }
  730. //}
  731. //if (devContainer.devAxis.isReady(AxisIndexList[i]))
  732. // AddTextEvent($"{stepIndex + 1}-{processName}", $"轴{AxisIndexList[i]}运行完成,当前命令位置:{devContainer.devAxis.getCmdPos_mm(AxisIndexList[i])},反馈位置:{devContainer.devAxis.getActualPos_mm(AxisIndexList[i])}");
  733. }
  734. if (sizeTagObj.ConsumeStepIndex == null) sizeTagObj.ConsumeStepIndex = "";
  735. sizeTagObj.ConsumeStepIndex += $"{stepIndex + 1}-{useIndex}, ";//消费工序ID
  736. //多轴同时运行后强制等待各轴完成
  737. AddTextEvent($"{stepIndex + 1}-{processName}", $"等待轴组运行完成...");
  738. while (!devContainer.devAxis.isReady())
  739. {
  740. Thread.Sleep(100);
  741. if (isBreakProcessRun())
  742. {
  743. currProcessIndex = stepIndex + 1;
  744. return stepIndex;
  745. }
  746. }
  747. AddTextEvent($"{stepIndex + 1}-{processName}", $"轴组运行完成。");
  748. #endregion
  749. break;
  750. case "Light":
  751. #region
  752. if (Config.SkipLight)
  753. {
  754. AddTextEvent($"{stepIndex + 1}-{processName}", $"设备禁用,忽略此步骤!");
  755. setDgvContentCol(liStatocStepIndex, $"设备禁用,忽略此步骤!");
  756. break;
  757. }
  758. int ChannelIndex = processParam.Value<int>("ChannelIndex"); //通道
  759. int DigitalValue = processParam.Value<int>("DigitalValue"); //亮度
  760. int nowDiaitalValue = devContainer.devLight.getDigitalValue(ChannelIndex);
  761. AddTextEvent($"{stepIndex + 1}-{processName}", $"通道{ChannelIndex}当前值:{nowDiaitalValue},准备更新值:{DigitalValue}...");
  762. devContainer.devLight.setDigitalValue(ChannelIndex, DigitalValue);
  763. nowDiaitalValue = devContainer.devLight.getDigitalValue(ChannelIndex);
  764. AddTextEvent($"{stepIndex + 1}-{processName}", $"通道{ChannelIndex}更新后当前值:{nowDiaitalValue}。");
  765. #endregion
  766. break;
  767. case "Scanner_GENTL":
  768. #region
  769. if (Config.SkipScannerGL)
  770. {
  771. AddTextEvent($"{stepIndex + 1}-{processName}", $"设备禁用,忽略此步骤!");
  772. setDgvContentCol(liStatocStepIndex, $"设备禁用,忽略此步骤!");
  773. break;
  774. }
  775. while (!devContainer.devAxis.isReady())//因启用轴异步功能,使用前需等待
  776. {
  777. Thread.Sleep(100);
  778. if (isBreakProcessRun())
  779. {
  780. //currProcessIndex = stepIndex;//本工序没执行,step不变
  781. return stepIndex;
  782. }
  783. }
  784. AIEngineLibEnum AIEngineLib = AIEngineLibEnum.缺陷库;
  785. if(processParam.ContainsKey("AIEngineLib"))
  786. AIEngineLib=(AIEngineLibEnum)processParam.Value<int>("AIEngineLib");
  787. float ExposureTime = processParam.Value<float>("ExposureTime"); //曝光
  788. float Gain = processParam.Value<float>("Gain"); //增益
  789. float ResultingFrameRate = processParam.Value<float>("ResultingFrameRate"); //帧率
  790. AddTextEvent($"{stepIndex + 1}-{processName}", $"相机开始采集照片...");
  791. devContainer.devScannerGentl.setParam(ExposureTime, Gain, ResultingFrameRate);
  792. endEvent = new AutoResetEvent(false);
  793. devContainer.devScannerGentl.ScanEvent = (num, bmpout) =>
  794. {
  795. AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片完成。");
  796. //----缺陷队列
  797. //bool cloneUse = false;
  798. if (AIEngineLib == AIEngineLibEnum.缺陷库 || AIEngineLib == AIEngineLibEnum.缺陷与测量库)
  799. {
  800. //cloneUse = true;
  801. var mat = OpenCvSharp.Extensions.BitmapConverter.ToMat(bmpout);
  802. scannerGBmpQueue.Enqueue(new scannerGBmpLoc(mat,
  803. devContainer.devAxis.getActualPos_mm(1),
  804. devContainer.devAxis.getActualPos_mm(2)));//Dequeue
  805. AddTextEvent($"{stepIndex + 1}-{processName}", $"缺陷图像队列数量: {scannerGBmpQueue.Count}");
  806. }
  807. if (AIEngineLib == AIEngineLibEnum.测量库 || AIEngineLib == AIEngineLibEnum.缺陷与测量库)
  808. {
  809. //v1.2.2. 修改传图
  810. //scannerCBmpQueue.Enqueue(new scannerCBmpLoc(
  811. // cloneUse?(Bitmap)bmpout.Clone(): bmpout,
  812. // devContainer.devAxis.getActualPos_mm(1),
  813. // devContainer.devAxis.getActualPos_mm(2)));//Dequeue
  814. scannerCBmpQueue.Enqueue(new scannerCBmpLoc(
  815. (Bitmap)bmpout.Clone(),
  816. devContainer.devAxis.getActualPos_mm(1),
  817. devContainer.devAxis.getActualPos_mm(2)));//Dequeue
  818. AddTextEvent($"{stepIndex + 1}-{processName}", $"添加尺寸图像队列,X:{devContainer.devAxis.getActualPos_mm(1)},y:{devContainer.devAxis.getActualPos_mm(2)},数量: {scannerCBmpQueue.Count}");
  819. }
  820. endEvent.Set();//线程返回
  821. };
  822. //AddTextEvent($"{stepIndex + 1}-{processName}", $"软触发拍照...");
  823. if (!devContainer.devScannerGentl.scan(1))//软触发拍照
  824. {
  825. devContainer.devScannerGentl.ScanEvent = null;
  826. AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片失败!", WarningEnum.Low);
  827. warning(WarningEnum.Low);//终止
  828. return stepIndex;
  829. }
  830. if (!endEvent.WaitOne(10000))
  831. {
  832. devContainer.devScannerGentl.ScanEvent = null;
  833. AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片超时!", WarningEnum.Low);
  834. warning(WarningEnum.Low);//终止
  835. return stepIndex;
  836. }
  837. devContainer.devScannerGentl.ScanEvent = null;
  838. #endregion
  839. break;
  840. case "Scanner_CC":
  841. #region
  842. if (Config.SkipScannerCC)
  843. {
  844. AddTextEvent($"{stepIndex + 1}-{processName}", $"设备禁用,忽略此步骤!");
  845. setDgvContentCol(liStatocStepIndex, $"设备禁用,忽略此步骤!");
  846. break;
  847. }
  848. while (!devContainer.devAxis.isReady())//因启用轴异步功能,使用前需等待
  849. {
  850. Thread.Sleep(100);
  851. if (isBreakProcessRun())
  852. {
  853. //currProcessIndex = stepIndex;//本工序没执行,step不变
  854. return stepIndex;
  855. }
  856. }
  857. float ExposureTimeCC = processParam.Value<float>("ExposureTime"); //曝光
  858. float GainCC = processParam.Value<float>("Gain"); //增益
  859. float ResultingFrameRateCC = processParam.Value<float>("ResultingFrameRate"); //帧率
  860. AddTextEvent($"{stepIndex + 1}-{processName}", $"相机开始采集照片...");
  861. devContainer.devScannerCC.setParam(ExposureTimeCC, GainCC, ResultingFrameRateCC);
  862. AddTextEvent($"{stepIndex + 1}-{processName}", $"相机参数设置完成。");
  863. AutoResetEvent endEventCC = new AutoResetEvent(false);
  864. //devContainer.devScannerCC.ScanEvent = (num, bmp2) =>
  865. //{
  866. // AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片完成.");
  867. // scannerCBmpQueue.Enqueue(bmp2);//Dequeue
  868. // endEventCC.Set();//线程返回
  869. //};
  870. devContainer.devScannerCC.ScanEventPath += new System.Action<int, string>((num, path2) =>
  871. {
  872. AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片完成.");
  873. scannerCBmpQueue.Enqueue(new scannerCBmpLoc(path2,
  874. devContainer.devAxis.getActualPos_mm(0),
  875. devContainer.devAxis.getActualPos_mm(2)));//Dequeue
  876. AddTextEvent($"{stepIndex + 1}-{processName}", $"添加尺寸图像队列,X:{ devContainer.devAxis.getActualPos_mm(0)},y: { devContainer.devAxis.getActualPos_mm(2)},数量: { scannerCBmpQueue.Count}");
  877. endEventCC.Set();//线程返回
  878. });
  879. if (!devContainer.devScannerCC.scan(1))//软触发拍照
  880. {
  881. devContainer.devScannerCC.ScanEventPath = null;
  882. AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片失败!", WarningEnum.Low);
  883. warning(WarningEnum.Low);//终止
  884. return stepIndex;
  885. }
  886. if (!endEventCC.WaitOne(10000))
  887. {
  888. devContainer.devScannerCC.ScanEventPath = null;
  889. AddTextEvent($"{stepIndex + 1}-{processName}", $"相机采集照片超时!", WarningEnum.Low);
  890. warning(WarningEnum.Low);//终止
  891. return stepIndex;
  892. }
  893. devContainer.devScannerCC.ScanEventPath = null;
  894. #endregion
  895. break;
  896. case "SmallAxis":
  897. #region
  898. if (Config.SkipSmallAxis)
  899. {
  900. AddTextEvent($"{stepIndex + 1}-{processName}", $"设备禁用,忽略此步骤!");
  901. setDgvContentCol(liStatocStepIndex, $"设备禁用,忽略此步骤!");
  902. break;
  903. }
  904. int CmdPos = processParam.Value<int>("CmdPos"); //命令脉冲
  905. AddTextEvent($"{stepIndex + 1}-{processName}", $"开始由起始位置{devContainer.devSmallAxis.getCurrPPU()}运动到{CmdPos}...");
  906. devContainer.devSmallAxis.gotoPos(CmdPos, true);
  907. AddTextEvent($"{stepIndex + 1}-{processName}", $"运动完成,当前位置:{devContainer.devSmallAxis.getCurrPPU()}");
  908. #endregion
  909. break;
  910. case "Size":
  911. #region
  912. asynRun = processParam.Value<bool>("AsynRun");//异步
  913. limitThresholdVal = processParam.Value<double>("LimitThresholdVal");
  914. lowerThresholdVal = processParam.Value<double>("LowerThresholdVal");
  915. int sizeIndex = processParam.Value<int>("Index");
  916. string sizeTag = processParam.ContainsKey("SizeTag") ? processParam.Value<string>("SizeTag") : "";
  917. //2023-10-27
  918. bool useMap = false;
  919. List<double> getPosList = new List<double>();
  920. try
  921. {
  922. useMap = processParam.Value<bool>("UseMapPoints");
  923. if (useMap) {
  924. var list = model.GetPointList.Split(',');
  925. List<double> dList = new List<double>();
  926. if (list.Length < 28)
  927. {
  928. for (int i = 0; i < 28; i++)
  929. {
  930. dList.Add(0);
  931. }
  932. }
  933. else
  934. {
  935. for (int i = 0; i < list.Length; i++)
  936. {
  937. dList.Add(double.Parse(list[i]));
  938. }
  939. }
  940. getPosList = dList;
  941. }
  942. else
  943. {
  944. for (int i = 0; i < 28; i++)
  945. getPosList.Add(0);
  946. }
  947. //getPosList = processParam.Value<JArray>("GetPointList").ToObject<List<double>>();
  948. }
  949. catch
  950. {
  951. for (int i = 0; i < 28; i++)
  952. getPosList.Add(0);
  953. }
  954. double[] getPosArray = getPosList.ToArray();
  955. if (scannerCBmpQueue.Count < 1)
  956. {
  957. AddTextEvent($"{stepIndex + 1}-{processName}", $"尺寸检测异常,无源图像!!", WarningEnum.Low);
  958. warning(WarningEnum.Low);//暂停
  959. return stepIndex;
  960. }
  961. var bmpCBmpQueue = scannerCBmpQueue.Dequeue();
  962. AddTextEvent($"{stepIndex + 1}-{processName}", $"开始尺寸检测,index:{sizeIndex},posX:{bmpCBmpQueue.PosX},posY:{bmpCBmpQueue.PosY},图像队列数量: {scannerCBmpQueue.Count}...");
  963. attachmentFile = model.AttachmentList.FirstOrDefault(x => x.Type == 0);
  964. AddTextEvent($"{stepIndex + 1}-{processName}", $"尺寸检测,index:{sizeIndex},{model.AttachmentList.Count}|{(attachmentFile == null ? "null": attachmentFile.NameTimestamp+ attachmentFile.ExtendName)}");
  965. if (attachmentFile != null)
  966. {
  967. gbxBmpPath = Application.StartupPath + $"\\Attachment\\product\\{attachmentFile.NameTimestamp}";
  968. if (!File.Exists(gbxBmpPath+ attachmentFile.ExtendName)) gbxBmpPath = "";
  969. }
  970. if ((sizeIndex == 333 || sizeIndex == 777) && gbxBmpPath == "")
  971. AddTextEvent($"{stepIndex + 1}-{processName}", $"尺寸检测,index:{sizeIndex},图纸不存在!", WarningEnum.Low);
  972. //2023-10-27
  973. //if ((sizeIndex == 3333)&&(getPosList != null) && (getPosList.Count() != 28))
  974. // AddTextEvent($"{stepIndex + 1}-{processName}", $"尺寸检测,index:{sizeIndex},图纸读点不存在!", WarningEnum.Low);
  975. if (useMap&&(sizeIndex == 3333) && (getPosArray != null) && (getPosArray.Count() == 28) && (getPosArray[0] != 0))
  976. AddTextEvent($"{stepIndex + 1}-{processName}", $"开始图纸读点,index:{sizeIndex},PT1:{getPosArray[0]},PT2:{getPosArray[2]},PT3:{getPosArray[4]},PT4:{getPosArray[6]},PT5:{getPosArray[8]}," +
  977. $"线宽1:[{getPosArray[10]},{getPosArray[11]}],线宽2:[{getPosArray[12]},{getPosArray[13]}],线宽3:[{getPosArray[14]},{getPosArray[15]}]," +
  978. $"线宽4:[{getPosArray[16]},{getPosArray[17]}],线宽5:[{getPosArray[18]},{getPosArray[19]}],线宽6:[{getPosArray[20]},{getPosArray[21]}]," +
  979. $"线宽7:[{getPosArray[22]},{getPosArray[23]}],线宽8:[{getPosArray[24]},{getPosArray[25]}],线宽9:[{getPosArray[26]},{getPosArray[27]}]");
  980. //需要偏移校正,index=0时不能异步 //10,20,30... 
  981. endEvent = new AutoResetEvent(false);
  982. devContainer.libSize.add(new SizeTask()
  983. {
  984. stepIndex = stepIndex,
  985. processName = processName,
  986. sizeTag = sizeTag,
  987. engineName = processParam.Value<string>("EngineName"),
  988. bmp = bmpCBmpQueue.BMP == null ? bmpCBmpQueue.BMP : (Bitmap)bmpCBmpQueue.BMP.Clone(),//bmp/file_path二选一,优先bmp
  989. file_path = bmpCBmpQueue.Path,
  990. drawingPagePath = gbxBmpPath,
  991. posX= bmpCBmpQueue.PosX,
  992. posY= bmpCBmpQueue.PosY,
  993. //2023-10-27
  994. PTandLinePos = getPosArray,
  995. index = sizeIndex,// scannerCBmpIndex++,
  996. ContoursAffineTrans1_Out=this.contoursAffineTrans1_Out,//只有777时才使用最近333输出的结果
  997. finishEvent = (res) =>
  998. {
  999. try
  1000. {
  1001. //比对
  1002. if (res.index == 777)//比对
  1003. {
  1004. if (res.isSucceed)
  1005. {
  1006. setDgvContentCol(liStatocStepIndex, $"index:{res.index}-{compBmpIndex},posX:{res.posX},posY:{res.posY},图像比对:{(res.CompResult ? "通过" : "未通过")} ");
  1007. AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"图像比对,index:{res.index}-{compBmpIndex},posX:{res.posX},posY:{res.posY},结果:{(res.CompResult ? "通过" : "未通过")}");
  1008. //
  1009. if (order.CompareResult < 2)
  1010. order.CompareResult = res.CompResult ? 1 : 2;
  1011. updateCompareResult(res.CompResult);//更新比对看板
  1012. if (!res.CompResult)
  1013. {
  1014. AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"图像比对,未通过结果:{JsonConvert.SerializeObject(res.defectInfor2RestorationDesk)}");
  1015. //转为图纸上坐标位置
  1016. if (res.defectInfor2RestorationDeskPage != null && res.defectInfor2RestorationDeskPage.Count > 0)
  1017. {
  1018. //AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"转换到图纸后坐标数据:{JsonConvert.SerializeObject(res.defectInfor2RestorationDeskPage)}");
  1019. if (order.DefectInfoList == null)
  1020. order.DefectInfoList = new List<DefectInfo>();
  1021. foreach (var item in res.defectInfor2RestorationDeskPage)
  1022. order.DefectInfoList.Add(new DefectInfo()
  1023. {
  1024. Type = 1,
  1025. Code = item[3],
  1026. X = double.Parse(item[1]),
  1027. Y = double.Parse(item[2]),
  1028. ZXD = double.Parse(item[4]),
  1029. ModifyUserCode = Config.loginUser.Code,
  1030. CreateUserCode = Config.loginUser.Code,
  1031. });
  1032. }
  1033. //比对失败的图片 -- 用于修复台调用
  1034. Bitmap bmpCompareFailZoomImage = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(res.Zoom_Image_mat);
  1035. lstCompareFailZoomImage.Add(bmpCompareFailZoomImage);
  1036. if (Config.SizeBmp_Zoom_Image_SavePath != "" && Directory.Exists(Config.SizeBmp_Zoom_Image_SavePath))
  1037. {
  1038. string path = Util.createSubDir(Config.SizeBmp_Zoom_Image_SavePath, new List<string> { order.CreateTime.ToString("yyyyMMdd"), order.SN });
  1039. //path += $"Size_SN{order.SN}_I{res.index}_X{res.Defects_X}_Y{res.Defects_Y}_C0_{ model.StepInfo.Name}";
  1040. path += $"Size_SN{order.SN}_I{compBmpIndex}_X{res.posX}_Y{res.posY}_C0_{ model.StepInfo.Name}";
  1041. bmpCompareFailZoomImage.Save(path + ".bmp", ImageFormat.Bmp);
  1042. if (res.defectInfor2RestorationDesk != null && res.defectInfor2RestorationDesk.Count > 0)
  1043. File.WriteAllText(path + ".json", JsonConvert.SerializeObject(res.defectInfor2RestorationDesk));
  1044. }
  1045. //保存原图
  1046. if (Config.SizeBmp_Compare_SavePath != "" && Directory.Exists(Config.SizeBmp_Compare_SavePath))
  1047. {
  1048. string path = Util.createSubDir(Config.SizeBmp_Compare_SavePath, new List<string> { order.CreateTime.ToString("yyyyMMdd"), order.SN });
  1049. path += $"Size_SN{order.SN}_I{res.index}_X{res.posX}_Y{res.posY}_{ model.StepInfo.Name}.bmp";
  1050. AddTextEvent($"{res.stepIndex + 1}-{processName}", $"未通过图片保存:{path}");
  1051. if (res.bmp != null)
  1052. res.bmp.Save(path, ImageFormat.Bmp);
  1053. else
  1054. API.CopyFile(res.file_path, path, false);//比.NET(File.Copy)更快
  1055. }
  1056. }
  1057. }
  1058. else
  1059. {
  1060. //2023-12-29 加入比对失败当作NG处理
  1061. order.CompareResult = 2;
  1062. updateCompareResult(false);//更新比对看板
  1063. //warning(WarningEnum.Low);//暂停
  1064. setDgvContentCol(liStatocStepIndex, $"index:{res.index},图像比对失败!");
  1065. AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"图像比对失败,index:{res.index}-{compBmpIndex}.", WarningEnum.Low);
  1066. }
  1067. compBmpIndex++;
  1068. }
  1069. //MARK
  1070. else if (res.index == 111 || res.index == 222 || res.index == 333 || res.index == 444)
  1071. {
  1072. AddTextEvent($"{res.stepIndex + 1}-{processName}", $"Mark点 Index={res.index},结果记录...");
  1073. if (res.index == 333) this.contoursAffineTrans1_Out = res.ContoursAffineTrans1_Out;//不管成功失败都替换
  1074. if (res.isSucceed)
  1075. {
  1076. Thread.Sleep(100);
  1077. AddTextEvent($"{res.stepIndex + 1}-{processName}", $"Mark点 Index={res.index}; 当前值:{string.Join(",", res.MarkPointList)}");
  1078. JArray markDatas;
  1079. if (string.IsNullOrWhiteSpace(order.MarkData))
  1080. markDatas = new JArray() { 0, 0, 0, 0, 0, 0, 0, 0 };
  1081. else
  1082. markDatas = JArray.Parse(order.MarkData);
  1083. for (int i = 0; i < res.MarkPointList.Count(); i++)
  1084. if (res.MarkPointList[i] != 0)
  1085. markDatas[i] = res.MarkPointList[i];
  1086. order.MarkData = markDatas.ToString();
  1087. setDgvContentCol(liStatocStepIndex, $"index:{res.index},Mark点:{order.MarkData} ");
  1088. AddTextEvent($"{res.stepIndex + 1}-{processName}", $"Mark点 Index={res.index};合并后:{order.MarkData}");
  1089. }
  1090. else
  1091. {
  1092. //warning(WarningEnum.Low);//暂停
  1093. setDgvContentCol(liStatocStepIndex, $"index:{res.index},Mark点计算失败!");
  1094. AddTextEvent($"{res.stepIndex + 1}-{processName}", $"Mark点计算失败,index:{res.index}.", WarningEnum.Low);
  1095. //2023-10-20 make暂停
  1096. if (Config.OpenMarkErrorStop)
  1097. warning(WarningEnum.Low);//暂停
  1098. }
  1099. //保存
  1100. if (Config.SizeBmp_SavePath != "" && Directory.Exists(Config.SizeBmp_SavePath))
  1101. {
  1102. string path = Util.createSubDir(Config.SizeBmp_SavePath, new List<string> { order.CreateTime.ToString("yyyyMMdd"), order.SN });
  1103. path += $"Size_SN{order.SN}_I{res.index}_X{res.posX}_Y{res.posY}_{ model.StepInfo.Name}.bmp";
  1104. if (res.bmp != null)
  1105. res.bmp.Save(path, ImageFormat.Bmp);
  1106. else
  1107. API.CopyFile(res.file_path, path, false);//比.NET(File.Copy)更快
  1108. }
  1109. }
  1110. else
  1111. {
  1112. int roundIndex = res.index % 10;
  1113. if (res.isSucceed)
  1114. {
  1115. string tagOutData = "";
  1116. if (res.index == 3333 && !string.IsNullOrWhiteSpace(res.sizeTag))
  1117. {
  1118. tagOutData = $"Tag:{res.sizeTag},posePT:[{string.Join(",", res.posePT)}]";
  1119. if (res.posePT.Length < 2 || res.posePT.Length % 2 != 0)
  1120. {
  1121. AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"尺寸检测输出Tag对应posePT非法: {tagOutData}", WarningEnum.High);
  1122. warning(WarningEnum.High);//急停
  1123. return;
  1124. }
  1125. //2023-10-27
  1126. AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"Tag对应posePT: {tagOutData}", WarningEnum.Normal);
  1127. if (order.SizeTagDataList == null)
  1128. order.SizeTagDataList = new List<SizeTagData>();
  1129. order.SizeTagDataList.Add(new SizeTagData()
  1130. {
  1131. SizeTag = res.sizeTag,
  1132. CreateStepIndex = res.stepIndex + 1,
  1133. posePT= string.Join(",", res.posePT)// 回转 Array.ConvertAll(sNums , double.Parse);
  1134. });
  1135. }
  1136. setDgvContentCol(liStatocStepIndex, $"index:{res.index},PT1:{res.PT1},PT2:{res.PT2},Shanxian:{res.Shanxian},Circle_Xmm:{res.Circle_Xmm},Circle_Ymm:{res.Circle_Ymm},offsetX:{res.offsetX},offsetY:{res.offsetY}, {tagOutData}");
  1137. AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"尺寸检测完成 index:{res.index},PT1:{res.PT1},PT2:{res.PT2},Shanxian:{res.Shanxian},Circle_Xmm:{res.Circle_Xmm},Circle_Ymm:{res.Circle_Ymm},offsetX:{res.offsetX},offsetY:{res.offsetY}, {tagOutData} ");
  1138. //测量
  1139. //------TEST
  1140. if (res.index>20 && res.index<30)
  1141. {
  1142. lock (lstPT)
  1143. {
  1144. lstPT.Add(Math.Round(res.PT1 + Config.PT_Offset, 4));
  1145. updatePTValueTest(model.PTBaseValue + model.PTUpFloatValue, model.PTBaseValue - model.PTDownFloatValue);
  1146. }
  1147. }
  1148. //------
  1149. if (roundIndex > 0)//1-9测量
  1150. {
  1151. if (res.index < 10)//11-13 (PT: 7-9 => 21-29(PT1)) 不用管,李工处理
  1152. {
  1153. //if (roundIndex >= 7)
  1154. //{
  1155. // lock (lstPT)
  1156. // {
  1157. // lstPT.Add(Math.Round(res.PT1, 4));
  1158. // lstPT.Add(res.index == 8 ? 0 : Math.Round(res.PT2, 4));
  1159. // updatePTValue(model.PTBaseValue + model.PTUpFloatValue, model.PTBaseValue - model.PTDownFloatValue);
  1160. // }
  1161. //}
  1162. lock (lstLineWidth)
  1163. {
  1164. lstLineWidth.Add(res.Shanxian > 0 ? Math.Round(res.Shanxian + Config.LineWidth_Offset, 2) : 0);
  1165. updateLineWidthValue(model.LineWidthBaseValue + model.LineWidthUpFloatValue, model.LineWidthBaseValue - model.LineWidthDownFloatValue);
  1166. }
  1167. }
  1168. }
  1169. //校正偏移 10,20,30...:偏移
  1170. else
  1171. {
  1172. AxMoveMode axSizeMode = AxMoveMode.绝对位置;
  1173. double xPos = 0;
  1174. double yPos = 0;
  1175. //绝对偏移
  1176. if (res.offsetX != 0 || res.offsetY != 0)
  1177. {
  1178. xPos += res.offsetX;
  1179. yPos += res.offsetY;
  1180. AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"offsetX/Y绝对校正, 0轴:{xPos}mm, 2轴:{yPos}mm");
  1181. }
  1182. else if (res.Circle_Xmm != 0 || res.Circle_Ymm != 0)//相对偏移校正
  1183. {
  1184. axSizeMode = AxMoveMode.相对位置;
  1185. AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"原点相对校正, 0轴:{res.Circle_Xmm}mm, 2轴:{res.Circle_Ymm}mm");
  1186. if (res.Circle_Xmm != 0) xPos = res.Circle_Xmm;
  1187. if (res.Circle_Ymm != 0) yPos = res.Circle_Ymm;
  1188. }
  1189. //当前工序直接移动
  1190. if (xPos != 0 || yPos != 0)
  1191. {
  1192. devContainer.devAxis.setAxisVelParam(0.1, 1, 1, 1, 0);
  1193. devContainer.devAxis.setAxisVelParam(0.1, 1, 1, 1, 2);
  1194. if (xPos != 0) devContainer.devAxis.move_ptp(0, xPos, axSizeMode);
  1195. if (yPos != 0) devContainer.devAxis.move_ptp(2, yPos, axSizeMode);
  1196. while (!devContainer.devAxis.isReady(0) || !devContainer.devAxis.isReady(2))
  1197. {
  1198. Thread.Sleep(100);
  1199. if (isBreakProcessRun())
  1200. break;
  1201. }
  1202. }
  1203. }
  1204. //保存
  1205. //string sizeFileName = Config.Size_SavePath + "\\" + DateTime.Now.ToString("yyyyMMdd_HHmmss_fff");
  1206. //API.CopyFile(res.file_path, defectFileName + ".bmp", false);//更快
  1207. //File.WriteAllText(defectFileName + ".json", JsonConvert.SerializeObject(res.informationList));
  1208. }
  1209. //失败
  1210. else
  1211. {
  1212. //------TEST
  1213. if (res.index > 20 && res.index < 30)
  1214. {
  1215. lock (lstPT)
  1216. {
  1217. lstPT.Add(0);
  1218. updatePTValueTest(model.PTBaseValue + model.PTUpFloatValue, model.PTBaseValue - model.PTDownFloatValue);
  1219. }
  1220. }
  1221. //------
  1222. if (roundIndex > 0)
  1223. {
  1224. //if (roundIndex >= 7)
  1225. //{
  1226. // lock (lstPT)
  1227. // {
  1228. // lstPT.Add(0);
  1229. // lstPT.Add(0);
  1230. // updatePTValue(model.PTBaseValue + model.PTUpFloatValue, model.PTBaseValue - model.PTDownFloatValue);
  1231. // }
  1232. //}
  1233. lock (lstLineWidth)
  1234. {
  1235. lstLineWidth.Add(0);
  1236. updateLineWidthValue(model.LineWidthBaseValue + model.LineWidthUpFloatValue, model.LineWidthBaseValue - model.LineWidthDownFloatValue);
  1237. }
  1238. }
  1239. setDgvContentCol(liStatocStepIndex, $"失败:{res.resultInfo}");
  1240. AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"尺寸检测失败index:{res.index}:{res.resultInfo}");
  1241. //warning(WarningEnum.Low);//暂停 这里不能暂停,stepIndex和scannerBmpQueue队列也不对了
  1242. }
  1243. //保存
  1244. if (Config.SizeBmp_SavePath != "" && Directory.Exists(Config.SizeBmp_SavePath))
  1245. {
  1246. string path = Util.createSubDir(Config.SizeBmp_SavePath, new List<string> { order.CreateTime.ToString("yyyyMMdd"), order.SN });
  1247. path += $"Size_SN{order.SN}_I{res.index}_X{res.posX}_Y{res.posY}_{ model.StepInfo.Name}.bmp";
  1248. if (res.bmp != null)
  1249. res.bmp.Save(path, ImageFormat.Bmp);
  1250. else
  1251. API.CopyFile(res.file_path, path, false);//比.NET(File.Copy)更快
  1252. }
  1253. }
  1254. }
  1255. catch(Exception ex)
  1256. {
  1257. AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"尺寸检测回调处理异常 index:{res.index},ex={ex.Message}");
  1258. }
  1259. //
  1260. //if (!asynRun)//是否异步执行endEvent.Set()都没问题
  1261. endEvent.Set();//roundIndex=0成功或失败线程返回
  1262. //---
  1263. if (res.bmp != null)
  1264. {
  1265. res.bmp.Dispose();
  1266. res.bmp = null;
  1267. }
  1268. else
  1269. {
  1270. API.DeleteFile(res.file_path);
  1271. }
  1272. }
  1273. });
  1274. //需等上面异步回调中的相对偏移校正完成再继续
  1275. if (!asynRun || sizeIndex % 10==0)
  1276. {
  1277. if (!endEvent.WaitOne(60000))
  1278. AddTextEvent($"{stepIndex + 1}-{processName}", $"{sizeIndex}等待超时,忽略继续!", WarningEnum.Low);
  1279. }
  1280. #endregion
  1281. break;
  1282. case "Defect":
  1283. #region
  1284. limitThresholdVal = processParam.Value<double>("LimitThresholdVal");
  1285. lowerThresholdVal = processParam.Value<double>("LowerThresholdVal");
  1286. if (scannerGBmpQueue.Count < 1)
  1287. {
  1288. AddTextEvent($"{stepIndex + 1}-{processName}", $"缺陷检测异常,无源图像!!", WarningEnum.Low);
  1289. warning(WarningEnum.Low);//终止
  1290. return stepIndex;
  1291. }
  1292. var bmpLoc = scannerGBmpQueue.Dequeue();
  1293. AddTextEvent($"{stepIndex + 1}-{processName}", $"开始缺陷检测,源图索引:{defectBmpNum},图像队列数量: {scannerGBmpQueue.Count}...");
  1294. string[] aarCut_size = processParam.Value<string>("CutSize").Split(',');
  1295. string[] aarResize = processParam.Value<string>("Resize").Split(',');
  1296. //图纸
  1297. attachmentFile = model.AttachmentList.FirstOrDefault(x => x.Type == 0);
  1298. if (attachmentFile != null)
  1299. {
  1300. gbxBmpPath = Application.StartupPath + $"\\Attachment\\product\\{attachmentFile.NameTimestamp}";
  1301. if (!File.Exists(gbxBmpPath + attachmentFile.ExtendName)) gbxBmpPath = "";
  1302. }
  1303. AddTextEvent($"{stepIndex + 1}-{processName}", $"图纸路径:{gbxBmpPath}");
  1304. devContainer.libDefect.add(new DefectTask()
  1305. {
  1306. stepIndex= stepIndex,
  1307. processName= processName,
  1308. drawingPagePath= gbxBmpPath,
  1309. index = defectBmpNum++,
  1310. bmp = bmpLoc.bmp,
  1311. Xmm = bmpLoc.Xmm,
  1312. Ymm = bmpLoc.Ymm,
  1313. cut_size = new System.Drawing.Size(Convert.ToInt32(aarCut_size[0]), Convert.ToInt32(aarCut_size[1])),
  1314. resize = new System.Drawing.Size(Convert.ToInt32(aarResize[0]), Convert.ToInt32(aarResize[1])),
  1315. thresholds = processParam.Value<float>("Thresholds"),
  1316. thresholdsClass = processParam.Value<string>("ThresholdsClass"),
  1317. recAreaThreshold= getProductAreaThreshol(model), //qxName,面积; qxName,面积; qxName,面积;
  1318. finishEvent = (res) =>
  1319. {
  1320. if (res.isSucceed)
  1321. {
  1322. setDgvContentCol(liStatocStepIndex, $"源图索引:{res.index},缺陷数:{res.defectCount},处理时间(ms):{string.Join("->", res.stopwatch.Select(i => i.ToString()).ToArray())}");
  1323. AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"缺陷检测完成(源图索引:{res.index}),缺陷数:{res.defectCount},处理时间(ms):{string.Join("->", res.stopwatch.Select(i => i.ToString()).ToArray())}");
  1324. string path;
  1325. if (res.defectCount > 0)
  1326. {
  1327. //UI显示小图 (含统计缺陷类型数量)
  1328. showDefectSmallBmps(res.bmps_tag, res.bmps_cut, res.Xmm, res.Ymm, res.informationList);
  1329. if (res.defectInfor2RestorationDeskPage != null && res.defectInfor2RestorationDeskPage.Count > 0)
  1330. {
  1331. AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"转换后坐标数据:{JsonConvert.SerializeObject(res.defectInfor2RestorationDeskPage)}");
  1332. if (order.DefectInfoList == null)
  1333. order.DefectInfoList = new List<DefectInfo>();
  1334. foreach (var item in res.defectInfor2RestorationDeskPage)
  1335. order.DefectInfoList.Add(new DefectInfo()
  1336. {
  1337. Type = 0,
  1338. Code = item[3],
  1339. X = double.Parse(item[1]),
  1340. Y = double.Parse(item[2]),
  1341. ZXD = double.Parse(item[4]),
  1342. ModifyUserCode = Config.loginUser.Code,
  1343. CreateUserCode = Config.loginUser.Code,
  1344. });
  1345. }
  1346. //保存原始大图
  1347. if (Config.Defect_SavePath != "" && Directory.Exists(Config.Defect_SavePath))
  1348. {
  1349. path = Util.createSubDir(Config.Defect_SavePath, new List<string> { order.CreateTime.ToString("yyyyMMdd"), order.SN });
  1350. path += $"Defect_SN{order.SN}_I{res.index}_X{res.Xmm}_Y{res.Ymm}_C{res.defectCount}_{ model.StepInfo.Name}";
  1351. //API.CopyFile(res.file_path, defectFileName + ".bmp", false);//比.NET(File.Copy)更快
  1352. //res.bmp.SaveImage(path + ".bmp");//opencv保存格式与BMP不同
  1353. OpenCvSharp.Extensions.BitmapConverter.ToBitmap(res.bmp).Save(path + ".bmp", ImageFormat.Bmp);
  1354. File.WriteAllText(path + ".json", JsonConvert.SerializeObject(res.informationList));
  1355. }
  1356. //保存小图
  1357. if (Config.Defect_Small_SavePath != "" && Directory.Exists(Config.Defect_Small_SavePath))
  1358. {
  1359. path = Util.createSubDir(Config.Defect_Small_SavePath, new List<string> { order.CreateTime.ToString("yyyyMMdd"), order.SN });
  1360. path += $"Defect_SN{order.SN}_I{res.index}_X{res.Xmm}_Y{res.Ymm}_{ model.StepInfo.Name}";
  1361. for (int i = 0; i < res.bmps_tag.Count(); i++)
  1362. res.bmps_tag[i].Save(path + $"_i{i}.bmp", ImageFormat.Bmp);
  1363. }
  1364. //保存原始小图
  1365. if (Config.Defect_SrcSmall_SavePath != "" && Directory.Exists(Config.Defect_SrcSmall_SavePath))
  1366. {
  1367. for (int i = 0; i < res.defectInfor2RestorationDesk.Count(); i++)
  1368. {
  1369. int indext = int.Parse(res.defectInfor2RestorationDesk[i][0]);
  1370. double thres = double.Parse(res.defectInfor2RestorationDesk[i][4]);
  1371. if (thres >= Config.Defect_SrcSmall_Thres)
  1372. {
  1373. path = Util.createSubDir(Config.Defect_SrcSmall_SavePath,
  1374. new List<string> { order.CreateTime.ToString("yyyyMMdd"),
  1375. order.SN,
  1376. order.ProductInfo.MainGrid == 1?"主栅":order.ProductInfo.ClassesId == 7?"rj":"pi",
  1377. res.defectInfor2RestorationDesk[i][3]});
  1378. path += $"Defect_SN{order.SN}_I{res.index}_X{res.Xmm}_Y{res.Ymm}_{model.StepInfo.Name}";
  1379. res.bmps_cut[indext].ImWrite(path + $"_i{i}.bmp");
  1380. }
  1381. }
  1382. }
  1383. //保存压缩大图 -- 用于修复台调用
  1384. if (Config.Defect_Compress_SavePath != "" && Directory.Exists(Config.Defect_Compress_SavePath))
  1385. {
  1386. path = Util.createSubDir(Config.Defect_Compress_SavePath, new List<string> { order.CreateTime.ToString("yyyyMMdd"), order.SN });
  1387. path += $"Defect_SN{order.SN}_I{res.index}_X{res.Xmm}_Y{res.Ymm}_C{res.defectCount}_{ model.StepInfo.Name}";
  1388. //res.bmpCompress.SaveImage(path + ".bmp");//opencv保存格式与BMP不同
  1389. OpenCvSharp.Extensions.BitmapConverter.ToBitmap(res.bmpCompress).Save(path + ".bmp", ImageFormat.Bmp);
  1390. File.WriteAllText(path + ".json", JsonConvert.SerializeObject(res.defectInfor2RestorationDesk));
  1391. }
  1392. }
  1393. else//没有缺陷
  1394. {
  1395. if (Config.SaveAllDefectImg && Config.Defect_SavePath != "" && Directory.Exists(Config.Defect_SavePath))
  1396. {
  1397. path = Util.createSubDir(Config.Defect_SavePath, new List<string> { order.CreateTime.ToString("yyyyMMdd"), order.SN });
  1398. path += $"Defect_SN{order.SN}_I{res.index}_X{res.Xmm}_Y{res.Ymm}_C{res.defectCount}_{ model.StepInfo.Name}";
  1399. //API.CopyFile(res.file_path, defectFileName + ".bmp", false);//比.NET(File.Copy)更快
  1400. //res.bmp.SaveImage(path + ".bmp");//opencv保存格式与BMP不同
  1401. OpenCvSharp.Extensions.BitmapConverter.ToBitmap(res.bmp).Save(path + ".bmp", ImageFormat.Bmp);
  1402. }
  1403. }
  1404. }
  1405. else
  1406. {
  1407. setDgvContentCol(liStatocStepIndex, $"失败:{res.resultInfo}");
  1408. AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"缺陷检测失败:{res.resultInfo}");
  1409. //warning(WarningEnum.Low);//暂停 这里不能暂停,stepIndex和scannerBmpQueue队列也不对了
  1410. }
  1411. defectBmpNumResult++;
  1412. foreach (var item in res.bmps_cut)
  1413. item.Dispose();
  1414. res.bmp.Dispose();
  1415. res.bmp = null;
  1416. res.bmps_tag = null;
  1417. if (res.bmpCompress != null)
  1418. {
  1419. res.bmpCompress.Dispose();
  1420. res.bmpCompress = null;
  1421. }
  1422. System.GC.Collect();
  1423. }
  1424. });
  1425. #endregion
  1426. break;
  1427. case "For":
  1428. #region
  1429. long UniqueId = processParam.Value<long>("UniqueId");
  1430. int GotoStepIndex = processParam.Value<int>("GotoStepIndex");//1-n
  1431. int LimitNum = processParam.Value<int>("LimitNum");//1-n
  1432. bool Reset = processParam.Value<bool>("Reset");
  1433. if (GotoStepIndex - 1 == stepIndex)
  1434. {
  1435. AddTextEvent($"{stepIndex + 1}-{processName}", $"For死循环!!!");
  1436. warning(WarningEnum.High);
  1437. return stepIndex;
  1438. }
  1439. if (!devContainer.libFor.dicData.ContainsKey(UniqueId))
  1440. devContainer.libFor.dicData.Add(UniqueId, 0);
  1441. //
  1442. int Num = devContainer.libFor.dicData[UniqueId];
  1443. Num++;
  1444. if (Num <= LimitNum)
  1445. {
  1446. if (Num == LimitNum)
  1447. {
  1448. setDgvContentCol(liStatocStepIndex, $"第[{Num}/{LimitNum}]次,循环完成");
  1449. AddTextEvent($"{stepIndex + 1}-{processName}", $"第[{Num}/{LimitNum}]次,循环完成。");
  1450. }
  1451. else
  1452. {
  1453. setDgvContentCol(liStatocStepIndex, $"第[{Num}/{LimitNum}]次");
  1454. AddTextEvent($"{stepIndex + 1}-{processName}", $"第[{Num}/{LimitNum}]次跳转到步骤[{GotoStepIndex}]...");
  1455. stepIndex = GotoStepIndex - 2;
  1456. }
  1457. devContainer.libFor.dicData[UniqueId] = Num;
  1458. }
  1459. else
  1460. {
  1461. setDgvContentCol(liStatocStepIndex, $"已失效不执行");
  1462. AddTextEvent($"{stepIndex + 1}-{processName}", $"本循环已失效不执行!");
  1463. }
  1464. //达到limit重置0
  1465. if (devContainer.libFor.dicData[UniqueId] >= LimitNum && Reset)
  1466. {
  1467. devContainer.libFor.dicData[UniqueId] = 0;
  1468. setDgvContentCol(liStatocStepIndex, $"第[0/{LimitNum}]次");
  1469. AddTextEvent($"{stepIndex + 1}-{processName}", $"计数器已重置。");
  1470. }
  1471. #endregion
  1472. break;
  1473. case "If":
  1474. #region
  1475. long UniqueId_if = processParam.Value<long>("UniqueId");
  1476. int GotoStepIndex_if = processParam.Value<int>("GotoStepIndex");//1-n
  1477. int LimitNum_if = processParam.Value<int>("LimitNum");//1-n
  1478. bool Reset_if = processParam.Value<bool>("Reset");
  1479. if (GotoStepIndex_if - 1 == stepIndex)
  1480. {
  1481. AddTextEvent($"{stepIndex + 1}-{processName}", $"If死循环,不可自我跳转!!!");
  1482. warning(WarningEnum.High);
  1483. return stepIndex;
  1484. }
  1485. //
  1486. if (!devContainer.libIF.dicData.ContainsKey(UniqueId_if))
  1487. devContainer.libIF.dicData.Add(UniqueId_if, 0);
  1488. //
  1489. int Num_if = devContainer.libIF.dicData[UniqueId_if];
  1490. Num_if++;
  1491. if (Num_if <= LimitNum_if)
  1492. {
  1493. if (Num_if == LimitNum_if)
  1494. {
  1495. setDgvContentCol(liStatocStepIndex, $"第[{Num_if}/{LimitNum_if}]次,跳转至[{GotoStepIndex_if}]");
  1496. AddTextEvent($"{stepIndex + 1}-{processName}", $"计数器[{Num_if}/{LimitNum_if}],跳转至步骤[{GotoStepIndex_if}]...");
  1497. stepIndex = GotoStepIndex_if - 2;
  1498. }
  1499. else
  1500. {
  1501. setDgvContentCol(liStatocStepIndex, $"第[{Num_if}/{LimitNum_if}]次,不跳转");
  1502. AddTextEvent($"{stepIndex + 1}-{processName}", $"计数器[{Num_if}/{LimitNum_if}],不跳转。");
  1503. }
  1504. //
  1505. devContainer.libIF.dicData[UniqueId_if] = Num_if;
  1506. }
  1507. else
  1508. {
  1509. setDgvContentCol(liStatocStepIndex, $"已失效不执行");
  1510. AddTextEvent($"{stepIndex + 1}-{processName}", $"本IF已失效不执行。");
  1511. }
  1512. //达到limit重置0
  1513. if (devContainer.libIF.dicData[UniqueId_if] >= LimitNum_if && Reset_if)
  1514. {
  1515. devContainer.libIF.dicData[UniqueId_if] = 0;
  1516. setDgvContentCol(liStatocStepIndex, $"第[0/{LimitNum_if}]次");
  1517. AddTextEvent($"{stepIndex + 1}-{processName}", $"计数器已重置。");
  1518. }
  1519. #endregion
  1520. break;
  1521. default:
  1522. AddTextEvent($"{stepIndex + 1}-{processName}", $"未知工序:{processInfo.ProcessCode}");
  1523. warning(WarningEnum.High);
  1524. return stepIndex;
  1525. }
  1526. if (sleepLater > 0) Thread.Sleep((int)sleepLater);
  1527. }
  1528. //============结束,判断是否自动下料
  1529. if (stepIndex == processList.Count - 1)
  1530. {
  1531. //厚度校正 直接更新并保存
  1532. if (isProductRevise)
  1533. {
  1534. isProductRevise = false;
  1535. if (MessageBox.Show($"厚度校正完成,是否保存?\r\nBase值:{model.HeightBaseDec}", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
  1536. {
  1537. //保存 //更新指定列
  1538. if (svcProduct.Update(it => new Product() { HeightBaseDec = model.HeightBaseDec }, it => it.Id == model.Id))
  1539. AddTextEvent($"产品校正", $"保存成功。");
  1540. else
  1541. AddTextEvent($"产品校正", $"保存失败!!");
  1542. }
  1543. //下料
  1544. currentState = CurrentStateEnum.自动流程结束;
  1545. gotoDownPT();
  1546. }
  1547. else//生产
  1548. {
  1549. //等待缺陷图显示完成
  1550. while (defectBmpNum != defectBmpNumResult)
  1551. Thread.Sleep(100);
  1552. //判断是否合格
  1553. DefectCodeEnum defectCode;
  1554. string defectNames = "";
  1555. if (model.QualifiedCriterionList!= null && model.QualifiedCriterionList.Count >0)
  1556. {
  1557. int itemDefectCount;
  1558. foreach (var item in model.QualifiedCriterionList)
  1559. {
  1560. defectCode = EnumUtil.Convert2Enum<DefectCodeEnum>(item.DefectCode);
  1561. itemDefectCount = getDefectCountFromCode(order, defectCode);
  1562. if (item.MaxDefectCount>-1 && itemDefectCount > item.MaxDefectCount)
  1563. {
  1564. order.Qualified = false;
  1565. defectNames += $"{((DefectNameEnum)(int)defectCode).ToString()}({itemDefectCount}),";
  1566. }
  1567. }
  1568. }
  1569. stopWatch.Stop();
  1570. long timeLen = stopWatch.ElapsedMilliseconds / 1000;
  1571. this.BeginInvoke(new System.Action(() =>
  1572. {
  1573. lblTimeLen.Visible = true;
  1574. lblTimeLen.Text = $"检测时长: {timeLen} 秒";
  1575. if (defectNames != "")
  1576. {
  1577. lblDefectResult.Text = "未通过";
  1578. lblDefectResultCount.Text = defectNames.Substring(0, defectNames.Length - 1);
  1579. this.toolTip1.SetToolTip(lblDefectResultCount, lblDefectResultCount.Text);
  1580. lblDefectResult.ForeColor = lblDefectResultCount.ForeColor = Color.Red;
  1581. }
  1582. }));
  1583. order.TimeLen = timeLen;
  1584. order.DefectCount = (int)this.gboxDefectList.Tag;
  1585. order.Succeed = true;
  1586. order.ModifyUserCode = order.CreateUserCode = Config.loginUser.Code;
  1587. order.Abnormalities = "";//无异常
  1588. order.RepairCode = "";//无修复人员
  1589. //如SN检测已存在,先删除
  1590. var oldSNOrder= svcOrder.GetFirst(m=> m.SN==order.SN);
  1591. if(oldSNOrder!=null)
  1592. {
  1593. AddTextEvent("删除记录", $"删除上一重复SN检测记录:SN={oldSNOrder.SN}, Date={oldSNOrder.CreateTime}");
  1594. svcOrder.DelNav(oldSNOrder);
  1595. }
  1596. if (!svcOrder.InsertNav(order))//导航插入
  1597. AddTextEvent("保存失败", $"保存生产记录失败!");
  1598. //更新本批次检测数量
  1599. if (!string.IsNullOrWhiteSpace(model.BatchId))
  1600. {
  1601. var expOrder = Expressionable.Create<Order>()
  1602. .And(m => m.ProductId == model.Id)
  1603. .And(m => m.BatchId == model.BatchId)
  1604. .ToExpression();//注意 这一句 不能少
  1605. currProductModel.CompleteCount = svcOrder.Count(expOrder);
  1606. }
  1607. //以主键为条件更新CompleteCount单列值
  1608. svcProduct.Update(it => new Product() { CompleteCount = currProductModel.CompleteCount }, it => it.Id == currProductModel.Id);
  1609. if (Config.MakeTag && order.DefectCount > 0)//要打标 and 有缺陷图
  1610. {
  1611. AddTextEvent("完成", $"工序结束,用时 {order.TimeLen} 秒;缺陷 {order.DefectCount} 张.");
  1612. //+(Config.MakeTag ? "开始自动打标...":"手动打标..."));
  1613. currentPT = CurrentPTEnum.MakeTag;
  1614. currentState = CurrentStateEnum.打标中;
  1615. setButtonEnabled(tsbtnGoDownPT, true);
  1616. setButtonEnabled(tsbtnReset, true);
  1617. setButtonEnabled(btnMakeTags, true);
  1618. //if (!Config.MakeTag)//自动打标
  1619. {
  1620. this.Invoke(new System.Action(() =>
  1621. {
  1622. btnMakeTag_Click(null, null);
  1623. }));
  1624. }
  1625. }
  1626. else//下料
  1627. {
  1628. AddTextEvent("完成", $"用时 {order.TimeLen} 秒,进行下料...");
  1629. currentState = CurrentStateEnum.自动流程结束;
  1630. gotoDownPT();
  1631. }
  1632. }
  1633. currProcessIndex = -1;
  1634. return -1;
  1635. }
  1636. else //继续
  1637. {
  1638. return ++stepIndex;
  1639. //return nextProcess(model, ++stepIndex);
  1640. }
  1641. }
  1642. catch (Exception ex)
  1643. {
  1644. AddTextEvent("工序", $"[{stepIndex+1}] Err:" + ex.Message+"\n"+ex.StackTrace);
  1645. warning(WarningEnum.Low);
  1646. return -2;
  1647. }
  1648. }
  1649. private Dictionary<string, float> getProductAreaThreshol(Product m)
  1650. {
  1651. Dictionary<string, float> dic = new Dictionary<string, float>();
  1652. foreach(var item in m.QualifiedCriterionList)
  1653. dic.Add(item.DefectCode, (float)(item.Size * 25.4 * 25.4 / m.HoleCount / m.HoleCount) );//网目 => mm^2
  1654. //全缺陷项
  1655. var lstDefect = Utils.EnumUtil.GetArrayList<DefectCodeEnum>();
  1656. foreach (DictionaryEntry item in lstDefect)
  1657. {
  1658. string code = item.Value.ToString();
  1659. if (!dic.ContainsKey(code))
  1660. dic.Add(code, 0);
  1661. }
  1662. return dic;
  1663. }
  1664. private void setDgvContentCol(int rowIndex, string info)
  1665. {
  1666. int row = rowIndex;//why -1 ???
  1667. this.Invoke(new System.Action(() =>
  1668. {
  1669. this.dgvProcess.Rows[row].Cells["colValue"].Value = info;
  1670. }));
  1671. }
  1672. /// <summary>
  1673. /// 报警,只响应low,high
  1674. /// </summary>
  1675. private void warning(WarningEnum level, bool buzzer = true)
  1676. {
  1677. if (level == WarningEnum.Normal)
  1678. return;
  1679. lock(myLock)
  1680. warningLevel = level;
  1681. if (level == WarningEnum.Low)//暂停
  1682. {
  1683. currentState = CurrentStateEnum.暂停;
  1684. pauseCommand(buzzer);
  1685. }
  1686. else if (level == WarningEnum.High)//急停
  1687. {
  1688. currentState = CurrentStateEnum.急停;
  1689. devContainer.devAxis.stopNow();
  1690. stopNowCommand();
  1691. }
  1692. //启用报警消除按钮
  1693. this.Invoke(new System.Action(() =>
  1694. {
  1695. tsbtnWarning.Enabled = true;
  1696. }));
  1697. }
  1698. private void updateTensionValue(double upperLimit,double lowerLimit)
  1699. {
  1700. int count = lstTension.Count();
  1701. if (count < 1) return;
  1702. switch (count)
  1703. {
  1704. case 1:
  1705. order.Tension1 = lstTension[count - 1];
  1706. AddTextEvent("张力值", $"张力1:{order.Tension1}");
  1707. break;
  1708. case 2:
  1709. order.Tension2 = lstTension[count - 1];
  1710. AddTextEvent("张力值", $"张力2:{order.Tension2}");
  1711. break;
  1712. case 3:
  1713. order.Tension3 = lstTension[count - 1];
  1714. AddTextEvent("张力值", $"张力3:{order.Tension3}");
  1715. break;
  1716. case 4:
  1717. order.Tension4 = lstTension[count - 1];
  1718. AddTextEvent("张力值", $"张力4:{order.Tension4}");
  1719. break;
  1720. case 5:
  1721. order.Tension5 = lstTension[count - 1];
  1722. AddTextEvent("张力值", $"张力5:{order.Tension5}");
  1723. break;
  1724. }
  1725. double value = Math.Round(lstTension.Average(), 2);
  1726. double valueMax = lstTension.Max();
  1727. double valueMin = lstTension.Min();
  1728. if (order != null) order.TensionValue = value;
  1729. Color color = (upperLimit+ lowerLimit>0 && (value > upperLimit || value < lowerLimit)) ? Color.Red : Color.White;
  1730. Color colorMax = (upperLimit + lowerLimit > 0 && (valueMax > upperLimit || valueMax < lowerLimit)) ? Color.Red : Color.White;
  1731. Color colorMin = (upperLimit + lowerLimit > 0 && (valueMin > upperLimit || valueMin < lowerLimit)) ? Color.Red : Color.White;
  1732. this.BeginInvoke(new System.Action(() =>
  1733. {
  1734. this.lblTension.Text = Math.Round(value, 2).ToString();
  1735. this.lblTension.ForeColor = color;
  1736. this.lblTensionMax.Text = Math.Round(valueMax, 2).ToString();
  1737. this.lblTensionMax.ForeColor = colorMax;
  1738. this.lblTensionMin.Text = Math.Round(valueMin, 2).ToString();
  1739. this.lblTensionMin.ForeColor = colorMin;
  1740. }));
  1741. //不合格
  1742. if (color == Color.Red) order.Qualified = false;
  1743. }
  1744. private void updateHeightValue(double upperLimit, double lowerLimit)
  1745. {
  1746. int count = lstHeight.Count();
  1747. if (count < 1) return;
  1748. AddTextEvent("厚度", string.Join(",", lstHeight));
  1749. switch (count)
  1750. {
  1751. case 1:
  1752. order.Height1 = lstHeight[count - 1];
  1753. AddTextEvent("厚度值", $"厚度1:{order.Height1}");
  1754. break;
  1755. case 2:
  1756. order.Height2 = lstHeight[count - 1];
  1757. AddTextEvent("厚度值", $"厚度2:{order.Height2}");
  1758. break;
  1759. case 3:
  1760. order.Height3 = lstHeight[count - 1];
  1761. AddTextEvent("厚度值", $"厚度3:{order.Height3}");
  1762. break;
  1763. case 4:
  1764. order.Height4 = lstHeight[count - 1];
  1765. AddTextEvent("厚度值", $"厚度4:{order.Height4}");
  1766. break;
  1767. case 5:
  1768. order.Height5 = lstHeight[count - 1];
  1769. AddTextEvent("厚度值", $"厚度5:{order.Height5}");
  1770. break;
  1771. }
  1772. double value = Math.Round(lstHeight.Average(), 2);
  1773. double valueMax = lstHeight.Max();
  1774. double valueMin = lstHeight.Min();
  1775. if (order != null) order.HeightValue = value;
  1776. Color color = (upperLimit + lowerLimit > 0 && (value > upperLimit || value < lowerLimit)) ? Color.Red : Color.White;
  1777. Color colorMax = (upperLimit + lowerLimit > 0 && (valueMax > upperLimit || valueMax < lowerLimit)) ? Color.Red : Color.White;
  1778. Color colorMin = (upperLimit + lowerLimit > 0 && (valueMin > upperLimit || valueMin < lowerLimit)) ? Color.Red : Color.White;
  1779. this.Invoke(new System.Action(() =>
  1780. {
  1781. this.lblHeight.Text = Math.Round(value, 2).ToString();
  1782. this.lblHeight.ForeColor = color;
  1783. this.lblHeightMax.Text = Math.Round(valueMax, 2).ToString();
  1784. this.lblHeightMax.ForeColor = colorMax;
  1785. this.lblHeightMin.Text = Math.Round(valueMin, 2).ToString();
  1786. this.lblHeightMin.ForeColor = colorMin;
  1787. }));
  1788. //不合格
  1789. if (color == Color.Red) order.Qualified = false;
  1790. }
  1791. private void updateLineWidthValue(double upperLimit, double lowerLimit)
  1792. {
  1793. int count = lstLineWidth.Count();
  1794. if (count < 1) return;
  1795. switch (count)
  1796. {
  1797. case 1:
  1798. order.LineWidth1 = lstLineWidth[count - 1];
  1799. AddTextEvent("线宽值", $"线宽1:{order.LineWidth1}");
  1800. break;
  1801. case 2:
  1802. order.LineWidth2 = lstLineWidth[count - 1];
  1803. AddTextEvent("线宽值", $"线宽2:{order.LineWidth2}");
  1804. break;
  1805. case 3:
  1806. order.LineWidth3 = lstLineWidth[count - 1];
  1807. AddTextEvent("线宽值", $"线宽3:{order.LineWidth3}");
  1808. break;
  1809. case 4:
  1810. order.LineWidth4 = lstLineWidth[count - 1];
  1811. AddTextEvent("线宽值", $"线宽4:{order.LineWidth4}");
  1812. break;
  1813. case 5:
  1814. order.LineWidth5 = lstLineWidth[count - 1];
  1815. AddTextEvent("线宽值", $"线宽5:{order.LineWidth5}");
  1816. break;
  1817. case 6:
  1818. order.LineWidth6 = lstLineWidth[count - 1];
  1819. AddTextEvent("线宽值", $"线宽6:{order.LineWidth6}");
  1820. break;
  1821. case 7:
  1822. order.LineWidth7 = lstLineWidth[count - 1];
  1823. AddTextEvent("线宽值", $"线宽7:{order.LineWidth7}");
  1824. break;
  1825. case 8:
  1826. order.LineWidth8 = lstLineWidth[count - 1];
  1827. AddTextEvent("线宽值", $"线宽8:{order.LineWidth8}");
  1828. break;
  1829. case 9:
  1830. order.LineWidth9 = lstLineWidth[count - 1];
  1831. AddTextEvent("线宽值", $"线宽9:{order.LineWidth9}");
  1832. break;
  1833. }
  1834. List<double> lstValidValue = new List<double>();
  1835. for (int i = 0; i < count; i++)
  1836. {
  1837. if (lstLineWidth[i] > 0)
  1838. lstValidValue.Add(lstLineWidth[i]);
  1839. }
  1840. if (lstValidValue.Count < 1) return;//WLQ 前面失败时会向lstLineWidth.add(0)
  1841. double value = Math.Round(lstValidValue.Average(), 2);
  1842. double valueMax = lstValidValue.Max();
  1843. double valueMin = lstValidValue.Min();
  1844. if (order != null) order.LineWidthValue = value;
  1845. Color color = (upperLimit + lowerLimit > 0 && (value > upperLimit || value < lowerLimit)) ? Color.Red : Color.White;
  1846. Color colorMax = (upperLimit + lowerLimit > 0 && (valueMax > upperLimit || valueMax < lowerLimit)) ? Color.Red : Color.White;
  1847. Color colorMin = (upperLimit + lowerLimit > 0 && (valueMin > upperLimit || valueMin < lowerLimit)) ? Color.Red : Color.White;
  1848. this.Invoke(new System.Action(() =>
  1849. {
  1850. this.lblLineWidth.Text = Math.Round(value, 2).ToString();
  1851. this.lblLineWidth.ForeColor = color;
  1852. this.lblLineWidthMax.Text = Math.Round(valueMax, 2).ToString();
  1853. this.lblLineWidthMax.ForeColor = colorMax;
  1854. this.lblLineWidthMin.Text = Math.Round(valueMin, 2).ToString();
  1855. this.lblLineWidthMin.ForeColor = colorMin;
  1856. }));
  1857. //不合格
  1858. if (color == Color.Red) order.Qualified = false;
  1859. }
  1860. private void updatePTValue(double upperLimit, double lowerLimit)
  1861. {
  1862. //每次加2个:PT1,PT2
  1863. int count = lstPT.Count();
  1864. if (count < 1) return;
  1865. switch (count)
  1866. {
  1867. case 2:
  1868. order.PT1 = lstPT[count - 2];
  1869. order.PT2 = lstPT[count - 1];
  1870. AddTextEvent("PT值",$"PT1:{order.PT1},PT2:{order.PT2}");
  1871. break;
  1872. case 4:
  1873. order.PT3 = lstPT[count - 2];
  1874. order.PT4 = lstPT[count - 1];
  1875. AddTextEvent("PT值", $"PT3:{order.PT3},PT4:{order.PT4}");
  1876. break;
  1877. case 6:
  1878. order.PT5 = lstPT[count - 2];
  1879. order.PT6 = lstPT[count - 1];
  1880. AddTextEvent("PT值", $"PT5:{order.PT5},PT6:{order.PT6}");
  1881. break;
  1882. }
  1883. List<double> lstValidValue = new List<double>();
  1884. for (int i = 0; i < count; i++)
  1885. {
  1886. if (lstPT[i] > 0)
  1887. lstValidValue.Add(lstPT[i]);
  1888. }
  1889. double value = Math.Round(lstValidValue.Average(), 4);
  1890. double valueMax = lstValidValue.Max();
  1891. double valueMin = lstValidValue.Min();
  1892. if (order != null) order.PTValue = value;
  1893. Color color = (upperLimit + lowerLimit > 0 && (value > upperLimit || value < lowerLimit)) ? Color.Red : Color.White;
  1894. Color colorMax = (upperLimit + lowerLimit > 0 && (valueMax > upperLimit || valueMax < lowerLimit)) ? Color.Red : Color.White;
  1895. Color colorMin = (upperLimit + lowerLimit > 0 && (valueMin > upperLimit || valueMin < lowerLimit)) ? Color.Red : Color.White;
  1896. this.Invoke(new System.Action(() =>
  1897. {
  1898. this.lblPT.Text = value.ToString();
  1899. this.lblPT.ForeColor = color;
  1900. this.lblPTMax.Text = Math.Round(valueMax, 4).ToString();
  1901. this.lblPTMax.ForeColor = colorMax;
  1902. this.lblPTMin.Text = Math.Round(valueMin, 4).ToString();
  1903. this.lblPTMin.ForeColor = colorMin;
  1904. }));
  1905. //不合格
  1906. if (color == Color.Red) order.Qualified = false;
  1907. }
  1908. private void updatePTValueTest(double upperLimit, double lowerLimit)
  1909. {
  1910. //每次加2个:PT1,PT2
  1911. int count = lstPT.Count();
  1912. if (count < 1) return;
  1913. switch (count)
  1914. {
  1915. case 1:
  1916. order.PT1 = lstPT[count - 1];
  1917. AddTextEvent("PT1", $"PT1:{order.PT1}");
  1918. break;
  1919. case 2:
  1920. order.PT2 = lstPT[count - 1];
  1921. AddTextEvent("PT2", $"PT2:{order.PT2}");
  1922. break;
  1923. case 3:
  1924. order.PT3 = lstPT[count - 1];
  1925. order.PT4 = 0;
  1926. AddTextEvent("PT3", $"PT3:{order.PT3}");
  1927. break;
  1928. case 4:
  1929. order.PT5 = lstPT[count - 1];
  1930. AddTextEvent("PT4", $"PT4:{order.PT5}");
  1931. break;
  1932. case 5:
  1933. order.PT6 = lstPT[count - 1];
  1934. AddTextEvent("PT5", $"PT5:{order.PT6}");
  1935. break;
  1936. }
  1937. List<double> lstValidValue = new List<double>();
  1938. for (int i = 0; i < count; i++)
  1939. {
  1940. if (lstPT[i] > 0)
  1941. lstValidValue.Add(lstPT[i]);
  1942. }
  1943. double value = Math.Round(lstValidValue.Average(), 4);
  1944. double valueMax = lstValidValue.Max();
  1945. double valueMin = lstValidValue.Min();
  1946. if (order != null) order.PTValue = value;
  1947. Color color = (upperLimit + lowerLimit > 0 && (value > upperLimit || value < lowerLimit)) ? Color.Red : Color.White;
  1948. Color colorMax = (upperLimit + lowerLimit > 0 && (valueMax > upperLimit || valueMax < lowerLimit)) ? Color.Red : Color.White;
  1949. Color colorMin = (upperLimit + lowerLimit > 0 && (valueMin > upperLimit || valueMin < lowerLimit)) ? Color.Red : Color.White;
  1950. this.Invoke(new System.Action(() =>
  1951. {
  1952. this.lblPT.Text = value.ToString();
  1953. this.lblPT.ForeColor = color;
  1954. this.lblPTMax.Text = Math.Round(valueMax, 4).ToString();
  1955. this.lblPTMax.ForeColor = colorMax;
  1956. this.lblPTMin.Text = Math.Round(valueMin, 4).ToString();
  1957. this.lblPTMin.ForeColor = colorMin;
  1958. }));
  1959. //不合格
  1960. if (color == Color.Red) order.Qualified = false;
  1961. }
  1962. private void updateCompareResult(bool compareResult)
  1963. {
  1964. this.Invoke(new System.Action(() =>
  1965. {
  1966. this.lblCompareResult.Text = (order.CompareResult==1 ? "通过" : "未通过");
  1967. if (!compareResult)
  1968. {
  1969. this.lblCompareResultCount.Text = (Convert.ToInt16(lblCompareResultCount.Text) + 1).ToString();
  1970. this.lblCompareResult.ForeColor = lblCompareResultCount.ForeColor=Color.Red;
  1971. //不合格
  1972. order.Qualified = false;
  1973. }
  1974. }));
  1975. }
  1976. private void resetUIValue()
  1977. {
  1978. this.Invoke(new System.Action(() =>
  1979. {
  1980. //保持产品名称和料号
  1981. //txtProductName.Text = txtProductCode.Text = txtProductSN.Text = "";
  1982. txtProductSN.Text = "";
  1983. lstHeight.Clear();
  1984. lstLineWidth.Clear();
  1985. lstTension.Clear();
  1986. lstPT.Clear();
  1987. this.lblTension.Text = this.lblHeight.Text = this.lblLineWidth.Text = "0.00";
  1988. this.lblPT.Text = this.lblPTMax.Text= this.lblPTMin.Text="0.0000";
  1989. this.lblCompareResult.Text =this.lblDefectResult.Text = "无";
  1990. this.lblTensionMax.Text = this.lblHeightMax.Text = this.lblLineWidthMax.Text
  1991. = this.lblTensionMin.Text = this.lblHeightMin.Text = this.lblLineWidthMin.Text = "0.00";
  1992. this.lblCompareResultCount.Text = "0";
  1993. this.lblDefectResultCount.Text = "无";
  1994. this.toolTip1.SetToolTip(lblDefectResultCount, lblDefectResultCount.Text);
  1995. //
  1996. this.lblTension.ForeColor = this.lblHeight.ForeColor = this.lblLineWidth.ForeColor = this.lblPT.ForeColor = this.lblCompareResult.ForeColor= this.lblDefectResult.ForeColor=Color.White;
  1997. this.lblTensionMax.ForeColor = this.lblHeightMax.ForeColor = this.lblLineWidthMax.ForeColor = this.lblPTMax.ForeColor
  1998. = this.lblTensionMin.ForeColor = this.lblHeightMin.ForeColor = this.lblLineWidthMin.ForeColor = this.lblPTMin.ForeColor = Color.White;
  1999. this.lblCompareResultCount.ForeColor = this.lblDefectResultCount.ForeColor=Color.White;
  2000. this.dgvProcess.DataSource = null;
  2001. this.lstLog.Items.Clear();
  2002. this.clearDefectBmps();
  2003. this.picScanner1.Image = this.picScanner2.Image = null;
  2004. picScanner1.Refresh();
  2005. picScanner2.Refresh();
  2006. this.btnMakeTags.Enabled = false;
  2007. }));
  2008. }
  2009. //info: [{"1":[["92.7542","80.85799","99.54083","86.05363","dk","0.52"]]},
  2010. private void showDefectSmallBmps(Bitmap[] bmps, Mat[] bmps_cut, double Xmm, double Ymm, List<Dictionary<int, List<string>[]>> info)
  2011. {
  2012. this.Invoke(new System.Action(() =>
  2013. {
  2014. int imgWidth = this.pnlBmpList.ClientSize.Width - 50;
  2015. int imgHeight = (int)((bmps[0].Height * 1.0f / bmps[0].Width) * imgWidth + 0.5);
  2016. int splitWidth = 20;
  2017. int pnlWidth = this.pnlBmpList.ClientSize.Width;
  2018. int index = (int)this.gboxDefectList.Tag;
  2019. for (int x = 0; x < info.Count(); x++)
  2020. {
  2021. foreach (var item in info[x]) //单个info[x] = {"1":[["92.7542","80.85799","99.54083","86.05363","dk","0.52"]]}
  2022. {
  2023. //统计缺陷类型
  2024. countDefectClass(item.Value);//[["92.7542","80.85799","99.54083","86.05363","dk","0.52"]]
  2025. //
  2026. PictureBox picbox = new PictureBox();
  2027. picbox.Width = imgWidth;
  2028. picbox.Height = imgHeight;
  2029. CheckBox checkBox = new CheckBox();
  2030. picbox.Image = (Bitmap)bmps[x].Clone();
  2031. picbox.Name = "imgDefect_" + index;
  2032. picbox.Tag = item.Key + "," + Xmm + "," + Ymm;
  2033. checkBox.Tag = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(bmps_cut[item.Key]); //Mat转Bitmap ;//原始小图
  2034. checkBox.Name = "chkDefect_" + index;
  2035. checkBox.Text = $"第{index + 1}张";
  2036. checkBox.CheckedChanged += new System.EventHandler(this.CheckBox_CheckedChanged);
  2037. if (Config.MakeTag)//自动打标
  2038. {
  2039. checkBox.Checked = true;
  2040. checkBox.Enabled = false;
  2041. }
  2042. picbox.Click += new EventHandler(defectBmpBox_Click);
  2043. picbox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
  2044. picbox.BorderStyle = BorderStyle.FixedSingle;
  2045. picbox.Margin = new Padding((pnlWidth - picbox.Width) / 2, splitWidth,0, 0);
  2046. checkBox.Margin = new Padding((pnlWidth - checkBox.Width) / 2 + splitWidth,
  2047. 0, 0, 0);
  2048. //
  2049. //if (this.pnlBmpList.Controls.Count > 0)
  2050. //{
  2051. // if ((this.pnlBmpList.Controls[this.pnlBmpList.Controls.Count - 1].Right + imgWidth + splitWidth) > this.pnlBmpList.Width)
  2052. // picbox.Location = new System.Drawing.Point(splitWidth, this.pnlBmpList.Controls[this.pnlBmpList.Controls.Count - 1].Bottom + splitWidth);
  2053. // else
  2054. // picbox.Location = new System.Drawing.Point(this.pnlBmpList.Controls[this.pnlBmpList.Controls.Count - 1].Right + splitWidth, this.pnlBmpList.Controls[this.pnlBmpList.Controls.Count - 1].Location.Y);
  2055. //}
  2056. //else
  2057. //{
  2058. // picbox.Location = new System.Drawing.Point(splitWidth, 0);
  2059. //}
  2060. //checkBox.Location = new System.Drawing.Point(picbox.Location.X + 5, picbox.Location.Y + 5);
  2061. //checkBox.ForeColor = Color.Black;
  2062. this.pnlBmpList.Controls.Add(picbox);
  2063. this.pnlBmpList.Controls.Add(checkBox);
  2064. break;
  2065. }
  2066. //
  2067. index++;
  2068. };
  2069. this.gboxDefectList.Tag = index;
  2070. this.gboxDefectList.Text = $"缺陷图像:{index} 张";
  2071. if (Config.MakeTag) {
  2072. lblDefectAddTag.Text = $"待打标数:{index}";
  2073. lblDefectAddTag.Tag = index;
  2074. }
  2075. pnlBmpList.VerticalScroll.Value = pnlBmpList.VerticalScroll.Maximum;
  2076. }));
  2077. }
  2078. //统计缺陷类型 [["92.7542","80.85799","99.54083","86.05363","dk","0.52"]]
  2079. private void countDefectClass(List<string>[] list)
  2080. {
  2081. string className;
  2082. for(int i=0; i<list.Length; i++)
  2083. {
  2084. className = list[i][4];
  2085. switch (className)
  2086. {
  2087. case "dk":
  2088. order.DKCount++;
  2089. break;
  2090. case "zw":
  2091. order.ZWCount++;
  2092. break;
  2093. case "gsyc":
  2094. order.GSYCCount++;
  2095. break;
  2096. case "xws":
  2097. order.XWSCount++;
  2098. break;
  2099. case "qk":
  2100. order.QKCount++;
  2101. break;
  2102. case "zk":
  2103. order.ZKCount++;
  2104. break;
  2105. case "pp":
  2106. order.PPCount++;
  2107. break;
  2108. case "hs":
  2109. order.HSCount++;
  2110. break;
  2111. case "yx":
  2112. order.YXCount++;
  2113. break;
  2114. case "xb":
  2115. order.XBCount++;
  2116. break;
  2117. case "sx":
  2118. order.SXCount++;
  2119. break;
  2120. }
  2121. }
  2122. }
  2123. private int getDefectCountFromCode(Order order, DefectCodeEnum defectCodeEnum)
  2124. {
  2125. switch (defectCodeEnum)
  2126. {
  2127. case DefectCodeEnum.dk:
  2128. return order.DKCount;
  2129. case DefectCodeEnum.zw:
  2130. return order.ZWCount;
  2131. case DefectCodeEnum.gsyc:
  2132. return order.GSYCCount;
  2133. case DefectCodeEnum.xws:
  2134. return order.XWSCount;
  2135. case DefectCodeEnum.qk:
  2136. return order.QKCount;
  2137. case DefectCodeEnum.zk:
  2138. return order.ZKCount;
  2139. case DefectCodeEnum.pp:
  2140. return order.PPCount;
  2141. case DefectCodeEnum.hs:
  2142. return order.HSCount;
  2143. case DefectCodeEnum.yx:
  2144. return order.YXCount;
  2145. case DefectCodeEnum.xb:
  2146. return order.XBCount;
  2147. case DefectCodeEnum.gsdl:
  2148. return order.SXCount;
  2149. default:
  2150. return 0;
  2151. }
  2152. }
  2153. private void CheckBox_CheckedChanged(object sender, EventArgs e)
  2154. {
  2155. CheckBox ck = (CheckBox)sender;
  2156. int cout = Convert.ToInt32(this.lblDefectAddTag.Tag);
  2157. if (ck.Checked)
  2158. cout++;
  2159. else
  2160. cout--;
  2161. lblDefectAddTag.Text = $"待打标数:{cout}";
  2162. lblDefectAddTag.Tag = cout;
  2163. }
  2164. private void defectBmpBox_Click(object sender, EventArgs e)
  2165. {
  2166. // if(autoMakeTagRuning) //自动打标中不可打开人工达标窗
  2167. PictureBox picbox = sender as PictureBox;
  2168. if (!devContainer.state || defectBmpNum != defectBmpNumResult || autoMakeTagRuning || currentState != CurrentStateEnum.自动流程结束)//检测中
  2169. {
  2170. //只查看
  2171. FrmPhoto frm = new FrmPhoto(this.pnlBmpList.Controls, Convert.ToInt32(picbox.Name.Split(new char[] { '_' })[1]));
  2172. frm.ShowDialog(this);
  2173. }
  2174. else//完成
  2175. {
  2176. FrmPhotoTag frm = new FrmPhotoTag(this.pnlBmpList.Controls, Convert.ToInt32(picbox.Name.Split(new char[] { '_' })[1])
  2177. ,(defectBmpNum == defectBmpNumResult ? this.devContainer : null));
  2178. frm.ShowDialog(this);
  2179. //
  2180. if (devContainer.state && !Config.SkipScannerCC)
  2181. {
  2182. devContainer.devScannerCC.setMode(false);
  2183. devContainer.devScannerCC.setPreviewWin(this.picScanner1.Handle);
  2184. }
  2185. }
  2186. }
  2187. private void clearDefectBmps()
  2188. {
  2189. this.pnlBmpList.Controls.Clear();
  2190. this.gboxDefectList.Text = $"缺陷图像";
  2191. this.gboxDefectList.Tag = 0;
  2192. this.lblDefectAddTag.Text = "";
  2193. this.lblDefectAddTag.Tag = 0;
  2194. }
  2195. public delegate void AddTextDelegate(string tag, string msg, WarningEnum level);
  2196. /// <summary>
  2197. /// 异步输出日志
  2198. /// </summary>
  2199. /// <param name="tag">模板标识</param>
  2200. /// <param name="msg">内容</param>
  2201. /// <param name="type"></param>
  2202. private void AddTextEvent(string tag, string msg, WarningEnum level = WarningEnum.Normal)
  2203. {
  2204. try
  2205. {
  2206. if (InvokeRequired)
  2207. {
  2208. Invoke(new AddTextDelegate(AddTextEvent), new object[]
  2209. {
  2210. tag,
  2211. msg,
  2212. level
  2213. });
  2214. }
  2215. else
  2216. {
  2217. if (tag != null && tag != "")
  2218. tag = $" - [{tag}]";
  2219. var now = DateTime.Now;
  2220. msg = now.ToString("HH:mm:ss fff") + tag + " - " + msg;
  2221. //cont = MyHelper.subString(cont, 300);
  2222. //写日志,warn和error日志直接写
  2223. writeLog(now, level, msg);
  2224. //
  2225. //if (type > 0)
  2226. // cont = $"<color=\"{(type == 1 ? "Yellow" : "Red")}\">{cont}</color>";
  2227. msg = (level == WarningEnum.Normal ? "B" : level == WarningEnum.Low ? "Y" : "R") + msg;
  2228. this.Invoke(new System.Action(() =>
  2229. {
  2230. if (this.lstLog.Items.Count > 1000)
  2231. this.lstLog.Items.Clear();
  2232. lstLog.Items.Insert(0, msg);
  2233. }));
  2234. //日志滚动
  2235. //lstLog.SelectedIndex = lstLog.Items.Count - 1;
  2236. }
  2237. }
  2238. catch (Exception ex)
  2239. {
  2240. //MessageBox.Show("AddTextEvent ex=(" + ex.Message + ")", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, 0);
  2241. }
  2242. }
  2243. private void lstLog_DrawItem(object sender, DrawItemEventArgs e)
  2244. {
  2245. e.DrawBackground();
  2246. if (e.Index < 0) return;
  2247. try
  2248. {
  2249. string str = lstLog.Items[e.Index].ToString();
  2250. e.Graphics.DrawString(str.Substring(1), e.Font,
  2251. new SolidBrush(str[0] == 'R' ? Color.Red : (str[0] == 'Y' ? Color.Orange : Color.Black)),
  2252. e.Bounds);
  2253. }
  2254. catch
  2255. {
  2256. ;
  2257. }
  2258. }
  2259. private void writeLog(DateTime now, WarningEnum level, string text)
  2260. {
  2261. string directory = Config.LogPath + "\\" + DateTime.Now.ToString("yyyyMM") + "\\";
  2262. //if (type == 0) directory = Application.StartupPath + "\\Log\\Info\\";
  2263. //else if (type == 1) directory = Application.StartupPath + "\\Log\\Warn\\";
  2264. //else directory = Application.StartupPath + "\\Log\\Error\\";
  2265. if (!System.IO.Directory.Exists(directory))
  2266. System.IO.Directory.CreateDirectory(directory);
  2267. File.AppendAllText(directory + now.ToString("yyyyMMdd") + ".log", text + "\r\n");
  2268. }
  2269. private void FrmMian_FormClosing(object sender, FormClosingEventArgs e)
  2270. {
  2271. if (devContainer.state)
  2272. {
  2273. MessageBox.Show("请先停止生产后才能关闭程序!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  2274. e.Cancel = true;
  2275. return;
  2276. }
  2277. if (!bExitApp && MessageBox.Show($"确认退出?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
  2278. {
  2279. e.Cancel = true;
  2280. return;
  2281. }
  2282. }
  2283. private void FrmMian_FormClosed(object sender, FormClosedEventArgs e)
  2284. {
  2285. webService.stop();
  2286. Application.Exit();
  2287. System.GC.Collect();
  2288. System.Environment.Exit(0);
  2289. }
  2290. private void tsbtnOpenDev_Click(object sender, EventArgs e)
  2291. {
  2292. //FrmGetPosByPic frr = new FrmGetPosByPic(new SizeLibProp());
  2293. //frr.ShowDialog();
  2294. Config.LoadAllConfig();
  2295. //设置程序最小/大线程池
  2296. // Get the current settings.
  2297. int minWorker, minIOC;
  2298. ThreadPool.GetMinThreads(out minWorker, out minIOC);
  2299. ThreadPool.SetMinThreads(25, minIOC);
  2300. //ThreadPool.SetMaxThreads(256, 256);
  2301. this.tsbtnProductRevise.Enabled = false;
  2302. this.tsbtnOpenDev.Enabled = false;
  2303. //scannerCBmpIndex = 0;
  2304. isProductRevise = false;
  2305. this.resetUIValue();
  2306. currProcessIndex = -1;
  2307. currentState = CurrentStateEnum.等待复位;
  2308. warningLevel = WarningEnum.Normal;
  2309. currentPT = CurrentPTEnum.InitPT;
  2310. this.tsbtnWarning.Enabled=this.tsbtnGoDownPT.Enabled=this.tsbtnStart.Enabled=this.tsbtnStopNow.Enabled=this.tsbtnPause.Enabled=this.tsbtnReset.Enabled=false;
  2311. //后台线程回调事件
  2312. devContainer.StateChange = (state, msg) =>
  2313. {
  2314. if (state)
  2315. {
  2316. //全局中断
  2317. devContainer.devIOCard.INEvent = globalBreakEvent;
  2318. devContainer.OutDebugEvent = (tag, debugInfo) =>
  2319. {
  2320. AddTextEvent(tag, debugInfo);
  2321. };
  2322. //
  2323. AddTextEvent("设备启动", "请先进行复位操作!");
  2324. this.Invoke(new System.Action(() =>
  2325. {
  2326. this.tsbtnReset.Enabled = true;
  2327. tsbtnWarning.Enabled = this.tsbtnStart.Enabled = this.tsbtnGoDownPT.Enabled
  2328. = this.tsbtnPause.Enabled = this.tsbtnStopNow.Enabled = false;
  2329. this.tsbtnOpenDev.Enabled = true;
  2330. this.tsbtnOpenDev.Visible = false;
  2331. this.tsbtnCloseDev.Visible = true;
  2332. }));
  2333. timer.Elapsed += Timer_Elapsed;
  2334. timer.Interval = 500;
  2335. timer.Start();
  2336. }
  2337. else
  2338. {
  2339. AddTextEvent("设备启动", $"启动失败,{msg}", WarningEnum.High);
  2340. this.Invoke(new System.Action(() =>
  2341. {
  2342. this.tsbtnOpenDev.Enabled = true;
  2343. this.tsbtnOpenDev.Visible = true;
  2344. this.tsbtnCloseDev.Visible = false;
  2345. }));
  2346. }
  2347. };
  2348. devContainer.WarningEvent = (level, msg) =>
  2349. {
  2350. AddTextEvent("设备事件", msg, level);
  2351. if (level == WarningEnum.High)
  2352. warning(level,true);
  2353. };
  2354. devContainer.start(this.picScanner1.Handle, this.picScanner2.Handle);
  2355. }
  2356. private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
  2357. {
  2358. this.Invoke(new System.Action(() =>
  2359. {
  2360. this.tsAxisState.Text = $"[命令位:{devContainer.devAxis.CmdPos[0]} 反馈位:{devContainer.devAxis.ActualPos[0]}] | " +
  2361. $"[命令位:{devContainer.devAxis.CmdPos[1]} 反馈位:{devContainer.devAxis.ActualPos[1]}] | " +
  2362. $"[命令位:{devContainer.devAxis.CmdPos[2]} 反馈位:{devContainer.devAxis.ActualPos[2]}] | " +
  2363. $"[命令位:{devContainer.devAxis.CmdPos[3]} 反馈位:{devContainer.devAxis.ActualPos[3]}]";
  2364. }));
  2365. }
  2366. private void tsbtnCloseDev_Click(object sender, EventArgs e)
  2367. {
  2368. AddTextEvent("设备停止", $"设备停止...");
  2369. this.tsbtnProductRevise.Enabled = false;
  2370. this.tsbtnOpenDev.Visible = true;
  2371. this.tsbtnCloseDev.Visible = false;
  2372. this.btnMakeTags.Enabled = false;
  2373. this.lblTimeLen.Visible = false;
  2374. this.tsbtnReset.Enabled = tsbtnWarning.Enabled = this.tsbtnStart.Enabled = this.tsbtnGoDownPT.Enabled
  2375. = this.tsbtnPause.Enabled = this.tsbtnStopNow.Enabled = false;
  2376. this.tsbtnSizeTag.Enabled = tsbtnSizeImage.Enabled = tsbtnDefectImage.Enabled = false;
  2377. if (devContainer.state)
  2378. {
  2379. devContainer.devIOCard.reset();
  2380. devContainer.io_output(CMDName.IO默认输出);
  2381. }
  2382. timer.Stop();
  2383. devContainer.stop();
  2384. }
  2385. /// <summary>
  2386. /// 全局中断
  2387. /// </summary>
  2388. private void globalBreakEvent(int portIndex, byte data)
  2389. {
  2390. if (compareIOInput(CMDName.启动按钮) && this.tsbtnStart.Enabled)
  2391. startCommand();
  2392. else if (compareIOInput(CMDName.暂停按钮) && this.tsbtnPause.Enabled)
  2393. warning(WarningEnum.Low, false);
  2394. else if (compareIOInput(CMDName.复位按钮) && this.tsbtnReset.Enabled)
  2395. resetCommand();
  2396. else if (compareIOInput(CMDName.张力读取) && currentPT == CurrentPTEnum.Moving)
  2397. readTension();
  2398. else if (!this.disableBuzzer && compareIOInput(CMDName.门磁告警输入))
  2399. warning(WarningEnum.Low, true);
  2400. else if (!this.disableBuzzer && compareIOInput(CMDName.喷墨告警输入))
  2401. warning(WarningEnum.Low, true);
  2402. }
  2403. private bool compareIOInput(CMDName key)
  2404. {
  2405. JObject joJson = Config.CMDProcess[key];
  2406. IODirectionEnum direction = (IODirectionEnum)joJson.Value<int>("Direction");
  2407. if (direction == IODirectionEnum.输入 || direction == IODirectionEnum.输入输出)
  2408. {
  2409. return Util.compareIOInput(
  2410. joJson.Value<JArray>("IN_OP_SHOW").ToObject<List<string>>().ToArray(),
  2411. devContainer.devIOCard.DIData);
  2412. }
  2413. return false;
  2414. }
  2415. private void readTension()
  2416. {
  2417. if (Config.SkipTension)
  2418. {
  2419. AddTextEvent("张力读取", $"张力设备禁用,忽略此步骤!");
  2420. return;
  2421. }
  2422. devContainer.io_output(CMDName.张力读取);
  2423. double tensionValue = devContainer.devTension.getValue() + Config.Tension_Offset;//加入张力偏差
  2424. tensionValue=Math.Round(tensionValue, 2);//保留2位小数
  2425. AddTextEvent("张力读取", $"张力值:{tensionValue}");
  2426. devContainer.io_output(CMDName.张力读取,false,true,500);
  2427. lstTension.Add(tensionValue);
  2428. updateTensionValue(currProductModel.TensionBaseValue + currProductModel.TensionUpFloatValue, currProductModel.TensionBaseValue - currProductModel.TensionDownFloatValue);
  2429. }
  2430. /// <summary>
  2431. /// 启动
  2432. /// </summary>
  2433. private void startCommand()
  2434. {
  2435. this.setButtonEnabled(this.tsbtnProductRevise, false);
  2436. //2023-10-23 运行前清除过期图片文件
  2437. Config.DelectPictureFile();
  2438. if (!devContainer.state || warningLevel != WarningEnum.Normal || currentState != CurrentStateEnum.等待启动)
  2439. return;
  2440. if (currentPT == CurrentPTEnum.MakeTag)
  2441. {
  2442. AddTextEvent("启动", "打标未结束,非可启动状态!", warningLevel);
  2443. return;
  2444. }
  2445. if (!devContainer.devAxis.isReady())
  2446. {
  2447. AddTextEvent("启动", "轴状态异常,不可启动!", warningLevel);
  2448. return;
  2449. }
  2450. if (!devContainer.devAxis.IsReset)
  2451. {
  2452. AddTextEvent("启动", "轴需先进行复位操作!", WarningEnum.High);
  2453. return;
  2454. }
  2455. devContainer.io_output(CMDName.启动按钮);
  2456. devContainer.io_output(CMDName.绿灯输出);
  2457. devContainer.io_output(CMDName.暂停按钮, false, true, 0);
  2458. devContainer.io_output(CMDName.红灯输出, false, true, 0);
  2459. devContainer.io_output(CMDName.黄灯输出, false, true, 0);
  2460. //暂停-》继续
  2461. if (currProcessIndex >= 0 && currentPT == CurrentPTEnum.Moving && currentState == CurrentStateEnum.等待启动)
  2462. {
  2463. AddTextEvent("启动", $"暂停 -> 继续 当前工序索引:{currProcessIndex + 1}");
  2464. threadProcess = new System.Threading.Thread(() =>
  2465. {
  2466. int nextStepId = currProcessIndex;
  2467. do
  2468. {
  2469. currentState = CurrentStateEnum.运行中;
  2470. nextStepId = nextProcess(currProductModel, nextStepId);
  2471. } while (nextStepId >= 0 && !isBreakProcessRun());
  2472. //nextProcess(currProductModel, currProcessIndex);
  2473. });
  2474. threadProcess.IsBackground = true;
  2475. threadProcess.Start();
  2476. this.setButtonEnabled(this.tsbtnPause, true);
  2477. this.setButtonEnabled(this.tsbtnStopNow, true);
  2478. }
  2479. else//开始/重新开始
  2480. {
  2481. //校正从复位-》运行,不会新启动
  2482. isProductRevise = false;
  2483. resetUIValue();
  2484. AddTextEvent("启动", "移动至上料位...");
  2485. gotoUpPT();
  2486. this.Invoke(new System.Action(() =>
  2487. {
  2488. //新开始
  2489. lblTimeLen.Visible = false;
  2490. runStep();
  2491. }));
  2492. this.setButtonEnabled(this.tsbtnPause, false);
  2493. this.setButtonEnabled(this.tsbtnStopNow, false);
  2494. }
  2495. this.setButtonEnabled(this.tsbtnStart, false);
  2496. this.setButtonEnabled(this.tsbtnReset, false);
  2497. this.setButtonEnabled(this.tsbtnGoDownPT, false);
  2498. }
  2499. /// <summary>
  2500. /// 暂停
  2501. /// </summary>
  2502. /// <param name="buzzer">是否响蜂鸣</param>
  2503. private void pauseCommand(bool buzzer = false)
  2504. {
  2505. devContainer.io_output(CMDName.暂停按钮);
  2506. if (buzzer)
  2507. {
  2508. devContainer.io_output(CMDName.红灯输出);
  2509. devContainer.io_output(CMDName.蜂鸣器输出);
  2510. }
  2511. else
  2512. devContainer.io_output(CMDName.黄灯输出);
  2513. devContainer.io_output(CMDName.启动按钮, false, true, 0);
  2514. devContainer.io_output(CMDName.绿灯输出, false, true, 0);
  2515. this.setButtonEnabled(this.tsbtnWarning, true);
  2516. this.setButtonEnabled(this.tsbtnGoDownPT, false);
  2517. this.setButtonEnabled(this.tsbtnStart, false);
  2518. this.setButtonEnabled(this.tsbtnPause, false);
  2519. this.setButtonEnabled(this.tsbtnStopNow, false);
  2520. this.setButtonEnabled(this.tsbtnReset, false);
  2521. AddTextEvent("暂停", $"当前工序索引:{currProcessIndex + 1}", WarningEnum.Low);
  2522. }
  2523. /// <summary>
  2524. /// 急停
  2525. /// </summary>
  2526. private void stopNowCommand()
  2527. {
  2528. if (!devContainer.state)
  2529. {
  2530. this.setButtonEnabled(this.tsbtnStopNow, false);
  2531. return;
  2532. }
  2533. devContainer.io_output(CMDName.Y轴复位输出, false, true, 0);
  2534. devContainer.io_output(CMDName.红灯输出);
  2535. if (!this.disableBuzzer) devContainer.io_output(CMDName.蜂鸣器输出);
  2536. devContainer.io_output(CMDName.暂停按钮, false, true, 0);
  2537. devContainer.io_output(CMDName.黄灯输出, false, true, 0);
  2538. devContainer.io_output(CMDName.启动按钮, false, true, 0);
  2539. devContainer.io_output(CMDName.绿灯输出, false, true, 0);
  2540. this.setButtonEnabled(this.tsbtnWarning, true);
  2541. this.setButtonEnabled(this.tsbtnGoDownPT, false);
  2542. this.setButtonEnabled(this.tsbtnStart, false);
  2543. this.setButtonEnabled(this.tsbtnPause, false);
  2544. this.setButtonEnabled(this.tsbtnStopNow, false);
  2545. this.setButtonEnabled(this.tsbtnReset, false);
  2546. AddTextEvent("急停", $"当前工序索引:{currProcessIndex + 1}", WarningEnum.High);
  2547. }
  2548. private bool reseting = false;
  2549. private void resetCommand()
  2550. {
  2551. currentState = CurrentStateEnum.等待复位;
  2552. warningLevel = WarningEnum.Normal;
  2553. currentPT = CurrentPTEnum.InitPT;
  2554. this.Invoke(new System.Action(() =>
  2555. {
  2556. lblTimeLen.Visible = false;
  2557. this.tsbtnWarning.Enabled = this.tsbtnGoDownPT.Enabled = this.tsbtnStart.Enabled = this.tsbtnStopNow.Enabled = this.tsbtnPause.Enabled = this.tsbtnReset.Enabled = false;
  2558. }));
  2559. try
  2560. {
  2561. if (devContainer.state && !reseting)
  2562. {
  2563. reseting = true;
  2564. isProductRevise = false;
  2565. resetUIValue();
  2566. AddTextEvent("复位", $"设备复位中...");
  2567. currProcessIndex = -1;
  2568. this.setButtonEnabled(this.tsbtnReset, false);
  2569. // I/O reset后,输出默认状态
  2570. AddTextEvent("复位", $"I/O复位中...");
  2571. if (!devContainer.devIOCard.reset())
  2572. {
  2573. AddTextEvent("复位", "I/O板卡复位失败!", WarningEnum.High);
  2574. return;
  2575. }
  2576. if (!devContainer.io_output(CMDName.IO默认输出))
  2577. {
  2578. //AddTextEvent("复位", "I/O板卡复位默认值失败!", WarningEnum.High);
  2579. //return;
  2580. }
  2581. //板卡复位输出灯
  2582. devContainer.io_output(CMDName.复位按钮);
  2583. devContainer.io_output(CMDName.黄灯输出, true);
  2584. //4.5X
  2585. if(!Config.SkipSmallAxis)
  2586. devContainer.devSmallAxis.gotoPos((int)SmallAxCmdPos.倍率4_5X, false);
  2587. //移动Axis前等待厚度传感器收回
  2588. AddTextEvent("复位", $"检测厚度传感器安全值...");
  2589. if (!Config.SkipHeight)
  2590. {
  2591. while (devContainer.devHeight.getHeight() < (double)Math.Abs(Config.HeightDev_SafeValue))
  2592. {
  2593. if (!devContainer.state || currentState != CurrentStateEnum.等待复位)
  2594. return;
  2595. Thread.Sleep(100);
  2596. Application.DoEvents();
  2597. }
  2598. }
  2599. //goto ORG
  2600. AddTextEvent("复位", $"轴正在回原点...");
  2601. devContainer.devAxis.closeJogMode();
  2602. devContainer.devAxis.resetAxisState(-1);//reset state
  2603. //AddTextEvent("复位", $"重置轴状态...");
  2604. for (int i = 0; i < Config.Axis_HomeMode.Length; i++)
  2605. {
  2606. //到起始位速度使用回HOME速度
  2607. devContainer.devAxis.setAxisVelParam((double)Config.Axis_HomeVelLow[i], (double)Config.Axis_HomeVelHigh[i],
  2608. (double)Config.Axis_HomeAcc[i], (double)Config.Axis_HomeDec[i], i);
  2609. if (i != 2)
  2610. {
  2611. //devContainer.devAxis.setAxisVelParam(40000,200000,5000000, 5000000,i,true);
  2612. devContainer.devAxis.home(i, (uint)Config.Axis_HomeMode[i], (uint)Config.Axis_HomeDir[i]);
  2613. }
  2614. else//Y轴 I/O控制回HOME
  2615. {
  2616. devContainer.io_output(CMDName.Y轴复位输出);
  2617. }
  2618. }
  2619. AddTextEvent("复位", $"等待轴状态完成...");
  2620. while (!devContainer.devAxis.isReady())
  2621. {
  2622. if (!devContainer.state || currentState != CurrentStateEnum.等待复位)
  2623. {
  2624. AddTextEvent("复位", $"当前状态:"+ ((CurrentStateEnum)currentState).ToString());
  2625. return;
  2626. }
  2627. //AddTextEvent("复位", $"轴0状态:"+ ((AxisState)devContainer.devAxis.AxState[0]).ToString());
  2628. //AddTextEvent("复位", $"轴1状态:" + ((AxisState)devContainer.devAxis.AxState[1]).ToString());
  2629. //AddTextEvent("复位", $"轴2状态:" + ((AxisState)devContainer.devAxis.AxState[2]).ToString());
  2630. //AddTextEvent("复位", $"轴3状态:" + ((AxisState)devContainer.devAxis.AxState[3]).ToString());
  2631. Thread.Sleep(1000);
  2632. Application.DoEvents();
  2633. }
  2634. //判断Y轴回原点完成I/O信号
  2635. AddTextEvent("复位", $"等待Y轴回HOME完成...");
  2636. while (!this.compareIOInput(CMDName.Y轴复位完成输入))
  2637. {
  2638. Thread.Sleep(100);
  2639. Application.DoEvents();
  2640. }
  2641. AddTextEvent("复位", $"Y轴回HOME已完成.");
  2642. devContainer.io_output(CMDName.Y轴复位输出, false, true, 0);
  2643. AddTextEvent("复位", $"重置Y轴反馈位置与命令位置.");
  2644. devContainer.devAxis.resetCmdPosition(2);
  2645. devContainer.devAxis.resetActualPosition(2);
  2646. //
  2647. if (devContainer.devAxis.isError())
  2648. throw new Exception("轴回原点失败!");
  2649. if (Config.OpenAxisXCalibration)
  2650. {
  2651. //2023-11-29 加入X1X2回原之后启动补偿
  2652. devContainer.io_output(CMDName.X1轴复位输出, false, true, 300);
  2653. devContainer.io_output(CMDName.X2轴复位输出, false, true, 300);
  2654. }
  2655. //
  2656. //goto InitPT
  2657. //AddTextEvent("复位", $"轴回原点完成,回到初始位...");
  2658. JArray arrPT = Config.joPTSetting.Value<JArray>("initPT");
  2659. for (int i = 0; i < arrPT.Count; i++)
  2660. {
  2661. if (!devContainer.state || currentState != CurrentStateEnum.等待复位)
  2662. return;
  2663. AddTextEvent($"复位", $"轴{i}准备运动至初始位:{(double)arrPT[i]}(当前轴状态:{((AxisState)devContainer.devAxis.AxState[i]).ToString()})...");
  2664. devContainer.devAxis.move_ptp(i, (double)arrPT[i], AxMoveMode.绝对位置);
  2665. }
  2666. while (!devContainer.devAxis.isReady())
  2667. {
  2668. if (!devContainer.state || warningLevel != WarningEnum.Normal)
  2669. return;
  2670. Thread.Sleep(100);
  2671. }
  2672. if (devContainer.devAxis.isError())
  2673. throw new Exception("轴移动至初始位失败!");
  2674. //
  2675. this.setButtonEnabled(this.tsbtnReset, true);
  2676. this.setButtonEnabled(this.tsbtnStart, true);
  2677. this.setButtonEnabled(this.tsbtnStopNow, true);
  2678. this.setButtonEnabled(this.tsbtnPause, false);
  2679. this.setButtonEnabled(this.tsbtnGoDownPT, false);
  2680. this.setButtonEnabled(this.tsbtnWarning, false);
  2681. devContainer.io_output(CMDName.复位按钮, false, true, 0);//熄灭
  2682. devContainer.io_output(CMDName.黄灯输出);//长亮
  2683. currentPT = CurrentPTEnum.InitPT;
  2684. currentState = CurrentStateEnum.等待启动;
  2685. AddTextEvent("复位", $"复位完成。");
  2686. this.setButtonEnabled(this.tsbtnProductRevise, true);
  2687. }
  2688. else
  2689. {
  2690. AddTextEvent("复位", "非可复位状态,请先停止后再复位!", WarningEnum.High);
  2691. }
  2692. }
  2693. catch (Exception ex)
  2694. {
  2695. AddTextEvent("复位", "复位失败 Err:" + ex.Message, WarningEnum.High);
  2696. warning(WarningEnum.High, true);
  2697. }
  2698. finally
  2699. {
  2700. reseting = false;
  2701. }
  2702. }
  2703. /// <summary>
  2704. /// 上料
  2705. /// </summary>
  2706. private void gotoUpPT()
  2707. {
  2708. try
  2709. {
  2710. JArray arrPT = Config.joPTSetting.Value<JArray>("upPT");
  2711. for (int i = 0; i < arrPT.Count; i++)
  2712. {
  2713. if (!devContainer.state || warningLevel != WarningEnum.Normal)
  2714. return;
  2715. AddTextEvent($"上料", $"轴{i}准备运动至上料位:{(double)arrPT[i]}(当前轴状态:{((AxisState)devContainer.devAxis.AxState[i]).ToString()})...");
  2716. devContainer.devAxis.move_ptp(i, (double)arrPT[i], AxMoveMode.绝对位置);
  2717. }
  2718. while (!devContainer.devAxis.isReady())
  2719. {
  2720. if (!devContainer.state || warningLevel != WarningEnum.Normal)
  2721. return;
  2722. Thread.Sleep(100);
  2723. }
  2724. if (devContainer.devAxis.isError())
  2725. throw new Exception("轴移动至上料位失败!");
  2726. //
  2727. currentPT = CurrentPTEnum.UpPT;
  2728. currentState = CurrentStateEnum.等待扫码;
  2729. AddTextEvent($"上料", "到达上料位!");
  2730. }
  2731. catch (Exception ex)
  2732. {
  2733. AddTextEvent("上料", "上料初始失败 Err:" + ex.Message, WarningEnum.High);
  2734. warning(WarningEnum.High);
  2735. }
  2736. }
  2737. /// <summary>
  2738. /// 下料
  2739. /// </summary>
  2740. private void gotoDownPT()
  2741. {
  2742. try
  2743. {
  2744. if (currentState != CurrentStateEnum.打标中 && currentState != CurrentStateEnum.等待启动 && currentState != CurrentStateEnum.自动流程结束)
  2745. {
  2746. AddTextEvent($"下料", $"非可下料状态:{currentState.ToString()}");
  2747. return;
  2748. }
  2749. currentState = CurrentStateEnum.下料中;
  2750. isProductRevise = false;
  2751. JArray arrPT = Config.joPTSetting.Value<JArray>("downPT");
  2752. for (int i = 0; i < arrPT.Count; i++)
  2753. {
  2754. if (!devContainer.state || warningLevel != WarningEnum.Normal || currentState != CurrentStateEnum.下料中)
  2755. return;
  2756. AddTextEvent($"下料", $"轴{i}准备运动至下料位:{(double)arrPT[i]}(当前轴状态:{((AxisState)devContainer.devAxis.AxState[i]).ToString()})...");
  2757. devContainer.devAxis.move_ptp(i, (double)arrPT[i], AxMoveMode.绝对位置);
  2758. }
  2759. while (!devContainer.devAxis.isReady())
  2760. {
  2761. if (!devContainer.state || warningLevel != WarningEnum.Normal || currentState != CurrentStateEnum.下料中)
  2762. return;
  2763. Thread.Sleep(100);
  2764. }
  2765. if (devContainer.devAxis.isError())
  2766. throw new Exception("轴移动至下料位失败!");
  2767. //
  2768. currentPT = CurrentPTEnum.DownPT;
  2769. currentState = CurrentStateEnum.等待启动;
  2770. devContainer.io_output(CMDName.下料完成输出);
  2771. setButtonEnabled(tsbtnStart, true);
  2772. AddTextEvent($"下料", "下料完成!");
  2773. }
  2774. catch (Exception ex)
  2775. {
  2776. AddTextEvent("下料", "下料失败 Err:" + ex.Message, WarningEnum.High);
  2777. warning(WarningEnum.High);
  2778. }
  2779. }
  2780. private void setButtonEnabled(ToolStripButton button, bool Enabled)
  2781. {
  2782. this.Invoke(new System.Action(() =>
  2783. {
  2784. button.Enabled = Enabled;
  2785. }));
  2786. }
  2787. private void setButtonEnabled(ToolStripMenuItem button, bool Enabled)
  2788. {
  2789. this.Invoke(new System.Action(() =>
  2790. {
  2791. button.Enabled = Enabled;
  2792. }));
  2793. }
  2794. private void setButtonEnabled(Control button, bool Enabled)
  2795. {
  2796. this.Invoke(new System.Action(() =>
  2797. {
  2798. button.Enabled = Enabled;
  2799. }));
  2800. }
  2801. private void FrmMian_Shown(object sender, EventArgs e)
  2802. {
  2803. }
  2804. private void FrmMian_Resize(object sender, EventArgs e)
  2805. {
  2806. }
  2807. private void 流程管理ToolStripMenuItem_Click(object sender, EventArgs e)
  2808. {
  2809. if (devContainer.state)
  2810. {
  2811. MessageBox.Show("请先停止生产,再进行流程修改!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  2812. return;
  2813. }
  2814. FrmStepList frm = new FrmStepList();
  2815. frm.ShowDialog();
  2816. }
  2817. private void 产品管理ToolStripMenuItem_Click(object sender, EventArgs e)
  2818. {
  2819. if (devContainer.state)
  2820. {
  2821. MessageBox.Show("请先停止生产,再进行产品修改!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  2822. return;
  2823. }
  2824. FrmProductList frm = new FrmProductList();
  2825. frm.ShowDialog();
  2826. loadProductCodeList();
  2827. }
  2828. private void tsbtnProductRevise_Click(object sender, EventArgs e)
  2829. {
  2830. if (!devContainer.state)
  2831. {
  2832. MessageBox.Show("请先启动设备!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
  2833. return;
  2834. }
  2835. if (currentPT != CurrentPTEnum.InitPT || currentState != CurrentStateEnum.等待启动)
  2836. {
  2837. MessageBox.Show("请先复位设备!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
  2838. return;
  2839. }
  2840. FrmProductList frm = new FrmProductList(true);
  2841. if (frm.ShowDialog() == DialogResult.Yes && frm.Product != null)//执行校正
  2842. {
  2843. AddTextEvent("校正", "开始执行产品base厚度校正...");
  2844. isProductRevise = true;
  2845. currProductModel = frm.Product;
  2846. currProductModel.HeightBaseDec = "";
  2847. this.txtProductCode.Text = currProductModel.Code;
  2848. this.txtProductName.Text = currProductModel.Name;
  2849. this.txtProductSN.Text = "";
  2850. this.dgvProcess.DataSource = new BindingSource(currProductModel.ReviseStepInfo.ProcessList, null);
  2851. devContainer.libFor.clear();
  2852. devContainer.libIF.clear();
  2853. //
  2854. this.setButtonEnabled(this.tsbtnStart, false);
  2855. this.setButtonEnabled(this.tsbtnPause, true);
  2856. this.setButtonEnabled(this.tsbtnStopNow, true);
  2857. threadProcess = new System.Threading.Thread(() =>
  2858. {
  2859. int nextStepId = 0;
  2860. do
  2861. {
  2862. currentState = CurrentStateEnum.运行中;
  2863. nextStepId = nextProcess(currProductModel, nextStepId);
  2864. } while (nextStepId >= 0 && !isBreakProcessRun());
  2865. });
  2866. threadProcess.IsBackground = true;
  2867. threadProcess.Start();
  2868. }
  2869. }
  2870. private void 设备调试ToolStripMenuItem_Click(object sender, EventArgs e)
  2871. {
  2872. if (devContainer.state)
  2873. {
  2874. MessageBox.Show("请先停止生产,再进行设备调试!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  2875. return;
  2876. }
  2877. FrmDebug3 frm = new FrmDebug3();
  2878. frm.ShowDialog();
  2879. }
  2880. private void 角色管理ToolStripMenuItem_Click(object sender, EventArgs e)
  2881. {
  2882. FrmRoleRight frm = new FrmRoleRight();
  2883. frm.ShowDialog(this);
  2884. }
  2885. private void 用户管理ToolStripMenuItem_Click(object sender, EventArgs e)
  2886. {
  2887. FrmUserList frm = new FrmUserList();
  2888. frm.ShowDialog(this);
  2889. }
  2890. private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
  2891. {
  2892. Application.Exit();
  2893. System.GC.Collect();
  2894. System.Environment.Exit(0);
  2895. }
  2896. private void 注销ToolStripMenuItem_Click(object sender, EventArgs e)
  2897. {
  2898. if (devContainer.state)
  2899. {
  2900. MessageBox.Show("请先停止生产再退出!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  2901. return;
  2902. }
  2903. if (MessageBox.Show($"确认退出?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
  2904. {
  2905. this.bExitApp = true;
  2906. Process.Start(Application.StartupPath + "\\ProductionControl.exe");
  2907. this.Close();
  2908. }
  2909. }
  2910. private void splitContainer1_Panel1_Resize(object sender, EventArgs e)
  2911. {
  2912. int allWidth = this.splitContainer1.Panel1.Width;
  2913. this.gpbProductInfo.Width = this.flpnlResultData.Width = this.gpbProcessList.Width = this.gpbLog.Width = allWidth;
  2914. //
  2915. this.txtProductName.Width = this.txtProductCode.Width = this.gpbProductInfo.Width - this.txtProductName.Left - 8;
  2916. this.txtProductSN.Width = this.txtBatchId.Width = (this.txtProductName.Width- lblBatchId.Width)/2;
  2917. this.lblBatchId.Left = this.txtProductSN.Right ;
  2918. this.txtBatchId.Left = this.lblBatchId.Right;
  2919. //
  2920. int spliceWidth = 5;
  2921. kanban1.Width = kanban2.Width = kanban3.Width = kanban4.Width = kanban5.Width = kanban6.Width = (flpnlResultData.Width-20) / 6;
  2922. //2023-10-17 更新log和步骤列表显示
  2923. this.gpbProcessList.Height = this.splitContainer1.Panel1.Height - this.gpbProcessList.Top - this.gpbLog.Height;
  2924. this.gpbLog.Top = this.splitContainer1.Panel1.Height - this.gpbLog.Height;
  2925. }
  2926. private void 关于ToolStripMenuItem_Click(object sender, EventArgs e)
  2927. {
  2928. AboutBox1 aboutBox1 = new AboutBox1();
  2929. aboutBox1.Show();
  2930. }
  2931. private void 系统设置ToolStripMenuItem_Click(object sender, EventArgs e)
  2932. {
  2933. FrmSysSetting frmSetting = new FrmSysSetting();
  2934. frmSetting.ShowDialog();
  2935. }
  2936. private void dgvProcess_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
  2937. {
  2938. //string processCode;
  2939. //for (int i = 0; i < this.dgvProcess.Rows.Count; i++)
  2940. //{
  2941. //processCode = dgvProcess.Rows[i].Cells[0].Value.ToString();
  2942. //dgvProcess.Rows[i].Cells[1].Value = Config.dicDevType[processCode];
  2943. //}
  2944. }
  2945. private void tsbtnWarning_Click(object sender, EventArgs e)
  2946. {
  2947. //if (warningLevel == WarningEnum.Normal)
  2948. //{
  2949. // tsbtnWarning.Enabled = false;
  2950. // return;
  2951. //}
  2952. //重置AXIS状态
  2953. devContainer.devAxis.resetAxisState();
  2954. if (!devContainer.devAxis.isReady())
  2955. {
  2956. AddTextEvent("解除报警", "轴状态未恢复,解除报警失败!", warningLevel);
  2957. return;
  2958. }
  2959. if (devContainer.devAxis.isError())
  2960. {
  2961. AddTextEvent("解除报警", "轴IO状态异常,解除报警失败!", warningLevel);
  2962. return;
  2963. }
  2964. if (!this.disableDoorSensor && compareIOInput(CMDName.门磁告警输入))
  2965. {
  2966. AddTextEvent("解除报警", "门磁告警未清除 ,解除报警失败!", warningLevel);
  2967. return;
  2968. }
  2969. if (!this.disableDoorSensor && compareIOInput(CMDName.喷墨告警输入))
  2970. {
  2971. AddTextEvent("解除报警", "喷墨告警输入未清除 ,解除报警失败!", warningLevel);
  2972. return;
  2973. }
  2974. //关闭蜂鸣器
  2975. devContainer.io_output(CMDName.蜂鸣器输出, false, true, 0);
  2976. devContainer.io_output(CMDName.红灯输出, false, true, 0);
  2977. devContainer.io_output(CMDName.复位按钮, false, true, 0);
  2978. if (warningLevel == WarningEnum.High)
  2979. {
  2980. AddTextEvent("解除报警", "急停告警已解除,但必需进行复位操作!", warningLevel);
  2981. currentState = CurrentStateEnum.等待复位;
  2982. this.tsbtnReset.Enabled = true;
  2983. tsbtnWarning.Enabled = this.tsbtnStart.Enabled = this.tsbtnGoDownPT.Enabled
  2984. = this.tsbtnPause.Enabled = this.tsbtnStopNow.Enabled = this.btnMakeTags.Enabled= false;
  2985. }
  2986. else
  2987. {
  2988. devContainer.io_output(CMDName.黄灯输出);
  2989. AddTextEvent("解除报警", "告警已解除,请继续选择下一步操作!", warningLevel);
  2990. if (currentPT == CurrentPTEnum.MakeTag)
  2991. currentState = CurrentStateEnum.打标中;
  2992. else
  2993. currentState = CurrentStateEnum.等待启动;
  2994. tsbtnWarning.Enabled = false;
  2995. this.tsbtnStart.Enabled = this.tsbtnGoDownPT.Enabled = true;
  2996. this.tsbtnReset.Enabled = this.tsbtnPause.Enabled = this.tsbtnStopNow.Enabled = true;
  2997. }
  2998. warningLevel = WarningEnum.Normal;
  2999. }
  3000. private void tsbtnGoDownPT_Click(object sender, EventArgs e)
  3001. {
  3002. if (!devContainer.state || warningLevel!= WarningEnum.Normal)
  3003. return;
  3004. if (!devContainer.devAxis.isReady())
  3005. {
  3006. AddTextEvent("下料失败", "轴状态异常!", WarningEnum.Low);
  3007. return;
  3008. }
  3009. gotoDownPT();
  3010. }
  3011. //急停
  3012. private void tsbtnStopNow_Click(object sender, EventArgs e)
  3013. {
  3014. this.warning(WarningEnum.High);
  3015. }
  3016. private Thread threadProcess;
  3017. private void tsbtnStart_Click(object sender, EventArgs e)
  3018. {
  3019. this.startCommand();
  3020. }
  3021. private void tsbtnPause_Click(object sender, EventArgs e)
  3022. {
  3023. warning(WarningEnum.Low,false);
  3024. }
  3025. //复位
  3026. private void tsbtnReset_Click(object sender, EventArgs e)
  3027. {
  3028. this.resetCommand();
  3029. }
  3030. private void tsbtnGButSetting_Click(object sender, EventArgs e)
  3031. {
  3032. if (devContainer.state)
  3033. {
  3034. MessageBox.Show("请先停止生产,再进行设置!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  3035. return;
  3036. }
  3037. FrmCMDProcess from = new FrmCMDProcess();
  3038. from.ShowDialog();
  3039. }
  3040. private void tsbtnPTSetting_Click(object sender, EventArgs e)
  3041. {
  3042. if (devContainer.state)
  3043. {
  3044. MessageBox.Show("请先停止生产,再进行设置!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  3045. return;
  3046. }
  3047. FrmPTSetting from = new FrmPTSetting();
  3048. from.ShowDialog();
  3049. }
  3050. private void tsMenuModifyPW_Click(object sender, EventArgs e)
  3051. {
  3052. FrmModifyPW frm = new FrmModifyPW();
  3053. frm.ShowDialog();
  3054. }
  3055. //分拆面板平均分配
  3056. private void splitContainer1_ClientSizeChanged(object sender, EventArgs e)
  3057. {
  3058. if (this.WindowState == FormWindowState.Minimized)
  3059. return;
  3060. SplitContainer sc = (SplitContainer)sender;
  3061. sc.SplitterDistance = sc.Width / 7*3;
  3062. }
  3063. private void splitContainer3_ClientSizeChanged(object sender, EventArgs e)
  3064. {
  3065. if (this.WindowState == FormWindowState.Minimized)
  3066. return;
  3067. SplitContainer sc = (SplitContainer)sender;
  3068. sc.SplitterDistance = sc.Height / 2;
  3069. }
  3070. private void Menu查询统计_Click(object sender, EventArgs e)
  3071. {
  3072. FrmWeb frm = new FrmWeb("查询统计", $"reportRecordSN?CustomerVer={Config.CustomerVer}");
  3073. frm.Show();
  3074. }
  3075. private void tsMenuOrder_Click(object sender, EventArgs e)
  3076. {
  3077. //FrmOrderList frm = new FrmOrderList();
  3078. string subject = (sender as ToolStripMenuItem).Text;
  3079. FrmWeb frm = new FrmWeb(subject, $"reportRecordSN?CustomerVer={Config.CustomerVer}");
  3080. frm.Show();
  3081. }
  3082. private void tsMenuOrderProduct_Click(object sender, EventArgs e)
  3083. {
  3084. string subject = (sender as ToolStripMenuItem).Text;
  3085. FrmWeb frm = new FrmWeb(subject, $"reportRecordProduct?CustomerVer={Config.CustomerVer}");
  3086. frm.Show();
  3087. }
  3088. private void tsMenuStatistics_Click(object sender, EventArgs e)
  3089. {
  3090. string subject = (sender as ToolStripMenuItem).Text;
  3091. FrmWeb frm = new FrmWeb(subject, $"bigscreen/index.html", "http://127.0.0.1:18082/static/");
  3092. frm.Show();
  3093. }
  3094. private void toolStripButton1_Click(object sender, EventArgs e)
  3095. {
  3096. //Bitmap[] bmps = new Bitmap[2];
  3097. //bmps[0] = new Bitmap(@"f:\1.bmp");
  3098. //bmps[1] = new Bitmap(@"f:\111.bmp");
  3099. //List<Dictionary<int, List<string>[]>> list = new List<Dictionary<int, List<string>[]>>();
  3100. //Dictionary<int, List<string>[]> dir = new Dictionary<int, List<string>[]>();
  3101. //List<string>[] vs = new List<string>[1];
  3102. //vs[0] = new List<string>();
  3103. //dir.Add(0, vs);
  3104. //list.Add(dir);
  3105. //showDefectSmallBmps(bmps, list);
  3106. var bmp = Bitmap.FromFile("f:\\1.jpg");
  3107. int pnlWidth = this.pnlBmpList.ClientSize.Width;
  3108. for (int i = 0; i < 5; i++)
  3109. {
  3110. int x = i;
  3111. this.Invoke(new System.Action(() =>
  3112. {
  3113. int imgWidth = 224;
  3114. int imgHeight = 200;
  3115. int splitWidth = 10;
  3116. int index = Convert.ToInt32(this.gboxDefectList.Tag);
  3117. PictureBox picbox = new PictureBox();
  3118. picbox.Width = imgWidth;
  3119. picbox.Height = imgHeight;
  3120. CheckBox checkBox = new CheckBox();
  3121. picbox.Image = bmp;
  3122. picbox.Name = "imgDefect_" + index;
  3123. picbox.Tag ="1,2,3";
  3124. checkBox.Name = "chkDefect_" + index;
  3125. checkBox.Text = $"第{index + 1}张";
  3126. checkBox.CheckedChanged += new System.EventHandler(this.CheckBox_CheckedChanged);
  3127. picbox.Click += new EventHandler(defectBmpBox_Click);
  3128. picbox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
  3129. picbox.BorderStyle = BorderStyle.FixedSingle;
  3130. picbox.Margin = new Padding((pnlWidth - picbox.Width) / 2, splitWidth, 0, 0);
  3131. checkBox.Margin = new Padding((pnlWidth - checkBox.Width) / 2+ splitWidth, 0, 0, 0);
  3132. //
  3133. //if (this.pnlBmpList.Controls.Count > 0)
  3134. // {
  3135. // if ((this.pnlBmpList.Controls[this.pnlBmpList.Controls.Count - 1].Right + imgWidth + splitWidth) > this.pnlBmpList.Width)
  3136. // picbox.Location = new System.Drawing.Point(splitWidth, this.pnlBmpList.Controls[this.pnlBmpList.Controls.Count - 1].Bottom + splitWidth);
  3137. // else
  3138. // picbox.Location = new System.Drawing.Point(this.pnlBmpList.Controls[this.pnlBmpList.Controls.Count - 1].Right + splitWidth, this.pnlBmpList.Controls[this.pnlBmpList.Controls.Count - 1].Location.Y);
  3139. // }
  3140. // else
  3141. // {
  3142. // picbox.Location = new System.Drawing.Point(splitWidth, 0);
  3143. // }
  3144. // checkBox.Location = new System.Drawing.Point(picbox.Location.X + 5, picbox.Location.Y + 5);
  3145. // checkBox.ForeColor = Color.Black;
  3146. //}
  3147. this.pnlBmpList.Controls.Add(picbox);
  3148. this.pnlBmpList.Controls.Add(checkBox);
  3149. //
  3150. index++;
  3151. this.gboxDefectList.Tag = index;
  3152. this.gboxDefectList.Text = $"缺陷图像:{index} 张";
  3153. pnlBmpList.VerticalScroll.Value = pnlBmpList.VerticalScroll.Maximum;
  3154. }));
  3155. }
  3156. }
  3157. private void chkBuzzer_CheckedChanged(object sender, EventArgs e)
  3158. {
  3159. this.disableBuzzer = chkBuzzer.Checked;
  3160. if (devContainer.state && this.disableBuzzer)
  3161. devContainer.io_output(CMDName.蜂鸣器输出, false, true, 0);
  3162. }
  3163. private void chkDoorSensor_CheckedChanged(object sender, EventArgs e)
  3164. {
  3165. this.disableDoorSensor = chkDoorSensor.Checked;
  3166. }
  3167. private void tsbtnLight_Click(object sender, EventArgs e)
  3168. {
  3169. if (devContainer.state)
  3170. {
  3171. if(tsbtnLight.Text.Trim()== "开灯")
  3172. {
  3173. if(devContainer.io_output(CMDName.日光灯输出))
  3174. tsbtnLight.Text = " 关灯 ";
  3175. }
  3176. else
  3177. {
  3178. if (devContainer.io_output(CMDName.日光灯输出, false, true, 0))
  3179. tsbtnLight.Text = " 开灯 ";
  3180. }
  3181. }
  3182. }
  3183. private void btnMakeTag_Click(object sender, EventArgs e)
  3184. {
  3185. if(currentPT != CurrentPTEnum.MakeTag)
  3186. {
  3187. AddTextEvent("打标失败", "非可打标状态!");
  3188. return;
  3189. }
  3190. btnMakeTags.Enabled = false;
  3191. autoMakeTagRuning = true;
  3192. Thread threadtest = new System.Threading.Thread(() =>
  3193. {
  3194. try
  3195. {
  3196. if (!devContainer.state)
  3197. {
  3198. AddTextEvent("打标", "设备已停机!");
  3199. return;
  3200. }
  3201. if ((int)this.lblDefectAddTag.Tag < 1)
  3202. {
  3203. AddTextEvent("打标", "打标队列为空!");
  3204. return;
  3205. }
  3206. int tagIndex;
  3207. double Xmm, Ymm;
  3208. Bitmap currBmp;
  3209. string[] tags;
  3210. for (int i = 0; i < this.pnlBmpList.Controls.Count; i += 2)
  3211. {
  3212. CheckBox cb = this.pnlBmpList.Controls[i + 1] as CheckBox;
  3213. if (cb.Checked)
  3214. {
  3215. PictureBox picBox = this.pnlBmpList.Controls[i] as PictureBox;
  3216. tags = picBox.Tag.ToString().Split(',');
  3217. tagIndex = Convert.ToInt32(tags[0]);
  3218. Xmm = Convert.ToDouble(tags[1]);
  3219. Ymm = Convert.ToDouble(tags[2]);
  3220. currBmp = (Bitmap)picBox.Image;
  3221. //打标
  3222. AddTextEvent("打标", $"第{i / 2 + 1}/{this.pnlBmpList.Controls.Count / 2}张 [索引:{tagIndex}, X:{Xmm}mm, Y:{Ymm}mm]");
  3223. var list = devContainer.libDefect.makeTag(tagIndex, Xmm, Ymm, currBmp.Width, currBmp.Height);
  3224. devContainer.devAxis.move_ptp(1, list[0], AxMoveMode.绝对位置);
  3225. devContainer.devAxis.move_ptp(2, list[1], AxMoveMode.绝对位置);
  3226. while (!devContainer.devAxis.isReady(1) || !devContainer.devAxis.isReady(2))
  3227. {
  3228. Application.DoEvents();
  3229. Thread.Sleep(100);
  3230. if (!devContainer.state)
  3231. throw new Exception("设备停止,打标中止!");
  3232. }
  3233. //
  3234. if (!devContainer.io_output(CMDName.喷墨输出, false, true, 500))
  3235. throw new Exception("请确认[喷墨输出]指令设置是否正确!");
  3236. this.Invoke(new System.Action(() =>
  3237. {
  3238. cb.Checked = false;
  3239. }));
  3240. }
  3241. }
  3242. //自动下料
  3243. AddTextEvent("打标完成", $"批量打标完成,进行下料...");
  3244. currentState = CurrentStateEnum.自动流程结束;
  3245. gotoDownPT();
  3246. }
  3247. catch (Exception ex)
  3248. {
  3249. AddTextEvent("打标失败", ex.Message, WarningEnum.High);
  3250. warning(WarningEnum.Low, true);
  3251. }
  3252. finally { autoMakeTagRuning=false; }
  3253. });
  3254. threadtest.IsBackground = true;
  3255. threadtest.Start();
  3256. }
  3257. private void btnInputCode_Click(object sender, EventArgs e)
  3258. {
  3259. txtProductCode_DoubleClick(null, null);
  3260. }
  3261. private void txtProductName_DoubleClick(object sender, EventArgs e)
  3262. {
  3263. txtProductCode_DoubleClick(null, null);
  3264. }
  3265. private void txtProductCode_DoubleClick(object sender, EventArgs e)
  3266. {
  3267. //不需要等待扫码才能选择
  3268. //if (currentState != CurrentStateEnum.等待扫码) return;
  3269. FrmInput frm = new FrmInput(productCodeList, "请选择产品料号:");
  3270. if (frm.ShowDialog() != DialogResult.OK && string.IsNullOrWhiteSpace(frm.inputData))
  3271. return;
  3272. //显示料号
  3273. //this.txtProductCode.Text = frm.inputData;
  3274. var model = svcProduct.GetModelNav(frm.inputData);
  3275. if (model != null && model.StepInfo.ProcessList.Count > 0)
  3276. {
  3277. this.txtProductCode.Text = model.Code;
  3278. this.txtProductName.Text = model.Name;
  3279. }
  3280. /*//屏蔽扫码枪事件
  3281. Task.Factory.StartNew(() =>
  3282. {
  3283. devContainer.devCodeScanner.ScanerEvent?.Invoke(frm.inputData);
  3284. });
  3285. */
  3286. //string code = Interaction.InputBox("请输入产品编码", "输入框", "", -1, -1).Trim();
  3287. //if(code != "")
  3288. //{
  3289. // Task.Factory.StartNew(() =>
  3290. // {
  3291. // devContainer.devCodeScanner.ScanerEvent?.Invoke(frm.inputData);
  3292. // });
  3293. //}
  3294. }
  3295. private void txtProductSN_DoubleClick(object sender, EventArgs e)
  3296. {
  3297. //if (currentState != CurrentStateEnum.等待扫码 || this.txtProductCode.Text.Trim()=="") return;
  3298. //string sn = Interaction.InputBox("请输入产品SN码", "输入框", "", -1, -1).Trim();
  3299. //if (sn != "")
  3300. //{
  3301. // this.txtProductSN.Text = sn;
  3302. // string code = this.txtProductCode.Text.Trim();
  3303. // Task.Factory.StartNew(() =>
  3304. // {
  3305. // devContainer.devCodeScanner.ScanerEvent?.Invoke(code);
  3306. // });
  3307. //}
  3308. }
  3309. private void 测试ToolStripMenuItem_Click(object sender, EventArgs e)
  3310. {
  3311. tsbtnDefectImage.Enabled = tsbtnSizeImage.Enabled=true;
  3312. return;
  3313. Form1 frm = new Form1();
  3314. frm.Show();
  3315. //tsbtnDefectImage_Click(null, null);
  3316. return;
  3317. try
  3318. {
  3319. //string ls = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,182.257722637742,182.257727282667,0,0";
  3320. //List<string> list = new List<string>(ls.Split(','));
  3321. //lstPT = list.Select<string, double>(q => Convert.ToDouble(q)).ToList();
  3322. //updatePTValue(1,2);
  3323. //lstPT.Add(10);
  3324. //lstPT.Add(0);
  3325. //updatePTValue(1, 2);
  3326. //{
  3327. // lstLineWidth.Add(res.Shanxian > 0 ? res.Shanxian : 0);
  3328. // updateLineWidthValue(model.LineWidthBaseValue + model.LineWidthUpFloatValue, model.LineWidthBaseValue - model.LineWidthDownFloatValue);
  3329. //}
  3330. //return;
  3331. //loadProductCodeList();
  3332. //FrmInput frm = new FrmInput(null, "请选择产品编码:");
  3333. //if (frm.ShowDialog() != DialogResult.OK)
  3334. // return;
  3335. //var model = svcProduct.GetModelNav(frm.inputData);
  3336. //if (model == null)
  3337. // throw new Exception("没有此产品!");
  3338. //order.ProductId = model.Id;
  3339. //order.BatchId = model.BatchId;
  3340. //order.StepId = model.StepId==null? 0:(int)model.StepId;
  3341. //frm = new FrmInput(null, "请输入SN:");
  3342. //if (frm.ShowDialog() != DialogResult.OK)
  3343. // return;
  3344. //order.SN = frm.inputData;
  3345. //frm = new FrmInput(null, "请输入主机台Mark点数据:", "[0,0,0,0,0,0,0,0]");
  3346. //if (frm.ShowDialog() != DialogResult.OK)
  3347. // return;
  3348. //order.MarkData= frm.inputData;
  3349. //order.Tension1 = order.Tension2 = order.Tension3 = order.Tension4 = order.Tension5 = order.Tension5 + 3;
  3350. //order.PT1 = order.PT4 = order.PT5 = order.PT6 = order.PT6 + 1.33;
  3351. //order.LineWidth2 = order.LineWidth3 = order.LineWidth5 = order.LineWidth6 = +order.LineWidth6 + 1.22;
  3352. //order.HeightValue = order.Height1 = order.Height3 = order.Height4 = 55;
  3353. //order.DefectCount = order.DefectCount + 22;
  3354. //order.YXCount = order.PPCount = 33;
  3355. //order.TimeLen = 1000;
  3356. //order.Succeed = true;
  3357. //order.ModifyUserCode = order.CreateUserCode = Config.loginUser.Code;
  3358. //if (!svcOrder.Insert(order))
  3359. // AddTextEvent("保存失败", $"保存生产记录失败!");
  3360. //MessageBox.Show("成功!");
  3361. //---------------
  3362. this.lstCompareFailZoomImage.Add((Bitmap)Bitmap.FromFile(@"f:\1.bmp"));
  3363. this.lstCompareFailZoomImage.Add((Bitmap)Bitmap.FromFile(@"f:\2.bmp"));
  3364. this.lstCompareFailZoomImage.Add((Bitmap)Bitmap.FromFile(@"f:\3.bmp"));
  3365. }
  3366. catch(Exception ex)
  3367. {
  3368. MessageBox.Show(ex.Message);
  3369. }
  3370. }
  3371. private void toolStripSeparator4_Click(object sender, EventArgs e)
  3372. {
  3373. }
  3374. private void chkHttpLog_CheckedChanged(object sender, EventArgs e)
  3375. {
  3376. if (this.chkHttpLog.Checked)
  3377. {
  3378. webService.LogEvent = (warning, msg) =>
  3379. {
  3380. AddTextEvent("HTTP服务", msg, warning);
  3381. };
  3382. }
  3383. else
  3384. webService.LogEvent = null;
  3385. }
  3386. //打开比对失败的图片
  3387. private void lblCompareResult_Click(object sender, EventArgs e)
  3388. {
  3389. if (lstCompareFailZoomImage.Count < 1) return;
  3390. FrmPhotoShow frm = new FrmPhotoShow(lstCompareFailZoomImage);
  3391. frm.ShowDialog();
  3392. }
  3393. //过程变量查看
  3394. private void tsbtnSizeTag_Click(object sender, EventArgs e)
  3395. {
  3396. if (order == null || order.SizeTagDataList == null || order.SizeTagDataList.Count<1)
  3397. return;
  3398. FrmShowSizeTag frm = new FrmShowSizeTag(order);
  3399. frm.Show();
  3400. }
  3401. //缺陷+比对与图纸查看
  3402. private void tsbtnDefectImage_Click(object sender, EventArgs e)
  3403. {
  3404. //currProductModel = svcProduct.GetModelNav(53);
  3405. //order = svcOrder.GetModelNav("20230814002");
  3406. AddTextEvent("打开窗口", "1");
  3407. if (currProductModel ==null || order == null || order.DefectInfoList == null || order.DefectInfoList.Count < 1)
  3408. return;
  3409. AddTextEvent("打开窗口", "2");
  3410. //图纸
  3411. try
  3412. {
  3413. string gbxBmpPath = "";
  3414. var attachmentFile = currProductModel.AttachmentList.FirstOrDefault(x => x.Type == 0);
  3415. if (attachmentFile != null)
  3416. {
  3417. gbxBmpPath = Application.StartupPath + $"\\Attachment\\product\\{attachmentFile.NameTimestamp}";
  3418. if (!File.Exists(gbxBmpPath + ".bmp")) gbxBmpPath = "";
  3419. }
  3420. AddTextEvent("打开窗口", "3");
  3421. if (string.IsNullOrEmpty(gbxBmpPath))
  3422. {
  3423. MessageBox.Show("图纸文件不存在!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  3424. return;
  3425. }
  3426. AddTextEvent("打开窗口", "4");
  3427. if (!File.Exists(gbxBmpPath + ".jpg"))//转背景后的图纸文件
  3428. {
  3429. AddTextEvent("打开窗口", "5");
  3430. //换背景JPG
  3431. Mat mat = Cv2.ImRead(gbxBmpPath + ".bmp");
  3432. Cv2.CvtColor(mat, mat, ColorConversionCodes.RGB2GRAY);//转灰度图
  3433. for (int i = 0; i < mat.Height; i++)
  3434. {
  3435. for (int j = 0; j < mat.Width; j++)
  3436. {
  3437. if (mat.At<byte>(i, j) == 255)//白色
  3438. mat.Set<byte>(i, j, 0);
  3439. else
  3440. mat.Set<byte>(i, j, 255);
  3441. }
  3442. }
  3443. AddTextEvent("打开窗口", "6");
  3444. //灰转彩
  3445. //Cv2.CvtColor(mat, mat, ColorConversionCodes.GRAY2RGB);
  3446. //for (int i = 0; i < mat.Height; i++)
  3447. //{
  3448. // for (int j = 0; j < mat.Width; j++)
  3449. // {
  3450. // if (mat.At<byte>(i, j) == 255)//白色
  3451. // mat.Set<byte>(i, j, 0); //黄色
  3452. // }
  3453. //}
  3454. OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat).Save(gbxBmpPath + ".jpg", ImageFormat.Jpeg);
  3455. }
  3456. AddTextEvent("打开窗口", "7");
  3457. //
  3458. ToolStripButton btn = sender as ToolStripButton;
  3459. AddTextEvent("打开窗口", btn.Tag.ToString());
  3460. FrmShowDefectImage frm = new FrmShowDefectImage(gbxBmpPath + ".jpg", order, string.IsNullOrEmpty(btn.Tag.ToString()) ? 0 : Convert.ToInt32(btn.Tag.ToString()));
  3461. frm.Show();
  3462. AddTextEvent("打开窗口", "9");
  3463. }
  3464. catch (Exception ex)
  3465. {
  3466. MessageBox.Show(ex.Message, "异常", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, 0);
  3467. }
  3468. }
  3469. private void tsbtnLog_Click(object sender, EventArgs e)
  3470. {
  3471. if (string.IsNullOrWhiteSpace(Config.LogPath)) return;
  3472. string lsPath = (Config.LogPath + "\\" + DateTime.Now.ToString("yyyyMM") + "\\").Replace("\\\\", "\\");
  3473. if(!Directory.Exists(lsPath))
  3474. Directory.CreateDirectory(lsPath);
  3475. System.Diagnostics.Process.Start("explorer.exe", lsPath);
  3476. }
  3477. }
  3478. }