From cc720a16549bbb691344afb31f702530588c75fd Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期二, 24 三月 2026 00:03:06 +0800
Subject: [PATCH] #

---
 src/main/java/com/zy/core/thread/impl/ZyStationV5Thread.java       |    9 +-
 src/main/java/com/zy/core/utils/StationOperateProcessUtils.java    |   49 +++++++++++++--
 src/main/java/com/zy/core/thread/impl/ZyStationV4Thread.java       |    9 +-
 src/main/java/com/zy/core/enums/RedisKeyType.java                  |    1 
 src/main/java/com/zy/core/network/real/ZyStationV4RealConnect.java |   56 ------------------
 5 files changed, 52 insertions(+), 72 deletions(-)

diff --git a/src/main/java/com/zy/core/enums/RedisKeyType.java b/src/main/java/com/zy/core/enums/RedisKeyType.java
index 122baa0..3a60047 100644
--- a/src/main/java/com/zy/core/enums/RedisKeyType.java
+++ b/src/main/java/com/zy/core/enums/RedisKeyType.java
@@ -46,6 +46,7 @@
     STATION_RUN_BLOCK_REROUTE_STATE_("station_run_block_reroute_state_"),
     STATION_RUN_BLOCK_TASK_LOOP_STATE_("station_run_block_task_loop_state_"),
     CHECK_STATION_IDLE_RECOVER_LIMIT_("check_station_idle_recover_limit_"),
+    STATION_COMMAND_DISPATCH_DEDUP_("station_command_dispatch_dedup_"),
     CHECK_SHALLOW_LOC_STATUS_LIMIT("check_shallow_loc_status_limit_"),
     GENERATE_ENABLE_IN_STATION_DATA_LIMIT("generate_enable_in_station_data_limit_"),
     GENERATE_STATION_BACK_LIMIT("generate_station_back_limit_"),
diff --git a/src/main/java/com/zy/core/network/real/ZyStationV4RealConnect.java b/src/main/java/com/zy/core/network/real/ZyStationV4RealConnect.java
index d1f0431..b5a45d8 100644
--- a/src/main/java/com/zy/core/network/real/ZyStationV4RealConnect.java
+++ b/src/main/java/com/zy/core/network/real/ZyStationV4RealConnect.java
@@ -244,32 +244,6 @@
             return commandResponse;
         }
 
-        if (isDuplicateStationCommand(statusEntity, command)) {
-            log.info("杈撻�佺嚎鍛戒护閲嶅锛屽凡璺宠繃褰撳墠绔欑偣鍛戒护銆備换鍔″彿={}锛岀珯鐐瑰彿={}锛岀洰鏍囩珯={}锛宼askWriteIdx={}锛宑urrentTaskNo={}锛宑urrentTargetStaNo={}",
-                    command.getTaskNo(),
-                    command.getStationId(),
-                    command.getTargetStaNo(),
-                    taskWriteIdx,
-                    statusEntity == null ? null : statusEntity.getTaskNo(),
-                    statusEntity == null ? null : statusEntity.getTargetStaNo());
-            commandResponse.setResult(true);
-            commandResponse.setMessage("鍛戒护閲嶅锛屽凡璺宠繃涓嬪彂");
-            return commandResponse;
-        }
-
-        Integer duplicateSlotIdx = findDuplicateTaskAreaSlot(stationIdx, command);
-        if (duplicateSlotIdx != null) {
-            log.info("杈撻�佺嚎鍛戒护閲嶅锛屽凡璺宠繃浠诲姟鍐欏叆鍖洪噸澶嶅懡浠ゃ�備换鍔″彿={}锛岀珯鐐瑰彿={}锛岀洰鏍囩珯={}锛宼askWriteIdx={}锛宒uplicateSlotIdx={}",
-                    command.getTaskNo(),
-                    command.getStationId(),
-                    command.getTargetStaNo(),
-                    taskWriteIdx,
-                    duplicateSlotIdx);
-            commandResponse.setResult(true);
-            commandResponse.setMessage("浠诲姟鍖哄凡鏈夌浉鍚屽懡浠わ紝宸茶烦杩囦笅鍙�");
-            return commandResponse;
-        }
-
         int useTaskWriteIdx = getTaskWriteIdx(stationIdx, taskWriteIdx);
         if (useTaskWriteIdx == -1) {
             commandResponse.setMessage("鍛戒护涓嬪彂瓒呮椂锛屾棤娉曟壘鍒板彲鐢ㄤ笅鍙戝尯鍩�");
@@ -358,36 +332,6 @@
             }
         }
         return useIdx;
