| | |
| | | public class StationOperateProcessUtils { |
| | | private static final int LOOP_LOAD_RESERVE_EXPIRE_SECONDS = 120; |
| | | private static final int OUT_ORDER_DISPATCH_LIMIT_SECONDS = 10; |
| | | private static final int STATION_IDLE_RECOVER_SECONDS = 10; |
| | | private static final int STATION_IDLE_RECOVER_LIMIT_SECONDS = 10; |
| | | private static final int STATION_IDLE_TRACK_EXPIRE_SECONDS = 60 * 60; |
| | | |
| | | @Autowired |
| | | private BasDevpService basDevpService; |
| | |
| | | private StationCycleCapacityService stationCycleCapacityService; |
| | | @Autowired |
| | | private StationPathPolicyService stationPathPolicyService; |
| | | @Autowired |
| | | private BasStationOptService basStationOptService; |
| | | |
| | | //执行输送站点入库任务 |
| | | public synchronized void stationInExecute() { |
| | |
| | | } |
| | | } |
| | | |
| | | //检测输送站点任务停留超时后重新计算路径 |
| | | public synchronized void checkStationIdleRecover() { |
| | | try { |
| | | List<BasDevp> basDevps = basDevpService.list(new QueryWrapper<>()); |
| | | List<Integer> outOrderList = new ArrayList<>(); |
| | | for (BasDevp basDevp : basDevps) { |
| | | outOrderList.addAll(basDevp.getOutOrderIntList()); |
| | | } |
| | | for (BasDevp basDevp : basDevps) { |
| | | StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, basDevp.getDevpNo()); |
| | | if (stationThread == null) { |
| | | continue; |
| | | } |
| | | |
| | | List<StationProtocol> list = stationThread.getStatus(); |
| | | for (StationProtocol stationProtocol : list) { |
| | | if (stationProtocol.isAutoing() |
| | | && stationProtocol.isLoading() |
| | | && stationProtocol.getTaskNo() > 0 |
| | | && !stationProtocol.isRunBlock() |
| | | ) { |
| | | checkStationIdleRecover(basDevp, stationThread, stationProtocol, outOrderList); |
| | | } |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | //获取输送线任务数量 |
| | | public synchronized int getCurrentStationTaskCount() { |
| | | return countCurrentStationTask(); |
| | |
| | | return; |
| | | } |
| | | redisUtil.del(RedisKeyType.WATCH_CIRCLE_STATION_.key + wrkNo); |
| | | } |
| | | |
| | | 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 = touchStationTaskIdleTrack(stationProtocol.getTaskNo(), stationProtocol.getStationId()); |
| | | 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; |
| | | } |
| | | |
| | | if (hasFollowUpMoveCommandAfterStay(idleTrack, stationProtocol.getTaskNo(), stationProtocol.getStationId())) { |
| | | return; |
| | | } |
| | | |
| | | Integer moveStaNo = resolveIdleRecoverTarget(stationProtocol, wrkMast, outOrderList); |
| | | if (moveStaNo == null || Objects.equals(moveStaNo, stationProtocol.getStationId())) { |
| | | return; |
| | | } |
| | | |
| | | redisUtil.set(RedisKeyType.CHECK_STATION_IDLE_RECOVER_LIMIT_.key + stationProtocol.getTaskNo(), "lock", STATION_IDLE_RECOVER_LIMIT_SECONDS); |
| | | |
| | | StationCommand command = stationThread.getCommand( |
| | | StationCommandType.MOVE, |
| | | wrkMast.getWrkNo(), |
| | | stationProtocol.getStationId(), |
| | | moveStaNo, |
| | | 0 |
| | | ); |
| | | if (command == null) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "站点任务停留超时后重算路径失败,当前站点={},目标站点={}", stationProtocol.getStationId(), moveStaNo); |
| | | return; |
| | | } |
| | | |
| | | MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command)); |
| | | saveStationTaskIdleTrack(new StationTaskIdleTrack(wrkMast.getWrkNo(), stationProtocol.getStationId(), System.currentTimeMillis())); |
| | | News.info("输送站点任务停留{}秒未运行,已重新计算路径并重启运行,站点号={},目标站={},工作号={},命令数据={}", |
| | | STATION_IDLE_RECOVER_SECONDS, stationProtocol.getStationId(), moveStaNo, wrkMast.getWrkNo(), JSON.toJSONString(command)); |
| | | } |
| | | |
| | | 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_DEVICE_RUN.sts) |
| | | || Objects.equals(wrkMast.getWrkSts(), WrkStsType.STATION_RUN.sts); |
| | | } |
| | | |
| | | private Integer resolveIdleRecoverTarget(StationProtocol stationProtocol, |
| | | WrkMast wrkMast, |
| | | List<Integer> outOrderList) { |
| | | if (stationProtocol == null || wrkMast == null) { |
| | | return null; |
| | | } |
| | | Integer currentStationId = stationProtocol.getStationId(); |
| | | if (currentStationId == null) { |
| | | return null; |
| | | } |
| | | if (Objects.equals(wrkMast.getWrkSts(), WrkStsType.STATION_RUN.sts)) { |
| | | return resolveDispatchOutOrderTarget(currentStationId, wrkMast.getStaNo(), outOrderList, true); |
| | | } |
| | | return wrkMast.getStaNo(); |
| | | } |
| | | |
| | | private boolean hasFollowUpMoveCommandAfterStay(StationTaskIdleTrack idleTrack, |
| | | Integer taskNo, |
| | | Integer stationId) { |
| | | if (idleTrack == null || taskNo == null || stationId == null || idleTrack.firstSeenTime == null) { |
| | | return false; |
| | | } |
| | | if (basStationOptService == null) { |
| | | return false; |
| | | } |
| | | |
| | | List<BasStationOpt> optList; |
| | | try { |
| | | optList = basStationOptService.list(new QueryWrapper<BasStationOpt>() |
| | | .select("id", "target_station_id") |
| | | .eq("task_no", taskNo) |
| | | .eq("source_station_id", stationId) |
| | | .eq("mode", String.valueOf(StationCommandType.MOVE)) |
| | | .eq("send", 1) |
| | | .ge("send_time", new Date(idleTrack.firstSeenTime)) |
| | | .orderByDesc("send_time") |
| | | .last("limit 3")); |
| | | } catch (Exception e) { |
| | | return false; |
| | | } |
| | | |
| | | if (optList == null || optList.isEmpty()) { |
| | | return false; |
| | | } |
| | | |
| | | for (BasStationOpt opt : optList) { |
| | | if (opt != null && opt.getTargetStationId() != null && !Objects.equals(opt.getTargetStationId(), stationId)) { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | private StationTaskIdleTrack touchStationTaskIdleTrack(Integer taskNo, Integer stationId) { |
| | | if (taskNo == null || taskNo <= 0 || stationId == null) { |
| | | return null; |
| | | } |
| | | long now = System.currentTimeMillis(); |
| | | StationTaskIdleTrack idleTrack = getStationTaskIdleTrack(taskNo); |
| | | if (idleTrack == null || !Objects.equals(idleTrack.stationId, stationId)) { |
| | | idleTrack = new StationTaskIdleTrack(taskNo, stationId, now); |
| | | saveStationTaskIdleTrack(idleTrack); |
| | | } |
| | | return idleTrack; |
| | | } |
| | | |
| | | private StationTaskIdleTrack getStationTaskIdleTrack(Integer taskNo) { |
| | | if (taskNo == null || taskNo <= 0) { |
| | | return null; |
| | | } |
| | | Object obj = redisUtil.get(RedisKeyType.STATION_TASK_IDLE_TRACK_.key + taskNo); |
| | | if (obj == null) { |
| | | return null; |
| | | } |
| | | try { |
| | | return JSON.parseObject(obj.toString(), StationTaskIdleTrack.class); |
| | | } catch (Exception e) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | private void saveStationTaskIdleTrack(StationTaskIdleTrack idleTrack) { |
| | | if (idleTrack == null || idleTrack.taskNo == null || idleTrack.taskNo <= 0) { |
| | | return; |
| | | } |
| | | redisUtil.set( |
| | | RedisKeyType.STATION_TASK_IDLE_TRACK_.key + idleTrack.taskNo, |
| | | JSON.toJSONString(idleTrack, SerializerFeature.DisableCircularReferenceDetect), |
| | | STATION_IDLE_TRACK_EXPIRE_SECONDS |
| | | ); |
| | | } |
| | | |
| | | public Integer getOutStationBatchSeq(List<NavigateNode> pathList, Integer searchStationId, String searchBatch) { |
| | |
| | | } |
| | | } |
| | | |
| | | private static class StationTaskIdleTrack { |
| | | private Integer taskNo; |
| | | private Integer stationId; |
| | | private Long firstSeenTime; |
| | | |
| | | private StationTaskIdleTrack() {} |
| | | |
| | | private StationTaskIdleTrack(Integer taskNo, Integer stationId, Long firstSeenTime) { |
| | | this.taskNo = taskNo; |
| | | this.stationId = stationId; |
| | | this.firstSeenTime = firstSeenTime; |
| | | } |
| | | |
| | | private boolean isTimeout(int seconds) { |
| | | if (firstSeenTime == null) { |
| | | return false; |
| | | } |
| | | return System.currentTimeMillis() - firstSeenTime >= seconds * 1000L; |
| | | } |
| | | |
| | | public Integer getTaskNo() { |
| | | return taskNo; |
| | | } |
| | | |
| | | public void setTaskNo(Integer taskNo) { |
| | | this.taskNo = taskNo; |
| | | } |
| | | |
| | | public Integer getStationId() { |
| | | return stationId; |
| | | } |
| | | |
| | | public void setStationId(Integer stationId) { |
| | | this.stationId = stationId; |
| | | } |
| | | |
| | | public Long getFirstSeenTime() { |
| | | return firstSeenTime; |
| | | } |
| | | |
| | | public void setFirstSeenTime(Long firstSeenTime) { |
| | | this.firstSeenTime = firstSeenTime; |
| | | } |
| | | } |
| | | |
| | | } |