From 8f3a85044b6e4b56a8dd0b104ca023933f1f129c Mon Sep 17 00:00:00 2001
From: huang <1532065656@qq.com>
Date: 星期三, 03 十二月 2025 16:58:36 +0800
Subject: [PATCH] 统一卧转立扫码、卧转立、大车、大理片笼的定时器逻辑和步骤状态;添加设备拓扑图清除数据、联机状态切换按钮,

---
 mes-processes/mes-plcSend/src/main/java/com/mes/interaction/vehicle/handler/LoadVehicleLogicHandler.java |  329 +++++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 247 insertions(+), 82 deletions(-)

diff --git a/mes-processes/mes-plcSend/src/main/java/com/mes/interaction/vehicle/handler/LoadVehicleLogicHandler.java b/mes-processes/mes-plcSend/src/main/java/com/mes/interaction/vehicle/handler/LoadVehicleLogicHandler.java
index 4a40192..62569ad 100644
--- a/mes-processes/mes-plcSend/src/main/java/com/mes/interaction/vehicle/handler/LoadVehicleLogicHandler.java
+++ b/mes-processes/mes-plcSend/src/main/java/com/mes/interaction/vehicle/handler/LoadVehicleLogicHandler.java
@@ -1,10 +1,12 @@
 package com.mes.interaction.vehicle.handler;
 
 import com.mes.device.entity.DeviceConfig;
+import com.mes.device.entity.DeviceStatus;
 import com.mes.device.service.DeviceConfigService;
 import com.mes.device.service.DeviceGroupRelationService;
 import com.mes.device.service.DevicePlcOperationService;
 import com.mes.device.service.GlassInfoService;
+import com.mes.device.service.DeviceStatusService;
 import com.mes.device.vo.DeviceGroupVO;
 import com.mes.device.vo.DevicePlcVO;
 import com.mes.interaction.BaseDeviceLogicHandler;
@@ -16,6 +18,8 @@
 import com.mes.s7.enhanced.EnhancedS7Serializer;
 import com.mes.s7.provider.S7SerializerProvider;
 import com.mes.service.PlcDynamicDataService;
+import com.mes.task.model.TaskExecutionContext;
+import com.mes.interaction.workstation.scanner.handler.HorizontalScannerLogicHandler;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
@@ -47,6 +51,9 @@
     
     @Autowired(required = false)
     private DeviceGroupRelationService deviceGroupRelationService;
+    
+    @Autowired(required = false)
+    private DeviceStatusService deviceStatusService;
     
     @Autowired(required = false)
     private PlcDynamicDataService plcDynamicDataService;
@@ -187,6 +194,9 @@
                 case "stopTaskMonitor":
                     result = handleStopTaskMonitor(deviceConfig);
                     break;
+                case "setOnlineState":
+                    result = handleSetOnlineState(deviceConfig, params, logicParams);
+                    break;
                 default:
                     log.warn("涓嶆敮鎸佺殑鎿嶄綔绫诲瀷: {}", operation);
                     result = DevicePlcVO.OperationResult.builder()