-    }
-
-    private boolean isDuplicateStationCommand(ZyStationStatusEntity statusEntity, StationCommand command) {
-        if (statusEntity == null || command == null) {
-            return false;
-        }
-        return command.getTaskNo() != null
-                && command.getTargetStaNo() != null
-                && command.getTaskNo().equals(statusEntity.getTaskNo())
-                && command.getTargetStaNo().equals(statusEntity.getTargetStaNo());
-    }
-
-    private Integer findDuplicateTaskAreaSlot(int stationIdx, StationCommand command) {
-        if (stationIdx < 0 || command == null || command.getTaskNo() == null || command.getTargetStaNo() == null) {
-            return null;
-        }
-        OperateResultExOne<byte[]> resultTask = siemensNet.Read("DB13." + (stationIdx * TASK_AREA_LENGTH), (short) TASK_AREA_LENGTH);
-        if (!resultTask.IsSuccess || resultTask.Content == null) {
-            return null;
-        }
-        for (int slotIdx = 1; slotIdx <= TASK_AREA_SLOT_COUNT; slotIdx++) {
-            int offset = slotIdx * TASK_AREA_SLOT_SIZE;
-            int taskNo = siemensNet.getByteTransform().TransInt32(resultTask.Content, offset);
-            int targetPoint = siemensNet.getByteTransform().TransInt16(resultTask.Content, offset + 6);
-            if (command.getTaskNo().equals(taskNo)
-                    && command.getTargetStaNo().equals(targetPoint)) {
-                return slotIdx;
-            }
-        }
-        return null;
     }
 
     private byte[] readTaskBufferRaw() {
diff --git a/src/main/java/com/zy/core/thread/impl/ZyStationV4Thread.java b/src/main/java/com/zy/core/thread/impl/ZyStationV4Thread.java
index 07a220a..1a8a4b7 100644
--- a/src/main/java/com/zy/core/thread/impl/ZyStationV4Thread.java
+++ b/src/main/java/com/zy/core/thread/impl/ZyStationV4Thread.java
@@ -272,6 +272,9 @@
             e.printStackTrace();
         } finally {
             BasStationOptService optService = SpringUtils.getBean(BasStationOptService.class);
+            if (optService == null) {
+                return commandResponse;
+            }
             List<ZyStationStatusEntity> statusListEntity = zyStationConnectDriver.getStatus();
             ZyStationStatusEntity matched = null;
             if (statusListEntity != null) {
@@ -294,12 +297,10 @@
                     null,
                     JSON.toJSONString(command),
                     JSON.toJSONString(matched),
-                    1,
+                    commandResponse != null && Boolean.TRUE.equals(commandResponse.getResult()) ? 1 : 0,
                     JSON.toJSONString(commandResponse)
             );
-            if (optService != null) {
-                optService.save(basStationOpt);
-            }
+            optService.save(basStationOpt);
         }
         return commandResponse;
     }
diff --git a/src/main/java/com/zy/core/thread/impl/ZyStationV5Thread.java b/src/main/java/com/zy/core/thread/impl/ZyStationV5Thread.java
index 69345d9..c0eb09e 100644
--- a/src/main/java/com/zy/core/thread/impl/ZyStationV5Thread.java
+++ b/src/main/java/com/zy/core/thread/impl/ZyStationV5Thread.java
@@ -362,6 +362,9 @@
             e.printStackTrace();
         } finally {
             BasStationOptService optService = SpringUtils.getBean(BasStationOptService.class);
+            if (optService == null) {
+                return commandResponse;
+            }
             List<ZyStationStatusEntity> statusListEntity = zyStationConnectDriver.getStatus();
             ZyStationStatusEntity matched = null;
             if (statusListEntity != null) {
@@ -384,12 +387,10 @@
                     null,
                     JSON.toJSONString(command),
                     JSON.toJSONString(matched),
-                    1,
+                    commandResponse != null && Boolean.TRUE.equals(commandResponse.getResult()) ? 1 : 0,
                     JSON.toJSONString(commandResponse)
             );
-            if (optService != null) {
-                optService.save(basStationOpt);
-            }
+            optService.save(basStationOpt);
         }
         return commandResponse;
     }
