#
Junjie
15 小时以前 aed8dfd97e8979b138cd858f35c15bec898542b3
src/main/java/com/zy/core/utils/CrnOperateProcessUtils.java
@@ -15,6 +15,7 @@
import com.zy.asrs.service.BasCrnpService;
import com.zy.asrs.service.BasStationService;
import com.zy.asrs.service.LocMastService;
import com.zy.asrs.service.WrkAnalysisService;
import com.zy.asrs.service.WrkMastService;
import com.zy.asrs.utils.NotifyUtils;
import com.zy.asrs.utils.Utils;
@@ -63,6 +64,10 @@
    private NotifyUtils notifyUtils;
    @Autowired
    private StationOperateProcessUtils stationOperateProcessUtils;
    @Autowired
    private WrkAnalysisService wrkAnalysisService;
    private static final String CRN_OUT_REQUIRE_STATION_OUT_ENABLE_CONFIG = "crnOutRequireStationOutEnable";
    public synchronized void crnIoExecute() {
        Object systemConfigMapObj = redisUtil.get(RedisKeyType.SYSTEM_CONFIG_MAP.key);
@@ -125,7 +130,7 @@
        List<WrkMast> taskQueue = wrkMastService.list(new QueryWrapper<WrkMast>()
                .in("crn_no", new ArrayList<>(dispatchCrnMap.keySet()))
                .in("wrk_sts",
                        WrkStsType.INBOUND_DEVICE_RUN.sts,
                        WrkStsType.INBOUND_STATION_RUN_COMPLETE.sts,
                        WrkStsType.NEW_OUTBOUND.sts,
                        WrkStsType.NEW_LOC_MOVE.sts));
        taskQueue.sort(Comparator
@@ -148,7 +153,7 @@
                continue;
            }
            if (wrkMast.getWrkSts() != null && wrkMast.getWrkSts() == WrkStsType.INBOUND_DEVICE_RUN.sts) {
            if (wrkMast.getWrkSts() != null && wrkMast.getWrkSts() == WrkStsType.INBOUND_STATION_RUN_COMPLETE.sts) {
                boolean result = this.crnExecuteInPlanner(basCrnp, crnThread, wrkMast);
                if (result) {
                    crnProtocol.setLastIo("O");
@@ -214,209 +219,6 @@
                && !Cools.isEmpty(wrkMast.getBatch());
    }
    private synchronized boolean crnExecuteIn(BasCrnp basCrnp, CrnThread crnThread) {
        CrnProtocol crnProtocol = crnThread.getStatus();
        if(crnProtocol == null){
            return false;
        }
        if(!basCrnp.getInEnable().equals("Y")){
            News.info("堆垛机:{} 可入信号不满足", basCrnp.getCrnNo());
            return false;
        }
        List<StationObjModel> inStationList = basCrnp.getInStationList$();
        if(inStationList.isEmpty()){
            News.info("堆垛机:{} 入库站点未设置", basCrnp.getCrnNo());
            return false;
        }
        Integer crnNo = basCrnp.getCrnNo();
        for (StationObjModel stationObjModel : inStationList) {
            StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, stationObjModel.getDeviceNo());
            if (stationThread == null) {
                continue;
            }
            Map<Integer, StationProtocol> stationProtocolMap = stationThread.getStatusMap();
            StationProtocol stationProtocol = stationProtocolMap.get(stationObjModel.getStationId());
            if (stationProtocol == null) {
                continue;
            }
            if (!stationProtocol.isAutoing()) {
                continue;
            }
            if (!stationProtocol.isLoading()) {
                continue;
            }
            if (stationProtocol.getTaskNo() <= 0) {
                continue;
            }
            if (!stationProtocol.isInEnable()) {
                News.taskInfo(stationProtocol.getTaskNo(), "取货站点:{} 没有可入信号", stationObjModel.getStationId());
                continue;
            }
            // 获取任务
            WrkMast wrkMast = wrkMastService.selectByWorkNo(stationProtocol.getTaskNo());
            if (null == wrkMast) {
                News.taskInfo(stationProtocol.getTaskNo(), "工作号:{} 任务信息不存在", stationProtocol.getTaskNo());
                continue;
            }
            if (!wrkMast.getCrnNo().equals(basCrnp.getCrnNo())) {
                continue;
            }
            if(wrkMast.getWrkSts() != WrkStsType.INBOUND_DEVICE_RUN.sts){
                continue;
            }
            // 获取库位信息
            LocMast locMast = locMastService.getById(wrkMast.getLocNo());
            if (locMast == null) {
                News.taskInfo(wrkMast.getWrkNo(), "目标库位:{} 信息不存在", wrkMast.getLocNo());
                continue;
            }
            if (!locMast.getLocSts().equals("S")) {
                News.taskInfo(wrkMast.getWrkNo(), "目标库位:{} 状态异常", wrkMast.getLocNo());
                continue;
            }
            //检测浅库位状态
            boolean checkStatus = checkShallowLocStatus(locMast.getLocNo(), wrkMast.getWrkNo());
            if (!checkStatus) {
                News.taskInfo(wrkMast.getWrkNo(), "因浅库位堵塞无法执行");
                continue;
            }
            String sourceLocNo = Utils.getLocNo(stationObjModel.getDeviceRow(), stationObjModel.getDeviceBay(), stationObjModel.getDeviceLev());
            CrnCommand command = crnThread.getPickAndPutCommand(sourceLocNo, wrkMast.getLocNo(), wrkMast.getWrkNo(), crnNo);
            wrkMast.setWrkSts(WrkStsType.INBOUND_RUN.sts);
            wrkMast.setCrnNo(crnNo);
            wrkMast.setSystemMsg("");
            wrkMast.setIoTime(new Date());
            if (wrkMastService.updateById(wrkMast)) {
                MessageQueue.offer(SlaveType.Crn, crnNo, new Task(2, command));
                notifyUtils.notify(String.valueOf(SlaveType.Crn), crnNo, String.valueOf(wrkMast.getWrkNo()), wrkMast.getWmsWrkNo(), NotifyMsgType.CRN_IN_TASK_RUN, null);
                News.info("堆垛机命令下发成功,堆垛机号={},任务数据={}", crnNo, JSON.toJSON(command));
                return true;
            }
        }
        return false;
    }
    private synchronized boolean crnExecuteOut(BasCrnp basCrnp, CrnThread crnThread) {
        CrnProtocol crnProtocol = crnThread.getStatus();
        if(crnProtocol == null){
            return false;
        }
        if(!basCrnp.getOutEnable().equals("Y")){
            News.info("堆垛机:{} 可出信号不满足", basCrnp.getCrnNo());
            return false;
        }
        List<StationObjModel> outStationList = basCrnp.getOutStationList$();
        if(outStationList.isEmpty()){
            News.info("堆垛机:{} 出库站点未设置", basCrnp.getCrnNo());
            return false;
        }
        if (isOutboundStationTaskLimitReached()) {
            return false;
        }
        Integer crnNo = basCrnp.getCrnNo();
        List<WrkMast> wrkMasts = wrkMastService.list(new QueryWrapper<WrkMast>()
                .eq("crn_no", crnNo)
                .eq("wrk_sts", WrkStsType.NEW_OUTBOUND.sts)
                .orderBy(true, true, "batch_seq")
        );
        for (WrkMast wrkMast : wrkMasts) {
            if (isOutboundTargetStationTaskLimitReached(wrkMast)) {
                continue;
            }
            if (!allowBatchOutboundExecute(wrkMast)) {
                continue;
            }
            for (StationObjModel stationObjModel : outStationList) {
                StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, stationObjModel.getDeviceNo());
                if (stationThread == null) {
                    continue;
                }
                Map<Integer, StationProtocol> stationProtocolMap = stationThread.getStatusMap();
                StationProtocol stationProtocol = stationProtocolMap.get(stationObjModel.getStationId());
                if (stationProtocol == null) {
                    continue;
                }
                if (!stationProtocol.isAutoing()) {
                    continue;
                }
                if (stationProtocol.isLoading()) {
                    continue;
                }
                if (stationProtocol.getTaskNo() != 0) {
                    continue;
                }
                if (!stationProtocol.isOutEnable()) {
                    News.info("放货站点:{} 没有可出信号", stationObjModel.getStationId());
                    continue;
                }
                // 获取库位信息
                LocMast locMast = locMastService.getById(wrkMast.getSourceLocNo());
                if (locMast == null) {
                    News.taskInfo(wrkMast.getWrkNo(), "源库位:{} 信息不存在", wrkMast.getSourceLocNo());
                    continue;
                }
                if (!locMast.getLocSts().equals("R")) {
                    News.taskInfo(wrkMast.getWrkNo(), "源库位:{} 状态异常", wrkMast.getSourceLocNo());
                    continue;
                }
                //检测浅库位状态
                boolean checkStatus = checkShallowLocStatus(locMast.getLocNo(), wrkMast.getWrkNo());
                if (!checkStatus) {
                    News.taskInfo(wrkMast.getWrkNo(), "因浅库位堵塞无法执行");
                    continue;
                }
                String targetLocNo = Utils.getLocNo(stationObjModel.getDeviceRow(), stationObjModel.getDeviceBay(), stationObjModel.getDeviceLev());
                CrnCommand command = crnThread.getPickAndPutCommand(wrkMast.getSourceLocNo(), targetLocNo, wrkMast.getWrkNo(), crnNo);
                wrkMast.setWrkSts(WrkStsType.OUTBOUND_RUN.sts);
                wrkMast.setCrnNo(crnNo);
                wrkMast.setSystemMsg("");
                wrkMast.setIoTime(new Date());
                if (wrkMastService.updateById(wrkMast)) {
                    MessageQueue.offer(SlaveType.Crn, crnNo, new Task(2, command));
                    notifyUtils.notify(String.valueOf(SlaveType.Crn), crnNo, String.valueOf(wrkMast.getWrkNo()), wrkMast.getWmsWrkNo(), NotifyMsgType.CRN_OUT_TASK_RUN, null);
                    News.info("堆垛机命令下发成功,堆垛机号={},任务数据={}", crnNo, JSON.toJSON(command));
                    return true;
                }
            }
        }
        return false;
    }
    private synchronized boolean crnExecuteInPlanner(BasCrnp basCrnp, CrnThread crnThread, WrkMast wrkMast) {
        CrnProtocol crnProtocol = crnThread.getStatus();
        if (crnProtocol == null) {
@@ -469,7 +271,7 @@
                continue;
            }
            if (wrkMast.getWrkSts() != WrkStsType.INBOUND_DEVICE_RUN.sts) {
            if (wrkMast.getWrkSts() != WrkStsType.INBOUND_STATION_RUN_COMPLETE.sts) {
                continue;
            }
@@ -496,11 +298,14 @@
            CrnCommand command = crnThread.getPickAndPutCommand(sourceLocNo, wrkMast.getLocNo(), wrkMast.getWrkNo(), crnNo);
            Date now = new Date();
            wrkMast.setWrkSts(WrkStsType.INBOUND_RUN.sts);
            wrkMast.setCrnNo(crnNo);
            wrkMast.setSystemMsg("");
            wrkMast.setIoTime(new Date());
            wrkMast.setIoTime(now);
            wrkMast.setModiTime(now);
            if (wrkMastService.updateById(wrkMast)) {
                wrkAnalysisService.markCraneStart(wrkMast, now);
                MessageQueue.offer(SlaveType.Crn, crnNo, new Task(2, command));
                notifyUtils.notify(String.valueOf(SlaveType.Crn), crnNo, String.valueOf(wrkMast.getWrkNo()), wrkMast.getWmsWrkNo(), NotifyMsgType.CRN_IN_TASK_RUN, null);
                News.info("堆垛机命令下发成功,堆垛机号={},任务数据={}", crnNo, JSON.toJSON(command));
@@ -565,8 +370,8 @@
                continue;
            }
            if (!stationProtocol.isOutEnable()) {
                News.info("放货站点:{} 没有可出信号", stationObjModel.getStationId());
            if (isRequireOutboundStationOutEnable() && !stationProtocol.isOutEnable()) {
                News.taskInfo(wrkMast.getWrkNo(), "放货站点:{} 没有可出信号", stationObjModel.getStationId());
                continue;
            }
@@ -593,11 +398,14 @@
            CrnCommand command = crnThread.getPickAndPutCommand(wrkMast.getSourceLocNo(), targetLocNo, wrkMast.getWrkNo(), crnNo);
            Date now = new Date();
            wrkMast.setWrkSts(WrkStsType.OUTBOUND_RUN.sts);
            wrkMast.setCrnNo(crnNo);
            wrkMast.setSystemMsg("");
            wrkMast.setIoTime(new Date());
            wrkMast.setIoTime(now);
            wrkMast.setModiTime(now);
            if (wrkMastService.updateById(wrkMast)) {
                wrkAnalysisService.markCraneStart(wrkMast, now);
                MessageQueue.offer(SlaveType.Crn, crnNo, new Task(2, command));
                notifyUtils.notify(String.valueOf(SlaveType.Crn), crnNo, String.valueOf(wrkMast.getWrkNo()), wrkMast.getWmsWrkNo(), NotifyMsgType.CRN_OUT_TASK_RUN, null);
                News.info("堆垛机命令下发成功,堆垛机号={},任务数据={}", crnNo, JSON.toJSON(command));
@@ -645,6 +453,24 @@
            return true;
        }
        List<WrkMast> unfinishedBatchWrkMasts = listUnfinishedBatchWrkMasts(wrkMast.getBatch());
        if (hasMissingBatchSeq(unfinishedBatchWrkMasts)) {
            News.taskInfo(wrkMast.getWrkNo(), "批次:{} 存在未配置批次序号的未完成任务,暂不允许堆垛机出库", wrkMast.getBatch());
            return false;
        }
        if (!isWithinBatchExecuteWindow(wrkMast, unfinishedBatchWrkMasts, batchRunningLimit)) {
            Integer windowStartSeq = unfinishedBatchWrkMasts.get(0).getBatchSeq();
            Integer windowEndSeq = unfinishedBatchWrkMasts.get(Math.min(batchRunningLimit, unfinishedBatchWrkMasts.size()) - 1).getBatchSeq();
            News.taskInfo(wrkMast.getWrkNo(),
                    "批次:{} 当前严格执行窗口序号为[{}-{}],当前序号={},暂不允许堆垛机出库",
                    wrkMast.getBatch(),
                    windowStartSeq,
                    windowEndSeq,
                    wrkMast.getBatchSeq());
            return false;
        }
        long batchRunningCount = wrkMastService.count(new QueryWrapper<WrkMast>()
                .eq("io_type", WrkIoType.OUT.id)
                .eq("batch", wrkMast.getBatch())
@@ -658,6 +484,46 @@
        }
        return true;
    }
    private List<WrkMast> listUnfinishedBatchWrkMasts(String batch) {
        if (Cools.isEmpty(batch)) {
            return new ArrayList<>();
        }
        return wrkMastService.list(new QueryWrapper<WrkMast>()
                .eq("io_type", WrkIoType.OUT.id)
                .eq("batch", batch)
                .notIn("wrk_sts",
                        WrkStsType.COMPLETE_OUTBOUND.sts,
                        WrkStsType.SETTLE_OUTBOUND.sts)
                .orderByAsc("batch_seq")
                .orderByAsc("wrk_no"));
    }
    private boolean hasMissingBatchSeq(List<WrkMast> wrkMasts) {
        if (wrkMasts == null || wrkMasts.isEmpty()) {
            return false;
        }
        for (WrkMast item : wrkMasts) {
            if (item == null || Cools.isEmpty(item.getBatchSeq())) {
                return true;
            }
        }
        return false;
    }
    private boolean isWithinBatchExecuteWindow(WrkMast wrkMast, List<WrkMast> unfinishedBatchWrkMasts, int batchRunningLimit) {
        if (wrkMast == null || unfinishedBatchWrkMasts == null || unfinishedBatchWrkMasts.isEmpty()) {
            return true;
        }
        int windowSize = Math.min(batchRunningLimit, unfinishedBatchWrkMasts.size());
        for (int i = 0; i < windowSize; i++) {
            WrkMast current = unfinishedBatchWrkMasts.get(i);
            if (current != null && wrkMast.getWrkNo().equals(current.getWrkNo())) {
                return true;
            }
        }
        return false;
    }
    private boolean isOutboundStationTaskLimitReached() {
@@ -707,58 +573,30 @@
        }
    }
    private synchronized boolean crnExecuteLocTransfer(BasCrnp basCrnp, CrnThread crnThread) {
        CrnProtocol crnProtocol = crnThread.getStatus();
        if(crnProtocol == null){
            return false;
    private boolean isRequireOutboundStationOutEnable() {
        return getSystemConfigBoolean(CRN_OUT_REQUIRE_STATION_OUT_ENABLE_CONFIG, true);
    }
    private boolean getSystemConfigBoolean(String code, boolean defaultValue) {
        Object systemConfigMapObj = redisUtil.get(RedisKeyType.SYSTEM_CONFIG_MAP.key);
        if (!(systemConfigMapObj instanceof Map)) {
            return defaultValue;
        }
        Integer crnNo = basCrnp.getCrnNo();
        List<WrkMast> wrkMasts = wrkMastService.list(new QueryWrapper<WrkMast>()
                .eq("crn_no", crnNo)
                .eq("wrk_sts", WrkStsType.NEW_LOC_MOVE.sts)
        );
        for (WrkMast wrkMast : wrkMasts) {
            // 获取源库位信息
            LocMast sourceLocMast = locMastService.getById(wrkMast.getSourceLocNo());
            if (sourceLocMast == null) {
                News.taskInfo(wrkMast.getWrkNo(), "源库位:{} 信息不存在", wrkMast.getSourceLocNo());
                continue;
        try {
            Object value = ((Map<?, ?>) systemConfigMapObj).get(code);
            if (value == null) {
                return defaultValue;
            }
            if(!sourceLocMast.getLocSts().equals("R")){
                News.taskInfo(wrkMast.getWrkNo(), "源库位:{} 状态异常,不属于出库预约状态", wrkMast.getSourceLocNo());
                continue;
            }
            // 获取库位信息
            LocMast locMast = locMastService.getById(wrkMast.getLocNo());
            if (locMast == null) {
                News.taskInfo(wrkMast.getWrkNo(), "库位:{} 信息不存在", wrkMast.getLocNo());
                continue;
            }
            if (!locMast.getLocSts().equals("S")) {
                News.taskInfo(wrkMast.getWrkNo(), "库位:{} 状态异常,不属于入库预约状态", wrkMast.getLocNo());
                continue;
            }
            CrnCommand command = crnThread.getPickAndPutCommand(wrkMast.getSourceLocNo(), wrkMast.getLocNo(), wrkMast.getWrkNo(), crnNo);
            wrkMast.setWrkSts(WrkStsType.LOC_MOVE_RUN.sts);
            wrkMast.setCrnNo(crnNo);
            wrkMast.setSystemMsg("");
            wrkMast.setIoTime(new Date());
            if (wrkMastService.updateById(wrkMast)) {
                MessageQueue.offer(SlaveType.Crn, crnNo, new Task(2, command));
                notifyUtils.notify(String.valueOf(SlaveType.Crn), crnNo, String.valueOf(wrkMast.getWrkNo()), wrkMast.getWmsWrkNo(), NotifyMsgType.CRN_TRANSFER_TASK_RUN, null);
                News.info("堆垛机命令下发成功,堆垛机号={},任务数据={}", crnNo, JSON.toJSON(command));
            String text = String.valueOf(value).trim();
            if ("Y".equalsIgnoreCase(text) || "true".equalsIgnoreCase(text) || "1".equals(text)) {
                return true;
            }
            if ("N".equalsIgnoreCase(text) || "false".equalsIgnoreCase(text) || "0".equals(text)) {
                return false;
            }
        } catch (Exception ignore) {
        }
        return false;
        return defaultValue;
    }
    //堆垛机任务执行完成
@@ -792,6 +630,7 @@
                }
                Long updateWrkSts = null;
                Date now = new Date();
                if(wrkMast.getWrkSts() == WrkStsType.INBOUND_RUN.sts){
                    updateWrkSts = WrkStsType.COMPLETE_INBOUND.sts;
                    notifyUtils.notify(String.valueOf(SlaveType.Crn), crnProtocol.getCrnNo(), String.valueOf(wrkMast.getWrkNo()), wrkMast.getWmsWrkNo(), NotifyMsgType.CRN_IN_TASK_COMPLETE, null);
@@ -823,8 +662,10 @@
                wrkMast.setWrkSts(updateWrkSts);
                wrkMast.setSystemMsg("");
                wrkMast.setIoTime(new Date());
                wrkMast.setIoTime(now);
                wrkMast.setModiTime(now);
                if (wrkMastService.updateById(wrkMast)) {
                    wrkAnalysisService.markCraneComplete(wrkMast, now, updateWrkSts);
                    CrnCommand resetCommand = crnThread.getResetCommand(crnProtocol.getTaskNo(), crnProtocol.getCrnNo());
                    MessageQueue.offer(SlaveType.Crn, crnProtocol.getCrnNo(), new Task(2, resetCommand));
                    News.info("堆垛机任务状态更新成功,堆垛机号={},工作号={}", basCrnp.getCrnNo(), crnProtocol.getTaskNo());
@@ -970,11 +811,14 @@
        CrnCommand command = crnThread.getPickAndPutCommand(wrkMast.getSourceLocNo(), wrkMast.getLocNo(), wrkMast.getWrkNo(), crnNo);
        Date now = new Date();
        wrkMast.setWrkSts(WrkStsType.LOC_MOVE_RUN.sts);
        wrkMast.setCrnNo(crnNo);
        wrkMast.setSystemMsg("");
        wrkMast.setIoTime(new Date());
        wrkMast.setIoTime(now);
        wrkMast.setModiTime(now);
        if (wrkMastService.updateById(wrkMast)) {
            wrkAnalysisService.markCraneStart(wrkMast, now);
            MessageQueue.offer(SlaveType.Crn, crnNo, new Task(2, command));
            notifyUtils.notify(String.valueOf(SlaveType.Crn), crnNo, String.valueOf(wrkMast.getWrkNo()), wrkMast.getWmsWrkNo(), NotifyMsgType.CRN_TRANSFER_TASK_RUN, null);
            News.info("堆垛机命令下发成功,堆垛机号={},任务数据={}", crnNo, JSON.toJSON(command));