@@ -219,8 +229,14 @@
      * 鍒ゆ柇鎿嶄綔鏄惁闇�瑕佺姸鎬佹鏌�
      */
     private boolean needsStateCheck(String operation) {
-        // 鎵�鏈夋搷浣滈兘闇�瑕佹鏌ョ姸鎬侊紝闄や簡鏌ヨ绫绘搷浣�
-        return !"query".equals(operation) && !"status".equals(operation);
+        // 鎵�鏈夋搷浣滈兘闇�瑕佹鏌ョ姸鎬侊紝闄や簡鏌ヨ绫绘搷浣滃拰鐗瑰畾鍐呴儴妫�鏌�
+        if ("query".equals(operation) || "status".equals(operation)) {
+            return false;
+        }
+        if ("checkMesConfirm".equals(operation)) {
+            return false;
+        }
+        return true;
     }
 
     /**
@@ -256,7 +272,23 @@
         }
         
         // 浠庨厤缃腑鑾峰彇閫熷害锛堝鏋滄湁锛�
-        Double speed = getLogicParam(logicParams, "vehicleSpeed", null);
+        Object speedObj = logicParams != null ? logicParams.get("vehicleSpeed") : null;
+        Double speed = null;
+        if (speedObj != null) {
+            if (speedObj instanceof Double) {
+                speed = (Double) speedObj;
+            } else if (speedObj instanceof Integer) {
+                speed = ((Integer) speedObj).doubleValue();
+            } else if (speedObj instanceof Number) {
+                speed = ((Number) speedObj).doubleValue();
+            } else {
+                try {
+                    speed = Double.parseDouble(String.valueOf(speedObj));
+                } catch (NumberFormatException e) {
+                    log.warn("鏃犳硶瑙f瀽vehicleSpeed: {}", speedObj);
+                }
+            }
+        }
         if (speed != null) {
             task.setSpeed(speed);
             task.calculateEstimatedEndTime();
@@ -284,7 +316,7 @@
 
         // 浠庨�昏緫鍙傛暟涓幏鍙栭厤缃紙浠� extraParams.deviceLogic 璇诲彇锛�
         Integer vehicleCapacity = getLogicParam(logicParams, "vehicleCapacity", 6000);
-        Integer glassIntervalMs = getLogicParam(logicParams, "glassIntervalMs", 1000);
+        Integer glassGap = getLogicParam(logicParams, "glassGap", 200); // 鐜荤拑涔嬮棿鐨勭墿鐞嗛棿闅旓紙mm锛夛紝榛樿200mm
         Boolean autoFeed = getLogicParam(logicParams, "autoFeed", true);
         Integer maxRetryCount = getLogicParam(logicParams, "maxRetryCount", 5);
 
@@ -301,7 +333,7 @@
         Integer positionValue = (Integer) params.get("positionValue");
         Boolean triggerRequest = (Boolean) params.getOrDefault("triggerRequest", autoFeed);
 
-        List<GlassInfo> plannedGlasses = planGlassLoading(glassInfos, vehicleCapacity,
+        List<GlassInfo> plannedGlasses = planGlassLoading(glassInfos, vehicleCapacity, glassGap,
                 deviceConfig.getDeviceId());
         if (plannedGlasses == null) {
             // 鐜荤拑娌℃湁闀垮害鏃惰繑鍥瀗ull琛ㄧず閿欒
@@ -311,11 +343,20 @@
                     .build();
         }
         if (plannedGlasses.isEmpty()) {
+            // 瑁呬笉涓嬶紝閫氱煡鍗ц浆绔嬫壂鐮佽澶囨殏鍋�
+            notifyScannerPause(params, true);
+            log.warn("澶ц溅璁惧瑁呬笉涓嬶紝宸查�氱煡鍗ц浆绔嬫壂鐮佹殏鍋�: deviceId={}, glassCount={}, vehicleCapacity={}", 
+                    deviceConfig.getId(), glassInfos.size(), vehicleCapacity);
             return DevicePlcVO.OperationResult.builder()
                     .success(false)
-                    .message("褰撳墠鐜荤拑灏哄瓒呭嚭杞﹁締瀹归噺锛屾棤娉曡杞�")
+                    .message("褰撳墠鐜荤拑灏哄瓒呭嚭杞﹁締瀹归噺锛屾棤娉曡杞斤紝宸查�氱煡鍗ц浆绔嬫壂鐮佹殏鍋�")
                     .build();
         }
+        
+        // 瑁呭緱涓嬶紝纭繚鍗ц浆绔嬫壂鐮佺户缁繍琛�
+        notifyScannerPause(params, false);
+        
+        // 缁х画鎵ц鍘熸湁閫昏緫
 
         // 鏋勫缓鍐欏叆鏁版嵁
         Map<String, Object> payload = new HashMap<>();
@@ -328,17 +369,21 @@
         }
         payload.put("plcGlassCount", plcSlots);
 
-        // 鍐欏叆浣嶇疆淇℃伅
+        // 鍐欏叆浣嶇疆淇℃伅锛歅LC渚ф湡鏈涚殑鏄� MES 缂栧彿锛堝1001/1002锛夛紝鑰屼笉鏄綅缃槧灏勫悗鐨勬牸瀛愬��
+        Integer plcPosition = null;
         if (positionValue != null) {
-            payload.put("inPosition", positionValue);
+            // 濡傛灉璋冪敤鏂圭洿鎺ヤ紶浜嗘暟鍊硷紝鍒欒涓鸿繖鏄疢ES缂栧彿锛岀洿鎺ュ啓鍏�
+            plcPosition = positionValue;
         } else if (positionCode != null) {
-            // 浠庝綅缃槧灏勪腑鑾峰彇浣嶇疆鍊�
-            @SuppressWarnings("unchecked")
-            Map<String, Integer> positionMapping = getLogicParam(logicParams, "positionMapping", new HashMap<>());
-            Integer mappedValue = positionMapping.get(positionCode);
-            if (mappedValue != null) {
-                payload.put("inPosition", mappedValue);
+            // 灏濊瘯灏嗕綅缃唬鐮佽В鏋愪负鏁板瓧锛堜緥濡� "900" -> 900锛�
+            try {
+                plcPosition = Integer.parseInt(positionCode.trim());
+            } catch (NumberFormatException ignore) {
+                // 闈炴暟瀛楃紪鐮佹椂锛屼笉鍐欏叆inPosition锛岀敱PLC鎴栧悗缁�昏緫鑷澶勭悊
             }
+        }
+        if (plcPosition != null) {
+            payload.put("inPosition", plcPosition);
         }
 
         // 鑷姩瑙﹀彂璇锋眰瀛�
@@ -354,18 +399,11 @@
         log.info("澶ц溅璁惧鐜荤拑涓婃枡: deviceId={}, glassCount={}, position={}, plannedGlassIds={}",
                 deviceConfig.getId(), plcSlots, positionCode, plannedGlasses);
 
-        if (glassIntervalMs != null && glassIntervalMs > 0) {
-            try {
-                Thread.sleep(glassIntervalMs);
-            } catch (InterruptedException e) {
-                Thread.currentThread().interrupt();
-            }
-        }
-
+        // 鍐欏叆PLC锛岃澶ц溅寮�濮嬭鐜荤拑
         DevicePlcVO.OperationResult result = devicePlcOperationService.writeFields(
             deviceConfig.getId(), payload, operationName);
         
-        // 濡傛灉鎵ц鎴愬姛锛屾洿鏂颁綅缃俊鎭埌鐘舵�侊紝骞跺惎鍔ㄧ姸鎬佺洃鎺�
+        // 濡傛灉鎵ц鎴愬姛锛屾洿鏂颁綅缃俊鎭埌鐘舵��
         if (Boolean.TRUE.equals(result.getSuccess())) {
             VehicleStatus status = statusManager.getOrCreateVehicleStatus(
                 deviceConfig.getDeviceId(), deviceConfig.getDeviceName());
@@ -373,9 +411,16 @@
                 VehiclePosition position = new VehiclePosition(positionCode, positionValue);
                 status.setCurrentPosition(position);
             }
-            
-            // 鍚姩鑷姩鐘舵�佺洃鎺э紝褰� state=1 鏃惰嚜鍔ㄥ崗璋冨崸杞珛璁惧
-            startStateMonitoring(deviceConfig, logicParams);
+
+            // 浠呭湪鈥滈潪澶氳澶囦换鍔♀�濆満鏅笅锛屾墠鍚姩澶ц溅鑷韩鐨勮嚜鍔ㄧ姸鎬佺洃鎺у拰 MES 浠诲姟鐩戞帶
+            boolean inMultiDeviceTask = params != null && params.containsKey("_taskContext");
+            if (!inMultiDeviceTask) {
+                // 鍚姩鑷姩鐘舵�佺洃鎺э紝褰� state=1 鏃惰嚜鍔ㄥ崗璋冨崸杞珛璁惧
+                startStateMonitoring(deviceConfig, logicParams);
+
+                // 浠� PLC/MES 鍒涘缓姝e紡浠诲姟骞跺惎鍔ㄧ洃鎺х殑閫昏緫锛屼繚鐣欑粰鐙珛 MES 鍦烘櫙浣跨敤
+                // 澶氳澶囦换鍔″満鏅笅锛岃繖閮ㄥ垎浜ょ敱 TaskExecutionEngine 缁熶竴缂栨帓
+            }
         }
         
         return result;
@@ -430,6 +475,7 @@
         Map<String, Object> payload = new HashMap<>();
         payload.put("plcRequest", 0);
         payload.put("plcReport", 0);
+        payload.put("onlineState", Boolean.TRUE);
         
         log.info("澶ц溅璁惧閲嶇疆: deviceId={}", deviceConfig.getId());
         
@@ -444,8 +490,65 @@
             statusManager.clearVehicleTask(deviceConfig.getDeviceId());
             statusManager.updateVehicleStatus(deviceConfig.getDeviceId(), VehicleState.IDLE);
             stopStateMonitoring(deviceConfig.getDeviceId());
+            updateDeviceOnlineStatus(deviceConfig, true);
         }
         
+        return result;
+    }
+
+    /**
+     * 璁剧疆鑱旀満鐘舵��
+     * @param deviceConfig 璁惧閰嶇疆
+     * @param params 鍙傛暟锛屽彲鍖呭惈 onlineState锛�1=鑱旀満锛�0=鑴辨満锛�
+     * @param logicParams 閫昏緫鍙傛暟
+     * @return 鎿嶄綔缁撴灉
+     */
+    private DevicePlcVO.OperationResult handleSetOnlineState(
+            DeviceConfig deviceConfig,
+            Map<String, Object> params,
+            Map<String, Object> logicParams) {
+
+        // 浠庡弬鏁颁腑鑾峰彇鑱旀満鐘舵�佸�硷紝榛樿涓簍rue锛堣仈鏈猴級
+        boolean onlineState = true;
+        if (params != null && params.containsKey("onlineState")) {
+            Object stateObj = params.get("onlineState");
+            if (stateObj instanceof Boolean) {
+                onlineState = (Boolean) stateObj;
+            } else if (stateObj instanceof Number) {
+                onlineState = ((Number) stateObj).intValue() != 0;
+            } else if (stateObj instanceof String) {
+                try {
+                    String str = ((String) stateObj).trim();
+                    if ("true".equalsIgnoreCase(str)) {
+                        onlineState = true;
+                    } else if ("false".equalsIgnoreCase(str)) {
+                        onlineState = false;
+                    } else {
+                        onlineState = Integer.parseInt(str) != 0;
+                    }
+                } catch (NumberFormatException e) {
+                    log.warn("瑙f瀽onlineState澶辫触锛屼娇鐢ㄩ粯璁ゅ�紅rue: deviceId={}, value={}", 
+                            deviceConfig.getId(), stateObj);
+                }
+            }
+        }
+
+        Map<String, Object> payload = new HashMap<>();
+        payload.put("onlineState", onlineState);
+        
+        String stateText = onlineState ? "鑱旀満" : "鑴辨満";
+        log.info("澶ц溅璁惧璁剧疆鑱旀満鐘舵��: deviceId={}, onlineState={} ({})", 
+                deviceConfig.getId(), onlineState, stateText);
+        
+        DevicePlcVO.OperationResult result = devicePlcOperationService.writeFields(
+                deviceConfig.getId(),
+                payload,
+                "澶ц溅璁惧-璁剧疆鑱旀満鐘舵��(" + stateText + ")"
+        );
+        
+        if (Boolean.TRUE.equals(result.getSuccess())) {
+            updateDeviceOnlineStatus(deviceConfig, onlineState);
+        }
         return result;
     }
 
