package com.mes.util; import com.alibaba.fastjson2.JSONObject; import com.mes.ui.DataUtil; import com.mes.ui.MesClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.swing.*; import java.awt.*; import java.util.Timer; import java.util.TimerTask; public class WorkTimer { private static final Logger log = LoggerFactory.getLogger(WorkTimer.class); /** 非 OK 状态需连续确认次数,避免 20→21 等过渡码被立刻判 NG */ private static final int NG_CONFIRM_NEEDED = 2; private static int ngConfirmCount = 0; private static int pendingNgStatusCode = -1; private static Timer stopTimer = null; private static Timer workTimer = null; private WorkTimer() { } public static void start() { if(workTimer != null){ workTimer = null; } resetEndConfirm(); workTimer = new Timer(); workTimer.schedule(new WorkTimerTask(), 1000, 2000); } public static void stop() { if (workTimer != null) { workTimer.cancel(); workTimer = null; } resetEndConfirm(); } /** 扫下一件 / 复位时清空结束确认状态 */ public static void resetEndConfirm() { ngConfirmCount = 0; pendingNgStatusCode = -1; } // 发送禁止运行的定时任务 private static class StopTimerTask extends TimerTask { @Override public void run() { try { if (MesClient.work_status == 0 || !MesClient.check_quality_result) { ATEQ.stop(); // 发送重置命令, 禁止设备启动 } } catch (Exception e) { log.error("向设备发送禁止运行的定时任务报错"); } } } // 工作流程定时任务 private static class WorkTimerTask extends TimerTask { @Override public void run() { try { // 如果开始工作,则循环查询测量结果 // 每项读法: 先 10 30 04,再读 压力/单位/泄漏/单位/状态 if (MesClient.work_status == 1) { final ATEQ.MeasureResult measureResult = ATEQ.readMeasureResult(); log.info(measureResult.toString()); // 先在定时线程判定是否真正结束(OK 立刻结束;疑似 NG 需连续确认) final boolean isEnd = resolveTestEnd(measureResult); // 测完提交前:若稳压/测试时长为空,再读一次程序参数 if (isEnd) { if ((MesClient.curStabilizeTime == null || MesClient.curStabilizeTime.trim().isEmpty()) || (MesClient.curTestDuration == null || MesClient.curTestDuration.trim().isEmpty())) { log.info("提交前补读稳压时长/测试时长"); MesClient.loadAteqProgramTimes(); } } SwingUtilities.invokeLater(new Runnable() { @Override public void run() { try { if (measureResult.isTesting) { MesClient.setMenuStatus("测试中", 0); } else if (MesClient.mesStartFlag == 1 && !isEnd && !measureResult.isPass) { MesClient.setMenuStatus( String.format("结果确认中(0x%02X)...", measureResult.statusCode), 0); } String pressureText = formatValue(measureResult.pressureValue, measureResult.pressureUnit); String leakText = formatValue(measureResult.leakValue, measureResult.leakUnit); // 实时更新显示(不因单项失败而整页空白) MesClient.param1.setText(pressureText); MesClient.param2.setText(leakText); if (isEnd) { if (measureResult.leakValue == 0 && !measureResult.isPass) { MesClient.param2.setText("9999"); } String lastRet = measureResult.isPass ? "OK" : "NG"; if (lastRet.equals("OK")) { MesClient.result.setText("OK"); MesClient.result.setForeground(Color.GREEN); } else { MesClient.result.setText("NG"); MesClient.result.setForeground(Color.RED); } String testDate = DateLocalUtils.getCurrentTime(); TestParam testParam = new TestParam(); testParam.setSn(MesClient.product_sn.getText().trim()); testParam.setUcode(MesClient.user_menu.getText().trim()); testParam.setLineSn(MesClient.configParam.getLineSn()); testParam.setOprno(MesClient.configParam.getOprno()); testParam.setOprnoTitle(MesClient.configParam.getOprnoTitle()); testParam.setParam1(measureResult.pressureValue + ""); testParam.setParam2(measureResult.pressureUnit); testParam.setParam3(measureResult.leakValue + ""); testParam.setParam4(measureResult.leakUnit); testParam.setParam5(MesClient.programNo.getText().trim()); testParam.setResult(lastRet); testParam.setDeviceType("ateq"); // 提交字段 by=稳压时长, cs=测试时长 String byVal = MesClient.curStabilizeTime != null ? MesClient.curStabilizeTime.trim() : ""; String csVal = MesClient.curTestDuration != null ? MesClient.curTestDuration.trim() : ""; testParam.setStabilizeTime(byVal); testParam.setTestDuration(csVal); log.info("准备提交时长: by(稳压时长)={}, cs(测试时长)={}", byVal, csVal); testParam.setRemark(measureResult.isPass ? "" : String.format("状态码:0x%02X", measureResult.statusCode)); testParam.setCreateTime(testDate); JdbcUtils.insertTestRecord(testParam); if (MesClient.mes_enable) { // MES开启 JSONObject retObj = DataUtil.qmResultData(testParam); if (retObj != null && retObj.get("result") != null && retObj.get("result").toString().equalsIgnoreCase("true")) { MesClient.resetScanA(); MesClient.setMenuStatus("测试结果上传成功,请扫下一件", 0); } else { MesClient.setMenuStatus("测试结果上传失败,请重试", -1); return; } } else { MesClient.resetScanA(); } if (MesClient.configParam.getPrintLabel().equals("是") && lastRet.equals("OK")) { PrintUtil.printLabel(testParam.getSn(), testParam.getParam1() + testParam.getParam2(), testParam.getParam3() + testParam.getParam4(), testDate); } } } catch (Exception uiEx) { log.error("更新界面失败: {}", uiEx.getMessage()); } } }); } } catch (Exception e) { e.printStackTrace(); log.error("工作定时任务报错:"+e.getMessage()); } } } /** * 判定测试是否结束: * - 0x00:测试中 * - 0x21:OK,立即结束 * - 其他非 00:疑似 NG,需连续 {@link #NG_CONFIRM_NEEDED} 次相同状态才结束, * 期间若变为 0x21 则按 OK 结束,避免过渡码误判 */ private static boolean resolveTestEnd(ATEQ.MeasureResult measureResult) { if (measureResult.isTesting) { MesClient.mesStartFlag = 1; resetEndConfirm(); return false; } if (MesClient.mesStartFlag != 1) { return false; } if (measureResult.isPass) { log.info("状态码 0x21,判定 OK"); resetEndConfirm(); return true; } // 疑似 NG:连续确认 if (pendingNgStatusCode != measureResult.statusCode) { pendingNgStatusCode = measureResult.statusCode; ngConfirmCount = 1; log.info("疑似 NG 状态 0x{},等待确认 {}/{}", String.format("%02X", measureResult.statusCode), ngConfirmCount, NG_CONFIRM_NEEDED); return false; } ngConfirmCount++; log.info("疑似 NG 状态 0x{},确认 {}/{}", String.format("%02X", measureResult.statusCode), ngConfirmCount, NG_CONFIRM_NEEDED); if (ngConfirmCount >= NG_CONFIRM_NEEDED) { resetEndConfirm(); return true; } return false; } private static String formatValue(Double value, String unit) { if (value == null) { return ""; } String u = unit == null ? "" : unit.trim(); return u.isEmpty() ? String.valueOf(value) : (value + " " + u); } }