| | |
| | | import com.zy.core.model.Task; |
| | | import com.zy.core.model.command.StationCommand; |
| | | import com.zy.core.model.protocol.StationProtocol; |
| | | import com.zy.core.service.StationTaskLoopService; |
| | | import com.zy.core.thread.StationThread; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | |
| | | private StationPathPolicyService stationPathPolicyService; |
| | | @Autowired |
| | | private BasStationOptService basStationOptService; |
| | | @Autowired |
| | | private StationTaskLoopService stationTaskLoopService; |
| | | |
| | | //执行输送站点入库任务 |
| | | public synchronized void stationInExecute() { |
| | |
| | | return countCurrentStationTask(); |
| | | } |
| | | |
| | | public synchronized int getCurrentOutboundTaskCountByTargetStation(Integer stationId) { |
| | | if (stationId == null) { |
| | | return 0; |
| | | } |
| | | return (int) wrkMastService.count(new QueryWrapper<WrkMast>() |
| | | .eq("io_type", WrkIoType.OUT.id) |
| | | .eq("sta_no", stationId) |
| | | .in("wrk_sts", |
| | | WrkStsType.OUTBOUND_RUN.sts, |
| | | WrkStsType.OUTBOUND_RUN_COMPLETE.sts, |
| | | WrkStsType.STATION_RUN.sts)); |
| | | } |
| | | |
| | | // 检测出库排序 |
| | | public synchronized void checkStationOutOrder() { |
| | | List<BasDevp> basDevps = basDevpService.list(new QueryWrapper<BasDevp>()); |
| | |
| | | if (!Objects.equals(dispatchStationId, wrkMast.getStaNo()) |
| | | && isCurrentOutOrderStation(currentStationId, outOrderStationIds) |
| | | && isWatchingCircleArrival(wrkMast.getWrkNo(), currentStationId)) { |
| | | return new OutOrderDispatchDecision(dispatchStationId, true); |
| | | return new OutOrderDispatchDecision(dispatchStationId, true, null, false); |
| | | } |
| | | return new OutOrderDispatchDecision(dispatchStationId, false); |
| | | } |
| | |
| | | if (hasReachableOutReleaseSlot(currentStationId, wrkMast.getStaNo())) { |
| | | return new OutOrderDispatchDecision(wrkMast.getStaNo(), false); |
| | | } |
| | | Integer circleTarget = resolveNextCircleOrderTarget(currentStationId, outOrderStationIds); |
| | | StationTaskLoopService.LoopEvaluation loopEvaluation = evaluateOutOrderLoop( |
| | | wrkMast.getWrkNo(), |
| | | currentStationId, |
| | | outOrderStationIds |
| | | ); |
| | | Integer circleTarget = resolveNextCircleOrderTarget( |
| | | currentStationId, |
| | | outOrderStationIds, |
| | | loopEvaluation.getExpectedLoopIssueCount() |
| | | ); |
| | | if (circleTarget == null) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "目标站当前不可进,且未找到可执行的下一排序检测点,当前站点={}", currentStationId); |
| | | return null; |
| | | } |
| | | return new OutOrderDispatchDecision(circleTarget, true); |
| | | return new OutOrderDispatchDecision(circleTarget, true, loopEvaluation, true); |
| | | } |
| | | |
| | | Integer circleTarget = resolveNextCircleOrderTarget(currentStationId, outOrderStationIds); |
| | | StationTaskLoopService.LoopEvaluation loopEvaluation = evaluateOutOrderLoop( |
| | | wrkMast.getWrkNo(), |
| | | currentStationId, |
| | | outOrderStationIds |
| | | ); |
| | | Integer circleTarget = resolveNextCircleOrderTarget( |
| | | currentStationId, |
| | | outOrderStationIds, |
| | | loopEvaluation.getExpectedLoopIssueCount() |
| | | ); |
| | | if (circleTarget == null) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "未找到可执行的下一排序检测点,当前站点={}", currentStationId); |
| | | return null; |
| | | } |
| | | return new OutOrderDispatchDecision(circleTarget, true); |
| | | return new OutOrderDispatchDecision(circleTarget, true, loopEvaluation, true); |
| | | } |
| | | |
| | | private boolean shouldApplyOutOrder(WrkMast wrkMast, List<Integer> outOrderStationIds) { |
| | |
| | | } |
| | | if (dispatchDecision.isCircle()) { |
| | | saveWatchCircleCommand(wrkMast.getWrkNo(), command); |
| | | if (dispatchDecision.shouldCountLoopIssue() |
| | | && stationTaskLoopService != null |
| | | && dispatchDecision.getLoopEvaluation() != null) { |
| | | stationTaskLoopService.recordLoopIssue(dispatchDecision.getLoopEvaluation(), "OUT_ORDER_CIRCLE"); |
| | | } |
| | | } else { |
| | | clearWatchCircleCommand(wrkMast.getWrkNo()); |
| | | } |
| | | } |
| | | |
| | | private StationTaskLoopService.LoopEvaluation evaluateOutOrderLoop(Integer taskNo, |
| | | Integer currentStationId, |
| | | List<Integer> outOrderStationIds) { |
| | | if (stationTaskLoopService == null) { |
| | | return new StationTaskLoopService.LoopEvaluation( |
| | | taskNo, |
| | | currentStationId, |
| | | StationTaskLoopService.LoopIdentitySnapshot.empty(), |
| | | 0, |
| | | 0, |
| | | false |
| | | ); |
| | | } |
| | | return stationTaskLoopService.evaluateLoop( |
| | | taskNo, |
| | | currentStationId, |
| | | true, |
| | | outOrderStationIds, |
| | | "outOrderCircle" |
| | | ); |
| | | } |
| | | |
| | | private Integer resolveDispatchOutOrderTarget(Integer sourceStationId, |
| | |
| | | || (stationProtocol.getTaskNo() != null && stationProtocol.getTaskNo() > 0); |
| | | } |
| | | |
| | | private Integer resolveNextCircleOrderTarget(Integer currentStationId, List<Integer> orderedOutStationList) { |
| | | private Integer resolveNextCircleOrderTarget(Integer currentStationId, |
| | | List<Integer> orderedOutStationList, |
| | | Integer expectedLoopIssueCount) { |
| | | if (currentStationId == null || orderedOutStationList == null || orderedOutStationList.size() <= 1) { |
| | | return null; |
| | | } |
| | | |
| | | int startIndex = orderedOutStationList.indexOf(currentStationId); |
| | | int total = orderedOutStationList.size(); |
| | | List<Integer> reachableStationIdList = new ArrayList<>(); |
| | | for (int offset = 1; offset < total; offset++) { |
| | | int candidateIndex = (startIndex + offset + total) % total; |
| | | Integer candidateStationId = orderedOutStationList.get(candidateIndex); |
| | |
| | | try { |
| | | List<NavigateNode> path = navigateUtils.calcByStationId(currentStationId, candidateStationId); |
| | | if (path != null && !path.isEmpty()) { |
| | | return candidateStationId; |
| | | reachableStationIdList.add(candidateStationId); |
| | | } |
| | | } catch (Exception ignore) {} |
| | | } |
| | | return null; |
| | | if (reachableStationIdList.isEmpty()) { |
| | | return null; |
| | | } |
| | | int gradualIndex = resolveGradualCircleTargetIndex(expectedLoopIssueCount, reachableStationIdList.size()); |
| | | return reachableStationIdList.get(gradualIndex); |
| | | } |
| | | |
| | | private int resolveGradualCircleTargetIndex(Integer expectedLoopIssueCount, int candidateCount) { |
| | | if (candidateCount <= 1) { |
| | | return 0; |
| | | } |
| | | if (expectedLoopIssueCount == null || expectedLoopIssueCount <= 2) { |
| | | return 0; |
| | | } |
| | | int gradualIndex = expectedLoopIssueCount - 2; |
| | | if (gradualIndex < 1) { |
| | | gradualIndex = 1; |
| | | } |
| | | return Math.min(gradualIndex, candidateCount - 1); |
| | | } |
| | | |
| | | private boolean tryAcquireOutOrderDispatchLock(Integer wrkNo, Integer stationId) { |
| | |
| | | private static class OutOrderDispatchDecision { |
| | | private final Integer targetStationId; |
| | | private final boolean circle; |
| | | private final StationTaskLoopService.LoopEvaluation loopEvaluation; |
| | | private final boolean countLoopIssue; |
| | | |
| | | private OutOrderDispatchDecision(Integer targetStationId, boolean circle) { |
| | | this(targetStationId, circle, null, false); |
| | | } |
| | | |
| | | private OutOrderDispatchDecision(Integer targetStationId, |
| | | boolean circle, |
| | | StationTaskLoopService.LoopEvaluation loopEvaluation, |
| | | boolean countLoopIssue) { |
| | | this.targetStationId = targetStationId; |
| | | this.circle = circle; |
| | | this.loopEvaluation = loopEvaluation; |
| | | this.countLoopIssue = countLoopIssue; |
| | | } |
| | | |
| | | private Integer getTargetStationId() { |
| | |
| | | private boolean isCircle() { |
| | | return circle; |
| | | } |
| | | |
| | | private StationTaskLoopService.LoopEvaluation getLoopEvaluation() { |
| | | return loopEvaluation; |
| | | } |
| | | |
| | | private boolean shouldCountLoopIssue() { |
| | | return countLoopIssue; |
| | | } |
| | | } |
| | | |
| | | private void saveLoopLoadReserve(Integer wrkNo, LoopHitResult loopHitResult) { |