Junjie
2026-04-13 045ee53a62cd7866c1395961076426e9c8782b26
#输送命令优化
8个文件已修改
311 ■■■■■ 已修改文件
src/main/java/com/zy/core/enums/RedisKeyType.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/plugin/FakeProcess.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/plugin/GslProcess.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/plugin/NormalProcess.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/plugin/XiaosongProcess.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/task/MainProcessLane.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/utils/StationOperateProcessUtils.java 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/utils/station/StationRerouteProcessor.java 191 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/RedisKeyType.java
@@ -52,7 +52,6 @@
    CHECK_STATION_RUN_BLOCK_LIMIT_("check_station_run_block_limit_"),
    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_"),
    STATION_MOVE_SESSION_("station_move_session_"),
    CHECK_SHALLOW_LOC_STATUS_LIMIT("check_shallow_loc_status_limit_"),
src/main/java/com/zy/core/plugin/FakeProcess.java
@@ -116,8 +116,6 @@
        stationOperateProcessUtils.submitCheckTaskToCompleteTasks(MAIN_DISPATCH_INTERVAL_MS);
        // 检测并处理出库排序
        stationOperateProcessUtils.submitCheckStationOutOrderTasks(MainProcessLane.FAKE_STATION_OUT_ORDER, MAIN_DISPATCH_INTERVAL_MS);
        // 监控输送线绕圈站点
        stationOperateProcessUtils.submitWatchCircleStationTasks(MainProcessLane.FAKE_STATION_WATCH_CIRCLE, MAIN_DISPATCH_INTERVAL_MS);
        // 执行双工位堆垛机任务
        dualCrnOperateProcessUtils.submitDualCrnIoTasks(MainProcessLane.FAKE_DUAL_CRN_IO, MAIN_DISPATCH_INTERVAL_MS);
        // 双工位堆垛机任务执行完成
src/main/java/com/zy/core/plugin/GslProcess.java
@@ -81,12 +81,8 @@
        stationOperateProcessUtils.submitCheckTaskToCompleteTasks(DISPATCH_INTERVAL_MS);
        // 检测并处理出库排序
        stationOperateProcessUtils.submitCheckStationOutOrderTasks(MAINTENANCE_INTERVAL_MS);
//        // 监控输送线绕圈站点
//        stationOperateProcessUtils.submitWatchCircleStationTasks(MAINTENANCE_INTERVAL_MS);
        // 检测输送线运行堵塞
        stationOperateProcessUtils.submitCheckStationRunBlockTasks(MAINTENANCE_INTERVAL_MS);
//        // 检测站台空闲超时后的恢复处理
//        stationOperateProcessUtils.submitCheckStationIdleRecoverTasks(MAINTENANCE_INTERVAL_MS);
    }
    @Override