diff --git a/src/main/java/com/zy/core/utils/StationOperateProcessUtils.java b/src/main/java/com/zy/core/utils/StationOperateProcessUtils.java
index a6f36f0..ec8a453 100644
--- a/src/main/java/com/zy/core/utils/StationOperateProcessUtils.java
+++ b/src/main/java/com/zy/core/utils/StationOperateProcessUtils.java
@@ -39,6 +39,7 @@
 public class StationOperateProcessUtils {
     private static final int LOOP_LOAD_RESERVE_EXPIRE_SECONDS = 120;
     private static final int OUT_ORDER_DISPATCH_LIMIT_SECONDS = 2;
+    private static final int STATION_COMMAND_DISPATCH_DEDUP_SECONDS = 10;
     private static final int STATION_IDLE_RECOVER_SECONDS = 10;
     private static final int STATION_IDLE_RECOVER_LIMIT_SECONDS = 30;
     private static final int STATION_IDLE_TRACK_EXPIRE_SECONDS = 60 * 60;
@@ -157,7 +158,7 @@
                         wrkMast.setModiTime(now);
                         if (wrkMastService.updateById(wrkMast)) {
                             wrkAnalysisService.markInboundStationStart(wrkMast, now);
-                            MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command));
+                            offerDevpCommandWithDedup(basDevp.getDevpNo(), command, "stationInExecute");
                             News.info("杈撻�佺珯鐐瑰叆搴撳懡浠や笅鍙戞垚鍔燂紝绔欑偣鍙�={}锛屽伐浣滃彿={}锛屽懡浠ゆ暟鎹�={}", stationId, wrkMast.getWrkNo(), JSON.toJSONString(command));
                             redisUtil.set(RedisKeyType.STATION_IN_EXECUTE_LIMIT.key + stationId, "lock", 5);
                             loadGuardState.reserveLoopTask(loopHitResult.getLoopNo());
@@ -251,7 +252,7 @@
                     wrkMast.setModiTime(now);
                     if (wrkMastService.updateById(wrkMast)) {
                         wrkAnalysisService.markOutboundStationStart(wrkMast, now);
-                        MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command));
+                        offerDevpCommandWithDedup(stationObjModel.getDeviceNo(), command, "crnStationOutExecute");
                         News.info("杈撻�佺珯鐐瑰嚭搴撳懡浠や笅鍙戞垚鍔燂紝绔欑偣鍙�={}锛屽伐浣滃彿={}锛屽懡浠ゆ暟鎹�={}", stationProtocol.getStationId(), wrkMast.getWrkNo(), JSON.toJSONString(command));
                         redisUtil.set(RedisKeyType.STATION_OUT_EXECUTE_LIMIT.key + stationProtocol.getStationId(), "lock", 5);
                         redisUtil.del(RedisKeyType.CRN_OUT_TASK_COMPLETE_STATION_INFO.key + wrkMast.getWrkNo());
@@ -319,7 +320,7 @@
                     wrkMast.setSystemMsg("");
                     wrkMast.setIoTime(new Date());
                     if (wrkMastService.updateById(wrkMast)) {
-                        MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command));
+                        offerDevpCommandWithDedup(stationObjModel.getDeviceNo(), command, "dualCrnStationOutExecute");
                         notifyUtils.notify(String.valueOf(SlaveType.Devp), stationObjModel.getDeviceNo(), String.valueOf(wrkMast.getWrkNo()), wrkMast.getWmsWrkNo(), NotifyMsgType.STATION_OUT_TASK_RUN, null);
                         News.info("杈撻�佺珯鐐瑰嚭搴撳懡浠や笅鍙戞垚鍔燂紝绔欑偣鍙�={}锛屽伐浣滃彿={}锛屽懡浠ゆ暟鎹�={}", stationProtocol.getStationId(), wrkMast.getWrkNo(), JSON.toJSONString(command));
                         redisUtil.set(RedisKeyType.STATION_OUT_EXECUTE_LIMIT.key + stationProtocol.getStationId(), "lock", 5);
@@ -542,7 +543,7 @@
                                 }
 
                                 if (wrkMastService.updateById(wrkMast)) {
-                                    MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command));
+                                    offerDevpCommandWithDedup(basDevp.getDevpNo(), command, "checkStationRunBlock_direct");
                                 }
                             } else {
                                 News.error("璇锋眰WMS鎺ュ彛澶辫触锛侊紒锛乺esponse锛歿}", response);
@@ -576,7 +577,7 @@
                                 continue;
                             }
 
