WorkTimer.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. package com.mes.util;
  2. import com.alibaba.fastjson2.JSONObject;
  3. import com.mes.ui.DataUtil;
  4. import com.mes.ui.MesClient;
  5. import org.slf4j.Logger;
  6. import org.slf4j.LoggerFactory;
  7. import javax.swing.*;
  8. import java.awt.*;
  9. import java.util.Timer;
  10. import java.util.TimerTask;
  11. public class WorkTimer {
  12. private static final Logger log = LoggerFactory.getLogger(WorkTimer.class);
  13. /** 非 OK 状态需连续确认次数,避免 20→21 等过渡码被立刻判 NG */
  14. private static final int NG_CONFIRM_NEEDED = 2;
  15. private static int ngConfirmCount = 0;
  16. private static int pendingNgStatusCode = -1;
  17. private static Timer stopTimer = null;
  18. private static Timer workTimer = null;
  19. private WorkTimer() {
  20. }
  21. public static void start() {
  22. if(workTimer != null){
  23. workTimer = null;
  24. }
  25. resetEndConfirm();
  26. workTimer = new Timer();
  27. workTimer.schedule(new WorkTimerTask(), 1000, 2000);
  28. }
  29. public static void stop() {
  30. if (workTimer != null) {
  31. workTimer.cancel();
  32. workTimer = null;
  33. }
  34. resetEndConfirm();
  35. }
  36. /** 扫下一件 / 复位时清空结束确认状态 */
  37. public static void resetEndConfirm() {
  38. ngConfirmCount = 0;
  39. pendingNgStatusCode = -1;
  40. }
  41. // 发送禁止运行的定时任务
  42. private static class StopTimerTask extends TimerTask {
  43. @Override
  44. public void run() {
  45. try {
  46. if (MesClient.work_status == 0 || !MesClient.check_quality_result) {
  47. ATEQ.stop(); // 发送重置命令, 禁止设备启动
  48. }
  49. } catch (Exception e) {
  50. log.error("向设备发送禁止运行的定时任务报错");
  51. }
  52. }
  53. }
  54. // 工作流程定时任务
  55. private static class WorkTimerTask extends TimerTask {
  56. @Override
  57. public void run() {
  58. try {
  59. // 如果开始工作,则循环查询测量结果
  60. // 每项读法: 先 10 30 04,再读 压力/单位/泄漏/单位/状态
  61. if (MesClient.work_status == 1) {
  62. final ATEQ.MeasureResult measureResult = ATEQ.readMeasureResult();
  63. log.info(measureResult.toString());
  64. // 先在定时线程判定是否真正结束(OK 立刻结束;疑似 NG 需连续确认)
  65. final boolean isEnd = resolveTestEnd(measureResult);
  66. // 测完提交前:若稳压/测试时长为空,再读一次程序参数
  67. if (isEnd) {
  68. if ((MesClient.curStabilizeTime == null || MesClient.curStabilizeTime.trim().isEmpty())
  69. || (MesClient.curTestDuration == null || MesClient.curTestDuration.trim().isEmpty())) {
  70. log.info("提交前补读稳压时长/测试时长");
  71. MesClient.loadAteqProgramTimes();
  72. }
  73. }
  74. SwingUtilities.invokeLater(new Runnable() {
  75. @Override
  76. public void run() {
  77. try {
  78. if (measureResult.isTesting) {
  79. MesClient.setMenuStatus("测试中", 0);
  80. } else if (MesClient.mesStartFlag == 1 && !isEnd && !measureResult.isPass) {
  81. MesClient.setMenuStatus(
  82. String.format("结果确认中(0x%02X)...", measureResult.statusCode), 0);
  83. }
  84. String pressureText = formatValue(measureResult.pressureValue, measureResult.pressureUnit);
  85. String leakText = formatValue(measureResult.leakValue, measureResult.leakUnit);
  86. // 实时更新显示(不因单项失败而整页空白)
  87. MesClient.param1.setText(pressureText);
  88. MesClient.param2.setText(leakText);
  89. if (isEnd) {
  90. if (measureResult.leakValue == 0 && !measureResult.isPass) {
  91. MesClient.param2.setText("9999");
  92. }
  93. String lastRet = measureResult.isPass ? "OK" : "NG";
  94. if (lastRet.equals("OK")) {
  95. MesClient.result.setText("OK");
  96. MesClient.result.setForeground(Color.GREEN);
  97. } else {
  98. MesClient.result.setText("NG");
  99. MesClient.result.setForeground(Color.RED);
  100. }
  101. String testDate = DateLocalUtils.getCurrentTime();
  102. TestParam testParam = new TestParam();
  103. testParam.setSn(MesClient.product_sn.getText().trim());
  104. testParam.setUcode(MesClient.user_menu.getText().trim());
  105. testParam.setLineSn(MesClient.configParam.getLineSn());
  106. testParam.setOprno(MesClient.configParam.getOprno());
  107. testParam.setOprnoTitle(MesClient.configParam.getOprnoTitle());
  108. testParam.setParam1(measureResult.pressureValue + "");
  109. testParam.setParam2(measureResult.pressureUnit);
  110. testParam.setParam3(measureResult.leakValue + "");
  111. testParam.setParam4(measureResult.leakUnit);
  112. testParam.setParam5(MesClient.programNo.getText().trim());
  113. testParam.setResult(lastRet);
  114. testParam.setDeviceType("ateq");
  115. // 提交字段 by=稳压时长, cs=测试时长
  116. String byVal = MesClient.curStabilizeTime != null ? MesClient.curStabilizeTime.trim() : "";
  117. String csVal = MesClient.curTestDuration != null ? MesClient.curTestDuration.trim() : "";
  118. testParam.setStabilizeTime(byVal);
  119. testParam.setTestDuration(csVal);
  120. log.info("准备提交时长: by(稳压时长)={}, cs(测试时长)={}", byVal, csVal);
  121. testParam.setRemark(measureResult.isPass ? "" : String.format("状态码:0x%02X", measureResult.statusCode));
  122. testParam.setCreateTime(testDate);
  123. JdbcUtils.insertTestRecord(testParam);
  124. if (MesClient.mes_enable) { // MES开启
  125. JSONObject retObj = DataUtil.qmResultData(testParam);
  126. if (retObj != null && retObj.get("result") != null && retObj.get("result").toString().equalsIgnoreCase("true")) {
  127. MesClient.resetScanA();
  128. MesClient.setMenuStatus("测试结果上传成功,请扫下一件", 0);
  129. } else {
  130. MesClient.setMenuStatus("测试结果上传失败,请重试", -1);
  131. return;
  132. }
  133. } else {
  134. MesClient.resetScanA();
  135. }
  136. if (MesClient.configParam.getPrintLabel().equals("是") && lastRet.equals("OK")) {
  137. PrintUtil.printLabel(testParam.getSn(), testParam.getParam1() + testParam.getParam2(), testParam.getParam3() + testParam.getParam4(), testDate);
  138. }
  139. }
  140. } catch (Exception uiEx) {
  141. log.error("更新界面失败: {}", uiEx.getMessage());
  142. }
  143. }
  144. });
  145. }
  146. } catch (Exception e) {
  147. e.printStackTrace();
  148. log.error("工作定时任务报错:"+e.getMessage());
  149. }
  150. }
  151. }
  152. /**
  153. * 判定测试是否结束:
  154. * - 0x00:测试中
  155. * - 0x21:OK,立即结束
  156. * - 其他非 00:疑似 NG,需连续 {@link #NG_CONFIRM_NEEDED} 次相同状态才结束,
  157. * 期间若变为 0x21 则按 OK 结束,避免过渡码误判
  158. */
  159. private static boolean resolveTestEnd(ATEQ.MeasureResult measureResult) {
  160. if (measureResult.isTesting) {
  161. MesClient.mesStartFlag = 1;
  162. resetEndConfirm();
  163. return false;
  164. }
  165. if (MesClient.mesStartFlag != 1) {
  166. return false;
  167. }
  168. if (measureResult.isPass) {
  169. log.info("状态码 0x21,判定 OK");
  170. resetEndConfirm();
  171. return true;
  172. }
  173. // 疑似 NG:连续确认
  174. if (pendingNgStatusCode != measureResult.statusCode) {
  175. pendingNgStatusCode = measureResult.statusCode;
  176. ngConfirmCount = 1;
  177. log.info("疑似 NG 状态 0x{},等待确认 {}/{}",
  178. String.format("%02X", measureResult.statusCode), ngConfirmCount, NG_CONFIRM_NEEDED);
  179. return false;
  180. }
  181. ngConfirmCount++;
  182. log.info("疑似 NG 状态 0x{},确认 {}/{}",
  183. String.format("%02X", measureResult.statusCode), ngConfirmCount, NG_CONFIRM_NEEDED);
  184. if (ngConfirmCount >= NG_CONFIRM_NEEDED) {
  185. resetEndConfirm();
  186. return true;
  187. }
  188. return false;
  189. }
  190. private static String formatValue(Double value, String unit) {
  191. if (value == null) {
  192. return "";
  193. }
  194. String u = unit == null ? "" : unit.trim();
  195. return u.isEmpty() ? String.valueOf(value) : (value + " " + u);
  196. }
  197. }