@@ -472,6 +575,7 @@
         payload.put("plcGlassCount", 0);
         payload.put("plcRequest", 0);
         payload.put("plcReport", 0);
+        payload.put("onlineState", Boolean.TRUE);
 
         if (params != null && params.containsKey("positionValue")) {
             payload.put("inPosition", params.get("positionValue"));
@@ -492,9 +596,23 @@
             statusManager.clearVehicleTask(deviceConfig.getDeviceId());
             statusManager.updateVehicleStatus(deviceConfig.getDeviceId(), VehicleState.IDLE);
             stopStateMonitoring(deviceConfig.getDeviceId());
+            updateDeviceOnlineStatus(deviceConfig, true);
         }
         
         return result;
+    }
+
+    private void updateDeviceOnlineStatus(DeviceConfig deviceConfig, boolean online) {
+        if (deviceStatusService == null || deviceConfig == null || deviceConfig.getId() == null) {
+            return;
+        }
+        try {
+            String status = online ? DeviceStatus.Status.ONLINE : DeviceStatus.Status.OFFLINE;
+            deviceStatusService.updateDeviceOnlineStatus(deviceConfig.getId(), status);
+        } catch (Exception e) {
+            log.warn("鍚屾璁惧鍦ㄧ嚎鐘舵�佸埌鏁版嵁搴撳け璐�: deviceId={}, online={}, error={}",
+                    deviceConfig.getDeviceId(), online, e.getMessage());
+        }
     }
 
     private List<String> resolveGlassSlotFields(Map<String, Object> logicParams, int fallbackCount) {
@@ -532,9 +650,9 @@
             return "杞﹁締瀹归噺(vehicleCapacity)蹇呴』澶т簬0";
         }
 