-                            MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command));
+                            offerDevpCommandWithDedup(basDevp.getDevpNo(), command, "checkStationRunBlock_reroute");
                             syncOutOrderWatchState(wrkMast, stationProtocol.getStationId(), outOrderStationIds, dispatchDecision, command);
                             News.info("杈撻�佺珯鐐瑰牭濉炲悗閲嶆柊璁$畻璺緞鍛戒护涓嬪彂鎴愬姛锛岀珯鐐瑰彿={}锛屽伐浣滃彿={}锛屽懡浠ゆ暟鎹�={}", stationProtocol.getStationId(), wrkMast.getWrkNo(), JSON.toJSONString(command));
                         }
@@ -707,7 +708,7 @@
                     continue;
                 }
                 syncOutOrderWatchState(wrkMast, stationProtocol.getStationId(), outOrderStationIds, dispatchDecision, command);
-                MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command));
+                offerDevpCommandWithDedup(stationObjModel.getDeviceNo(), command, "checkStationOutOrder");
                 News.info(dispatchDecision.isCircle() ? "{}浠诲姟杩涜缁曞湀" : "{}浠诲姟鐩存帴鍘荤洰鏍囩偣", wrkMast.getWrkNo());
             }
         }
@@ -783,7 +784,7 @@
                     continue;
                 }
                 syncOutOrderWatchState(wrkMast, stationProtocol.getStationId(), outOrderList, dispatchDecision, command);
-                MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command));
+                offerDevpCommandWithDedup(basDevp.getDevpNo(), command, "watchCircleStation");
             }
         }
     }
@@ -1354,7 +1355,7 @@
             return;
         }
 
-        MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command));
+        offerDevpCommandWithDedup(basDevp.getDevpNo(), command, "checkStationIdleRecover");
         syncOutOrderWatchState(wrkMast, stationProtocol.getStationId(), outOrderList, dispatchDecision, command);
         saveStationTaskIdleTrack(new StationTaskIdleTrack(wrkMast.getWrkNo(), stationProtocol.getStationId(), System.currentTimeMillis()));
         News.info("杈撻�佺珯鐐逛换鍔″仠鐣檣}绉掓湭杩愯锛屽凡閲嶆柊璁$畻璺緞骞堕噸鍚繍琛岋紝绔欑偣鍙�={}锛岀洰鏍囩珯={}锛屽伐浣滃彿={}锛屾竻鐞嗘棫鍒嗘鍛戒护鏁�={}锛屽懡浠ゆ暟鎹�={}",
@@ -1403,6 +1404,38 @@
         return count;
     }
 
+    private boolean offerDevpCommandWithDedup(Integer deviceNo, StationCommand command, String scene) {
+        if (deviceNo == null || command == null) {
+            return false;
+        }
+        String dedupKey = buildStationCommandDispatchDedupKey(deviceNo, command);
+        if (redisUtil != null) {
+            Object lock = redisUtil.get(dedupKey);
+            if (lock != null) {
+                News.info("杈撻�佺珯鐐瑰懡浠ょ煭鏃堕噸澶嶆淳鍙戯紝宸茶烦杩囥�俿cene={}锛宒eviceNo={}锛宼askNo={}锛宻tationId={}锛宼argetStaNo={}锛宑ommandType={}",
+                        scene,
+                        deviceNo,
+                        command.getTaskNo(),
+                        command.getStationId(),
+                        command.getTargetStaNo(),
+                        command.getCommandType());
+                return false;
+            }
+            redisUtil.set(dedupKey, "lock", STATION_COMMAND_DISPATCH_DEDUP_SECONDS);
+        }
+        boolean offered = MessageQueue.offer(SlaveType.Devp, deviceNo, new Task(2, command));
+        if (!offered && redisUtil != null) {
+            redisUtil.del(dedupKey);
+        }
+        return offered;
+    }
+
+    private String buildStationCommandDispatchDedupKey(Integer deviceNo, StationCommand command) {
+        return RedisKeyType.STATION_COMMAND_DISPATCH_DEDUP_.key
+                + command.getTaskNo() + "_"
+                + command.getStationId();
+    }
+
     private int clearIssuedMoveCommandsDuringIdleStay(StationTaskIdleTrack idleTrack,
                                                       Integer taskNo,
                                                       Integer stationId) {

--
Gitblit v1.9.1