瀏覽代碼

流程拆分质量检查和工位结果提交

wangxichen 2 周之前
父節點
當前提交
a987f5b557

+ 14 - 11
config/project_config.json

@@ -1,22 +1,25 @@
 {
-	"currentLineId":"P4",
+	"currentLineId":"P3",
 	"currentProductId":"AY7-520",
 	"deviceIp":"192.168.0.6",
-	"stationCodeOverride":"OP300A",
+	"stationCodeOverride":"OP150A",
 	"lineSnOverride":"XT",
-	"serverIpOverride":"192.168.113.99",
-	"deviceEnabledOverride":false,
+	"serverIpOverride":"192.168.112.99",
+	"deviceEnabledOverride":true,
 	"uiOverride":{
-		"deviceRow1Enabled":false,
+		"deviceRow1Enabled":true,
 		"deviceRow1Label":"M5",
-		"deviceRow2Enabled":false,
-		"showMaterialInput":true
+		"deviceRow2Enabled":true,
+		"deviceRow2Label":"M6",
+		"showMaterialInput":false
 	},
 	"featuresOverride":{
 		"cold_plate":false,
-		"riveting":false,
-		"prod_params":false,
-		"bottom_plate":true
+		"riveting":true,
+		"prod_params":true,
+		"bottom_plate":false,
+		"quality_submit":false,
+		"check_quality":false
 	},
-	"lastModified":1783321584563
+	"lastModified":1784086182537
 }

+ 13 - 0
src/com/mes/prod/ProdDataUploader.java