-        Integer glassIntervalMs = getLogicParam(logicParams, "glassIntervalMs", null);
-        if (glassIntervalMs != null && glassIntervalMs < 0) {
-            return "鐜荤拑闂撮殧鏃堕棿(glassIntervalMs)涓嶈兘涓鸿礋鏁�";
+        Integer glassGap = getLogicParam(logicParams, "glassGap", null);
+        if (glassGap != null && glassGap < 0) {
+            return "鐜荤拑闂撮殧(glassGap)涓嶈兘涓鸿礋鏁�";
         }
 
         return null; // 楠岃瘉閫氳繃
@@ -544,7 +662,7 @@
     public String getDefaultLogicParams() {
         Map<String, Object> defaultParams = new HashMap<>();
         defaultParams.put("vehicleCapacity", 6000);
-        defaultParams.put("glassIntervalMs", 1000);
+        defaultParams.put("glassGap", 200); // 鐜荤拑涔嬮棿鐨勭墿鐞嗛棿闅旓紙mm锛夛紝榛樿200mm
         defaultParams.put("autoFeed", true);
         defaultParams.put("maxRetryCount", 5);
         defaultParams.put("defaultGlassLength", 2000);
@@ -647,16 +765,19 @@
     /**
      * 瑙勫垝鐜荤拑瑁呰浇
      * @param source 婧愮幓鐠冨垪琛�
-     * @param vehicleCapacity 杞﹁締瀹归噺
+     * @param vehicleCapacity 杞﹁締瀹归噺锛坢m锛�
+     * @param glassGap 鐜荤拑涔嬮棿鐨勭墿鐞嗛棿闅旓紙mm锛夛紝榛樿200mm
      * @param deviceId 璁惧ID锛堢敤浜庢棩蹇楋級
      * @return 瑙勫垝鍚庣殑鐜荤拑鍒楄〃锛屽鏋滅幓鐠冩病鏈夐暱搴﹀垯杩斿洖null锛堢敤浜庢祴璇昅ES绋嬪簭锛�
      */
     private List<GlassInfo> planGlassLoading(List<GlassInfo> source,
                                              int vehicleCapacity,
+                                             int glassGap,
                                              String deviceId) {
         List<GlassInfo> planned = new ArrayList<>();
         int usedLength = 0;
         int capacity = Math.max(vehicleCapacity, 1);
+        int gap = Math.max(glassGap, 0); // 纭繚闂撮殧涓嶄负璐熸暟
 
         for (GlassInfo info : source) {
             Integer glassLength = info.getLength();
@@ -671,17 +792,26 @@
             int length = glassLength;
             
             if (planned.isEmpty()) {
+                // 绗竴鍧楃幓鐠冿紝涓嶉渶瑕侀棿闅�
                 planned.add(info.withLength(length));
                 usedLength = length;
                 continue;
             }
-            if (usedLength + length <= capacity) {
+            
+            // 鍚庣画鐜荤拑闇�瑕佽�冭檻闂撮殭锛氱幓鐠冮暱搴� + 闂撮殭
+            int requiredLength = length + gap;
+            if (usedLength + requiredLength <= capacity) {
                 planned.add(info.withLength(length));
-                usedLength += length;
+                usedLength += requiredLength; // 鍖呭惈闂撮殭
             } else {
+                // 瑁呬笉涓嬩簡锛屽仠姝㈡坊鍔�
                 break;
             }
         }
+        
+        log.debug("鐜荤拑瑁呰浇瑙勫垝: deviceId={}, total={}, planned={}, usedLength={}, capacity={}, glassGap={}", 
+                deviceId, source.size(), planned.size(), usedLength, capacity, gap);
+        
         return planned;
     }
 
@@ -1586,65 +1716,80 @@
             log.info("宸茬粰MES姹囨姤({}浠诲姟): deviceId={}, glassId={}", 
                     taskType, deviceConfig.getDeviceId(), taskInfo.glassId);
             
-            // 绛夊緟MES纭
-            waitForMesConfirm(deviceConfig, serializer, taskInfo, logicParams);
-            
+            // 澶氳澶囦换鍔″満鏅笅锛屼笉鍦ㄨ繖閲岄樆濉炵瓑寰匨ES纭锛岀敱浠诲姟寮曟搸瀹氭椂璋冪敤checkMesConfirm
         } catch (Exception e) {
             log.error("缁橫ES姹囨姤寮傚父: deviceId={}", deviceConfig.getDeviceId(), e);
         }
     }
 
     /**
-     * 绛夊緟MES纭
+     * 妫�鏌ES纭鐘舵�侊紙渚涗换鍔″紩鎿庡懆鏈熸�ц皟鐢級
+     * 杩斿洖OperationResult.data涓殑 completed 鏍囧織琛ㄧず鏄惁宸茬‘璁ゅ畬鎴�
      */
-    private void waitForMesConfirm(DeviceConfig deviceConfig,
-                                  EnhancedS7Serializer serializer,
-                                  MesTaskInfo taskInfo,
-                                  Map<String, Object> logicParams) {
-        
+    public DevicePlcVO.OperationResult checkMesConfirm(DeviceConfig deviceConfig,
+                                                       Map<String, Object> logicParams) {
+        if (plcDynamicDataService == null || s7SerializerProvider == null) {
+            return DevicePlcVO.OperationResult.builder()
+                    .success(false)
+                    .message("PlcDynamicDataService鎴朣7SerializerProvider鏈敞鍏�")
+                    .build();
+        }
+        EnhancedS7Serializer serializer = s7SerializerProvider.getSerializer(deviceConfig);
+        if (serializer == null) {
+            return DevicePlcVO.OperationResult.builder()
+                    .success(false)
+                    .message("鑾峰彇PLC搴忓垪鍖栧櫒澶辫触")
+                    .build();
+        }
+
+        Map<String, Object> data = new HashMap<>();
         try {
-            // 璇诲彇纭瀛楋紙鍋囪瀛楁鍚嶄负mesConfirm锛�
-            Integer maxWaitTime = getLogicParam(logicParams, "mesConfirmTimeoutMs", 30000); // 榛樿30绉�
-            long startTime = System.currentTimeMillis();
-            
-            while (System.currentTimeMillis() - startTime < maxWaitTime) {
-                Object confirmValue = plcDynamicDataService.readPlcField(
-                        deviceConfig, "mesConfirm", serializer);
-                Integer confirm = parseInteger(confirmValue);
-                
-                if (confirm != null && confirm == 1) {
-                    // MES宸茬‘璁わ紝娓呯┖state鍜屾眹鎶ュ瓧
-                    clearTaskStates(deviceConfig, serializer);
-                    
-                    // 浠诲姟瀹屾垚锛屾仮澶嶄负绌洪棽鐘舵��
-                    statusManager.updateVehicleStatus(
-                            deviceConfig.getDeviceId(), VehicleState.IDLE);
-                    statusManager.clearVehicleTask(deviceConfig.getDeviceId());
-                    
-                    // 绉婚櫎浠诲姟
-                    currentTasks.remove(deviceConfig.getDeviceId());
-                    
-                    // 鍋滄浠诲姟鐩戞帶
-                    handleStopTaskMonitor(deviceConfig);
-                    
-                    // 鎭㈠plcRequest=1锛堝彲浠ユ帴鏀舵柊浠诲姟锛�
-                    Map<String, Object> payload = new HashMap<>();
-                    payload.put("plcRequest", 1);
-                    plcDynamicDataService.writePlcData(deviceConfig, payload, serializer);
-                    
-                    log.info("MES浠诲姟宸插畬鎴�: deviceId={}, glassId={}", 
-                            deviceConfig.getDeviceId(), taskInfo.glassId);
-                    return;
-                }
-                
-                Thread.sleep(500); // 绛夊緟500ms鍚庨噸璇�
+            Object confirmValue = plcDynamicDataService.readPlcField(
+                    deviceConfig, "mesConfirm", serializer);
+            Integer confirm = parseInteger(confirmValue);
+            boolean completed = confirm != null && confirm == 1;
+            data.put("completed", completed);
+
+            if (completed) {
+                // MES宸茬‘璁わ紝娓呯┖state鍜屾眹鎶ュ瓧
+                clearTaskStates(deviceConfig, serializer);
+
+                // 浠诲姟瀹屾垚锛屾仮澶嶄负绌洪棽鐘舵��
+                statusManager.updateVehicleStatus(
+                        deviceConfig.getDeviceId(), VehicleState.IDLE);
+                statusManager.clearVehicleTask(deviceConfig.getDeviceId());
+
+                // 绉婚櫎浠诲姟璁板綍锛堝鏋滄湁锛�
+                currentTasks.remove(deviceConfig.getDeviceId());
+
+                // 鍋滄浠诲姟鐩戞帶
+                handleStopTaskMonitor(deviceConfig);
+
+                // 鎭㈠plcRequest=1锛堝彲浠ユ帴鏀舵柊浠诲姟锛�
+                Map<String, Object> payload = new HashMap<>();
+                payload.put("plcRequest", 1);
+                plcDynamicDataService.writePlcData(deviceConfig, payload, serializer);
+
+                log.info("MES浠诲姟宸茬‘璁ゅ畬鎴�: deviceId={}", deviceConfig.getDeviceId());
+                return DevicePlcVO.OperationResult.builder()
+                        .success(true)
+                        .message("MES浠诲姟宸茬‘璁ゅ畬鎴�")
+                        .data(data)
+                        .build();
             }
-            
-            log.warn("绛夊緟MES纭瓒呮椂: deviceId={}, glassId={}", 
-                    deviceConfig.getDeviceId(), taskInfo.glassId);
-            
+
+            return DevicePlcVO.OperationResult.builder()
+                    .success(true)
+                    .message("绛夊緟MES纭涓�")
+                    .data(data)
+                    .build();
         } catch (Exception e) {
-            log.error("绛夊緟MES纭寮傚父: deviceId={}", deviceConfig.getDeviceId(), e);
+            log.error("妫�鏌ES纭鐘舵�佸紓甯�: deviceId={}", deviceConfig.getDeviceId(), e);
+            return DevicePlcVO.OperationResult.builder()
+                    .success(false)
+                    .message("妫�鏌ES纭鐘舵�佸紓甯�: " + e.getMessage())
+                    .data(data)
+                    .build();
         }
     }
 
@@ -1754,5 +1899,25 @@
             Thread.currentThread().interrupt();
         }
     }
+    
+    /**
+     * 閫氱煡鍗ц浆绔嬫壂鐮佽澶囨殏鍋滄垨缁х画
+     * @param params 鍙傛暟锛屽寘鍚玙taskContext寮曠敤
+     * @param pause true=鏆傚仠锛宖alse=缁х画
+     */
+    private void notifyScannerPause(Map<String, Object> params, boolean pause) {
+        if (params == null) {
+            return;
+        }
+        
+        Object contextObj = params.get("_taskContext");
+        if (contextObj instanceof TaskExecutionContext) {
+            TaskExecutionContext context = (TaskExecutionContext) contextObj;
+            HorizontalScannerLogicHandler.setPauseFlag(context, pause);
+            log.info("宸查�氱煡鍗ц浆绔嬫壂鐮佽澶噞}: pause={}", pause ? "鏆傚仠" : "缁х画", pause);
+        } else {
+            log.debug("鏈壘鍒癟askExecutionContext锛屾棤娉曢�氱煡鍗ц浆绔嬫壂鐮佽澶囨殏鍋�");
+        }
+    }
 }
 

--
Gitblit v1.8.0