package com.zy.core.utils.station; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.core.common.Cools; import com.core.exception.CoolException; import com.zy.asrs.entity.BasDevp; import com.zy.asrs.entity.LocMast; import com.zy.asrs.entity.WrkMast; import com.zy.asrs.service.BasDevpService; import com.zy.asrs.service.LocMastService; import com.zy.asrs.service.WrkMastService; import com.zy.common.entity.FindCrnNoResult; import com.zy.common.model.StartupDto; import com.zy.common.service.CommonService; import com.zy.common.utils.RedisUtil; import com.zy.core.News; import com.zy.core.cache.SlaveConnection; import com.zy.core.dispatch.StationCommandDispatchResult; import com.zy.core.dispatch.StationCommandDispatcher; import com.zy.core.enums.RedisKeyType; import com.zy.core.enums.SlaveType; import com.zy.core.enums.StationCommandType; import com.zy.core.enums.WrkIoType; import com.zy.core.enums.WrkStsType; import com.zy.core.model.StationObjModel; import com.zy.core.model.command.StationCommand; import com.zy.core.model.protocol.StationProtocol; import com.zy.core.model.protocol.StationTaskBufferItem; import com.zy.core.move.StationMoveCoordinator; import com.zy.core.move.StationMoveSession; import com.zy.core.thread.StationThread; import com.zy.core.utils.station.model.OutOrderDispatchDecision; import com.zy.core.utils.station.model.RerouteCommandPlan; import com.zy.core.utils.station.model.RerouteContext; import com.zy.core.utils.station.model.RerouteDecision; import com.zy.core.utils.station.model.RerouteExecutionResult; import com.zy.core.utils.station.model.RerouteSceneType; import com.zy.core.utils.WmsOperateUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Objects; @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 private BasDevpService basDevpService; @Autowired private WrkMastService wrkMastService; @Autowired private CommonService commonService; @Autowired private RedisUtil redisUtil; @Autowired private LocMastService locMastService; @Autowired private WmsOperateUtils wmsOperateUtils; @Autowired private StationMoveCoordinator stationMoveCoordinator; @Autowired private StationCommandDispatcher stationCommandDispatcher; @Autowired private StationOutboundDecisionSupport stationOutboundDecisionSupport; @Autowired private StationDispatchRuntimeStateSupport stationDispatchRuntimeStateSupport; public void checkStationRunBlock() { try { List basDevps = basDevpService.list(new QueryWrapper<>()); for (BasDevp basDevp : basDevps) { StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, basDevp.getDevpNo()); if (stationThread == null) { continue; } List runBlockReassignLocStationList = new ArrayList<>(); for (StationObjModel stationObjModel : basDevp.getRunBlockReassignLocStationList$()) { runBlockReassignLocStationList.add(stationObjModel.getStationId()); } List outOrderStationIds = basDevp.getOutOrderIntList(); for (StationProtocol stationProtocol : stationThread.getStatus()) { if (stationProtocol.isAutoing() && stationProtocol.isLoading() && stationProtocol.getTaskNo() > 0 && stationProtocol.isRunBlock()) { WrkMast wrkMast = wrkMastService.selectByWorkNo(stationProtocol.getTaskNo()); if (wrkMast == null) { News.info("输送站点号={} 运行阻塞,但无法找到对应任务,工作号={}", stationProtocol.getStationId(), stationProtocol.getTaskNo()); continue; } Object lock = redisUtil.get(RedisKeyType.CHECK_STATION_RUN_BLOCK_LIMIT_.key + stationProtocol.getTaskNo()); if (lock != null) { continue; } redisUtil.set(RedisKeyType.CHECK_STATION_RUN_BLOCK_LIMIT_.key + stationProtocol.getTaskNo(), "lock", 15); if (shouldUseRunBlockDirectReassign(wrkMast, stationProtocol.getStationId(), runBlockReassignLocStationList)) { executeRunBlockDirectReassign(basDevp, stationThread, stationProtocol, wrkMast); continue; } Double pathLenFactor = stationOutboundDecisionSupport.resolveOutboundPathLenFactor(wrkMast); RerouteContext context = RerouteContext.create( RerouteSceneType.RUN_BLOCK_REROUTE, basDevp, stationThread, stationProtocol, wrkMast, outOrderStationIds, pathLenFactor, "checkStationRunBlock_reroute" ).withRunBlockCommand() .withSuppressDispatchGuard() .withCancelSessionBeforeDispatch() .withResetSegmentCommandsBeforeDispatch(); executeSharedReroute(context); } } } } catch (Exception e) { e.printStackTrace(); } } public void checkStationIdleRecover() { try { List 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()) { if (stationProtocol.isAutoing() && stationProtocol.isLoading() && stationProtocol.getTaskNo() > 0 && !stationProtocol.isRunBlock()) { checkStationIdleRecover(basDevp, stationThread, stationProtocol, basDevp.getOutOrderIntList()); } } } } catch (Exception e) { e.printStackTrace(); } } public void checkStationOutOrder() { List basDevps = basDevpService.list(new QueryWrapper()); for (BasDevp basDevp : basDevps) { StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, basDevp.getDevpNo()); if (stationThread == null) { continue; } Map statusMap = stationThread.getStatusMap(); List orderList = basDevp.getOutOrderList$(); List outOrderStationIds = basDevp.getOutOrderIntList(); for (StationObjModel stationObjModel : orderList) { StationProtocol stationProtocol = statusMap.get(stationObjModel.getStationId()); if (stationProtocol == null || !stationProtocol.isAutoing() || !stationProtocol.isLoading() || stationProtocol.getTaskNo() <= 0 || stationProtocol.isRunBlock() || !stationProtocol.getStationId().equals(stationProtocol.getTargetStaNo())) { continue; } WrkMast wrkMast = wrkMastService.selectByWorkNo(stationProtocol.getTaskNo()); if (wrkMast == null || !Objects.equals(wrkMast.getWrkSts(), WrkStsType.STATION_RUN.sts) || Objects.equals(stationProtocol.getStationId(), wrkMast.getStaNo())) { continue; } if (stationOutboundDecisionSupport.shouldSkipOutOrderDispatchForExistingRoute(wrkMast.getWrkNo(), stationProtocol.getStationId())) { continue; } Double pathLenFactor = stationOutboundDecisionSupport.resolveOutboundPathLenFactor(wrkMast); RerouteContext context = RerouteContext.create( RerouteSceneType.OUT_ORDER, basDevp, stationThread, stationProtocol, wrkMast, outOrderStationIds, pathLenFactor, "checkStationOutOrder" ).withDispatchDeviceNo(stationObjModel.getDeviceNo()) .withSuppressDispatchGuard() .withOutOrderDispatchLock() .withResetSegmentCommandsBeforeDispatch(); executeSharedReroute(context); } } } public void watchCircleStation() { List basDevps = basDevpService.list(new QueryWrapper()); for (BasDevp basDevp : basDevps) { StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, basDevp.getDevpNo()); if (stationThread == null) { continue; } List outOrderList = basDevp.getOutOrderIntList(); for (StationProtocol stationProtocol : stationThread.getStatus()) { if (!stationProtocol.isAutoing() || !stationProtocol.isLoading() || stationProtocol.getTaskNo() <= 0 || !stationOutboundDecisionSupport.isWatchingCircleArrival(stationProtocol.getTaskNo(), stationProtocol.getStationId())) { continue; } WrkMast wrkMast = wrkMastService.selectByWorkNo(stationProtocol.getTaskNo()); if (wrkMast == null || !Objects.equals(wrkMast.getWrkSts(), WrkStsType.STATION_RUN.sts) || Objects.equals(stationProtocol.getStationId(), wrkMast.getStaNo())) { continue; } Double pathLenFactor = stationOutboundDecisionSupport.resolveOutboundPathLenFactor(wrkMast); RerouteContext context = RerouteContext.create( RerouteSceneType.WATCH_CIRCLE, basDevp, stationThread, stationProtocol, wrkMast, outOrderList, pathLenFactor, "watchCircleStation" ).withSuppressDispatchGuard() .withOutOrderDispatchLock() .withResetSegmentCommandsBeforeDispatch(); executeSharedReroute(context); } } } public RerouteCommandPlan buildRerouteCommandPlan(RerouteContext context, RerouteDecision decision) { if (context == null) { return RerouteCommandPlan.skip("missing-context"); } if (decision == null) { return RerouteCommandPlan.skip("missing-decision"); } if (decision.skip()) { return RerouteCommandPlan.skip(decision.skipReason()); } if (context.stationThread() == null || context.stationProtocol() == null || context.wrkMast() == null) { return RerouteCommandPlan.skip("missing-runtime-dependency"); } Integer currentStationId = context.stationProtocol().getStationId(); Integer targetStationId = decision.targetStationId(); if (currentStationId == null || targetStationId == null) { return RerouteCommandPlan.skip("missing-target-station"); } if (Objects.equals(currentStationId, targetStationId)) { return RerouteCommandPlan.skip("same-station"); } StationCommand command = context.useRunBlockCommand() ? context.stationThread().getRunBlockRerouteCommand( context.wrkMast().getWrkNo(), currentStationId, targetStationId, 0, context.pathLenFactor() ) : stationOutboundDecisionSupport.buildOutboundMoveCommand( context.stationThread(), context.wrkMast(), currentStationId, targetStationId, 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()); } public RerouteExecutionResult executeReroutePlan(RerouteContext context, RerouteCommandPlan plan) { if (context == null) { return RerouteExecutionResult.skip("missing-context"); } if (plan == null) { return RerouteExecutionResult.skip("missing-plan"); } if (plan.skip()) { return RerouteExecutionResult.skip(plan.skipReason()); } StationProtocol stationProtocol = context.stationProtocol(); if (stationProtocol == null) { return RerouteExecutionResult.skip("missing-station-protocol"); } Integer taskNo = stationProtocol.getTaskNo(); Integer stationId = stationProtocol.getStationId(); if (taskNo == null || taskNo <= 0 || stationId == null) { return RerouteExecutionResult.skip("invalid-station-task"); } if (stationMoveCoordinator != null) { return stationMoveCoordinator.withTaskDispatchLock(taskNo, () -> executeReroutePlanWithTaskLock(context, plan, stationProtocol, taskNo, stationId)); } return executeReroutePlanWithTaskLock(context, plan, stationProtocol, taskNo, stationId); } public RerouteDecision resolveSharedRerouteDecision(RerouteContext context) { if (context == null || context.wrkMast() == null || context.stationProtocol() == null) { return RerouteDecision.skip("missing-runtime-dependency"); } Integer currentStationId = context.stationProtocol().getStationId(); if (currentStationId == null) { return RerouteDecision.skip("missing-current-station"); } if (context.sceneType() == RerouteSceneType.IDLE_RECOVER && !Objects.equals(context.wrkMast().getWrkSts(), WrkStsType.STATION_RUN.sts)) { Integer targetStationId = context.wrkMast().getStaNo(); return targetStationId == null || Objects.equals(targetStationId, currentStationId) ? RerouteDecision.skip("same-station") : RerouteDecision.proceed(targetStationId); } OutOrderDispatchDecision dispatchDecision = stationOutboundDecisionSupport.resolveOutboundDispatchDecision( currentStationId, context.wrkMast(), context.outOrderStationIds(), context.pathLenFactor() ); Integer targetStationId = dispatchDecision == null ? null : dispatchDecision.getTargetStationId(); if (targetStationId == null || Objects.equals(targetStationId, currentStationId)) { return RerouteDecision.skip("same-station"); } return RerouteDecision.proceed(targetStationId, dispatchDecision); } public boolean shouldUseRunBlockDirectReassign(WrkMast wrkMast, Integer stationId, List runBlockReassignLocStationList) { return wrkMast != null && Objects.equals(wrkMast.getIoType(), WrkIoType.IN.id) && stationId != null && runBlockReassignLocStationList != null && 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 RerouteExecutionResult executeReroutePlanWithTaskLock(RerouteContext context, RerouteCommandPlan plan, StationProtocol stationProtocol, 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) { News.info("输送站点运行堵塞重规划检测到旧分段命令残留,已先清理本地状态后继续重发。站点号={},工作号={},当前任务命令数={}", stationId, taskNo, currentTaskBufferCommandCount); } if (!runBlockReroute && context.checkSuppressDispatch() && stationMoveCoordinator != null && stationMoveCoordinator.shouldSuppressDispatch(taskNo, stationId, plan.command())) { return RerouteExecutionResult.skip("dispatch-suppressed"); } if (context.requireOutOrderDispatchLock() && !stationDispatchRuntimeStateSupport.tryAcquireOutOrderDispatchLock(taskNo, stationId, OUT_ORDER_DISPATCH_LIMIT_SECONDS)) { return RerouteExecutionResult.skip("out-order-lock"); } if (context.cancelSessionBeforeDispatch() && stationMoveCoordinator != null) { stationMoveCoordinator.markCancelPending(taskNo, "reroute_pending"); } if (runBlockReroute) { if (context.cancelSessionBeforeDispatch() && stationMoveCoordinator != null) { stationMoveCoordinator.cancelSession(taskNo); } if (context.resetSegmentCommandsBeforeDispatch()) { stationDispatchRuntimeStateSupport.signalSegmentReset(taskNo, STATION_MOVE_RESET_WAIT_MS); } } if (!runBlockReroute && context.cancelSessionBeforeDispatch() && stationMoveCoordinator != null) { stationMoveCoordinator.cancelSession(taskNo); } if (!isBlank(context.executionLockKey()) && !stationDispatchRuntimeStateSupport.tryAcquireLock(context.executionLockKey(), context.executionLockSeconds())) { return RerouteExecutionResult.skip("scene-lock"); } if (!runBlockReroute && context.resetSegmentCommandsBeforeDispatch()) { stationDispatchRuntimeStateSupport.signalSegmentReset(taskNo, STATION_MOVE_RESET_WAIT_MS); } int clearedCommandCount = 0; if (context.clearIdleIssuedCommands()) { clearedCommandCount = stationDispatchRuntimeStateSupport.clearIssuedMoveCommandsDuringIdleStay(context.idleTrack(), taskNo, stationId); } boolean offered = offerDevpCommandWithDedup(context.dispatchDeviceNo(), plan.command(), plan.dispatchScene()); if (!offered) { return RerouteExecutionResult.skip("dispatch-dedup"); } applyRerouteDispatchEffects(context, plan, clearedCommandCount); return RerouteExecutionResult.dispatched(plan.command(), clearedCommandCount); } private RerouteExecutionResult executeSharedReroute(RerouteContext context) { RerouteDecision decision = resolveSharedRerouteDecision(context); if (decision.skip()) { return RerouteExecutionResult.skip(decision.skipReason()); } RerouteCommandPlan plan = buildRerouteCommandPlan(context, decision); return executeReroutePlan(context, plan); } private void applyRerouteDispatchEffects(RerouteContext context, RerouteCommandPlan plan, int clearedCommandCount) { if (context == null || plan == null || plan.command() == null || context.wrkMast() == null || context.stationProtocol() == null) { return; } WrkMast wrkMast = context.wrkMast(); StationProtocol stationProtocol = context.stationProtocol(); OutOrderDispatchDecision dispatchDecision = plan.decision() == null ? null : plan.decision().dispatchDecision(); stationOutboundDecisionSupport.syncOutOrderWatchState( wrkMast, stationProtocol.getStationId(), context.outOrderStationIds(), dispatchDecision, plan.command() ); if (stationMoveCoordinator != null) { stationMoveCoordinator.recordDispatch( wrkMast.getWrkNo(), stationProtocol.getStationId(), plan.dispatchScene(), plan.command(), 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(), wrkMast.getWrkNo(), JSON.toJSONString(plan.command())); return; } if (context.sceneType() == RerouteSceneType.OUT_ORDER) { News.info(dispatchDecision != null && dispatchDecision.isCircle() ? "{}任务进行绕圈" : "{}任务直接去目标点", wrkMast.getWrkNo()); } } private void checkStationIdleRecover(BasDevp basDevp, StationThread stationThread, StationProtocol stationProtocol, List 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, 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("输送站点运行堵塞重分配已跳过,缓存区仍存在当前任务命令。站点号={},工作号={},当前任务命令数={}", stationProtocol.getStationId(), stationProtocol.getTaskNo(), currentTaskBufferCommandCount); return; } 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); return; } JSONObject jsonObject = JSON.parseObject(response); if (!jsonObject.getInteger("code").equals(200)) { News.error("请求WMS接口失败!!!response:{}", response); return; } 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; } if (stationMoveCoordinator != null) { stationMoveCoordinator.recordDispatch( wrkMast.getWrkNo(), stationProtocol.getStationId(), "checkStationRunBlock_direct", command, 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 taskBufferItems, Integer currentTaskNo) { if (taskBufferItems == null || taskBufferItems.isEmpty() || currentTaskNo == null || currentTaskNo <= 0) { return 0; } int count = 0; for (StationTaskBufferItem item : taskBufferItems) { if (item == null || item.getTaskNo() == null) { continue; } if (currentTaskNo.equals(item.getTaskNo())) { count++; } } return count; } private boolean offerDevpCommandWithDedup(Integer deviceNo, StationCommand command, String scene) { StationCommandDispatchResult dispatchResult = stationCommandDispatcher .dispatch(deviceNo, command, "station-operate-process", scene); return dispatchResult.isAccepted(); } private boolean isBlank(String value) { return value == null || value.trim().isEmpty(); } }