@@ -91,6 +91,19 @@ public class ProdDataUploader {
     }
 
     /**
+     * 立即上传指定工位当前队列里的数据(不等定时轮询)
+     * 副机模式收尾时调用: 保证当前工件的所有过程参数在重置前发出。
+     * 失败会自动 requeue 到队列, 下次定时兜底重传。
+     */
+    public void uploadNow(String stationCode) {
+        ProdDataCollector collector = collectors.get(stationCode);
+        if (collector == null) return;
+        List<ProdRecord> records = collector.drainRecords();
+        if (records.isEmpty()) return;
+        upload(collector, records);
+    }
+
+    /**
      * 批量上传过程参数到MES服务器
      */
     private void upload(ProdDataCollector collector, List<ProdRecord> records) {

+ 51 - 4
src/com/mes/step/ResetStationStep.java

@@ -1,31 +1,78 @@
 package com.mes.step;
 
+import com.mes.core.StationConfig;
 import com.mes.core.StationContext;
+import com.mes.device.IDeviceDriver;
+import com.mes.prod.ProdDataCollector;
+import com.mes.prod.ProdDataUploader;
 import com.mes.ui.component.WorkstationPanel;
 
 /**
  * 重置工位步骤
- * 清空工位状态,准备处理下一件工件
+ * 职责(每次工件加工完必走的收尾):
+ * 1. 若 quality_submit 关且 prod_params 开: 立即上传当前工件的采集参数(副机模式闭环)
+ * 2. 清零 PLC 计数寄存器 (66/68/70) —— 原来放在 upload_result 里, 现集中在此
+ * 3. 重置 context 状态 + 刷新 UI + 弹扫码框
  */
 public class ResetStationStep extends AbstractStep {
 
+    // 由 MainFrame 在 rebuildWorkflows 时注入(用于副机模式立即上传)
+    private ProdDataCollector prodDataCollector;
+    private ProdDataUploader prodDataUploader;
+
     public ResetStationStep() {
         super("reset_station", "重置工位");
         this.async = false;
         this.requiresUserInteraction = false;  // 自动执行
     }
 
+    public void setProdDataCollector(ProdDataCollector collector) {
+        this.prodDataCollector = collector;
+    }
+
+    public void setProdDataUploader(ProdDataUploader uploader) {
+        this.prodDataUploader = uploader;
+    }
+
     @Override
     public boolean execute(StationContext context) {
         log.info("[{}] 执行工位重置", context.getStationCode());
 
-        // 重置上下文状态
+        // 1) 副机模式闭环: quality_submit 关 且 有采集器时, 立即把队列里的过程参数发出去
+        //    避免下一个工件覆盖 lastFinishedCount 前数据未上传
+        StationConfig cfg = StationConfig.getInstance();
+        boolean qualitySubmit = cfg.isFeatureEnabled("quality_submit");
+        if (!qualitySubmit && prodDataCollector != null && prodDataUploader != null) {
+            try {
+                prodDataUploader.uploadNow(context.getStationCode());
+                log.info("[{}] 副机模式: 已触发立即上传拉铆参数", context.getStationCode());
+            } catch (Exception e) {
+                log.warn("[{}] 立即上传拉铆参数异常(队列自动重试): {}",
+                        context.getStationCode(), e.getMessage());
+            }
+        }
+
+        // 2) 清零 PLC 计数寄存器 (地址 66=已完成, 68=合格, 70=NG)
+        //    原逻辑放在 UploadResultStep MQDW 成功后, 现统一在此处理
+        IDeviceDriver driver = context.getDeviceDriver();
+        if (driver != null && driver.isConnected()) {
+            try {
+                driver.writeRegister(66, 0);
+                driver.writeRegister(68, 0);
+                driver.writeRegister(70, 0);
+                log.info("[{}] PLC计数器清零成功", context.getStationCode());
+            } catch (Exception e) {
+                log.error("[{}] PLC计数器清零失败: {}", context.getStationCode(), e.getMessage());
+            }
+        }
+
+        // 3) 重置上下文状态
         context.reset();
 
-        // 刷新UI
+        // 4) 刷新 UI
         context.updateUI();
 
-        // 自动弹出扫码框,准备下一件
+        // 5) 自动弹出扫码框, 准备下一件
         WorkstationPanel panel = context.getUiPanel();
         if (panel != null) {
             panel.requestScan();

+ 10 - 1
src/com/mes/step/ScanProductStep.java

@@ -66,7 +66,16 @@ public class ScanProductStep extends AbstractStep {
     @Override
     public void onSuccess(StationContext context) {
         super.onSuccess(context);
-        // 扫码成功,自动进入质量检查
+        // 若 check_quality feature 关闭(副机模式),扫码后无 AQDW 步骤兜底置 qualityPassed
+        // 让后续 reset_device_count / wait_device_complete / upload_result 的 canExecute 能通过
+        try {
+            if (!com.mes.core.StationConfig.getInstance().isFeatureEnabled("check_quality")) {
+                context.setQualityPassed(true);
+                log.info("[{}] check_quality 未启用, 自动置 qualityPassed=true", context.getStationCode());
+            }
+        } catch (Exception ignore) {
+            // 配置未加载时忽略
+        }
     }
 
     @Override

+ 12 - 0
src/com/mes/step/StepFactory.java

@@ -133,6 +133,18 @@ public class StepFactory implements WorkflowEngine.StepFactory {
     }
 
     /**
+     * 注入过程参数采集器与上传器(用于 ResetStationStep 副机模式立即上传)
+     */
+    public void injectProdParams(IWorkflowStep step,
+                                 com.mes.prod.ProdDataCollector collector,
+                                 com.mes.prod.ProdDataUploader uploader) {
+        if (step instanceof ResetStationStep) {
+            ((ResetStationStep) step).setProdDataCollector(collector);
+            ((ResetStationStep) step).setProdDataUploader(uploader);
+        }
+    }
+
+    /**
      * 检查步骤是否已注册
      */
     public boolean isRegistered(String stepId) {

+ 1 - 14
src/com/mes/step/UploadResultStep.java

@@ -200,20 +200,7 @@ public class UploadResultStep extends AbstractStep {
         if ("OK".equalsIgnoreCase(resultCode)) {
             context.setResultUploaded(true);
             log.info("[{}] 结果上传成功", context.getStationCode());
-            
-            // 清零PLC计数器(地址66、68、70)
-            if (context.getDeviceDriver() != null) {
-                try {
-                    log.info("[{}] 开始清零PLC计数器", context.getStationCode());
-                    context.getDeviceDriver().writeRegister(66, 0);
-                    context.getDeviceDriver().writeRegister(68, 0);
-                    context.getDeviceDriver().writeRegister(70, 0);
-                    log.info("[{}] PLC计数器清零成功", context.getStationCode());
-                } catch (Exception e) {
-                    log.error("[{}] PLC计数器清零失败: {}", context.getStationCode(), e.getMessage());
-                }
-            }
-            
+            // 注:PLC计数器清零(66/68/70)已迁移到 ResetStationStep 统一处理
             context.setStatusMessage("结果提交成功,请扫下一件", 0);
             onSuccess(context);
         } else {

+ 22 - 5
src/com/mes/ui/MainFrame.java

@@ -630,6 +630,8 @@ public class MainFrame extends JFrame {
                         ((WaitCompleteStep) step).setProdDataCollector(collector);
                         log.info("[{}] 过程参数采集器已注入", stationInfo.getCode());
                     }
+                    // 注入到 ResetStationStep 供副机模式立即上传使用
+                    stepFactory.injectProdParams(step, collector, prodDataUploader);
                 }
                 prodDataUploader.addCollector(stationInfo.getCode(), collector);
             }
@@ -784,8 +786,17 @@ public class MainFrame extends JFrame {
         com.mes.step.IWorkflowStep uploadStep = engine.getStep("upload_result");
         if (uploadStep instanceof UploadResultStep) {
             ((UploadResultStep) uploadStep).setResult(result);
+        } else {
+            // 副机模式: 关闭 quality_submit 时 upload_result 不加载, OK/NG 按钮本应隐藏
+            // 若用户仍触发到这里, 直接跳到 reset_station 完成闭环
+            log.warn("[{}] quality_submit 已关闭, 无 upload_result 步骤, 直接重置工位",
+                    context.getStationCode());
+            if (engine.jumpToStep("reset_station")) {
+                engine.triggerCurrentStep();
+            }
+            return;
         }
-        
+
         if (currentStep instanceof UploadResultStep) {
             // 当前步骤已经是上传结果,直接触发
             log.info("[{}] 当前步骤是 UploadResultStep,直接触发", context.getStationCode());
@@ -1767,6 +1778,8 @@ public class MainFrame extends JFrame {
                     if (step instanceof WaitCompleteStep) {
                         ((WaitCompleteStep) step).setProdDataCollector(collector);
                     }
+                    // 注入到 ResetStationStep 供副机模式立即上传使用
+                    stepFactory.injectProdParams(step, collector, prodDataUploader);
                 }
                 prodDataUploader.addCollector(c.getStationCode(), collector);
             }
@@ -1798,10 +1811,12 @@ public class MainFrame extends JFrame {
         }
         // 功能显示名映射
         Map<String, String> labels = new LinkedHashMap<>();
-        labels.put("cold_plate",   "扫+校验冷板码");
-        labels.put("bottom_plate", "扫+校验底护板码");
-        labels.put("riveting",     "拉铆流程(心跳+计数+等待+停心跳)");
-        labels.put("prod_params",  "拉铆过程参数采集");
+        labels.put("check_quality",  "质量查询(发AQDW问工件能否加工)");
+        labels.put("cold_plate",     "扫+校验冷板码");
+        labels.put("bottom_plate",   "扫+校验底护板码");
+        labels.put("riveting",       "拉铆流程(心跳+计数+等待+停心跳)");
+        labels.put("prod_params",    "拉铆过程参数采集");
+        labels.put("quality_submit", "提交工位结果(MBDW+MQDW;关闭=副机模式)");
 
         // 构建复选框(按 yaml 声明顺序)
         JPanel panel = new JPanel();
@@ -1978,6 +1993,8 @@ public class MainFrame extends JFrame {
                     if (step instanceof WaitCompleteStep) {
                         ((WaitCompleteStep) step).setProdDataCollector(collector);
                     }
+                    // 注入到 ResetStationStep 供副机模式立即上传使用
+                    stepFactory.injectProdParams(step, collector, prodDataUploader);
                 }
                 prodDataUploader.addCollector(ctx.getStationCode(), collector);
             }

+ 12 - 0
src/com/mes/ui/component/WorkstationPanel.java

@@ -141,6 +141,13 @@ public class WorkstationPanel extends JPanel {
         }
 
         initUI();
+
+        // 初始化后按 quality_submit 决定 OK/NG 按钮显隐(副机模式关闭时隐藏)
+        if (config != null) {
+            boolean qualitySubmit = config.isFeatureEnabled("quality_submit");
+            if (okButton != null) okButton.setVisible(qualitySubmit);
+            if (ngButton != null) ngButton.setVisible(qualitySubmit);
+        }
     }
 
     /**
@@ -994,6 +1001,11 @@ public class WorkstationPanel extends JPanel {
         if (finishedCountLabel2 != null) finishedCountLabel2.setVisible(showDeviceInfo2);
         if (finishedCountField2 != null) finishedCountField2.setVisible(showDeviceInfo2);
 
+        // OK/NG 按钮显隐: 跟随 quality_submit feature (副机模式关闭 -> 按钮隐藏)
+        boolean qualitySubmit = cfg.isFeatureEnabled("quality_submit");
+        if (okButton != null) okButton.setVisible(qualitySubmit);
+        if (ngButton != null) ngButton.setVisible(qualitySubmit);
+
         revalidate();
         repaint();
     }

+ 18 - 9
src/resources/config/station.yaml

@@ -20,10 +20,12 @@ workflow:
 
   # 功能开关(yaml为默认值,运行时可在"设置→工艺流程配置"勾选,写入config/project_config.json覆盖)
   features:
-    cold_plate:    true   # 扫+校验冷板码
-    bottom_plate:  false  # 扫+校验底护板码
-    riveting:      true   # 拉铆流程(心跳+计数+等待完成+停心跳)
-    prod_params:   true   # 拉铆过程参数采集(device.prod_params 生效状态受此开关控制)
+    check_quality:  true   # 质量查询(发AQDW询问工件能否加工)
+    cold_plate:     true   # 扫+校验冷板码
+    bottom_plate:   false  # 扫+校验底护板码
+    riveting:       true   # 拉铆流程(心跳+计数+等待完成+停心跳)
+    prod_params:    true   # 拉铆过程参数采集(device.prod_params 生效状态受此开关控制)
+    quality_submit: true   # 提交工位结果(发MBDW+MQDW;关闭时OK/NG按钮隐藏,副机模式不上报质量)
 
   steps:
     - id: scan_product
@@ -32,9 +34,12 @@ workflow:
       config:
         prefix: "+KB24"
 
-    - id: check_quality
-      name: 质量检查
-      craft: "100000"   # 质量检查工艺号
+    # ========== 质量查询(feature: check_quality) ==========
+    - feature: check_quality
+      steps:
+        - id: check_quality
+          name: 质量检查
+          craft: "100000"   # 质量检查工艺号
 
     # ========== 冷板(feature: cold_plate) ==========
     - feature: cold_plate
@@ -81,8 +86,12 @@ workflow:
         - id: stop_heartbeat
           name: 停止心跳
 
-    - id: upload_result
-      name: 上传结果
+    # ========== 工位结果提交(feature: quality_submit) ==========
+    # 关闭时跳过 MBDW/MQDW 上报,OK/NG 按钮隐藏;副机(M6)配置:关闭
+    - feature: quality_submit
+      steps:
+        - id: upload_result
+          name: 上传结果
 
     - id: reset_station
       name: 重置工位