liuwei 4 dagar sedan
förälder
incheckning
7fa09f302b

+ 4 - 3
src/com/mes/ui/DataUtil.java

@@ -276,10 +276,10 @@ public class DataUtil {
                     +"&title="+URLEncoder.encode(titleBase64, "UTF-8")
                     +"&remark="+URLEncoder.encode(testParam.getRemark() != null ? testParam.getRemark() : "", "UTF-8")
                     +"&deviceType="+URLEncoder.encode(testParam.getDeviceType() != null ? testParam.getDeviceType() : "", "UTF-8")
-                    // 添加服务器端期望的参数
+                    // cq=填充 by=稳压时长 cs=测试时长(秒);testTime 仍为完成时刻
                     +"&cq="+URLEncoder.encode("", "UTF-8")
-                    +"&by="+URLEncoder.encode("", "UTF-8")
-                    +"&cs="+URLEncoder.encode("", "UTF-8")
+                    +"&by="+URLEncoder.encode(testParam.getStabilizeTime() != null ? testParam.getStabilizeTime() : "", "UTF-8")
+                    +"&cs="+URLEncoder.encode(testParam.getTestDuration() != null ? testParam.getTestDuration() : "", "UTF-8")
                     +"&leakRate="+URLEncoder.encode("", "UTF-8")
                     +"&leakRateUnit="+URLEncoder.encode("", "UTF-8")
                     +"&type="+URLEncoder.encode("", "UTF-8");
@@ -288,6 +288,7 @@ public class DataUtil {
 //            if (MesClient.sessionid != null && !MesClient.sessionid.isEmpty()) {
 //                params += "&__sid=" + MesClient.sessionid;
 //            }
+            log.info("提交时长字段 by(稳压时长)={}, cs(测试时长)={}", testParam.getStabilizeTime(), testParam.getTestDuration());
             log.info("params="+params);
             String result = doPost(url,params);
             log.info("result="+result);

+ 14 - 2
src/com/mes/ui/ExportUtil.java

@@ -35,7 +35,13 @@ public class ExportUtil {
             cell4.setCellValue("泄露值");
 
             Cell cell5 = headerRow.createCell(4);
-            cell5.setCellValue("结果");
+            cell5.setCellValue("稳压时长");
+
+            Cell cell6 = headerRow.createCell(5);
+            cell6.setCellValue("测试时长");
+
+            Cell cell7 = headerRow.createCell(6);
+            cell7.setCellValue("结果");
 
             int row = 0;
             for (QmData qmData : lists) {
@@ -54,7 +60,13 @@ public class ExportUtil {
                 scell4.setCellValue(qmData.getParam2());
 
                 Cell scell5 = dataRow.createCell(4);
-                scell5.setCellValue(qmData.getResult());
+                scell5.setCellValue(qmData.getStabilizeTime() != null ? qmData.getStabilizeTime() : "");
+
+                Cell scell6 = dataRow.createCell(5);
+                scell6.setCellValue(qmData.getTestDuration() != null ? qmData.getTestDuration() : "");
+
+                Cell scell7 = dataRow.createCell(6);
+                scell7.setCellValue(qmData.getResult());
 
                 row++;
             }

+ 84 - 13
src/com/mes/ui/MesClient.java

@@ -97,7 +97,7 @@ public class MesClient extends JFrame {
     public static JLabel curTaskName;
 
     public static JTable table;
-    public static Object[] columnNames = {"工件码", "测试日期", "压力", "泄露值","结果"};
+    public static Object[] columnNames = {"工件码", "测试日期", "压力", "泄露值", "稳压时长", "测试时长", "结果"};
 //    public static Object[][] rowData = null;
     //    public static Object[][] rowData = {
 //        {"151245P00001213100100024120700111","2024-12-09 12:30:30","60","60","60","200kPa","3ml/min","OK"},
@@ -105,7 +105,7 @@ public class MesClient extends JFrame {
 //        {"151245P00001213100100024120700113","2024-12-09 14:30:30","60","60","60","200kPa","3ml/min","OK"},
 //        {"151245P00001213100100024120700113","2024-12-09 14:30:30","60","60","60","200kPa","3ml/min","OK"},
 //    };
-    public static Object[][] rowData = new Object[12][5];
+    public static Object[][] rowData = new Object[12][7];
     public static JLabel pageLabel;
     public static int pageNo=1 ; // 当前页
     public static int totalPages; // 总页数
@@ -136,6 +136,11 @@ public class MesClient extends JFrame {
     public static Integer isConfigEdit = 0;
     public static Integer mesStartFlag = 0;
 
+    /** 本轮稳压时长(秒),来自 ATEQ 程序参数 */
+    public static String curStabilizeTime = "";
+    /** 本轮测试时长(秒),来自 ATEQ 程序参数 */
+    public static String curTestDuration = "";
+
     public static List<TaskParam> taskParamList = new ArrayList<>();
     public static TaskParam curTaskParam = null;
 
@@ -340,6 +345,14 @@ public class MesClient extends JFrame {
         tjFlag = 0;
         mesStartFlag = 0;
         curTaskName.setText("");
+        curStabilizeTime = "";
+        curTestDuration = "";
+        if (param3 != null) {
+            param3.setText("");
+        }
+        if (param4 != null) {
+            param4.setText("");
+        }
 
 //        f_scan_data_bt_1.setIcon(new ImageIcon(MesClient.class.getResource("/bg/scan_barcode.png")));
 //        f_scan_data_bt_1.setText("扫码");
@@ -616,9 +629,58 @@ public class MesClient extends JFrame {
 
     public static void scanBarcode() {
         if (work_status == 1) {
+            loadAteqProgramTimes();
             MesClient.serialPortUtils.start();
             return;
         }
+        setMenuStatus("请先扫工件码", -1);
+    }
+
+    /**
+     * 从 ATEQ 读取当前程序的稳压时长、测试时长并显示到工作面板。
+     * 非 ateq 或读取失败时不阻断主流程。
+     */
+    public static void loadAteqProgramTimes() {
+        try {
+            if (serialPortUtils == null || !serialPortUtils.isOpen) {
+                return;
+            }
+            String deviceType = serialPortUtils.device != null ? serialPortUtils.device.trim() : "";
+            if (deviceType.isEmpty() && configParam != null && configParam.getDevice() != null) {
+                deviceType = configParam.getDevice().trim();
+            }
+            if (!"ateq".equalsIgnoreCase(deviceType)) {
+                return;
+            }
+            String programNoStr = "1";
+            if (configParam != null && configParam.getProgramNo() != null && !configParam.getProgramNo().trim().isEmpty()) {
+                programNoStr = configParam.getProgramNo().trim();
+            } else if (programNo != null && programNo.getText() != null && !programNo.getText().trim().isEmpty()) {
+                programNoStr = programNo.getText().trim();
+            }
+            ATEQ.Parameters parameters = ATEQ.getParams(Integer.valueOf(programNoStr));
+            curStabilizeTime = formatSeconds(parameters.stabilizeTime);
+            curTestDuration = formatSeconds(parameters.testTime);
+            if (param3 != null) {
+                param3.setText(curStabilizeTime.isEmpty() ? "" : (curStabilizeTime + " s"));
+            }
+            if (param4 != null) {
+                param4.setText(curTestDuration.isEmpty() ? "" : (curTestDuration + " s"));
+            }
+            log.info("程序时长参数: 稳压时长={}s, 测试时长={}s", curStabilizeTime, curTestDuration);
+        } catch (Exception e) {
+            log.error("读取稳压/测试时长失败: {}", e.getMessage());
+        }
+    }
+
+    private static String formatSeconds(Double value) {
+        if (value == null) {
+            return "";
+        }
+        if (Math.abs(value - Math.rint(value)) < 0.0001) {
+            return String.valueOf((int) Math.rint(value));
+        }
+        return String.valueOf(value);
     }
 
     public static void scanBarcode2() {
@@ -679,6 +741,7 @@ public class MesClient extends JFrame {
 
         if(checkProductSn(scanBarcode.trim())){
             serialPortUtils.changeProgram(); // 切换程序
+            loadAteqProgramTimes();
             if(MesClient.mes_enable){
                 getUser();
                 // 查询工件质量
@@ -986,29 +1049,29 @@ public class MesClient extends JFrame {
         param2.setBounds(597, 210, 150, 40);
         indexPanelA.add(param2);
         
-        JLabel lblNewLabel_2 = new JLabel("测电阻电压");
+        JLabel lblNewLabel_2 = new JLabel("稳压时长");
         lblNewLabel_2.setHorizontalAlignment(SwingConstants.RIGHT);
         lblNewLabel_2.setFont(new Font("微软雅黑", Font.PLAIN, 20));
         lblNewLabel_2.setBounds(137, 288, 140, 40);
-//        indexPanelA.add(lblNewLabel_2);
+        indexPanelA.add(lblNewLabel_2);
         
         param3 = new JTextField();
         param3.setEditable(false);
         param3.setColumns(10);
         param3.setBounds(287, 288, 150, 40);
-//        indexPanelA.add(param3);
+        indexPanelA.add(param3);
         
-        JLabel lblNewLabel_1_1 = new JLabel("电阻");
+        JLabel lblNewLabel_1_1 = new JLabel("测试时长");
         lblNewLabel_1_1.setHorizontalAlignment(SwingConstants.RIGHT);
         lblNewLabel_1_1.setFont(new Font("微软雅黑", Font.PLAIN, 20));
         lblNewLabel_1_1.setBounds(447, 288, 140, 40);
-//        indexPanelA.add(lblNewLabel_1_1);
+        indexPanelA.add(lblNewLabel_1_1);
         
         param4 = new JTextField();
         param4.setEditable(false);
         param4.setColumns(10);
         param4.setBounds(597, 288, 150, 40);
-//        indexPanelA.add(param4);
+        indexPanelA.add(param4);
 
 
         result = new JLabel("等待结果") {
@@ -1217,12 +1280,20 @@ public class MesClient extends JFrame {
 //        table.getColumnModel().getColumn(3).setCellRenderer(new TableCellRendererButton());
 //        table.getColumnModel().getColumn(3).setCellEditor(new TableCellEditorButton());
 
-        // 设置第二列的长度为100像素
         TableColumn column = table.getColumnModel().getColumn(0);
-        column.setPreferredWidth(290);
+        column.setPreferredWidth(220);
 
         column = table.getColumnModel().getColumn(1);
-        column.setPreferredWidth(160);
+        column.setPreferredWidth(140);
+
+        if (table.getColumnCount() > 4) {
+            column = table.getColumnModel().getColumn(4);
+            column.setPreferredWidth(90);
+        }
+        if (table.getColumnCount() > 5) {
+            column = table.getColumnModel().getColumn(5);
+            column.setPreferredWidth(90);
+        }
 
         CenterRenderer centerRenderer = new CenterRenderer();
         for (int i = 0; i < table.getColumnCount(); i++) {
@@ -1677,7 +1748,7 @@ public class MesClient extends JFrame {
         });
         indexPanelTest.add(testSendBtn);
 
-        JLabel testTipLabel = new JLabel("说明:泄漏=先发 10 30 04 00 00,再发 03 22 15 00 02;设备需为 ateq");
+        JLabel testTipLabel = new JLabel("说明:泄漏=先发 10 30 04,再发 03 22 0A 00 02;设备需为 ateq");
         testTipLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
         testTipLabel.setBounds(80, 280, 700, 30);
         indexPanelTest.add(testTipLabel);
@@ -2070,7 +2141,7 @@ public class MesClient extends JFrame {
         if (testSendBtn != null) {
             testSendBtn.setEnabled(false);
         }
-        appendTestLog("正在发送: 压力(10 30 04→22 06),泄漏(先 10 30 04 00 00 再 22 15)...");
+        appendTestLog("正在发送: 压力(10 30 04→22 06),泄漏(先 10 30 04 再 22 0A)...");
         new Thread(new Runnable() {
             @Override
             public void run() {

+ 1 - 0
src/com/mes/ui/MesRevice.java

@@ -18,6 +18,7 @@ public class MesRevice {
                 MesClient.tjFlag = 1;
                 MesClient.setMenuStatus("该工件可以测试,等待测试",0);
                 MesClient.product_sn.setEditable(false);
+                MesClient.loadAteqProgramTimes();
                 if(MesClient.configParam.getStartMode().equals("自动启动")){
                     MesClient.serialPortUtils.start();
                 }

+ 18 - 0
src/com/mes/ui/QmData.java

@@ -5,6 +5,8 @@ public class QmData {
     private String createTime;
     private String param1;
     private String param2;
+    private String stabilizeTime;
+    private String testDuration;
     private String result;
 
     public String getSn() {
@@ -39,6 +41,22 @@ public class QmData {
         this.param2 = param2;
     }
 
+    public String getStabilizeTime() {
+        return stabilizeTime;
+    }
+
+    public void setStabilizeTime(String stabilizeTime) {
+        this.stabilizeTime = stabilizeTime;
+    }
+
+    public String getTestDuration() {
+        return testDuration;
+    }
+
+    public void setTestDuration(String testDuration) {
+        this.testDuration = testDuration;
+    }
+
     public String getResult() {
         return result;
     }

+ 53 - 30
src/com/mes/util/ATEQ.java

@@ -35,7 +35,7 @@ public class ATEQ {
 
     /**
      * 读保持寄存器
-     * @param addrHex 起始地址,如 "22 15"
+     * @param addrHex 起始地址,如 "22 0A"
      * @param quantity 寄存器数量
      */
     public static byte[] readHolding(String addrHex, int quantity) {
@@ -102,14 +102,14 @@ public class ATEQ {
         return parseUnit(selectThenReadHolding("22 08", 2));
     }
 
-    /** 泄漏量 0x2215:先 10 30 04,再 03 22 15 00 02 */
+    /** 泄漏量(Flow) 0x220A:先 10 30 04,再 03 22 0A 00 02(ATEQ 实时区仅 2201~220D) */
     public static double readLeak() {
-        return parseDwordValue(selectThenReadHolding("22 15", 2));
+        return parseDwordValue(selectThenReadHolding("22 0A", 2));
     }
 
-    /** 泄漏单位 0x2217:先 10 30 04,再 03 22 17 00 02 */
+    /** 泄漏单位 0x220C:先 10 30 04,再 03 22 0C 00 02 */
     public static String readLeakUnit() {
-        return parseUnit(selectThenReadHolding("22 17", 2));
+        return parseUnit(selectThenReadHolding("22 0C", 2));
     }
 
     /**
@@ -132,7 +132,7 @@ public class ATEQ {
     /**
      * 通讯测试-泄漏:
      * 1) 先发 01 10 30 04 00 01 02 00 00 + CRC,等待应答
-     * 2) 再发 01 03 22 15 00 02 + CRC,解析泄漏值
+     * 2) 再发 01 03 22 0A 00 02 + CRC,解析泄漏值(手册 Flow=220A/220B,非 2215)
      */
     public static double readTestLeakOnly() {
         String selectCmd = DataUtils.CRC16(ATEQ.getStationNo() + " 10 30 04 00 01 02 00 00");
@@ -148,11 +148,11 @@ public class ATEQ {
 
         sleepQuiet(100);
 
-        String leakCmd = DataUtils.CRC16(ATEQ.getStationNo() + " 03 22 15 00 02");
+        String leakCmd = DataUtils.CRC16(ATEQ.getStationNo() + " 03 22 0A 00 02");
         log.info("测试页泄漏-读寄存器: {}", leakCmd);
         byte[] leakResp = MesClient.serialPortUtils.read(leakCmd);
         log.info("测试页泄漏-读寄存器应答: {}", DataUtils.bytesToHex(leakResp));
-        checkModbusResponse(leakResp, "22 15");
+        checkModbusResponse(leakResp, "22 0A");
         return parseDwordValue(leakResp);
     }
 
@@ -292,24 +292,40 @@ public class ATEQ {
 
 
 
-    // 获取参数, 传入程序号, 获取对应程序号的参数
+    /**
+     * 读取程序设定的填充/稳压时长/测试时长(秒)。
+     * 使用 Direct Access(与压力/泄漏相同读法,每次最多2字):
+     * 先 10 30 04 选程序,再读 2002=稳压时长、2003=测试时长(可选 2001=填充)。
+     */
     public static Parameters getParams(Integer programNumber) {
+        if (programNumber == null || programNumber < 1) {
+            programNumber = 1;
+        }
+        String station = getStationNo();
+        // 将目标程序置于编辑/读取状态
+        String s1 = DataUtils.CRC16(station + " 10 30 04 00 01 02 " + DataUtils.intToWord(programNumber - 1));
+        log.info("读程序时间参数-选程序: {}", s1);
+        byte[] selectResp = MesClient.serialPortUtils.read(s1);
+        log.info("读程序时间参数-选程序应答: {}", DataUtils.bytesToHex(selectResp));
+        checkModbusResponse(selectResp, "30 04");
+        sleepQuiet(100);
 
-        // 步骤1: 选择要编辑的程序
-        String s1 = DataUtils.CRC16("01 10 30 04 00 01 02 " + DataUtils.intToWord(programNumber - 1));
-        MesClient.serialPortUtils.read(s1);
-
-        // 步骤2: 写入要读取的标识符
-        String s2 = "01 10 00 00 00 04 08 03 00 01 00 02 00 03 00 F6 F6"; // s2 表示读取3个参数, 分别是 填充时间、稳定时间、测试时间
-        MesClient.serialPortUtils.read(s2);
-
-        // 步骤3: 读取数据
-        byte[] read = MesClient.serialPortUtils.read("01 03 00 00 00 09 85 CC");
-        if(read.length > 22) {
-            return new Parameters(read);
-        } else {
-            throw new RuntimeException("读取参数时, 返回的数据长度不够");
+        Double fillTime = null;
+        Double stabilizeTime = null;
+        Double testTime = null;
+        try {
+            fillTime = parseDwordValue(readHolding("20 01", 2));
+        } catch (Exception e) {
+            log.warn("读填充时间失败: {}", e.getMessage());
         }
+        sleepQuiet(50);
+        stabilizeTime = parseDwordValue(readHolding("20 02", 2));
+        sleepQuiet(50);
+        testTime = parseDwordValue(readHolding("20 03", 2));
+
+        Parameters parameters = new Parameters(fillTime, stabilizeTime, testTime);
+        log.info("读程序时间参数成功: {}", parameters);
+        return parameters;
     }
 
     // 获取站号
@@ -463,15 +479,22 @@ public class ATEQ {
 
     // 参数类
     public static class Parameters {
-        public final Integer fillTime;         // 填充时间
-        public final Integer stabilizeTime;    // 稳定时间
-        public final Integer testTime;         // 测试时间
+        public final Double fillTime;         // 填充时长(秒)
+        public final Double stabilizeTime;    // 稳压时长(秒)
+        public final Double testTime;         // 测试时长(秒)
+
+        public Parameters(Double fillTime, Double stabilizeTime, Double testTime) {
+            this.fillTime = fillTime;
+            this.stabilizeTime = stabilizeTime;
+            this.testTime = testTime;
+        }
 
+        /** 兼容旧的批量应答解析 */
         public Parameters(byte[] data) {
-            log.info("时间参数:"+DataUtils.bytesToHex(data));
-            this.fillTime = DataUtils.bytesToInt(Arrays.copyOfRange(data, 5, 9)) / 1000;
-            this.stabilizeTime = DataUtils.bytesToInt(Arrays.copyOfRange(data, 11, 15)) / 1000;
-            this.testTime = DataUtils.bytesToInt(Arrays.copyOfRange(data, 17, 21)) / 1000;
+            log.info("时间参数:" + DataUtils.bytesToHex(data));
+            this.fillTime = DataUtils.bytesToInt(Arrays.copyOfRange(data, 5, 9)) / 1000.0;
+            this.stabilizeTime = DataUtils.bytesToInt(Arrays.copyOfRange(data, 11, 15)) / 1000.0;
+            this.testTime = DataUtils.bytesToInt(Arrays.copyOfRange(data, 17, 21)) / 1000.0;
         }
 
         @Override

+ 56 - 14
src/com/mes/util/JdbcUtils.java

@@ -92,6 +92,16 @@ public class JdbcUtils {
 
 		statement.executeUpdate(testRecord);
 
+		// 兼容已有库:补充稳压时长、测试时长字段
+		try {
+			statement.executeUpdate("ALTER TABLE test_record ADD COLUMN stab_time VARCHAR(48)");
+		} catch (SQLException ignore) {
+		}
+		try {
+			statement.executeUpdate("ALTER TABLE test_record ADD COLUMN test_duration VARCHAR(48)");
+		} catch (SQLException ignore) {
+		}
+
 		String configRecord = "CREATE TABLE if not exists config(\n" +
 				"   id INTEGER PRIMARY KEY AUTOINCREMENT, -- 自增ID\n" +
 				"   content VARCHAR(2000)                    -- 配置内容,json格式 \n" +
@@ -166,9 +176,11 @@ public class JdbcUtils {
 				JdbcUtils.openConnection();
 			}
 			Statement statement=conn.createStatement();
-			String insertSQL = "INSERT INTO test_record (oprno,oprno_title,ucode, sn, line_sn, create_time, param1,param2,param3,param4,param5,result,remark,device_type)" +
+			String insertSQL = "INSERT INTO test_record (oprno,oprno_title,ucode, sn, line_sn, create_time, param1,param2,param3,param4,param5,result,remark,device_type,stab_time,test_duration)" +
 					"VALUES('"+testParam.getOprno()+"','" + testParam.getOprnoTitle() + "','"+testParam.getUcode()+"', '" + testParam.getSn() + "', '" + testParam.getLineSn() + "', '" + testParam.getCreateTime() + "', '" + testParam.getParam1() + "', '"
-					+testParam.getParam2()+"','"+testParam.getParam3()+"','"+testParam.getParam4()+"','"+testParam.getParam5()+"','"+testParam.getResult()+"','"+testParam.getRemark()+"','"+testParam.getDeviceType()+"')";
+					+testParam.getParam2()+"','"+testParam.getParam3()+"','"+testParam.getParam4()+"','"+testParam.getParam5()+"','"+testParam.getResult()+"','"+testParam.getRemark()+"','"+testParam.getDeviceType()+"','"
+					+(testParam.getStabilizeTime() != null ? testParam.getStabilizeTime() : "")+"','"
+					+(testParam.getTestDuration() != null ? testParam.getTestDuration() : "")+"')";
 			statement.executeUpdate(insertSQL);
 			statement.close();
 			ret = true;
@@ -314,13 +326,15 @@ public class JdbcUtils {
 
 
 			while (ret.next()) {
-				MesClient.rowData[rowIndex][0] = ret.getString(2);  // sn (工件码)
-				MesClient.rowData[rowIndex][1] = ret.getString(7);  // create_time (测试日期)
-				MesClient.rowData[rowIndex][2] = ret.getString(8)+ret.getString(9);  // param1 (压力)
-				MesClient.rowData[rowIndex][3] = ret.getString(10)+ret.getString(11); // param3 (泄漏值)
-				MesClient.rowData[rowIndex][4] = ret.getString(13); // result (结果)
-//				MesClient.rowData[rowIndex][5] = ret.getString(8);
-//				MesClient.rowData[rowIndex][6] = ret.getString(9);
+				MesClient.rowData[rowIndex][0] = ret.getString("sn");  // 工件码
+				MesClient.rowData[rowIndex][1] = ret.getString("create_time");  // 测试日期
+				String pressure = nullToEmpty(ret.getString("param1")) + nullToEmpty(ret.getString("param2"));
+				String leak = nullToEmpty(ret.getString("param3")) + nullToEmpty(ret.getString("param4"));
+				MesClient.rowData[rowIndex][2] = pressure;  // 压力
+				MesClient.rowData[rowIndex][3] = leak; // 泄漏值
+				MesClient.rowData[rowIndex][4] = formatDurationDisplay(safeGetColumn(ret, "stab_time")); // 稳压时长
+				MesClient.rowData[rowIndex][5] = formatDurationDisplay(safeGetColumn(ret, "test_duration")); // 测试时长
+				MesClient.rowData[rowIndex][6] = ret.getString("result"); // 结果
 				rowIndex++;
 			}
 
@@ -372,11 +386,13 @@ public class JdbcUtils {
 
 			while (ret.next()) {
 				QmData qmData = new QmData();
-				qmData.setSn(ret.getString(2));
-				qmData.setCreateTime(ret.getString(7));
-				qmData.setParam1(ret.getString(8)+ret.getString(9));
-				qmData.setParam2(ret.getString(10)+ret.getString(11));
-				qmData.setResult(ret.getString(13));
+				qmData.setSn(ret.getString("sn"));
+				qmData.setCreateTime(ret.getString("create_time"));
+				qmData.setParam1(nullToEmpty(ret.getString("param1")) + nullToEmpty(ret.getString("param2")));
+				qmData.setParam2(nullToEmpty(ret.getString("param3")) + nullToEmpty(ret.getString("param4")));
+				qmData.setStabilizeTime(formatDurationDisplay(safeGetColumn(ret, "stab_time")));
+				qmData.setTestDuration(formatDurationDisplay(safeGetColumn(ret, "test_duration")));
+				qmData.setResult(ret.getString("result"));
 				lists.add(qmData);
 				rowIndex++;
 			}
@@ -390,6 +406,32 @@ public class JdbcUtils {
 		return lists;
 	}
 
+	private static String nullToEmpty(String value) {
+		return value == null ? "" : value;
+	}
+
+	private static String safeGetColumn(ResultSet ret, String column) {
+		try {
+			return ret.getString(column);
+		} catch (SQLException e) {
+			return "";
+		}
+	}
+
+	private static String formatDurationDisplay(String value) {
+		if (value == null) {
+			return "";
+		}
+		String v = value.trim();
+		if (v.isEmpty()) {
+			return "";
+		}
+		if (v.endsWith("s") || v.endsWith("S") || v.endsWith("秒")) {
+			return v;
+		}
+		return v + " s";
+	}
+
 
 
 	public static void close(){

+ 1 - 1
src/com/mes/util/SerialPortUtils.java

@@ -327,7 +327,7 @@ public class SerialPortUtils {
             log.info("向串口写入: {}", sendData);
             serialPort.writeBytes(bytesToSend, bytesToSend.length);
 
-            long deadline = System.currentTimeMillis() + 800;
+            long deadline = System.currentTimeMillis() + 1500;
             while (System.currentTimeMillis() < deadline) {
                 synchronized (this) {
                     if (isModbusFrameComplete()) {

+ 22 - 0
src/com/mes/util/TestParam.java

@@ -17,6 +17,10 @@ public class TestParam {
     public String result;
     public String remark;
     public String deviceType;
+    /** 稳压时长(秒),对应上传 by */
+    public String stabilizeTime;
+    /** 测试时长(秒),对应上传 cs */
+    public String testDuration;
 
     public Integer getId() {
         return id;
@@ -130,6 +134,22 @@ public class TestParam {
         this.deviceType = deviceType;
     }
 
+    public String getStabilizeTime() {
+        return stabilizeTime;
+    }
+
+    public void setStabilizeTime(String stabilizeTime) {
+        this.stabilizeTime = stabilizeTime;
+    }
+
+    public String getTestDuration() {
+        return testDuration;
+    }
+
+    public void setTestDuration(String testDuration) {
+        this.testDuration = testDuration;
+    }
+
     public String getLineSn() {
         return lineSn;
     }
@@ -156,6 +176,8 @@ public class TestParam {
                 ", result='" + result + '\'' +
                 ", remark='" + remark + '\'' +
                 ", deviceType='" + deviceType + '\'' +
+                ", stabilizeTime='" + stabilizeTime + '\'' +
+                ", testDuration='" + testDuration + '\'' +
                 '}';
     }
 }

+ 16 - 0
src/com/mes/util/WorkTimer.java

@@ -61,6 +61,16 @@ public class WorkTimer {
                     final ATEQ.MeasureResult measureResult = ATEQ.readMeasureResult();
                     log.info(measureResult.toString());
 
+                    // 测完提交前:若稳压/测试时长为空,再读一次程序参数
+                    boolean willEnd = !measureResult.isTesting && MesClient.mesStartFlag == 1;
+                    if (willEnd) {
+                        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() {
@@ -111,6 +121,12 @@ public class WorkTimer {
                                     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);