Junjie
9 小时以前 6296120dadc9088e7c2318358abf4b8bdef01ad2
src/main/java/com/zy/core/utils/StationOperateProcessUtils.java
@@ -483,169 +483,25 @@
                        }
                        redisUtil.set(RedisKeyType.CHECK_STATION_RUN_BLOCK_LIMIT_.key + stationProtocol.getTaskNo(), "lock", 15);
                        if (wrkMast.getIoType() == WrkIoType.IN.id && runBlockReassignLocStationList.contains(stationProtocol.getStationId())) {
                            //站点处于重新分配库位区域
                            int currentTaskBufferCommandCount = countCurrentTaskBufferCommands(
                                    stationProtocol.getTaskBufferItems(),
                                    stationProtocol.getTaskNo()
                            );
                            if (currentTaskBufferCommandCount > 0) {
                                News.info("输送站点运行堵塞重分配已跳过,缓存区仍存在当前任务命令。站点号={},工作号={},当前任务命令数={}",
                                        stationProtocol.getStationId(),
                                        stationProtocol.getTaskNo(),
                                        currentTaskBufferCommandCount);
                                continue;
                            }
                            if (stationMoveCoordinator != null) {
                                stationMoveCoordinator.cancelSession(wrkMast.getWrkNo());
                            }
                            //运行堵塞,重新申请任务
                            String response = wmsOperateUtils.applyReassignTaskLocNo(wrkMast.getWrkNo(), stationProtocol.getStationId());
                            if (Cools.isEmpty(response)) {
                                News.taskError(wrkMast.getWrkNo(), "请求WMS重新分配库位接口失败,接口未响应!!!response:{}", response);
                                continue;
                            }
                            JSONObject jsonObject = JSON.parseObject(response);
                            if (jsonObject.getInteger("code").equals(200)) {
                                StartupDto dto = jsonObject.getObject("data", StartupDto.class);
                                String sourceLocNo = wrkMast.getLocNo();
                                String locNo = dto.getLocNo();
                                LocMast sourceLocMast = locMastService.queryByLoc(sourceLocNo);
                                if (sourceLocMast == null) {
                                    News.taskInfo(wrkMast.getWrkNo(), "库位号:{} 源库位信息不存在", sourceLocNo);
                                    continue;
                                }
                                if (!sourceLocMast.getLocSts().equals("S")) {
                                    News.taskInfo(wrkMast.getWrkNo(), "库位号:{} 源库位状态不处于入库预约", sourceLocNo);
                                    continue;
                                }
                                LocMast locMast = locMastService.queryByLoc(locNo);
                                if (locMast == null) {
                                    News.taskInfo(wrkMast.getWrkNo(), "库位号:{} 目标库位信息不存在", locNo);
                                    continue;
                                }
                                if (!locMast.getLocSts().equals("O")) {
                                    News.taskInfo(wrkMast.getWrkNo(), "库位号:{} 目标库位状态不处于空库位", locNo);
                                    continue;
                                }
                                FindCrnNoResult findCrnNoResult = commonService.findCrnNoByLocNo(locNo);
                                if (findCrnNoResult == null) {
                                    News.taskInfo(wrkMast.getWrkNo(), "{}工作,未匹配到堆垛机", wrkMast.getWrkNo());
                                    continue;
                                }
                                Integer crnNo = findCrnNoResult.getCrnNo();
                                Integer targetStationId = commonService.findInStationId(findCrnNoResult, stationProtocol.getStationId());
                                if (targetStationId == null) {
                                    News.taskInfo(wrkMast.getWrkNo(), "{}站点,搜索入库站点失败", stationProtocol.getStationId());
                                    continue;
                                }
                                StationCommand command = stationThread.getCommand(StationCommandType.MOVE, wrkMast.getWrkNo(), stationProtocol.getStationId(), targetStationId, 0);
                                if (command == null) {
                                    News.taskInfo(wrkMast.getWrkNo(), "{}工作,获取输送线命令失败", wrkMast.getWrkNo());
                                    continue;
                                }
                                //更新源库位
                                sourceLocMast.setLocSts("O");
                                sourceLocMast.setModiTime(new Date());
                                locMastService.updateById(sourceLocMast);
                                //更新目标库位
                                locMast.setLocSts("S");
                                locMast.setModiTime(new Date());
                                locMastService.updateById(locMast);
                                //更新工作档数据
                                wrkMast.setLocNo(locNo);
                                wrkMast.setStaNo(targetStationId);
                                if (findCrnNoResult.getCrnType().equals(SlaveType.Crn)) {
                                    wrkMast.setCrnNo(crnNo);
                                } else if (findCrnNoResult.getCrnType().equals(SlaveType.DualCrn)) {
                                    wrkMast.setDualCrnNo(crnNo);
                                } else {
                                    throw new CoolException("未知设备类型");
                                }
                                if (wrkMastService.updateById(wrkMast)) {
                                    boolean offered = offerDevpCommandWithDedup(basDevp.getDevpNo(), command, "checkStationRunBlock_direct");
                                    if (!offered) {
                                        continue;
                                    }
                                    if (stationMoveCoordinator != null) {
                                        stationMoveCoordinator.recordDispatch(
                                                wrkMast.getWrkNo(),
                                                stationProtocol.getStationId(),
                                                "checkStationRunBlock_direct",
                                                command,
                                                false
                                        );
                                    }
                                }
                            } else {
                                News.error("请求WMS接口失败!!!response:{}", response);
                            }
                        } else {
                            //运行堵塞,重新计算路线
                            Double pathLenFactor = resolveOutboundPathLenFactor(wrkMast);
                            OutOrderDispatchDecision dispatchDecision = resolveOutboundDispatchDecision(
                                    stationProtocol.getStationId(),
                                    wrkMast,
                                    outOrderStationIds,
                                    pathLenFactor
                            );
                            Integer moveStaNo = dispatchDecision == null ? null : dispatchDecision.getTargetStationId();
                            if (moveStaNo == null || Objects.equals(moveStaNo, stationProtocol.getStationId())) {
                                continue;
                            }
                            if (countCurrentTaskBufferCommands(stationProtocol.getTaskBufferItems(), stationProtocol.getTaskNo()) > 0) {
                                continue;
                            }
                            StationCommand command = stationThread.getRunBlockRerouteCommand(
                                    wrkMast.getWrkNo(),
                                    stationProtocol.getStationId(),
                                    moveStaNo,
                                    0,
                                    pathLenFactor
                            );
                            if (command == null) {
                                News.taskInfo(wrkMast.getWrkNo(),
                                        "输送站点堵塞重规划未找到可下发路线,当前站点={},目标站点={}",
                                        stationProtocol.getStationId(),
                                        moveStaNo);
                                continue;
                            }
                            if (stationMoveCoordinator != null) {
                                stationMoveCoordinator.cancelSession(wrkMast.getWrkNo());
                            }
                            resetSegmentMoveCommandsBeforeReroute(wrkMast.getWrkNo());
                            boolean offered = offerDevpCommandWithDedup(basDevp.getDevpNo(), command, "checkStationRunBlock_reroute");
                            if (!offered) {
                                continue;
                            }
                            syncOutOrderWatchState(wrkMast, stationProtocol.getStationId(), outOrderStationIds, dispatchDecision, command);
                            if (stationMoveCoordinator != null) {
                                stationMoveCoordinator.recordDispatch(
                                        wrkMast.getWrkNo(),
                                        stationProtocol.getStationId(),
                                        "checkStationRunBlock_reroute",
                                        command,
                                        dispatchDecision != null && dispatchDecision.isCircle()
                                );
                            }
                            News.info("输送站点堵塞后重新计算路径命令下发成功,站点号={},工作号={},命令数据={}", stationProtocol.getStationId(), wrkMast.getWrkNo(), JSON.toJSONString(command));
                        if (shouldUseRunBlockDirectReassign(wrkMast, stationProtocol.getStationId(), runBlockReassignLocStationList)) {
                            executeRunBlockDirectReassign(basDevp, stationThread, stationProtocol, wrkMast);
                            continue;
                        }
                        Double pathLenFactor = resolveOutboundPathLenFactor(wrkMast);
                        RerouteContext context = RerouteContext.create(
                                RerouteSceneType.RUN_BLOCK_REROUTE,
                                basDevp,
                                stationThread,
                                stationProtocol,
                                wrkMast,
                                outOrderStationIds,
                                pathLenFactor,
                                "checkStationRunBlock_reroute"
                        ).withRunBlockCommand()
                                .withCancelSessionBeforeDispatch()
                                .withResetSegmentCommandsBeforeDispatch();
                        executeSharedReroute(context);
                    }
                }
            }