src/main/java/com/zy/core/plugin/NormalProcess.java
@@ -69,8 +69,6 @@
        //检测输送站点是否运行堵塞,按 lane 串行提交
        stationOperateProcessUtils.submitCheckStationRunBlockTasks(DISPATCH_INTERVAL_MS);
        //检测输送站点任务停留超时后重新计算路径,按 lane 串行提交
        stationOperateProcessUtils.submitCheckStationIdleRecoverTasks(DISPATCH_INTERVAL_MS);
    }
    /**
src/main/java/com/zy/core/plugin/XiaosongProcess.java
@@ -73,9 +73,6 @@
        stationOperateProcessUtils.submitDualCrnStationOutTasks(DISPATCH_INTERVAL_MS);
        //检测输送站点是否运行堵塞,按 lane 串行提交
        stationOperateProcessUtils.submitCheckStationRunBlockTasks(DISPATCH_INTERVAL_MS);
        //检测输送站点任务停留超时后重新计算路径,按 lane 串行提交
        stationOperateProcessUtils.submitCheckStationIdleRecoverTasks(DISPATCH_INTERVAL_MS);
        // 执行双工位堆垛机任务,按 lane 串行提交
        dualCrnOperateProcessUtils.submitDualCrnIoTasks(DISPATCH_INTERVAL_MS);
        // 双工位堆垛机任务执行完成,按 lane 串行提交
src/main/java/com/zy/core/task/MainProcessLane.java
@@ -14,16 +14,13 @@
    STATION_IN_ARRIVAL("station-in-arrival-"),
    STATION_COMPLETE("station-complete-"),
    STATION_OUT_ORDER("station-out-order-"),
    STATION_WATCH_CIRCLE("station-watch-circle-"),
    STATION_RUN_BLOCK("station-run-block-"),
    STATION_IDLE_RECOVER("station-idle-recover-"),
    GENERATE_STORE("generate-store-"),
    FAKE_CRN_IO("fake-crn-io-"),
    FAKE_CRN_IO_FINISH("fake-crn-io-finish-"),
    FAKE_STATION_IN("fake-station-in-"),
    FAKE_STATION_OUT("fake-station-out-"),
    FAKE_STATION_OUT_ORDER("fake-station-out-order-"),
    FAKE_STATION_WATCH_CIRCLE("fake-station-watch-circle-"),
    FAKE_STATION_RUN_BLOCK("fake-station-run-block-"),
    FAKE_DUAL_CRN_IO("fake-dual-crn-io-"),
    FAKE_DUAL_CRN_IO_FINISH("fake-dual-crn-io-finish-"),
src/main/java/com/zy/core/utils/StationOperateProcessUtils.java
@@ -110,11 +110,6 @@
        stationRerouteProcessor.checkStationRunBlock(basDevp, stationId);
    }
    // 检测单个站点任务停留超时后的恢复处理
    public void checkStationIdleRecover(BasDevp basDevp, Integer stationId) {
        stationRerouteProcessor.checkStationIdleRecover(basDevp, stationId);
    }
    //获取输送线任务数量
    public int getCurrentStationTaskCount() {
        return stationDispatchLoadSupport.countCurrentStationTask();
@@ -136,11 +131,6 @@
    // 检测单个站点的出库排序
    public void checkStationOutOrder(BasDevp basDevp, StationObjModel stationObjModel) {
        stationRerouteProcessor.checkStationOutOrder(basDevp, stationObjModel);
    }
    // 监控单个绕圈站点
    public void watchCircleStation(BasDevp basDevp, Integer stationId) {
        stationRerouteProcessor.watchCircleStation(basDevp, stationId);
    }
    public void submitStationInTasks(long minIntervalMs) {
@@ -329,40 +319,6 @@
        }
    }
    public void submitWatchCircleStationTasks(long minIntervalMs) {
        submitWatchCircleStationTasks(MainProcessLane.STATION_WATCH_CIRCLE, minIntervalMs);
    }
    public void submitWatchCircleStationTasks(MainProcessLane lane, long minIntervalMs) {
        List<BasDevp> basDevps = basDevpService.list(new QueryWrapper<>());
        for (BasDevp basDevp : basDevps) {
            StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, basDevp.getDevpNo());
            if (stationThread == null) {
                continue;
            }
            for (StationProtocol stationProtocol : stationThread.getStatus()) {
                Integer stationId = stationProtocol == null ? null : stationProtocol.getStationId();
                if (stationId == null) {
                    continue;
                }
                if (!stationProtocol.isAutoing()
                        || !stationProtocol.isLoading()
                        || stationProtocol.getTaskNo() <= 0
                        || !stationOutboundDecisionSupport.isWatchingCircleArrival(stationProtocol.getTaskNo(), stationProtocol.getStationId())) {
                    continue;
                }
                mainProcessTaskSubmitter.submitKeyedSerialTask(
                        lane,
                        stationId,
                        "watchCircleStation",
                        minIntervalMs,
                        () -> watchCircleStation(basDevp, stationId)
                );
            }
        }
    }
    public void submitCheckStationRunBlockTasks(long minIntervalMs) {
        submitCheckStationRunBlockTasks(MainProcessLane.STATION_RUN_BLOCK, minIntervalMs);
    }
@@ -396,42 +352,6 @@
        }
    }
    public void submitCheckStationIdleRecoverTasks(long minIntervalMs) {
        submitCheckStationIdleRecoverTasks(MainProcessLane.STATION_IDLE_RECOVER, minIntervalMs);
    }
    public void submitCheckStationIdleRecoverTasks(MainProcessLane lane, long minIntervalMs) {
        List<BasDevp> basDevps = basDevpService.list(new QueryWrapper<>());
        for (BasDevp basDevp : basDevps) {
            StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, basDevp.getDevpNo());
            if (stationThread == null) {
                continue;
            }
            for (StationProtocol stationProtocol : stationThread.getStatus()) {
                Integer stationId = stationProtocol == null ? null : stationProtocol.getStationId();
                if (stationId == null) {
                    continue;
                }
                if (!isIdleRecoverCandidateStation(basDevp, stationId)) {
                    continue;
                }
                if (!stationProtocol.isAutoing()
                        || !stationProtocol.isLoading()
                        || stationProtocol.getTaskNo() <= 0
                        || stationProtocol.isRunBlock()) {
                    continue;
                }
                mainProcessTaskSubmitter.submitKeyedSerialTask(
                        lane,
                        stationId,
                        "checkStationIdleRecover",
                        minIntervalMs,
                        () -> checkStationIdleRecover(basDevp, stationId)
                );
            }
        }
    }
    RerouteCommandPlan buildRerouteCommandPlan(RerouteContext context,
                                               RerouteDecision decision) {
        return stationRerouteProcessor.buildRerouteCommandPlan(context, decision);
@@ -450,31 +370,6 @@
                                            Integer stationId,
                                            List<Integer> runBlockReassignLocStationList) {
        return stationRerouteProcessor.shouldUseRunBlockDirectReassign(wrkMast, stationId, runBlockReassignLocStationList);
    }
    public boolean isIdleRecoverCandidateStation(BasDevp basDevp, Integer stationId) {
        if (basDevp == null || stationId == null) {
            return false;
        }
        return !containsStation(basDevp.getBarcodeStationList$(), stationId)
                && !containsStation(basDevp.getInStationList$(), stationId)
                && !containsStation(basDevp.getOutStationList$(), stationId);
    }
    private boolean containsStation(List<StationObjModel> stationList, Integer stationId) {
        if (stationList == null || stationList.isEmpty() || stationId == null) {
            return false;
        }
        for (StationObjModel stationObjModel : stationList) {
            if (stationObjModel != null && Objects.equals(stationObjModel.getStationId(), stationId)) {
                return true;
            }
        }
        return false;
    }
    private boolean shouldSkipIdleRecoverForRecentDispatch(Integer taskNo, Integer stationId) {
        return stationRerouteProcessor.shouldSkipIdleRecoverForRecentDispatch(taskNo, stationId);
    }
    public void attemptClearTaskPath(StationThread stationThread, Integer taskNo) {
src/main/java/com/zy/core/utils/station/StationRerouteProcessor.java
@@ -50,8 +50,6 @@
@Component
public class StationRerouteProcessor {
    private static final int OUT_ORDER_DISPATCH_LIMIT_SECONDS = 2;
    private static final int STATION_IDLE_RECOVER_SECONDS = 10;
    private static final int STATION_IDLE_RECOVER_LIMIT_SECONDS = 30;
    private static final long STATION_MOVE_RESET_WAIT_MS = 1000L;
    @Autowired
@@ -149,33 +147,6 @@
        }
    }
    public void checkStationIdleRecover(BasDevp basDevp, Integer stationId) {
        try {
            if (basDevp == null || basDevp.getDevpNo() == null || stationId == null) {
                return;
            }
            if (!isIdleRecoverCandidateStation(basDevp, stationId)) {
                return;
            }
            StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, basDevp.getDevpNo());
            if (stationThread == null) {
                return;
            }
            Map<Integer, StationProtocol> statusMap = stationThread.getStatusMap();
            StationProtocol stationProtocol = statusMap == null ? null : statusMap.get(stationId);
            if (stationProtocol == null
                    || !stationProtocol.isAutoing()
                    || !stationProtocol.isLoading()
                    || stationProtocol.getTaskNo() <= 0
                    || stationProtocol.isRunBlock()) {
                return;
            }
            checkStationIdleRecover(basDevp, stationThread, stationProtocol, basDevp.getOutOrderIntList());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void checkStationOutOrder(BasDevp basDevp, StationObjModel stationObjModel) {
        try {
            if (basDevp == null || basDevp.getDevpNo() == null || stationObjModel == null || stationObjModel.getStationId() == null) {
@@ -218,51 +189,6 @@
                    "checkStationOutOrder"
            ).withDispatchDeviceNo(stationObjModel.getDeviceNo())
                    .withSuppressDispatchGuard()
                    .withOutOrderDispatchLock()
                    .withResetSegmentCommandsBeforeDispatch();
            executeSharedReroute(context);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void watchCircleStation(BasDevp basDevp, Integer stationId) {
        try {
            if (basDevp == null || basDevp.getDevpNo() == null || stationId == null) {
                return;
            }
            StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, basDevp.getDevpNo());
            if (stationThread == null) {
                return;
            }
            Map<Integer, StationProtocol> statusMap = stationThread.getStatusMap();
            StationProtocol stationProtocol = statusMap == null ? null : statusMap.get(stationId);
            if (stationProtocol == null
                    || !stationProtocol.isAutoing()
                    || !stationProtocol.isLoading()
                    || stationProtocol.getTaskNo() <= 0
                    || !stationOutboundDecisionSupport.isWatchingCircleArrival(stationProtocol.getTaskNo(), stationProtocol.getStationId())) {
                return;
            }
            WrkMast wrkMast = wrkMastService.selectByWorkNo(stationProtocol.getTaskNo());
            if (wrkMast == null
                    || !Objects.equals(wrkMast.getWrkSts(), WrkStsType.STATION_RUN.sts)
                    || Objects.equals(stationProtocol.getStationId(), wrkMast.getStaNo())) {
                return;
            }
            Double pathLenFactor = stationOutboundDecisionSupport.resolveOutboundPathLenFactor(wrkMast);
            RerouteContext context = RerouteContext.create(
                    RerouteSceneType.WATCH_CIRCLE,
                    basDevp,
                    stationThread,
                    stationProtocol,
                    wrkMast,
                    basDevp.getOutOrderIntList(),
                    pathLenFactor,
                    "watchCircleStation"
            ).withSuppressDispatchGuard()
                    .withOutOrderDispatchLock()
                    .withResetSegmentCommandsBeforeDispatch();
            executeSharedReroute(context);
@@ -396,43 +322,6 @@
                && runBlockReassignLocStationList.contains(stationId);
    }
    public boolean shouldSkipIdleRecoverForRecentDispatch(Integer taskNo, Integer stationId) {
        if (taskNo == null || taskNo <= 0 || stationId == null) {
            return false;
        }
        long thresholdMs = STATION_IDLE_RECOVER_SECONDS * 1000L;
        StationMoveSession session = stationMoveCoordinator == null ? null : stationMoveCoordinator.loadSession(taskNo);
        if (session != null && session.isActive() && session.getLastIssuedAt() != null) {
            if (Objects.equals(stationId, session.getCurrentStationId())
                    || Objects.equals(stationId, session.getDispatchStationId())
                    || session.containsStation(stationId)) {
                long elapsedMs = System.currentTimeMillis() - session.getLastIssuedAt();
                if (elapsedMs < thresholdMs) {
                    stationDispatchRuntimeStateSupport.saveIdleTrack(new StationTaskIdleTrack(taskNo, stationId, System.currentTimeMillis()));
                    News.info("输送站点任务刚完成命令下发,已跳过停留重算。站点号={},工作号={},距上次下发={}ms,routeVersion={}",
                            stationId, taskNo, elapsedMs, session.getRouteVersion());
                    return true;
                }
            }
        }
        if (!stationDispatchRuntimeStateSupport.hasRecentIssuedMoveCommand(taskNo, stationId, thresholdMs)) {
            return false;
        }
        stationDispatchRuntimeStateSupport.saveIdleTrack(new StationTaskIdleTrack(taskNo, stationId, System.currentTimeMillis()));
        News.info("输送站点任务刚完成命令下发,已跳过停留重算。站点号={},工作号={},距最近命令下发<{}ms,routeVersion={}",
                stationId, taskNo, thresholdMs, session == null ? null : session.getRouteVersion());
        return true;
    }
    private boolean isIdleRecoverCandidateStation(BasDevp basDevp, Integer stationId) {
        if (basDevp == null || stationId == null) {
            return false;
        }
        return !containsStation(basDevp.getBarcodeStationList$(), stationId)
                && !containsStation(basDevp.getInStationList$(), stationId)
                && !containsStation(basDevp.getOutStationList$(), stationId);
    }
    private boolean shouldSkipRunBlockStation(BasDevp basDevp, Integer stationId) {
        if (basDevp == null || stationId == null) {
            return false;
@@ -459,18 +348,8 @@
                                                                  Integer taskNo,
                                                                  Integer stationId) {
        boolean runBlockReroute = context.sceneType() == RerouteSceneType.RUN_BLOCK_REROUTE;
        if (context.checkRecentDispatch()
                && shouldSkipIdleRecoverForRecentDispatch(taskNo, stationId)) {
            return RerouteExecutionResult.skip("recent-dispatch");
        }
        int currentTaskBufferCommandCount = countCurrentTaskBufferCommands(stationProtocol.getTaskBufferItems(), taskNo);
        if (currentTaskBufferCommandCount > 0 && !runBlockReroute) {
            if (context.sceneType() == RerouteSceneType.IDLE_RECOVER) {
                News.info("输送站点任务停留超时,但缓存区仍存在当前任务命令,已跳过重算。站点号={},工作号={},当前任务命令数={}",
                        stationId,
                        taskNo,
                        currentTaskBufferCommandCount);
            }
            return RerouteExecutionResult.skip("buffer-has-current-task");
        }
        if (currentTaskBufferCommandCount > 0 && runBlockReroute) {
@@ -499,9 +378,6 @@
        }
        int clearedCommandCount = 0;
        if (context.clearIdleIssuedCommands()) {
            clearedCommandCount = stationDispatchRuntimeStateSupport.clearIssuedMoveCommandsDuringIdleStay(context.idleTrack(), taskNo, stationId);
        }
        boolean offered = offerDevpCommandWithDedup(context.dispatchDeviceNo(), plan.command(), plan.dispatchScene());
        if (!offered) {
@@ -552,17 +428,6 @@
                    dispatchDecision != null && dispatchDecision.isCircle()
            );
        }
        if (context.sceneType() == RerouteSceneType.IDLE_RECOVER) {
            stationDispatchRuntimeStateSupport.saveIdleTrack(new StationTaskIdleTrack(wrkMast.getWrkNo(), stationProtocol.getStationId(), System.currentTimeMillis()));
            News.info("输送站点任务停留{}秒未运行,已重新计算路径并重启运行,站点号={},目标站={},工作号={},清理旧分段命令数={},命令数据={}",
                    STATION_IDLE_RECOVER_SECONDS,
                    stationProtocol.getStationId(),
                    plan.command().getTargetStaNo(),
                    wrkMast.getWrkNo(),
                    clearedCommandCount,
                    JSON.toJSONString(plan.command()));
            return;
        }
        if (context.sceneType() == RerouteSceneType.RUN_BLOCK_REROUTE) {
            News.info("输送站点堵塞后重新计算路径命令下发成功,站点号={},工作号={},命令数据={}",
                    stationProtocol.getStationId(),
@@ -573,51 +438,6 @@
        if (context.sceneType() == RerouteSceneType.OUT_ORDER) {
            News.info(dispatchDecision != null && dispatchDecision.isCircle() ? "{}任务进行绕圈" : "{}任务直接去目标点", wrkMast.getWrkNo());
        }
    }
    private void checkStationIdleRecover(BasDevp basDevp,
                                         StationThread stationThread,
                                         StationProtocol stationProtocol,
                                         List<Integer> outOrderList) {
        if (stationProtocol == null || stationProtocol.getTaskNo() == null || stationProtocol.getTaskNo() <= 0) {
            return;
        }
        if (!Objects.equals(stationProtocol.getStationId(), stationProtocol.getTargetStaNo())) {
            return;
        }
        StationTaskIdleTrack idleTrack = stationDispatchRuntimeStateSupport.touchIdleTrack(stationProtocol.getTaskNo(), stationProtocol.getStationId());
        if (shouldSkipIdleRecoverForRecentDispatch(stationProtocol.getTaskNo(), stationProtocol.getStationId())) {
            return;
        }
        if (idleTrack == null || !idleTrack.isTimeout(STATION_IDLE_RECOVER_SECONDS)) {
            return;
        }
        WrkMast wrkMast = wrkMastService.selectByWorkNo(stationProtocol.getTaskNo());
        if (!canRecoverIdleStationTask(wrkMast, stationProtocol.getStationId())) {
            return;
        }
        Object lock = redisUtil.get(RedisKeyType.CHECK_STATION_IDLE_RECOVER_LIMIT_.key + stationProtocol.getTaskNo());
        if (lock != null) {
            return;
        }
        Double pathLenFactor = stationOutboundDecisionSupport.resolveOutboundPathLenFactor(wrkMast);
        RerouteContext context = RerouteContext.create(
                RerouteSceneType.IDLE_RECOVER,
                basDevp,
                stationThread,
                stationProtocol,
                wrkMast,
                outOrderList,
                pathLenFactor,
                "checkStationIdleRecover"
        ).withCancelSessionBeforeDispatch()
                .withExecutionLock(RedisKeyType.CHECK_STATION_IDLE_RECOVER_LIMIT_.key + stationProtocol.getTaskNo(), STATION_IDLE_RECOVER_LIMIT_SECONDS)
                .withResetSegmentCommandsBeforeDispatch()
                .clearIdleIssuedCommands(idleTrack);
        executeSharedReroute(context);
    }
    private void executeRunBlockDirectReassign(BasDevp basDevp,
@@ -729,17 +549,6 @@
                    false
            );
        }
    }
    private boolean canRecoverIdleStationTask(WrkMast wrkMast, Integer currentStationId) {
        if (wrkMast == null || currentStationId == null || wrkMast.getStaNo() == null) {
            return false;
        }
        if (Objects.equals(currentStationId, wrkMast.getStaNo())) {
            return false;
        }
        return Objects.equals(wrkMast.getWrkSts(), WrkStsType.INBOUND_STATION_RUN.sts)
                || Objects.equals(wrkMast.getWrkSts(), WrkStsType.STATION_RUN.sts);
    }
    private int countCurrentTaskBufferCommands(List<StationTaskBufferItem> taskBufferItems, Integer currentTaskNo) {