| | |
| | | import com.zy.common.service.CommonService; |
| | | import com.zy.common.utils.NavigateUtils; |
| | | import com.zy.common.utils.RedisUtil; |
| | | import com.zy.core.move.StationMoveCoordinator; |
| | | import com.zy.core.move.StationMoveSession; |
| | | import com.zy.core.News; |
| | | import com.zy.core.cache.MessageQueue; |
| | | import com.zy.core.cache.SlaveConnection; |
| | |
| | | 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; |
| | |
| | | private StationTaskLoopService stationTaskLoopService; |
| | | @Autowired |
| | | private WrkAnalysisService wrkAnalysisService; |
| | | @Autowired |
| | | private StationMoveCoordinator stationMoveCoordinator; |
| | | |
| | | //执行输送站点入库任务 |
| | | public synchronized void stationInExecute() { |
| | |
| | | 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()); |
| | |
| | | wrkMast.setModiTime(now); |
| | | if (wrkMastService.updateById(wrkMast)) { |
| | | wrkAnalysisService.markOutboundStationStart(wrkMast, now); |
| | | MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command)); |
| | | boolean offered = offerDevpCommandWithDedup(stationObjModel.getDeviceNo(), command, "crnStationOutExecute"); |
| | | if (offered && stationMoveCoordinator != null) { |
| | | stationMoveCoordinator.recordDispatch( |
| | | wrkMast.getWrkNo(), |
| | | stationProtocol.getStationId(), |
| | | "crnStationOutExecute", |
| | | command, |
| | | false |
| | | ); |
| | | } |
| | | 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()); |
| | |
| | | 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); |
| | |
| | | if (wrkMast == null || wrkMast.getWrkNo() == null) { |
| | | return; |
| | | } |
| | | if (stationMoveCoordinator != null) { |
| | | stationMoveCoordinator.finishSession(wrkMast.getWrkNo()); |
| | | } |
| | | Date now = new Date(); |
| | | wrkMast.setWrkSts(WrkStsType.STATION_RUN_COMPLETE.sts); |
| | | wrkMast.setIoTime(now); |
| | |
| | | } |
| | | |
| | | if (complete) { |
| | | if (stationMoveCoordinator != null) { |
| | | stationMoveCoordinator.finishSession(wrkNo); |
| | | } |
| | | wrkMast.setWrkSts(WrkStsType.COMPLETE_OUTBOUND.sts); |
| | | wrkMast.setIoTime(new Date()); |
| | | wrkMastService.updateById(wrkMast); |
| | |
| | | |
| | | 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)) { |
| | |
| | | } |
| | | |
| | | if (wrkMastService.updateById(wrkMast)) { |
| | | MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command)); |
| | | 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); |
| | |
| | | continue; |
| | | } |
| | | |
| | | if (countCurrentTaskBufferCommands(stationProtocol.getTaskBufferItems(), stationProtocol.getTaskNo()) > 0) { |
| | | continue; |
| | | } |
| | | |
| | | StationCommand command = stationThread.getRunBlockRerouteCommand( |
| | | wrkMast.getWrkNo(), |
| | | stationProtocol.getStationId(), |
| | |
| | | continue; |
| | | } |
| | | |
| | | MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command)); |
| | | 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)); |
| | | } |
| | | } |
| | |
| | | continue; |
| | | } |
| | | |
| | | if (isWatchingCircleArrival(wrkMast.getWrkNo(), stationProtocol.getStationId())) { |
| | | if (countCurrentTaskBufferCommands(stationProtocol.getTaskBufferItems(), stationProtocol.getTaskNo()) > 0) { |
| | | continue; |
| | | } |
| | | |
| | |
| | | News.taskInfo(wrkMast.getWrkNo(), "获取输送线命令失败"); |
| | | continue; |
| | | } |
| | | if (stationMoveCoordinator != null |
| | | && stationMoveCoordinator.shouldSuppressDispatch(wrkMast.getWrkNo(), stationProtocol.getStationId(), command)) { |
| | | continue; |
| | | } |
| | | if (!tryAcquireOutOrderDispatchLock(wrkMast.getWrkNo(), stationProtocol.getStationId())) { |
| | | continue; |
| | | } |
| | | resetSegmentMoveCommandsBeforeReroute(wrkMast.getWrkNo()); |
| | | boolean offered = offerDevpCommandWithDedup(stationObjModel.getDeviceNo(), command, "checkStationOutOrder"); |
| | | if (!offered) { |
| | | continue; |
| | | } |
| | | syncOutOrderWatchState(wrkMast, stationProtocol.getStationId(), outOrderStationIds, dispatchDecision, command); |
| | | MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command)); |
| | | if (stationMoveCoordinator != null) { |
| | | stationMoveCoordinator.recordDispatch( |
| | | wrkMast.getWrkNo(), |
| | | stationProtocol.getStationId(), |
| | | "checkStationOutOrder", |
| | | command, |
| | | dispatchDecision != null && dispatchDecision.isCircle() |
| | | ); |
| | | } |
| | | News.info(dispatchDecision.isCircle() ? "{}任务进行绕圈" : "{}任务直接去目标点", wrkMast.getWrkNo()); |
| | | } |
| | | } |
| | |
| | | if (Objects.equals(stationProtocol.getStationId(), wrkMast.getStaNo())) { |
| | | continue; |
| | | } |
| | | if (countCurrentTaskBufferCommands(stationProtocol.getTaskBufferItems(), stationProtocol.getTaskNo()) > 0) { |
| | | continue; |
| | | } |
| | | |
| | | Double pathLenFactor = resolveOutboundPathLenFactor(wrkMast); |
| | | OutOrderDispatchDecision dispatchDecision = resolveOutboundDispatchDecision( |
| | |
| | | News.taskInfo(wrkMast.getWrkNo(), "获取输送线命令失败"); |
| | | continue; |
| | | } |
| | | if (stationMoveCoordinator != null |
| | | && stationMoveCoordinator.shouldSuppressDispatch(wrkMast.getWrkNo(), stationProtocol.getStationId(), command)) { |
| | | continue; |
| | | } |
| | | if (!tryAcquireOutOrderDispatchLock(wrkMast.getWrkNo(), stationProtocol.getStationId())) { |
| | | continue; |
| | | } |
| | | resetSegmentMoveCommandsBeforeReroute(wrkMast.getWrkNo()); |
| | | boolean offered = offerDevpCommandWithDedup(basDevp.getDevpNo(), command, "watchCircleStation"); |
| | | if (!offered) { |
| | | continue; |
| | | } |
| | | syncOutOrderWatchState(wrkMast, stationProtocol.getStationId(), outOrderList, dispatchDecision, command); |
| | | MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command)); |
| | | if (stationMoveCoordinator != null) { |
| | | stationMoveCoordinator.recordDispatch( |
| | | wrkMast.getWrkNo(), |
| | | stationProtocol.getStationId(), |
| | | "watchCircleStation", |
| | | command, |
| | | dispatchDecision != null && dispatchDecision.isCircle() |
| | | ); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | private boolean isWatchingCircleArrival(Integer wrkNo, Integer stationId) { |
| | | if (stationMoveCoordinator != null) { |
| | | StationMoveSession session = stationMoveCoordinator.loadSession(wrkNo); |
| | | if (session != null && session.isActive() && stationId != null) { |
| | | if (stationId.equals(session.getNextDecisionStationId())) { |
| | | return true; |
| | | } |
| | | if (session.containsStation(stationId)) { |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | StationCommand command = getWatchCircleCommand(wrkNo); |
| | | return command != null && stationId != null && stationId.equals(command.getTargetStaNo()); |
| | | } |
| | | |
| | | private boolean isWatchingCircleTransit(Integer wrkNo, Integer stationId) { |
| | | if (stationMoveCoordinator != null) { |
| | | StationMoveSession session = stationMoveCoordinator.loadSession(wrkNo); |
| | | if (session != null && session.isActive() && stationId != null) { |
| | | if (stationId.equals(session.getNextDecisionStationId())) { |
| | | return false; |
| | | } |
| | | if (session.containsStation(stationId)) { |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | | StationCommand command = getWatchCircleCommand(wrkNo); |
| | | if (command == null || stationId == null || Objects.equals(stationId, command.getTargetStaNo())) { |
| | | return false; |
| | | } |
| | | List<Integer> navigatePath = command.getNavigatePath(); |
| | | return navigatePath != null && navigatePath.contains(stationId); |
| | | } |
| | | |
| | | private StationCommand getWatchCircleCommand(Integer wrkNo) { |
| | |
| | | return; |
| | | } |
| | | |
| | | if (stationMoveCoordinator != null) { |
| | | stationMoveCoordinator.cancelSession(stationProtocol.getTaskNo()); |
| | | } |
| | | 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()); |
| | |
| | | return; |
| | | } |
| | | |
| | | MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command)); |
| | | boolean offered = offerDevpCommandWithDedup(basDevp.getDevpNo(), command, "checkStationIdleRecover"); |
| | | if (!offered) { |
| | | return; |
| | | } |
| | | syncOutOrderWatchState(wrkMast, stationProtocol.getStationId(), outOrderList, dispatchDecision, command); |
| | | if (stationMoveCoordinator != null) { |
| | | stationMoveCoordinator.recordDispatch( |
| | | wrkMast.getWrkNo(), |
| | | stationProtocol.getStationId(), |
| | | "checkStationIdleRecover", |
| | | command, |
| | | dispatchDecision != null && dispatchDecision.isCircle() |
| | | ); |
| | | } |
| | | saveStationTaskIdleTrack(new StationTaskIdleTrack(wrkMast.getWrkNo(), stationProtocol.getStationId(), System.currentTimeMillis())); |
| | | News.info("输送站点任务停留{}秒未运行,已重新计算路径并重启运行,站点号={},目标站={},工作号={},清理旧分段命令数={},命令数据={}", |
| | | STATION_IDLE_RECOVER_SECONDS, stationProtocol.getStationId(), moveStaNo, wrkMast.getWrkNo(), clearedCommandCount, JSON.toJSONString(command)); |
| | |
| | | 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("输送站点命令短时重复派发,已跳过。scene={},deviceNo={},taskNo={},stationId={},targetStaNo={},commandType={}", |
| | | 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 |
| | | + deviceNo + "_" |
| | | + command.getTaskNo() + "_" |
| | | + command.getStationId() + "_" |
| | | + (stationMoveCoordinator == null ? Integer.toHexString(buildFallbackPathSignature(command).hashCode()) |
| | | : stationMoveCoordinator.buildPathSignatureHash(command)); |
| | | } |
| | | |
| | | private String buildFallbackPathSignature(StationCommand command) { |
| | | if (command == null) { |
| | | return ""; |
| | | } |
| | | return String.valueOf(command.getCommandType()) |
| | | + "_" + command.getStationId() |
| | | + "_" + command.getTargetStaNo() |
| | | + "_" + command.getNavigatePath() |
| | | + "_" + command.getLiftTransferPath() |
| | | + "_" + command.getOriginalNavigatePath(); |
| | | } |
| | | |
| | | private int clearIssuedMoveCommandsDuringIdleStay(StationTaskIdleTrack idleTrack, |
| | | Integer taskNo, |
| | | Integer stationId) { |