@@ -878,6 +734,19 @@
                context.pathLenFactor()
        );
        if (command == null) {
            if (context.sceneType() == RerouteSceneType.RUN_BLOCK_REROUTE) {
                News.taskInfo(context.wrkMast().getWrkNo(),
                        "输送站点堵塞重规划未找到可下发路线,当前站点={},目标站点={}",
                        currentStationId,
                        targetStationId);
            } else if (context.sceneType() == RerouteSceneType.IDLE_RECOVER) {
                News.taskInfo(context.wrkMast().getWrkNo(),
                        "站点任务停留超时后重算路径失败,当前站点={},目标站点={}",
                        currentStationId,
                        targetStationId);
            } else {
                News.taskInfo(context.wrkMast().getWrkNo(), "获取输送线命令失败");
            }
            return RerouteCommandPlan.skip("missing-command");
        }
        return RerouteCommandPlan.dispatch(command, decision, context.dispatchScene());
@@ -908,6 +777,12 @@
            return RerouteExecutionResult.skip("recent-dispatch");
        }
        if (countCurrentTaskBufferCommands(stationProtocol.getTaskBufferItems(), taskNo) > 0) {
            if (context.sceneType() == RerouteSceneType.IDLE_RECOVER) {
                News.info("输送站点任务停留超时,但缓存区仍存在当前任务命令,已跳过重算。站点号={},工作号={},当前任务命令数={}",
                        stationId,
                        taskNo,
                        countCurrentTaskBufferCommands(stationProtocol.getTaskBufferItems(), taskNo));
            }
            return RerouteExecutionResult.skip("buffer-has-current-task");
        }
        if (context.checkSuppressDispatch()
@@ -1571,67 +1446,143 @@
        if (lock != null) {
            return;
        }
        Double pathLenFactor = 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);
    }
    boolean shouldUseRunBlockDirectReassign(WrkMast wrkMast,
                                            Integer stationId,
                                            List<Integer> runBlockReassignLocStationList) {
        return wrkMast != null
                && Objects.equals(wrkMast.getIoType(), WrkIoType.IN.id)
                && stationId != null
                && runBlockReassignLocStationList != null
                && runBlockReassignLocStationList.contains(stationId);
    }
    private void executeRunBlockDirectReassign(BasDevp basDevp,
                                               StationThread stationThread,
                                               StationProtocol stationProtocol,
                                               WrkMast wrkMast) {
        if (basDevp == null || stationThread == null || stationProtocol == null || wrkMast == null) {
            return;
        }
        int currentTaskBufferCommandCount = countCurrentTaskBufferCommands(
                stationProtocol.getTaskBufferItems(),
                stationProtocol.getTaskNo()
        );
        if (currentTaskBufferCommandCount > 0) {
            News.info("输送站点任务停留超时,但缓存区仍存在当前任务命令,已跳过重算。站点号={},工作号={},当前任务命令数={}",
            News.info("输送站点运行堵塞重分配已跳过,缓存区仍存在当前任务命令。站点号={},工作号={},当前任务命令数={}",
                    stationProtocol.getStationId(),
                    stationProtocol.getTaskNo(),
                    currentTaskBufferCommandCount);
            return;
        }
        Double pathLenFactor = resolveOutboundPathLenFactor(wrkMast);
        OutOrderDispatchDecision dispatchDecision = null;
        Integer moveStaNo;
        if (Objects.equals(wrkMast.getWrkSts(), WrkStsType.STATION_RUN.sts)) {
            dispatchDecision = resolveOutboundDispatchDecision(stationProtocol.getStationId(), wrkMast, outOrderList, pathLenFactor);
            moveStaNo = dispatchDecision == null ? null : dispatchDecision.getTargetStationId();
        } else {
            moveStaNo = wrkMast.getStaNo();
        }
        if (moveStaNo == null || Objects.equals(moveStaNo, stationProtocol.getStationId())) {
            return;
        }
        if (stationMoveCoordinator != null) {
            stationMoveCoordinator.cancelSession(stationProtocol.getTaskNo());
            stationMoveCoordinator.cancelSession(wrkMast.getWrkNo());
        }
        redisUtil.set(RedisKeyType.CHECK_STATION_IDLE_RECOVER_LIMIT_.key + stationProtocol.getTaskNo(), "lock", STATION_IDLE_RECOVER_LIMIT_SECONDS);
        resetSegmentMoveCommandsBeforeReroute(stationProtocol.getTaskNo());
        int clearedCommandCount = clearIssuedMoveCommandsDuringIdleStay(idleTrack, stationProtocol.getTaskNo(), stationProtocol.getStationId());
        StationCommand command = buildOutboundMoveCommand(
                stationThread,
                wrkMast,
                stationProtocol.getStationId(),
                moveStaNo,
                pathLenFactor
        );
        if (command == null) {
            News.taskInfo(wrkMast.getWrkNo(), "站点任务停留超时后重算路径失败,当前站点={},目标站点={}", stationProtocol.getStationId(), moveStaNo);
        String response = wmsOperateUtils.applyReassignTaskLocNo(wrkMast.getWrkNo(), stationProtocol.getStationId());
        if (Cools.isEmpty(response)) {
            News.taskError(wrkMast.getWrkNo(), "请求WMS重新分配库位接口失败,接口未响应!!!response:{}", response);
            return;
        }
        JSONObject jsonObject = JSON.parseObject(response);
        if (!jsonObject.getInteger("code").equals(200)) {
            News.error("请求WMS接口失败!!!response:{}", response);
            return;
        }
        boolean offered = offerDevpCommandWithDedup(basDevp.getDevpNo(), command, "checkStationIdleRecover");
        StartupDto dto = jsonObject.getObject("data", StartupDto.class);
        String sourceLocNo = wrkMast.getLocNo();
        String locNo = dto.getLocNo();
        LocMast sourceLocMast = locMastService.queryByLoc(sourceLocNo);
        if (sourceLocMast == null) {
            News.taskInfo(wrkMast.getWrkNo(), "库位号:{} 源库位信息不存在", sourceLocNo);
            return;
        }
        if (!sourceLocMast.getLocSts().equals("S")) {
            News.taskInfo(wrkMast.getWrkNo(), "库位号:{} 源库位状态不处于入库预约", sourceLocNo);
            return;
        }
        LocMast locMast = locMastService.queryByLoc(locNo);
        if (locMast == null) {
            News.taskInfo(wrkMast.getWrkNo(), "库位号:{} 目标库位信息不存在", locNo);
            return;
        }
        if (!locMast.getLocSts().equals("O")) {
            News.taskInfo(wrkMast.getWrkNo(), "库位号:{} 目标库位状态不处于空库位", locNo);
            return;
        }
        FindCrnNoResult findCrnNoResult = commonService.findCrnNoByLocNo(locNo);
        if (findCrnNoResult == null) {
            News.taskInfo(wrkMast.getWrkNo(), "{}工作,未匹配到堆垛机", wrkMast.getWrkNo());
            return;
        }
        Integer crnNo = findCrnNoResult.getCrnNo();
        Integer targetStationId = commonService.findInStationId(findCrnNoResult, stationProtocol.getStationId());
        if (targetStationId == null) {
            News.taskInfo(wrkMast.getWrkNo(), "{}站点,搜索入库站点失败", stationProtocol.getStationId());
            return;
        }
        StationCommand command = stationThread.getCommand(StationCommandType.MOVE, wrkMast.getWrkNo(), stationProtocol.getStationId(), targetStationId, 0);
        if (command == null) {
            News.taskInfo(wrkMast.getWrkNo(), "{}工作,获取输送线命令失败", wrkMast.getWrkNo());
            return;
        }
        sourceLocMast.setLocSts("O");
        sourceLocMast.setModiTime(new Date());
        locMastService.updateById(sourceLocMast);
        locMast.setLocSts("S");
        locMast.setModiTime(new Date());
        locMastService.updateById(locMast);
        wrkMast.setLocNo(locNo);
        wrkMast.setStaNo(targetStationId);
        if (findCrnNoResult.getCrnType().equals(SlaveType.Crn)) {
            wrkMast.setCrnNo(crnNo);
        } else if (findCrnNoResult.getCrnType().equals(SlaveType.DualCrn)) {
            wrkMast.setDualCrnNo(crnNo);
        } else {
            throw new CoolException("未知设备类型");
        }
        if (!wrkMastService.updateById(wrkMast)) {
            return;
        }
        boolean offered = offerDevpCommandWithDedup(basDevp.getDevpNo(), command, "checkStationRunBlock_direct");
        if (!offered) {
            return;
        }
        syncOutOrderWatchState(wrkMast, stationProtocol.getStationId(), outOrderList, dispatchDecision, command);
        if (stationMoveCoordinator != null) {
            stationMoveCoordinator.recordDispatch(
                    wrkMast.getWrkNo(),
                    stationProtocol.getStationId(),
                    "checkStationIdleRecover",
                    "checkStationRunBlock_direct",
                    command,
                    dispatchDecision != null && dispatchDecision.isCircle()
                    false
            );
        }
        saveStationTaskIdleTrack(new StationTaskIdleTrack(wrkMast.getWrkNo(), stationProtocol.getStationId(), System.currentTimeMillis()));
        News.info("输送站点任务停留{}秒未运行,已重新计算路径并重启运行,站点号={},目标站={},工作号={},清理旧分段命令数={},命令数据={}",
                STATION_IDLE_RECOVER_SECONDS, stationProtocol.getStationId(), moveStaNo, wrkMast.getWrkNo(), clearedCommandCount, JSON.toJSONString(command));
    }
    private boolean canRecoverIdleStationTask(WrkMast wrkMast, Integer currentStationId) {