1
TQS
2025-03-29 e5ac1f2efeeb6031d27129436344c7bd14419cfc
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java
@@ -7,10 +7,7 @@
import com.core.common.Cools;
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.mapper.BasCrnErrorMapper;
import com.zy.asrs.mapper.BasDevpMapper;
import com.zy.asrs.mapper.WrkChargeMapper;
import com.zy.asrs.mapper.WrkMastMapper;
import com.zy.asrs.mapper.*;
import com.zy.asrs.service.*;
import com.zy.asrs.utils.Utils;
import com.zy.common.model.LocTypeDto;
@@ -95,6 +92,8 @@
    private WrkChargeMapper wrkChargeMapper;
    @Autowired
    private BasDevpMapper basDevpMapper;
    @Autowired
    private WaitPakinMapper waitPakinMapper;
    /**
     * 组托
@@ -121,27 +120,45 @@
                        && !staProtocol.isEmptyMk() && (workNo == 0 || (workNo >= 9990 && workNo <= 9999))
                        && staProtocol.isPakMk()) {
                    //20230201. 2号堆垛机有出库任务时,禁止新板入库
                    if (staProtocol.getWorkNo() == 9995) {
                        if ( inSta.getStaNo()==103 && devpThread.ioModeOf1F == IoModeType.PAKOUT_MODE) {
                            //有出库任务,退库到入库口
                            staProtocol.setWorkNo((short) 9999);
                            staProtocol.setStaNo((short)100);
                            devpThread.setPakMk(staProtocol.getSiteId(), false);
                            boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                            News.error("MainServiceImpl  generateStoreWrkFile"+"103为出库模式,禁止入库,退回入库口。!!!");
                            continue;
                        }
                        if ( inSta.getStaNo()==203 && devpThread.ioModeOf2F == IoModeType.PAKOUT_MODE) {
                            //有出库任务,退库到入库口
                            staProtocol.setWorkNo((short) 9999);
                            staProtocol.setStaNo((short)200);
                            devpThread.setPakMk(staProtocol.getSiteId(), false);
                            boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                            News.error("MainServiceImpl  generateStoreWrkFile"+"203为出库模式,禁止入库,退回入库口。!!!");
                            continue;
                        }
                    }
//                    //20230201. 2号堆垛机有出库任务时,禁止新板入库
//                    if (staProtocol.getWorkNo() == 9995) {
//                        if ( inSta.getStaNo()==103 && devpThread.ioModeOf1F == IoModeType.PAKOUT_MODE) {
//                            //有出库任务,退库到入库口
//                            staProtocol.setWorkNo((short) 9999);
//                            staProtocol.setStaNo((short)100);
//                            devpThread.setPakMk(staProtocol.getSiteId(), false);
//                            boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                            News.error("MainServiceImpl  generateStoreWrkFile"+"103为出库模式,禁止入库,退回入库口。!!!");
//                            continue;
//                        }
//                        if ( inSta.getStaNo()==203 && devpThread.ioModeOf2F == IoModeType.PAKOUT_MODE) {
//                            //有出库任务,退库到入库口
//                            staProtocol.setWorkNo((short) 9999);
//                            staProtocol.setStaNo((short)200);
//                            devpThread.setPakMk(staProtocol.getSiteId(), false);
//                            boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                            News.error("MainServiceImpl  generateStoreWrkFile"+"203为出库模式,禁止入库,退回入库口。!!!");
//                            continue;
//                        }
//                        if ( inSta.getStaNo()==113 && devpThread.ioModeOf3F == IoModeType.PAKOUT_MODE) {
//                            //有出库任务,退库到入库口
//                            staProtocol.setWorkNo((short) 9999);
//                            staProtocol.setStaNo((short)114);
//                            devpThread.setPakMk(staProtocol.getSiteId(), false);
//                            boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                            News.error("MainServiceImpl  generateStoreWrkFile"+"103为出库模式,禁止入库,退回入库口。!!!");
//                            continue;
//                        }
//                        if ( inSta.getStaNo()==213 && devpThread.ioModeOf4F == IoModeType.PAKOUT_MODE) {
//                            //有出库任务,退库到入库口
//                            staProtocol.setWorkNo((short) 9999);
//                            staProtocol.setStaNo((short)214);
//                            devpThread.setPakMk(staProtocol.getSiteId(), false);
//                            boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                            News.error("MainServiceImpl  generateStoreWrkFile"+"203为出库模式,禁止入库,退回入库口。!!!");
//                            continue;
//                        }
//                    }
                    // 获取条码扫描仪信息
                    BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, inSta.getBarcode());
@@ -149,9 +166,9 @@
                        continue;
                    }
                    String barcode = barcodeThread.getBarcode();
                    if(!Cools.isEmpty(barcode)) {
                    if (!Cools.isEmpty(barcode)) {
//                        News.info("{}号条码扫描器检测条码信息:{}", inSta.getBarcode(), barcode);
                        if("NG".endsWith(barcode) || "NoRead".equals(barcode) || "empty".equals(barcode)) {
                        if ("NG".endsWith(barcode) || "NoRead".equals(barcode) || "empty".equals(barcode)) {
                            staProtocol.setWorkNo((short) 9995);
                            staProtocol.setStaNo(inSta.getBackSta().shortValue());
                            devpThread.setPakMk(staProtocol.getSiteId(), false);
@@ -213,7 +230,7 @@
                            // plc 处理
                            barcodeThread.setBarcode("");
                            staProtocol.setWorkNo(dto.getWorkNo().shortValue());
                            staProtocol.setStaNo(dto.getStaNo().shortValue());
                            staProtocol.setStaNo(Utils.getStaNoConvertCentreOther3(dto.getStaNo(), inSta.getStaNo()).shortValue());
                            devpThread.setPakMk(staProtocol.getSiteId(), false);
                            ledThread.errorReset();
@@ -222,15 +239,27 @@
                            if (!result) {
                                throw new CoolException("更新plc站点信息失败");
                            }
                        } else if (code == 500){
//                        } else if (code == 500){
//                            if (ledThread != null) {
//                                String errorMsg = jsonObject.getString("msg");
//                                if (!Cools.isEmpty(errorMsg)) {
//                                    MessageQueue.offer(SlaveType.Led, inSta.getLed(), new Task(3, errorMsg));
//                                }
//                            }
//                            News.error("请求接口失败!!!url:{};request:{};response:{}", wmsUrl + "/rpc/pakin/loc/v1", JSON.toJSONString(param), response);
                        }else if (code == 800) {
                            staProtocol.setWorkNo((short) 9995);
                            staProtocol.setStaNo(inSta.getBackSta().shortValue());
                            devpThread.setPakMk(staProtocol.getSiteId(), false);
                            MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                            // led 异常显示
                            if (ledThread != null) {
                                String errorMsg = jsonObject.getString("msg");
                                if (!Cools.isEmpty(errorMsg)) {
                                    MessageQueue.offer(SlaveType.Led, inSta.getLed(), new Task(3, errorMsg));
                                }
                                String errorMsg = barcode + "没有对应空库位";
                                MessageQueue.offer(SlaveType.Led, inSta.getLed(), new Task(3, errorMsg));
                            }
                            News.error("请求接口失败!!!url:{};request:{};response:{}", wmsUrl + "/rpc/pakin/loc/v1", JSON.toJSONString(param), response);
                        } else if (code == 700) {
                        }
                        else if (code == 700) {
                            staProtocol.setWorkNo((short) 9995);
                            staProtocol.setStaNo(inSta.getBackSta().shortValue());
                            devpThread.setPakMk(staProtocol.getSiteId(), false);
@@ -241,6 +270,40 @@
                                String errorMsg = barcode + "托盘识别异常,请先进行组托!";
                                MessageQueue.offer(SlaveType.Led, inSta.getLed(), new Task(3, errorMsg));
                            }
                        } else if (code == 500 || code == 1000) {
                            if (inSta.getStaNo().equals(103)) {
                                staProtocol.setWorkNo((short) 9996);
                                staProtocol.setStaNo((short) 203);
                            }
                            if (inSta.getStaNo().equals(203)) {
                                staProtocol.setWorkNo((short) 9996);
                                staProtocol.setStaNo((short) 103);
                            }
                            if (inSta.getStaNo().equals(113)) {
                                staProtocol.setWorkNo((short) 9995);
                                staProtocol.setStaNo((short) 114);
                            } else if (inSta.getStaNo().equals(213)) {
                                staProtocol.setWorkNo((short) 9995);
                                staProtocol.setStaNo((short) 214);
                            }
                            devpThread.setPakMk(staProtocol.getSiteId(), false);
                            MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                            String data = jsonObject.getString("data");
                            String msg = jsonObject.getString("msg");
                            if (code == 500) {
                                // led 异常显示
                                if (ledThread != null) {
                                    String errorMsg = "入库站:" + staProtocol.getStaNo() + "---" + barcode + "检索库位失败,请检查库存剩余。===>>" + data + "--" + msg;
                                    MessageQueue.offer(SlaveType.Led, inSta.getLed(), new Task(3, errorMsg));
                                }
                            } else if (code == 1000) {
                                // led 异常显示
                                if (ledThread != null) {
                                    String errorMsg = "入库站:" + staProtocol.getStaNo() + "---" + barcode + "需要换入库站。";
                                    MessageQueue.offer(SlaveType.Led, inSta.getLed(), new Task(3, errorMsg));
                                }
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
@@ -276,7 +339,9 @@
                        && staProtocol.isPakMk()) {
                    // 判断重复工作档
                    WrkMast wrkMast = wrkMastMapper.selectPakInStep11(inSta.getStaNo());
                    if (wrkMast == null) { continue; }
                    if (wrkMast == null) {
                        continue;
                    }
                    // 命令下发区 --------------------------------------------------------------------------
@@ -303,7 +368,7 @@
    /**
     * 拣料、并板、盘点再入库 【第1阶段】
     */
    public synchronized void stnToCrnStnPick0(){
    public synchronized void stnToCrnStnPick0() {
        for (DevpSlave devp : slaveProperties.getDevp()) {
            // 遍历拣料入库口
            for (DevpSlave.Sta pickSta : devp.getPickOutSta()) {
@@ -334,23 +399,21 @@
                        case 104:
                        case 108:
                            staNo = 103;
                            if (basDevps1.size()!=0 && basDevps2.size()!=0){
                            if (basDevps1.size() != 0 && basDevps2.size() != 0) {
                                continue;
                            } else if (basDevps1.size()!=0){
                                staNo = 203;
                            }
                            List<WrkMast> wrkMasts1 = wrkMastMapper.selectWrkStsAndIoType((int)staNo);
                            if (wrkMasts1.size()!=0){
                            List<WrkMast> wrkMasts1 = wrkMastMapper.selectWrkStsAndIoType((int) staNo);
                            if (wrkMasts1.size() != 0) {
                                boolean flag = false;
                                for (WrkMast wrkMast1:wrkMasts1){
                                    if (!wrkMast1.getWrkNo().equals(wrkMast.getWrkNo())){
                                for (WrkMast wrkMast1 : wrkMasts1) {
                                    if (!wrkMast1.getWrkNo().equals(wrkMast.getWrkNo())) {
                                        flag = true;
                                        break;
                                    }
                                }
                                if (flag)  {
                                    News.error("MainServiceImpl  324行"+"104站点存在货物,捡料盘点货物暂时不重新入库!!!");
                                if (flag) {
                                    News.error("MainServiceImpl  324行" + "104站点存在货物,捡料盘点货物暂时不重新入库!!!");
                                    continue;
                                }
                            }
@@ -358,26 +421,24 @@
                        case 204:
                        case 208:
                            staNo = 203;
                            if (basDevps1.size()!=0 && basDevps2.size()!=0){
                            if (basDevps1.size() != 0 && basDevps2.size() != 0) {
                                continue;
                            } else if (basDevps2.size()!=0){
                                staNo = 103;
                            }
//                            if (basDevps2.size()!=0){
//                                continue;
//                            }
                            List<WrkMast> wrkMasts2 = wrkMastMapper.selectWrkStsAndIoType((int)staNo);
                            if (wrkMasts2.size()!=0){
                            List<WrkMast> wrkMasts2 = wrkMastMapper.selectWrkStsAndIoType((int) staNo);
                            if (wrkMasts2.size() != 0) {
                                boolean flag = false;
                                for (WrkMast wrkMast1:wrkMasts2){
                                    if (!wrkMast1.getWrkNo().equals(wrkMast.getWrkNo())){
                                for (WrkMast wrkMast1 : wrkMasts2) {
                                    if (!wrkMast1.getWrkNo().equals(wrkMast.getWrkNo())) {
                                        flag = true;
                                        break;
                                    }
                                }
                                if (flag)  {
                                    News.error("MainServiceImpl  346行"+"204站点存在货物,捡料盘点货物暂时不重新入库!!!");
                                if (flag && devpThread.getStation().get(204).isLoading()) {
                                    News.error("MainServiceImpl  346行" + "204站点存在货物,捡料盘点货物暂时不重新入库!!!");
                                    continue;
                                }
                            }
@@ -391,9 +452,17 @@
                    staProtocol.setWorkNo(wrkMast.getWrkNo().shortValue());
                    staProtocol.setStaNo(staNo);
                    devpThread.setPakMk(staProtocol.getSiteId(), false);
                    if (staProtocol.getStaNo().equals(300)) {
                        BasDevp basDevp = basDevpMapper.selectByDevNo(300);
                        basDevp.setWrkNo1(wrkMast.getWrkNo());
                        basDevpService.selectById(basDevp);
                        News.info("300站去入库站任务下发,更新站点表,[任务号:{},站点号:{}]", wrkMast.getWrkNo().shortValue(), staNo);
                    }
                    boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                    if (!result) {
                        News.error("发布命令至输送线队列失败!!! [plc编号:{}]", devp.getId());
                    } else {
                        News.info("300站去入库站任务已下发,[任务号:{},站点号:{}]", wrkMast.getWrkNo().shortValue(), staNo);
                    }
                }
            }
@@ -404,7 +473,7 @@
     * 拣料、并板、盘点再入库【第2阶段】
     */
    @Transactional
    public synchronized void stnToCrnStnPick1(){
    public synchronized void stnToCrnStnPick1() {
        for (DevpSlave devp : slaveProperties.getDevp()) {
            // 遍历拣料入库口
            for (DevpSlave.Sta pickSta : devp.getPickInSta()) {
@@ -423,7 +492,7 @@
                        // 0 - 9990 或者 9996
                        && ((staProtocol.getWorkNo() > 0 && staProtocol.getWorkNo() < 9990) || staProtocol.getWorkNo() == 9996)
                        && staProtocol.getStaNo().equals(staProtocol.getSiteId().shortValue())
                        && staProtocol.isPakMk()){
                        && staProtocol.isPakMk()) {
                    // 获取条码扫描仪信息
                    BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, pickSta.getBarcode());
@@ -440,9 +509,9 @@
                    }
                    if (staProtocol.getWorkNo() == 9996) {
                        String barcode = barcodeThread.getBarcode();
                        if(!Cools.isEmpty(barcode)) {
                        if (!Cools.isEmpty(barcode)) {
                            News.info("{}号条码扫描器检测条码信息:{}", pickSta.getBarcode(), barcode);
                            if("NG".endsWith(barcode) || "NoRead".equals(barcode) || "empty".equals(barcode)) {
                            if ("NG".endsWith(barcode) || "NoRead".equals(barcode) || "empty".equals(barcode)) {
                                staProtocol.setWorkNo((short) 9995);
                                staProtocol.setStaNo(pickSta.getBackSta().shortValue());
                                devpThread.setPakMk(staProtocol.getSiteId(), false);
@@ -481,7 +550,7 @@
                        continue;
                    }
                    if ((wrkMast.getIoType() != 103 && wrkMast.getIoType() != 104 && wrkMast.getIoType() != 107)
                        || Cools.isEmpty(wrkMast.getStaNo()) || Cools.isEmpty(wrkMast.getSourceStaNo()) ) {
                            || Cools.isEmpty(wrkMast.getStaNo()) || Cools.isEmpty(wrkMast.getSourceStaNo())) {
                        continue;
                    }
@@ -500,7 +569,9 @@
                        } else {
                            errorMsg = "当前拣料任务请移动至103站";
                        }
                        if (ledThread != null) {MessageQueue.offer(SlaveType.Led, pickSta.getLed(), new Task(3, errorMsg));}
                        if (ledThread != null) {
                            MessageQueue.offer(SlaveType.Led, pickSta.getLed(), new Task(3, errorMsg));
                        }
                        News.error("入库路径不存在!type_no={},stn_no={},crn_no={}", wrkMast.getIoType(), pickSta.getStaNo(), wrkMast.getCrnNo());
                        continue;
                    }
@@ -563,13 +634,18 @@
                    // 条码设备处理
                    barcodeThread.setBarcode("");
                    if(wrkMast.getIoType()>100){
                    if (wrkMast.getIoType() > 100) {
                        throw new CoolException("再入库更新工作档失败,不能给PLC下发任务===>>" + wrkMast.getWrkNo());
                    }
                    // 更新站点信息 且 下发plc命令
                    staProtocol.setWorkNo(wrkMast.getWrkNo().shortValue());
                    staProtocol.setStaNo(wrkMast.getStaNo().shortValue());
                    devpThread.setPakMk(staProtocol.getSiteId(), false);
                    if (staProtocol.getStaNo().equals(300)) {
                        BasDevp basDevp = basDevpMapper.selectByDevNo(300);
                        basDevp.setWrkNo1(wrkMast.getWrkNo());
                        basDevpService.selectById(basDevp);
                    }
                    boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                    if (!result) {
                        News.error("发布命令至输送线队列失败!!! [plc编号:{}]", devp.getId());
@@ -758,13 +834,15 @@
//                        && staProtocol.isInEnable()
                        && staProtocol.getWorkNo() > 0
                        && staProtocol.getStaNo().equals(staProtocol.getSiteId().shortValue())
                        && staProtocol.isPakMk()){
                        && staProtocol.isPakMk()) {
                    WrkMast wrkMast = wrkMastMapper.selectById(staProtocol.getWorkNo());
                    if(Cools.isEmpty(wrkMast)){
                    if (Cools.isEmpty(wrkMast)) {
                        News.error("拣料/盘点转全板,任务号工作档不存在===>>[任务号:{}]", staProtocol.getWorkNo());
                        continue;
                    }
                    if (wrkMast.getIoType() != 101) { continue; }
                    if (wrkMast.getIoType() != 101) {
                        continue;
                    }
                    //拣料转全板默认出库站100站,当100站有物时,目标改200站
                    Integer staNo = 100;
@@ -819,6 +897,67 @@
                    // 查询工作档
                    WrkMast wrkMast = wrkMastMapper.selectPakOutStep16(staProtocol.getSiteId());
                    if (wrkMast == null) {
                        try {
                            if (crnSlave.getId() != 2) {
                                // 判断吊车是否实际已完成,且电脑状态在move中,以备电脑进行更新工作档
                                CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crnSlave.getId());
                                CrnProtocol crnProtocol = crnThread.getCrnProtocol();
                                if (crnProtocol.statusType == CrnStatusType.FETCHING || crnProtocol.statusType == CrnStatusType.PUTTING) {
                                    // 移动中
                                    continue;
                                }
                                WrkMast onlyWrkNo = wrkMastMapper.selectByOnlyWrkNo(crnProtocol.getTaskNo().intValue());
                                if (Cools.isEmpty(onlyWrkNo) && (crnStn.getStaNo() == 112 || crnStn.getStaNo() == 212)) {
                                    //  判断堆垛机状态等待确认
                                    if (crnProtocol.modeType == CrnModeType.AUTO
                                            && crnProtocol.statusType == CrnStatusType.WAITING
                                            && crnProtocol.forkPosType == CrnForkPosType.HOME
                                            && crnProtocol.getBay().equals(crnStn.getBay().shortValue()) && crnProtocol.getLevel().equals(crnStn.getLev().shortValue())) {
                                        News.info("堆垛机接驳任务完成,工作号:" + crnProtocol.getTaskNo() + ";执行堆垛机号:" + crnSlave.getId() + ";接驳放货位:" + crnStn.getStaNo() + ";接驳行走目标站:" + Utils.getStaNoConvertCentreOther2(crnStn.getStaNo()));
                                        // 下发站点信息
                                        News.error("new867===>" + crnProtocol.getTaskNo());
                                        News.error("new867===>" + Utils.getStaNoConvertCentreOther2(crnStn.getStaNo()).toString());
                                        staProtocol.setWorkNo(crnProtocol.getTaskNo());
                                        staProtocol.setStaNo(Utils.getStaNoConvertCentreOther2(crnStn.getStaNo()).shortValue());
                                        if (!MessageQueue.offer(SlaveType.Devp, crnStn.getDevpPlcId(), new Task(2, staProtocol))) {
                                            continue;
                                        }
                                        // 复位堆垛机
                                        crnThread.setResetFlag(true);
                                        continue;
                                    }
                                }
                                if (Cools.isEmpty(onlyWrkNo) ||
                                        ((onlyWrkNo.getStaNo() != 114 && onlyWrkNo.getStaNo() != 214 &&
                                                onlyWrkNo.getSourceStaNo() != 114 && onlyWrkNo.getSourceStaNo() != 214)
                                                &&
                                                (onlyWrkNo.getStaNo() != 113 && onlyWrkNo.getStaNo() != 213 &&
                                                        onlyWrkNo.getSourceStaNo() != 113 && onlyWrkNo.getSourceStaNo() != 213))
                                ) {
                                    continue;
                                }
                                //  判断堆垛机状态等待确认
                                if (crnProtocol.modeType == CrnModeType.AUTO
                                        && crnProtocol.statusType == CrnStatusType.WAITING
                                        && crnProtocol.forkPosType == CrnForkPosType.HOME
                                        && crnProtocol.getBay().equals(crnStn.getBay().shortValue()) && crnProtocol.getLevel().equals(crnStn.getLev().shortValue())) {
                                    News.info("堆垛机接驳任务完成,工作号:" + crnProtocol.getTaskNo() + ";执行堆垛机号:" + crnSlave.getId() + ";接驳放货位:" + crnStn.getStaNo() + ";接驳行走目标站:" + Utils.getStaNoConvertCentreOther2(crnStn.getStaNo()));
                                    // 下发站点信息
                                    News.error("new867===>" + crnProtocol.getTaskNo());
                                    News.error("new867===>" + Utils.getStaNoConvertCentreOther2(crnStn.getStaNo()).toString());
                                    staProtocol.setWorkNo(crnProtocol.getTaskNo());
                                    staProtocol.setStaNo(Utils.getStaNoConvertCentreOther2(crnStn.getStaNo()).shortValue());
                                    if (!MessageQueue.offer(SlaveType.Devp, crnStn.getDevpPlcId(), new Task(2, staProtocol))) {
                                        continue;
                                    }
                                    // 复位堆垛机
                                    crnThread.setResetFlag(true);
                                    continue;
                                }
                            }
                        } catch (Exception e) {
                            News.info("堆垛机接驳任务完成,异常:" + e.getMessage());
                        }
                        continue;
                    }
                    // 判断工作档条件
@@ -841,7 +980,9 @@
                        // 下发站点信息
                        staProtocol.setWorkNo(wrkMast.getWrkNo().shortValue());
                        staProtocol.setStaNo(wrkMast.getStaNo().shortValue());
                        News.error("new902===>" + crnProtocol.getCrnNo().toString());
                        News.error("new902===>" + wrkMast.getStaNoConvert(crnProtocol.getCrnNo()).toString());
                        staProtocol.setStaNo(wrkMast.getStaNoConvert(crnProtocol.getCrnNo()).shortValue());
                        if (!MessageQueue.offer(SlaveType.Devp, crnStn.getDevpPlcId(), new Task(2, staProtocol))) {
                            continue;
                        }
@@ -868,12 +1009,14 @@
    /**
     * 入出库  ===>>  堆垛机入出库作业下发
     */
    public synchronized void crnIoExecute(){
    public synchronized void crnIoExecute() {
        for (CrnSlave crn : slaveProperties.getCrn()) {
            // 获取堆垛机信息
            CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crn.getId());
            CrnProtocol crnProtocol = crnThread.getCrnProtocol();
            if (crnProtocol == null) { continue; }
            if (crnProtocol == null) {
                continue;
            }
            BasCrnp basCrnp = basCrnpService.selectById(crn.getId());
            if (basCrnp == null) {
                News.error("{}号堆垛机尚未在数据库进行维护!", crn.getId());
@@ -924,7 +1067,7 @@
    /**
     * 入库  ===>>  堆垛机站到库位
     */
    public synchronized boolean crnStnToLoc(CrnSlave slave, CrnProtocol crnProtocol){
    public synchronized boolean crnStnToLoc(CrnSlave slave, CrnProtocol crnProtocol) {
        for (CrnSlave.CrnStn crnStn : slave.getCrnInStn()) {
            boolean flag = false;
            // 获取堆垛机入库站信息
@@ -944,25 +1087,106 @@
            // 获取工作状态为 2,3,4,5,6 的入库工作档
            WrkMast wrkMast = wrkMastMapper.selectPakInStep23456(slave.getId(), staProtocol.getWorkNo().intValue(), crnStn.getStaNo());
            if(null == wrkMast) {
//                News.error("{}站点查询无待入库数据 工作号={}", crnStn.getStaNo(), staProtocol.getWorkNo());
            if (null == wrkMast) {
                try {
                    WrkMast onlyWrkNo = wrkMastMapper.selectByOnlyWrkNo(staProtocol.getWorkNo().intValue());
                    if (!Cools.isEmpty(onlyWrkNo) && onlyWrkNo.getCrnNo() == 2 && onlyWrkNo.getWrkSts() == 2 && crnProtocol.getCrnNo() != 2 && (onlyWrkNo.getIoType() == 1 || onlyWrkNo.getIoType() == 10)) {
                        //                News.error("{}站点查询无待入库数据 工作号={}", crnStn.getStaNo(), staProtocol.getWorkNo());
                        // 已经存在吊车执行任务时,则过滤
                        if (wrkMastMapper.selectWorking(slave.getId()) != null) {
                            continue;
                        }
                        if (Cools.isEmpty(staProtocol.getWorkNo()) || !staProtocol.isLoading()) {
                            continue;
                        }
                        //  判断堆垛机状态等待确认
                        if (crnProtocol.modeType == CrnModeType.AUTO
                                && crnProtocol.statusType == CrnStatusType.IDLE
                                && crnProtocol.forkPosType == CrnForkPosType.HOME && crnStn.getBay() != (short) 4) {
                            News.info("堆垛机接驳任务执行,工作号:" + staProtocol.getWorkNo() + ";执行堆垛机号:" + slave.getId() + ";接驳取货位:" + crnStn.getStaNo() + ";接驳放货位:" + staProtocol.getSiteId());
                            // 堆垛机接驳任务命令下发区 --------------------------------------------------------------------------
                            CrnCommand crnCommand = new CrnCommand();
                            crnCommand.setCrnNo(slave.getId()); // 堆垛机编号
                            crnCommand.setTaskNo(onlyWrkNo.getWrkNo().shortValue()); // 工作号
                            crnCommand.setAckFinish((short) 0);  // 任务完成确认位
                            crnCommand.setCommand((short) 0);
                            crnCommand.setTaskMode(CrnTaskModeType.LOC_MOVE); // 任务模式:  库位移转
                            crnCommand.setSourcePosX(crnStn.getRow().shortValue());     // 源库位排
                            crnCommand.setSourcePosY(crnStn.getBay().shortValue());     // 源库位列
                            crnCommand.setSourcePosZ(crnStn.getLev().shortValue());     // 源库位层
                            crnCommand.setDestinationPosX(Utils.getRow(staProtocol.getSiteId()));     // 目标库位排
                            crnCommand.setDestinationPosY(Utils.getBay(staProtocol.getSiteId()));     // 目标库位列
                            crnCommand.setDestinationPosZ(Utils.getLev(staProtocol.getSiteId()));     // 目标库位层
                            if (!MessageQueue.offer(SlaveType.Crn, slave.getId(), new Task(2, crnCommand))) {
                                News.error("堆垛机命令下发失败,堆垛机号={},任务数据={}", slave.getId(), JSON.toJSONString(crnCommand));
                            }
                            return true;
                        }
                    } else if (!Cools.isEmpty(onlyWrkNo) && onlyWrkNo.getCrnNo() == 2 && onlyWrkNo.getWrkSts() > 16 && crnProtocol.getCrnNo() != 2 && onlyWrkNo.getIoType() > 100) {
                        //                News.error("{}站点查询无待入库数据 工作号={}", crnStn.getStaNo(), staProtocol.getWorkNo());
                        // 已经存在吊车执行任务时,则过滤
                        if (wrkMastMapper.selectWorking(slave.getId()) != null) {
                            continue;
                        }
                        if (Cools.isEmpty(staProtocol.getWorkNo()) || !staProtocol.isLoading()) {
                            continue;
                        }
                        //  判断堆垛机状态等待确认
                        if (crnProtocol.modeType == CrnModeType.AUTO
                                && crnProtocol.statusType == CrnStatusType.IDLE
                                && crnProtocol.forkPosType == CrnForkPosType.HOME && crnStn.getBay() == (short) 4) {
                            News.info("堆垛机接驳任务执行,工作号:" + staProtocol.getWorkNo() + ";执行堆垛机号:" + slave.getId() + ";接驳取货位:" + crnStn.getStaNo() + ";接驳放货位:" + staProtocol.getSiteId());
                            // 堆垛机接驳任务命令下发区 --------------------------------------------------------------------------
                            CrnCommand crnCommand = new CrnCommand();
                            crnCommand.setCrnNo(slave.getId()); // 堆垛机编号
                            crnCommand.setTaskNo(onlyWrkNo.getWrkNo().shortValue()); // 工作号
                            crnCommand.setAckFinish((short) 0);  // 任务完成确认位
                            crnCommand.setCommand((short) 0);
                            crnCommand.setTaskMode(CrnTaskModeType.LOC_MOVE); // 任务模式:  库位移转
                            crnCommand.setSourcePosX(crnStn.getRow().shortValue());     // 源库位排
                            crnCommand.setSourcePosY(crnStn.getBay().shortValue());     // 源库位列
                            crnCommand.setSourcePosZ(crnStn.getLev().shortValue());     // 源库位层
                            crnCommand.setDestinationPosX(Utils.getRow(staProtocol.getSiteId()));     // 目标库位排
                            crnCommand.setDestinationPosY(Utils.getBay(staProtocol.getSiteId()));     // 目标库位列
                            crnCommand.setDestinationPosZ(Utils.getLev(staProtocol.getSiteId()));     // 目标库位层
                            if (!MessageQueue.offer(SlaveType.Crn, slave.getId(), new Task(2, crnCommand))) {
                                News.error("堆垛机命令下发失败,堆垛机号={},任务数据={}", slave.getId(), JSON.toJSONString(crnCommand));
                            }
                            return true;
                        }
                    }
                    continue;
                } catch (Exception e) {
                    News.info("堆垛机接驳任务执行,异常:" + e.getMessage());
                }
                continue;
            }
            // 入库深库位是否有非F、D、X库位进行校验
            if (wrkMastMapper.selectShallowLoc(Integer.parseInt(wrkMast.getLocNo().substring(0, 2)),Integer.parseInt(wrkMast.getLocNo().substring(2, 5)),Integer.parseInt(wrkMast.getLocNo().substring(5, 7)))!=null){
                continue;
            // 入库深库位是否有非F、D、X库位进行校验 ( Q、P、R、S)
            if (wrkMastMapper.selectShallowLoc(Integer.parseInt(wrkMast.getLocNo().substring(0, 2)), Integer.parseInt(wrkMast.getLocNo().substring(2, 5)), Integer.parseInt(wrkMast.getLocNo().substring(5, 7))) != null) {
                //检查入库库位是否是在堆垛机边库位
                ArrayList<Integer> outLoc = new ArrayList<>();
                outLoc.add(3);
                outLoc.add(4);
                outLoc.add(11);
                outLoc.add(12);
                outLoc.add(18);
                outLoc.add(19);
                if (!outLoc.contains(Integer.parseInt(wrkMast.getLocNo().substring(0, 2)))) {
                    continue;
                }
            }
            //加强判断,只要存在移库任务,说明出库任务未完全结束,不执行入库任务
            WrkMast one = wrkMastMapper.selectLocMoveData(slave.getId());
            if(!Cools.isEmpty(one)){
            if (!Cools.isEmpty(one)) {
                News.error("入库 ===>> 存在移库未完成任务,不能入库。移库任务号={},堆垛机号={}", one.getWrkNo(), slave.getId());
//                continue;
            }
            //入库库位不是最外层库位,判断最外层库位是否为空库位,如不是则进行移库任务
            if(!locMastService.isOutMost(wrkMast.getLocNo())) {
            if (!locMastService.isOutMost(wrkMast.getLocNo())) {
                WrkMast wrkMastMove = wrkMastMapper.selectLocMoveWorking(slave.getId());
                if (wrkMastMove != null && wrkMast.getWrkNo() == 111) {
                    continue;
@@ -1022,24 +1246,25 @@
                    }
                }
            }
            if(flag){
                return false;
            if (flag) {
                continue;
//                return false;
            }
            // 判断是否已存在小车绑定任务
            BasSte basSte = basSteService.findByCrnNo(wrkMast.getCrnNo());
            if(basSte == null) continue;
            if (basSte == null) continue;
            WrkMast one1 = wrkMastService.selectOne(new EntityWrapper<WrkMast>()
                    .eq("ste_no",basSte.getSteNo())
                    .eq("ste_no", basSte.getSteNo())
                    .last(" and wrk_sts > 10"));
            if(one1 != null){
            if (one1 != null) {
                News.error("{}入库任务无法作业,因出库任务已绑定小车!", wrkMast.getWrkNo());
                continue;
            }
            if (wrkMast.getWrkSts() < 3) {
                if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.getWorkNo() > 0 && staProtocol.isInEnable()
                        && staDetl.getCanining()!=null && staDetl.getCanining().equals("Y")) {
                        && staDetl.getCanining() != null && staDetl.getCanining().equals("Y")) {
                    flag = true;
                }
                if (!flag) {
@@ -1096,7 +1321,7 @@
                    if (wrkMast.getWrkSts() == 3L) {
                        this.carMoveOut(wrkMast, steNo, crnProtocol);
                    }
                // 没有小车
                    // 没有小车
                } else {
                    // 当前入库库位组没有小车 堆垛机则去站点取货入库
@@ -1139,7 +1364,7 @@
                }
            // 目标库位 ===>> 非最外层库位
                // 目标库位 ===>> 非最外层库位
            } else {
                // 判断小车是否在当前组库位,如果是则将穿梭车移至最外层,等待堆垛机放货;如果不是,则堆垛机寻找穿梭车,并放置当前组最外层
                Integer steNo = this.hasCarOfIdle(wrkMast.getLocNo());
@@ -1157,7 +1382,10 @@
                        // 小车处于空闲
                        SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, steNo);
                        SteProtocol steProtocol = steThread.getSteProtocol();
                        if (steProtocol == null) { continue; }
                        if (steProtocol == null) {
                            continue;
                        }
                        if (steProtocol.loca == 0) continue;
                        if (steProtocol.isIdle()) {
                            // 已经存在吊车执行任务时,则过滤
@@ -1192,7 +1420,7 @@
                            }
                        }
                    }
                // 没有小车
                    // 没有小车
                } else {
                    if (wrkMast.getWrkSts() == 2L && (wrkMast.getSteNo() == null || wrkMast.getSteNo() == 0)) {
                        // 寻找当前堆垛机对应的小车
@@ -1207,8 +1435,8 @@
                    }
                    // 堆垛机搬运小车
                    if (wrkMast.getWrkSts() == 3L) {
                        if (Cools.isEmpty(wrkMast.getSteNo()) || wrkMast.getSteNo()==0){
                            News.error("工作号={}即将开始搬运小车但是工作档没有小车号",wrkMast.getWrkNo());
                        if (Cools.isEmpty(wrkMast.getSteNo()) || wrkMast.getSteNo() == 0) {
                            News.error("工作号={}即将开始搬运小车但是工作档没有小车号", wrkMast.getWrkNo());
                            return false;
                        }
                        this.carMoveIn(wrkMast, wrkMast.getSteNo(), crnProtocol);
@@ -1223,13 +1451,24 @@
    /**
     * 出库  ===>>  库位到堆垛机站
     */
    public synchronized boolean locToCrnStn(CrnSlave slave, CrnProtocol crnProtocol){
    public synchronized boolean locToCrnStn(CrnSlave slave, CrnProtocol crnProtocol) {
        Collections.shuffle(slave.getCrnOutStn());
        for (CrnSlave.CrnStn crnStn : slave.getCrnOutStn()) {
            // 获取工作状态为11(生成出库ID)的出库工作档
            // 获取工作状态为11,12,13,14,15, 16(生成出库ID)的出库工作档
            WrkMast wrkMast = wrkMastMapper.selectPakOutStep111215(slave.getId(), crnStn.getStaNo());
            if (wrkMast == null) {
                continue;
            }
            /*
             * 100、200存在进行中的盘点任务,则不执行盘点任务
             * */
            if (wrkMast.getIoType().equals(107)) {
                Integer countPan = wrkMastMapper.selectWrkStsAndIoType107Count(wrkMast.getSourceStaNo(), wrkMast.getWrkNo());
                if (countPan > 0) {
                    News.error("MainServiceImpl  locToCrnStn 1271行" + "盘点出库跳过,存在进行中可能堵塞任务数{}个", countPan);
                    continue;
                }
            }
            // 获取堆垛机出库站信息
@@ -1241,41 +1480,49 @@
                staProtocol = staProtocol.clone();
            }
            if (wrkMast.getCrnNo().equals(2)){
            if (wrkMast.getCrnNo().equals(2)) {
                if (wrkMast.getStaNo() == 103 && devpThread.ioModeOf1F != IoModeType.PAKOUT_MODE) {
                    News.error("MainServiceImpl  locToCrnStn"+"103非出库模式,禁止出库。任务号:{}!!!",wrkMast.getWrkNo());
                    News.error("MainServiceImpl  locToCrnStn" + "103非出库模式,禁止出库。任务号:{}!!!", wrkMast.getWrkNo());
                    return false;
                }
                if (wrkMast.getStaNo() == 203 && devpThread.ioModeOf2F != IoModeType.PAKOUT_MODE) {
                    News.error("MainServiceImpl  locToCrnStn"+"203非出库模式,禁止出库。任务号:{}!!!",wrkMast.getWrkNo());
                    News.error("MainServiceImpl  locToCrnStn" + "203非出库模式,禁止出库。任务号:{}!!!", wrkMast.getWrkNo());
                    return false;
                }
                if (wrkMast.getStaNo() == 113 && devpThread.ioModeOf3F != IoModeType.PAKOUT_MODE) {
                    News.error("MainServiceImpl  locToCrnStn" + "113非出库模式,禁止出库。任务号:{}!!!", wrkMast.getWrkNo());
                    return false;
                }
                if (wrkMast.getStaNo() == 213 && devpThread.ioModeOf4F != IoModeType.PAKOUT_MODE) {
                    News.error("MainServiceImpl  locToCrnStn" + "213非出库模式,禁止出库。任务号:{}!!!", wrkMast.getWrkNo());
                    return false;
                }
                if (wrkMast.getWrkSts() == 11 && (wrkMast.getIoType() == 103 || wrkMast.getIoType() == 107)){
                if (wrkMast.getWrkSts() == 11 && (wrkMast.getIoType() == 103 || wrkMast.getIoType() == 107)) {
                    Integer sour = wrkMast.getSourceStaNo();
                    List<WrkMast> wrkMasts = wrkMastMapper.selectWrkStsAndIoType0(sour);
                    if (wrkMasts.size() > 0){
                        News.error("MainServiceImpl  1028行"+"存在捡料、盘点未入库货物,2号堆垛机暂时禁止出库!!!");
                    if (wrkMasts.size() > 0) {
                        News.error("MainServiceImpl  1300行" + "存在捡料、盘点未入库货物,2号堆垛机暂时禁止出库!!!");
                        return false;
                    }
                    //如果存在目标站300且正在执行的拣料/盘点任务,则2号堆垛机不允许做拣料/盘点出库
                    WrkMast one = wrkMastService.selectOne(new EntityWrapper<WrkMast>()
                            .eq("sta_no",300)
                            .eq("sta_no", 300)
                            .last(" and wrk_sts>11 and io_type in (103,107) "));
                    if(!Cools.isEmpty(one)){
                        News.error("MainServiceImpl  1099行"+"存在捡料、盘点未入库货物,2号堆垛机暂时禁止出库!!!");
                    if (!Cools.isEmpty(one)) {
                        News.error("MainServiceImpl  1309行" + "存在捡料、盘点未入库货物,2号堆垛机暂时禁止出库!!!");
                        continue;
                    }
                }
                if (wrkMast.getWrkSts() == 11 && wrkMast.getIoType() == 101){
                if (wrkMast.getWrkSts() == 11 && wrkMast.getIoType() == 101) {
                    Integer sour = wrkMast.getSourceStaNo();
                    List<WrkMast> wrkMasts = wrkMastMapper.selectWrkStsAndIoType1(sour);
                    if (wrkMasts.size() > 0){
                        for (WrkMast one : wrkMasts){
                            if(one.getWrkNo().equals(wrkMast.getWrkNo())){
                                News.error("MainServiceImpl  1028行"+"204存在全板出库中货物,2号堆垛机暂时禁止全板出库!!!");
                    if (wrkMasts.size() > 0) {
                        for (WrkMast one : wrkMasts) {
                            if (one.getWrkNo().equals(wrkMast.getWrkNo())) {
                                News.error("MainServiceImpl  1028行" + "204存在全板出库中货物,2号堆垛机暂时禁止全板出库!!!");
                                return false;
                            }
                        }
@@ -1285,35 +1532,35 @@
            // 判断是否已存在小车绑定任务
            BasSte basSte = basSteService.findByCrnNo(wrkMast.getCrnNo());
            if(basSte == null) continue;
            if (basSte == null) continue;
            WrkMast one1 = wrkMastService.selectOne(new EntityWrapper<WrkMast>()
                    .eq("ste_no",basSte.getSteNo())
                    .eq("ste_no", basSte.getSteNo())
                    .last(" and wrk_sts < 10"));
            if(one1 != null){
            if (one1 != null) {
                News.error("{}出库任务无法作业,因入库任务已绑定小车!", wrkMast.getWrkNo());
                return false;
            }
            //加强判断,确保因出库导致的移库整套任务全部结束后,才能执行下一笔出库任务。只有库位完成移库回去全部任务后,才认为当组出库任务完成
            WrkMast one = wrkMastMapper.selectLocMoveData(slave.getId());
            if(!Cools.isEmpty(one)){
            if (!Cools.isEmpty(one)) {
                //存在移库任务,且在移出中,且移库源库位与待出库库位不在同一库位组,时跳出,确保移库/出库全套任务完成后,再执行下一笔
                if(one.getWrkSts() > 10 && (Utils.getGroupRow(wrkMast.getSourceLocNo()) != Utils.getGroupRow(one.getSourceLocNo())
                if (one.getWrkSts() > 10 && (Utils.getGroupRow(wrkMast.getSourceLocNo()) != Utils.getGroupRow(one.getSourceLocNo())
                        || Utils.getBay(wrkMast.getSourceLocNo()) != Utils.getBay(one.getSourceLocNo())
                        || Utils.getLev(wrkMast.getSourceLocNo()) != Utils.getLev(one.getSourceLocNo()))){
                        || Utils.getLev(wrkMast.getSourceLocNo()) != Utils.getLev(one.getSourceLocNo()))) {
                    continue;
                }
                //存在移库任务,且在移回中,且移库目标库位与待出库库位不在同一库位组,时跳出,确保移库/出库全套任务完成后,再执行下一笔
                if(one.getWrkSts() < 11  && (Utils.getGroupRow(wrkMast.getSourceLocNo()) != Utils.getGroupRow(one.getLocNo())
                if (one.getWrkSts() < 11 && (Utils.getGroupRow(wrkMast.getSourceLocNo()) != Utils.getGroupRow(one.getLocNo())
                        || Utils.getBay(wrkMast.getSourceLocNo()) != Utils.getBay(one.getLocNo())
                        || Utils.getLev(wrkMast.getSourceLocNo()) != Utils.getLev(one.getLocNo()))){
                        || Utils.getLev(wrkMast.getSourceLocNo()) != Utils.getLev(one.getLocNo()))) {
                    continue;
                }
            }
            //出库库位不是最外层库位,判断最外层库位是否为空库位,如不是则进行移库任务
            boolean flag = false;
            if(!locMastService.isOutMost(wrkMast.getSourceLocNo())) {
            if (!locMastService.isOutMost(wrkMast.getSourceLocNo())) {
                WrkMast wrkMastMove = wrkMastMapper.selectLocMoveWorking(slave.getId());
                if (wrkMastMove != null && wrkMast.getWrkNo() == 111) {
                    continue;
@@ -1325,39 +1572,40 @@
                } else {
                    List<String> shallowLocs = Utils.getShallowLocs(wrkMast.getSourceLocNo());
                    if (!Cools.isEmpty(shallowLocs)) {
                        // 浅库位组有货
                        for (String shallowLocNo : shallowLocs) {
                            LocMast shallowLoc = locMastService.selectById(shallowLocNo);
                            WrkMast waitWrkMast = wrkMastMapper.selectByLocNo(shallowLocNo);
                            // 浅库位在作业中
                            if (shallowLoc.getLocSts().equals("P") || shallowLoc.getLocSts().equals("R")) {
                                if (Cools.isEmpty(waitWrkMast)){
                                if (Cools.isEmpty(waitWrkMast)) {
                                    News.error("库位异常");
                                }else {
                                    if (waitWrkMast.getIoType() != 11 || waitWrkMast.getWrkSts() != 17){
                                        if(waitWrkMast.getIoPri()<=9980.0){
                                            waitWrkMast.setIoPri(waitWrkMast.getIoPri()+10.0);
                                        }else {
                                } else {
                                    if (waitWrkMast.getIoType() != 11 || waitWrkMast.getWrkSts() != 17) {
                                        if (waitWrkMast.getIoPri() <= 9980.0) {
                                            waitWrkMast.setIoPri(waitWrkMast.getIoPri() + 10.0);
                                        } else {
                                            waitWrkMast.setIoPri(9999d);
                                        }
                                        if(wrkMast.getIoPri()>=9000.0){
                                            wrkMast.setIoPri(9999d);
                                        }else if (wrkMast.getIoPri()>20.0){
                                            wrkMast.setIoPri(wrkMast.getIoPri()-10.0);
                                        }else {
                                            wrkMast.setIoPri(13.0d);
                                        }
                                        if (wrkMastMapper.updateById(wrkMast)==0){
//                                        if (wrkMast.getIoPri()>23.0){
//                                            wrkMast.setIoPri(wrkMast.getIoPri()-10.0);
//                                        }else {
                                        wrkMast.setIoPri(15.0d);
//                                        }
                                        if (wrkMastMapper.updateById(wrkMast) == 0) {
                                            News.error("调整优先级失败");
                                        }
                                        if (wrkMastMapper.updateById(waitWrkMast)==0){
                                        if (wrkMastMapper.updateById(waitWrkMast) == 0) {
                                            News.error("调整优先级失败");
                                        }else if (waitWrkMast.getWrkSts() != 17){
                                        } else if (waitWrkMast.getWrkSts() != 17) {
                                            flag = true;
                                        }
                                        break;
                                    }
                                }
                            }else if (shallowLoc.getLocSts().equals("F") || shallowLoc.getLocSts().equals("D")) {
                                // 浅库位组有货,且没有在作业中
                            } else if (shallowLoc.getLocSts().equals("F") || shallowLoc.getLocSts().equals("D")) {
                                if (null == waitWrkMast) {
                                    // 生成一笔移库任务工作档、改变浅库位的源库/目标库 库位状态
                                    // 没有作业中的出库任务时,才能生成移库任务
@@ -1398,18 +1646,18 @@
                    }
                }
            }
            if(flag){
            if (flag) {
                return false;
            }
            // 工作档状态判断
            if (wrkMast.getIoType() < 100 || wrkMast.getSourceStaNo() == null){
            if (wrkMast.getIoType() < 100 || wrkMast.getSourceStaNo() == null) {
                News.error("查询工作档数据不符合条件--入出类型/站点, 工作号={},源库位={},入出类型={}", wrkMast.getWrkNo(), wrkMast.getSourceLocNo(), wrkMast.getIoType());
                continue;
            }
            // 获取源库位信息
            LocMast sourceSta = locMastService.selectById(wrkMast.getSourceLocNo());
            if (!sourceSta.getLocSts().equals("R") &&!sourceSta.getLocSts().equals("P")) {
            if (!sourceSta.getLocSts().equals("R") && !sourceSta.getLocSts().equals("P")) {
                News.error("出库操作库位状态不符合--状态, 库位号={},库位状态={}", wrkMast.getSourceLocNo(), sourceSta.getLocSts());
                continue;
            }
@@ -1421,7 +1669,7 @@
                continue;
            }
            // 判断堆垛机出库站状态
            if (staProtocol.isAutoing() && !staProtocol.isLoading() && staDetl.getCanouting() !=null && staDetl.getCanouting().equals("Y")
            if (staProtocol.isAutoing() && !staProtocol.isLoading() && staDetl.getCanouting() != null && staDetl.getCanouting().equals("Y")
                    && staProtocol.getWorkNo() == 0 && staProtocol.isOutEnable()) {
                // 命令下发区 --------------------------------------------------------------------------
@@ -1473,7 +1721,7 @@
                        }
                        return true;
                    }
                // 不是最外层库位,需要使用穿梭车搬运后,再堆垛机出库
                    // 不是最外层库位,需要使用穿梭车搬运后,再堆垛机出库
                } else {
                    // 当前组库位是否有穿梭车
                    Integer steNo = this.hasCarOfIdle(wrkMast.getSourceLocNo());
@@ -1484,12 +1732,15 @@
                            // 给穿梭车下发命令 让其将货物挪至堆垛机搬运点
                            SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, steNo);
                            SteProtocol steProtocol = steThread.getSteProtocol();
                            if (steProtocol == null) { continue; }
                            if (steProtocol == null) {
                                continue;
                            }
                            if (steProtocol.loca == 0) continue;
                            if (steProtocol.isIdle()) {
                                //小车只能绑定一笔作业中任务
                                WrkMast wrkMast1 = wrkMastMapper.selectSteNoData(steNo);
                                if(wrkMast1 != null){
                                if (wrkMast1 != null) {
                                    continue;
                                }
@@ -1502,7 +1753,7 @@
                                steCommand.setRow(Utils.getGroupRow(steProtocol.getRow().intValue()).shortValue());
                                steCommand.setBay(steProtocol.getBay());
                                steCommand.setLev(steProtocol.getLev());
                                steCommand.setMemo("11==>14小车搬出库任务,任务号"+wrkMast.getWrkNo()+"");
                                steCommand.setMemo("11==>14小车搬出库任务,任务号" + wrkMast.getWrkNo() + "");
                                if (!MessageQueue.offer(SlaveType.Ste, steNo, new Task(2, steCommand))) {
                                    News.error("穿梭车命令下发失败,穿梭车号={},任务数据={}", steNo, JSON.toJSON(steCommand));
@@ -1554,7 +1805,7 @@
                            }
                        }
                    // 没有小车
                        // 没有小车
                    } else {
                        if (wrkMast.getWrkSts() == 11L && wrkMast.getSteNo() == null) {
                            // 寻找最近的小车
@@ -1585,8 +1836,8 @@
                        }
                        // 堆垛机搬运小车
                        if (wrkMast.getWrkSts() == 12L) {
                            if (Cools.isEmpty(wrkMast.getSteNo()) || wrkMast.getSteNo()==0) {
                                News.error("工作号={}即将开始搬运小车但是工作档没有小车号",wrkMast.getWrkNo());
                            if (Cools.isEmpty(wrkMast.getSteNo()) || wrkMast.getSteNo() == 0) {
                                News.error("工作号={}即将开始搬运小车但是工作档没有小车号", wrkMast.getWrkNo());
                                return false;
                            }
                            this.carMoveIn(wrkMast, wrkMast.getSteNo(), crnProtocol);
@@ -1602,7 +1853,7 @@
    /**
     * 库位移转 NEW
     */
    public synchronized void locToLoc1(CrnSlave slave, CrnProtocol crnProtocol){
    public synchronized void locToLoc1(CrnSlave slave, CrnProtocol crnProtocol) {
        // 获取工作档信息
        WrkMast wrkMast = wrkMastMapper.selectLocMove(slave.getId());
        if (null == wrkMast) {
@@ -1616,11 +1867,11 @@
        // 判断是否已存在小车绑定任务
        BasSte basSte = basSteService.findByCrnNo(wrkMast.getCrnNo());
        if(basSte == null) return;
        if (basSte == null) return;
        WrkMast one = wrkMastService.selectOne(new EntityWrapper<WrkMast>()
                .eq("ste_no",basSte.getSteNo())
                .eq("ste_no", basSte.getSteNo())
                .last(" and io_type != 11 and wrk_sts < 10"));
        if(one != null){
        if (one != null) {
            News.error("{}移库任务无法作业,因入库任务已绑定小车!", wrkMast.getWrkNo());
            return;
        }
@@ -1703,12 +1954,14 @@
                    // 给穿梭车下发命令 让其将货物挪至堆垛机搬运点
                    SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, steNo);
                    SteProtocol steProtocol = steThread.getSteProtocol();
                    if (steProtocol == null) { return; }
                    if (steProtocol == null) {
                        return;
                    }
                    if (steProtocol.isIdle()) {
                        //小车只能绑定一笔作业中任务
                        WrkMast wrkMast1 = wrkMastMapper.selectSteNoData(steNo);
                        if(wrkMast1 != null){
                        if (wrkMast1 != null) {
                            return;
                        }
@@ -1798,7 +2051,7 @@
    /**
     * 库位移转(高频移库,io_type=111)
     */
    public synchronized void locToLoc111(CrnSlave slave, CrnProtocol crnProtocol){
    public synchronized void locToLoc111(CrnSlave slave, CrnProtocol crnProtocol) {
        // 获取工作档信息
        WrkMast wrkMast = wrkMastMapper.selectLocMove111(slave.getId());
        if (null == wrkMast) {
@@ -1812,11 +2065,11 @@
        // 判断是否已存在小车绑定任务
        BasSte basSte = basSteService.findByCrnNo(wrkMast.getCrnNo());
        if(basSte == null) return;
        if (basSte == null) return;
        WrkMast one = wrkMastService.selectOne(new EntityWrapper<WrkMast>()
                .eq("ste_no",basSte.getSteNo())
                .eq("ste_no", basSte.getSteNo())
                .last(" and io_type != 111 and wrk_sts < 10"));
        if(one != null){
        if (one != null) {
            News.error("{}移库任务无法作业,因入库任务已绑定小车!", wrkMast.getWrkNo());
            return;
        }
@@ -1894,7 +2147,7 @@
    /**
     * 库位移转,回原库位
     */
    public synchronized void locToLoc17(CrnSlave slave, CrnProtocol crnProtocol){
    public synchronized void locToLoc17(CrnSlave slave, CrnProtocol crnProtocol) {
        // 获取工作档信息
        WrkMast wrkMast = wrkMastMapper.selectLocMove17(slave.getId());
        if (null == wrkMast) {
@@ -1910,28 +2163,28 @@
            Integer lev = Utils.getLev(wrkMast.getSourceLocNo());
            String locNo = Utils.append(row, bay, lev);
            String[] deeplocs  = Utils.getDeepLocs(locNo);
            if(!Cools.isEmpty(deeplocs)){
            String[] deeplocs = Utils.getDeepLocs(locNo);
            if (!Cools.isEmpty(deeplocs)) {
                boolean ret = false;
                for(String deepLocNo : deeplocs) {
                for (String deepLocNo : deeplocs) {
                    LocMast deepLoc = locMastService.selectById(deepLocNo);
                    WrkMast waitWrkMast = wrkMastMapper.selectByLocNo1(deepLocNo);
                    if(deepLoc != null && !deepLoc.getLocSts().equals("F")
                    if (deepLoc != null && !deepLoc.getLocSts().equals("F")
                            && !deepLoc.getLocSts().equals("D")
                            && !deepLoc.getLocSts().equals("O")
                            && (waitWrkMast!=null && waitWrkMast.getWrkSts()<18)){
                            && (waitWrkMast != null && waitWrkMast.getWrkSts() < 18)) {
                        News.error("移库再回库时,深库位组深库位状态为作业中 ===>> deepLoc={},loc_sts={}", deepLoc.getLocNo(), deepLoc.getLocSts());
                        if(waitWrkMast.getIoPri()<9999) {//调高优先级
                        if (waitWrkMast.getIoPri() < 9999) {//调高优先级
                            waitWrkMast.setIoPri(waitWrkMast.getIoPri() + 1);
                            wrkMastService.updateById(waitWrkMast);
                        }
                        flag = true;
                        break;
                    }
                    if(deepLoc != null && deepLoc.getLocSts().equals("O")){
                    if (deepLoc != null && deepLoc.getLocSts().equals("O")) {
                        //修改移库工作档
                        wrkMast.setSourceLocNo(wrkMast.getLocNo());
                        wrkMast.setIoPri((double)9999);
                        wrkMast.setIoPri((double) 9999);
                        wrkMast.setWrkSts(2L);
                        wrkMast.setLocNo(deepLocNo);
                        wrkMast.setSteNo(0);
@@ -1940,7 +2193,7 @@
                            News.error("修改工作档状态 17.移库完成 => 2.移库再入库中 失败!!,工作号={}", wrkMast.getWrkNo());
                        }
                        if(deepLoc.getLocSts().equals("O")){
                        if (deepLoc.getLocSts().equals("O")) {
                            deepLoc.setLocSts("S"); // S.入库预约
                            deepLoc.setModiTime(new Date());
                            if (!locMastService.updateById(deepLoc)) {
@@ -1949,7 +2202,7 @@
                            }
                        }
                        LocMast sourceLoc = locMastService.selectById(wrkMast.getSourceLocNo());
                        if(sourceLoc.getLocSts().equals("R") || sourceLoc.getLocSts().equals("D")){
                        if (sourceLoc.getLocSts().equals("R") || sourceLoc.getLocSts().equals("D")) {
                            sourceLoc.setLocSts("R"); // R.出库预约
                            sourceLoc.setModiTime(new Date());
                            if (!locMastService.updateById(sourceLoc)) {
@@ -1960,12 +2213,12 @@
                        break;
                    }
                }
                if(ret == false && !flag){//深库位都不为O
                if (ret == false && !flag) {//深库位都不为O
                    LocMast curLoc = locMastService.selectById(locNo);
                    if(curLoc != null && curLoc.getLocSts().equals("O")){
                    if (curLoc != null && curLoc.getLocSts().equals("O")) {
                        //修改移库工作档
                        wrkMast.setSourceLocNo(wrkMast.getLocNo());
                        wrkMast.setIoPri((double)9999);
                        wrkMast.setIoPri((double) 9999);
                        wrkMast.setWrkSts(2L);
                        wrkMast.setLocNo(locNo);
                        wrkMast.setSteNo(0);
@@ -1974,7 +2227,7 @@
                            News.error("修改工作档状态 17.移库完成 => 2.移库再入库中 失败!!,工作号={}", wrkMast.getWrkNo());
                        }
                        if(curLoc.getLocSts().equals("O")){
                        if (curLoc.getLocSts().equals("O")) {
                            curLoc.setLocSts("S"); // S.入库预约
                            curLoc.setModiTime(new Date());
                            if (!locMastService.updateById(curLoc)) {
@@ -1983,7 +2236,7 @@
                            }
                        }
                        LocMast sourceLoc = locMastService.selectById(wrkMast.getSourceLocNo());
                        if(sourceLoc.getLocSts().equals("R") || sourceLoc.getLocSts().equals("D")){
                        if (sourceLoc.getLocSts().equals("R") || sourceLoc.getLocSts().equals("D")) {
                            sourceLoc.setLocSts("R"); // R.出库预约
                            sourceLoc.setModiTime(new Date());
                            if (!locMastService.updateById(sourceLoc)) {
@@ -1993,7 +2246,7 @@
                    }
                }
            }
            if(flag){
            if (flag) {
                return;
            }
        }
@@ -2050,7 +2303,9 @@
                        if (null == wrkMastMapper.selectPakin(slave.getId(), steNo)) {
                            SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, steNo);
                            SteProtocol steProtocol = steThread.getSteProtocol();
                            if (steProtocol == null) { return; }
                            if (steProtocol == null) {
                                return;
                            }
                            this.letCarBeWaiting(wrkMast, steNo, wrkMast.getLocNo());
//                            if(steProtocol.getLoca()==3 || steProtocol.getLoca()==4){
//                                //小车已经在待机位时,无需下发到待机位任务,直接更新状态微3,同时绑定小车
@@ -2070,7 +2325,9 @@
                        // 小车处于空闲
                        SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, steNo);
                        SteProtocol steProtocol = steThread.getSteProtocol();
                        if (steProtocol == null) { return; }
                        if (steProtocol == null) {
                            return;
                        }
                        if (steProtocol.isIdle()) {
                            // 已经存在吊车执行任务时,则过滤
@@ -2193,7 +2450,7 @@
    /**
     * 库位移转
     */
    public synchronized void locToLoc(CrnSlave slave, CrnProtocol crnProtocol){
    public synchronized void locToLoc(CrnSlave slave, CrnProtocol crnProtocol) {
        // 获取工作档信息
        WrkMast wrkMast = wrkMastMapper.selectLocMove(slave.getId());
        if (null == wrkMast) {
@@ -2285,7 +2542,9 @@
                        // 小车处于空闲
                        SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, steNo);
                        SteProtocol steProtocol = steThread.getSteProtocol();
                        if (steProtocol == null) { return; }
                        if (steProtocol == null) {
                            return;
                        }
                        if (steProtocol.isIdle()) {
                            // 已经存在吊车执行任务时,则过滤
@@ -2351,12 +2610,14 @@
                    // 给穿梭车下发命令 让其将货物挪至堆垛机搬运点
                    SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, steNo);
                    SteProtocol steProtocol = steThread.getSteProtocol();
                    if (steProtocol == null) { return; }
                    if (steProtocol == null) {
                        return;
                    }
                    if (steProtocol.isIdle()) {
                        //小车只能绑定一笔作业中任务
                        WrkMast wrkMast1 = wrkMastMapper.selectSteNoData(steNo);
                        if(wrkMast1 != null){
                        if (wrkMast1 != null) {
                            return;
                        }
@@ -2433,7 +2694,9 @@
                            // 小车处于空闲
                            SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, steNo);
                            SteProtocol steProtocol = steThread.getSteProtocol();
                            if (steProtocol == null) { return; }
                            if (steProtocol == null) {
                                return;
                            }
                            if (steProtocol.isIdle()) {
                                // 已经存在吊车执行任务时,则过滤
@@ -2487,8 +2750,8 @@
                }
                // 堆垛机搬运小车
                if (wrkMast.getWrkSts() == 12L) {
                    if (Cools.isEmpty(wrkMast.getSteNo()) || wrkMast.getSteNo()==0) {
                        News.error("工作号={}即将开始搬运小车但是工作档没有小车号",wrkMast.getWrkNo());
                    if (Cools.isEmpty(wrkMast.getSteNo()) || wrkMast.getSteNo() == 0) {
                        News.error("工作号={}即将开始搬运小车但是工作档没有小车号", wrkMast.getWrkNo());
                        return;
                    }
                    this.carMoveIn(wrkMast, wrkMast.getSteNo(), crnProtocol);
@@ -2505,7 +2768,11 @@
            // 获取堆垛机信息
            SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, ste.getId());
            SteProtocol steProtocol = steThread.getSteProtocol();
            if (steProtocol == null) { continue; }
            if (steProtocol == null) {
                continue;
            }
            if (Cools.isEmpty(steProtocol.loca)) continue;
            if (steProtocol.loca == 0) continue;
            if (Utils.getGroupRow(locNo).equals(Utils.getGroupRow(steProtocol.getRow().intValue())) && steProtocol.getBay() == Utils.getBay(locNo) && steProtocol.getLev() == Utils.getLev(locNo)) {
                return steProtocol.getSteNo().intValue();
            }
@@ -2521,7 +2788,11 @@
            // 获取堆垛机信息
            SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, ste.getId());
            SteProtocol steProtocol = steThread.getSteProtocol();
            if (steProtocol == null) { continue; }
            if (steProtocol == null) {
                continue;
            }
            if (Cools.isEmpty(steProtocol.loca)) continue;
            if (steProtocol.loca == 0) continue;
            if (steProtocol.isIdle()) {
                if (Utils.getGroupRow(locNo).equals(Utils.getGroupRow(steProtocol.getRow().intValue())) && steProtocol.getBay() == Utils.getBay(locNo) && steProtocol.getLev() == Utils.getLev(locNo)) {
                    return steProtocol.getSteNo().intValue();
@@ -2556,12 +2827,14 @@
        // 获取穿梭车信息
        SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, steNo);
        SteProtocol steProtocol = steThread.getSteProtocol();
        if (steProtocol == null) { return; }
        if (steProtocol == null) {
            return;
        }
        if (steProtocol.isIdle()) {
            //小车只能绑定一笔作业中任务
            WrkMast wrkMast1 = wrkMastMapper.selectSteNoData(steNo);
            if(wrkMast1 != null){
            if (wrkMast1 != null) {
                return;
            }
@@ -2593,7 +2866,9 @@
        // 获取穿梭车信息
        SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, steNo);
        SteProtocol steProtocol = steThread.getSteProtocol();
        if (steProtocol == null) { return; }
        if (steProtocol == null) {
            return;
        }
        if (!basSteService.updatePakMk(steNo, "Y")) {
            News.error("修改穿梭车作业状态 失败!!,穿梭车={}", steNo);
@@ -2602,7 +2877,7 @@
        //小车只能绑定一笔作业中任务
        WrkMast wrkMast1 = wrkMastMapper.selectSteNoData(steNo);
        if(wrkMast1 != null){
        if (wrkMast1 != null) {
            return;
        }
@@ -2636,12 +2911,14 @@
        // 获取穿梭车信息
        SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, steNo);
        SteProtocol steProtocol = steThread.getSteProtocol();
        if (steProtocol == null) { return; }
        if (steProtocol == null) {
            return;
        }
        if (steProtocol.isIdle()) {
            //小车只能绑定一笔作业中任务
            WrkMast wrkMast1 = wrkMastMapper.selectSteNoData(steNo);
            if(wrkMast1 != null){
            if (wrkMast1 != null) {
                return;
            }
@@ -2678,12 +2955,14 @@
        // 获取穿梭车信息
        SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, steNo);
        SteProtocol steProtocol = steThread.getSteProtocol();
        if (steProtocol == null) { return; }
        if (steProtocol == null) {
            return;
        }
        if (steProtocol.isIdle()) {
            //小车只能绑定一笔作业中任务
            WrkMast wrkMast1 = wrkMastMapper.selectSteNoData(steNo);
            if(wrkMast1 != null){
            if (wrkMast1 != null) {
                return;
            }
@@ -2717,8 +2996,10 @@
        // 获取堆垛机信息
        SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, steNo);
        SteProtocol steProtocol = steThread.getSteProtocol();
        if (steProtocol == null) { return; }
        if(steProtocol.getLoad() == 1){
        if (steProtocol == null) {
            return;
        }
        if (steProtocol.getLoad() == 1) {
            News.error("小车上方有货,无法下发任务===>>{}", steNo);
            return;
        }
@@ -2743,9 +3024,9 @@
                    crnCommand.setDestinationPosY(locMast.getBay1().shortValue());     // 目标库位列
                    crnCommand.setDestinationPosZ(locMast.getLev1().shortValue());     // 目标库位层
                    if( crnCommand.getSourcePosX() == crnCommand.getDestinationPosX()
                        && crnCommand.getSourcePosY() == crnCommand.getDestinationPosY()
                        && crnCommand.getSourcePosZ() == crnCommand.getDestinationPosZ()){
                    if (crnCommand.getSourcePosX() == crnCommand.getDestinationPosX()
                            && crnCommand.getSourcePosY() == crnCommand.getDestinationPosY()
                            && crnCommand.getSourcePosZ() == crnCommand.getDestinationPosZ()) {
                        //打补丁,如果出现源排列层 和目标排列层完全相同时,不给堆垛机发任务,状态直接由3 ==>> 6
                        // 修改穿梭车运行中排列层
                        steThread.modifyPos(Utils.getGroupRow(locMast.getLocNo()), locMast.getBay1(), locMast.getLev1());
@@ -2773,7 +3054,7 @@
                            }
                        }
                    }
                // 出库搬
                    // 出库搬
                } else {
                    locMast = locMastService.selectById(wrkMast.getSourceLocNo());
                    // 堆垛机命令下发区 --------------------------------------------------------------------------
@@ -2816,7 +3097,9 @@
        // 获取穿梭车信息
        SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, steNo);
        SteProtocol steProtocol = steThread.getSteProtocol();
        if (steProtocol == null) { return; }
        if (steProtocol == null) {
            return;
        }
        // 穿梭车空闲
        if (steProtocol.isIdle() && steProtocol.getLoad() == 0) {
            // 堆垛机空闲
@@ -2870,7 +3153,9 @@
            // 获取堆垛机信息
            CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crn.getId());
            CrnProtocol crnProtocol = crnThread.getCrnProtocol();
            if (crnProtocol == null) { continue; }
            if (crnProtocol == null) {
                continue;
            }
            //  状态:等待确认 并且  任务完成位 = 1
            if (crnProtocol.statusType == CrnStatusType.WAITING && crnProtocol.getTaskNo() != 0) {
                // 获取入库待确认工作档
@@ -2916,10 +3201,12 @@
                    }
                }
                if (wrkMast == null) { continue; }
                if (wrkMast == null) {
                    continue;
                }
                if (wrkMast.getIoType() != 11 && wrkMast.getIoType() != 111) {
                    // 入库 ==>> 货物搬入库
                    if (wrkMast.getWrkSts() == 7){
                    if (wrkMast.getWrkSts() == 7) {
                        // 判断是否需要小车入库
                        if (locMastService.isOutMost(wrkMast.getLocNo())) {
                            // ==> 9.入库完成
@@ -2939,7 +3226,10 @@
                            Integer steNo = wrkMast.getSteNo();
                            SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, steNo);
                            SteProtocol steProtocol = steThread.getSteProtocol();
                            if (steProtocol == null) { continue; }
                            if (steProtocol == null) {
                                continue;
                            }
//                            if (steProtocol.loca==0) continue;
                            if (steProtocol.isIdle()) {
                                // 命令下发区 --------------------------------------------------------------------------
                                SteCommand steCommand = new SteCommand();
@@ -3031,7 +3321,10 @@
                        Integer steNo = wrkMast.getSteNo();
                        SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, steNo);
                        SteProtocol steProtocol = steThread.getSteProtocol();
                        if (steProtocol == null) { continue; }
                        if (steProtocol == null) {
                            continue;
                        }
//                        if (steProtocol.loca==0) continue;
                        // 穿梭车重新定位排列层
                        if (!steThread.confirmPos()) {
                            News.error("{}号穿梭车重新定位失败!作业工作档任务号:{}", wrkMast.getSteNo(), wrkMast.getWrkNo());
@@ -3061,11 +3354,11 @@
                        }
                        // 移库 ===>> 堆垛机搬至目标库位组 完成
                    }
                // 库位移转(高频io_type111)
                } else if(wrkMast.getIoType() == 111) {
                    // 库位移转(高频io_type111)
                } else if (wrkMast.getIoType() == 111) {
                    Date now = new Date();
                    // 入库 ==>> 货物搬入库
                    if (wrkMast.getWrkSts() == 7){
                    if (wrkMast.getWrkSts() == 7) {
                        if (locMastService.isOutMost(wrkMast.getLocNo()) && locMastService.isOutMost(wrkMast.getSourceLocNo())) {
                            // ==> 9.入库完成
                            wrkMast.setWrkSts(9L);
@@ -3080,10 +3373,10 @@
                            }
                        }
                    }
                // 库位移转
                }else {
                    // 库位移转
                } else {
                    // 入库 ==>> 货物搬入库
                    if (wrkMast.getWrkSts() == 7){
                    if (wrkMast.getWrkSts() == 7) {
                        // 判断是否需要小车入库
                        if (locMastService.isOutMost(wrkMast.getLocNo())) {
                            // ==> 9.入库完成
@@ -3103,7 +3396,10 @@
                            Integer steNo = wrkMast.getSteNo();
                            SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, steNo);
                            SteProtocol steProtocol = steThread.getSteProtocol();
                            if (steProtocol == null) { continue; }
                            if (steProtocol == null) {
                                continue;
                            }
//                            if (steProtocol.loca==0) continue;
                            if (steProtocol.isIdle()) {
                                // 命令下发区 --------------------------------------------------------------------------
                                SteCommand steCommand = new SteCommand();
@@ -3216,7 +3512,7 @@
                            } else {
                                locSts = "D";
                            }
                            if(Cools.isEmpty(locSts)){
                            if (Cools.isEmpty(locSts)) {
                                News.error("库位移转 ===>> 库存状态为空;[源库位={}],[目标库位={}]", wrkMast.getSourceLocNo(), wrkMast.getLocNo());
                                continue;
                            }
@@ -3279,7 +3575,7 @@
                            News.error("修改工作档状态 4.迁入小车 => 6.小车待入 失败!!,工作号={}", wrkMast.getWrkNo());
                        }
                        // 入库 ===>> 迁出小车 完成
                    } else if (wrkMast.getWrkSts() == 7){
                    } else if (wrkMast.getWrkSts() == 7) {
                        // 判断是否需要小车入库
                        if (locMastService.isOutMost(wrkMast.getLocNo())) {
                            // ==> 9.入库完成
@@ -3299,7 +3595,10 @@
                            Integer steNo = wrkMast.getSteNo();
                            SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, steNo);
                            SteProtocol steProtocol = steThread.getSteProtocol();
                            if (steProtocol == null) { continue; }
                            if (steProtocol == null) {
                                continue;
                            }
                            if (steProtocol.loca == 0) continue;
                            if (steProtocol.isIdle()) {
                                // 命令下发区 --------------------------------------------------------------------------
                                SteCommand steCommand = new SteCommand();
@@ -3328,7 +3627,10 @@
                        Integer steNo = wrkMast.getSteNo();
                        SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, steNo);
                        SteProtocol steProtocol = steThread.getSteProtocol();
                        if (steProtocol == null) { continue; }
                        if (steProtocol == null) {
                            continue;
                        }
                        if (steProtocol.loca == 0) continue;
                        // 穿梭车重新定位排列层
                        if (!steThread.confirmPos()) {
                            News.error("{}号穿梭车重新定位失败!作业工作档任务号:{}", wrkMast.getSteNo(), wrkMast.getWrkNo());
@@ -3369,8 +3671,12 @@
            // 获取穿梭车信息
            SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, ste.getId());
            SteProtocol steProtocol = steThread.getSteProtocol();
            if (steProtocol == null) { continue; }
            if (steProtocol.getWaiting() && steProtocol.getTaskNo() == 0){
            if (steProtocol == null) {
                continue;
            }
            if (Cools.isEmpty(steProtocol.loca)) continue;
            if (steProtocol.loca == 0) continue;
            if (steProtocol.getWaiting() && steProtocol.getTaskNo() == 0) {
                News.info("ste[id={}] 收到等待WCS确认信号,但是任务号(地址V824)为0", steProtocol.getSteNo());
            }
@@ -3406,7 +3712,7 @@
                                    steThread.setResetFlag(true);
                                    News.info("ste[id={}]小车复位标记 25.小车去充电 ===>> 26.等待充电 成功!!,工作号={}", steProtocol.getSteNo(), wrkCharge.getWrkNo());
                                }
                            }  else if (wrkCharge.getWrkSts() == 32) {
                            } else if (wrkCharge.getWrkSts() == 32) {
                                // 32.小车走行 ===>> 33.小车待搬
                                wrkCharge.setWrkSts(33L);
                                if (!wrkChargeService.updateById(wrkCharge)) {
@@ -3426,16 +3732,18 @@
                                }
                            }
                        }
                    }else{
                    } else {
                        News.info("ste[id={}] 执行工作档完成,任务号={}, 穿梭车状态={},工作档状态={}",
                                steProtocol.getSteNo(), steProtocol.getTaskNo(), steProtocol.getStatus(), wrkMast.getWrkSts());
                    }
                    if (wrkMast == null) { continue; }
                    if (wrkMast == null) {
                        continue;
                    }
                    switch (wrkMast.getWrkSts().intValue()) {
                        case 2:
                            // 修改工作档状态 2.设备上走 => 3.小车待搬
                            if (Cools.isEmpty(wrkMast.getSteNo()) || wrkMast.getSteNo()==0){
                            if (Cools.isEmpty(wrkMast.getSteNo()) || wrkMast.getSteNo() == 0) {
                                News.error("修改工作档状态 2.设备上走 => 3.小车待搬 失败!!,工作号={}   原因:工作号没小车", wrkMast.getWrkNo());
                                break;
                            }
@@ -3522,7 +3830,7 @@
    /**
     * 堆垛机异常信息记录
     */
    private synchronized void recCrnErr(){
    private synchronized void recCrnErr() {
        Date now = new Date();
        for (CrnSlave crn : slaveProperties.getCrn()) {
            // 获取堆垛机信息
@@ -3542,7 +3850,7 @@
                            continue;
                        }
                        BasCrnError crnError = basCrnErrorMapper.selectById(crnProtocol.getAlarm());
                        String errName = crnError==null? "未知异常":crnError.getErrName();
                        String errName = crnError == null ? "未知异常" : crnError.getErrName();
                        BasErrLog basErrLog = new BasErrLog(
                                null,    // 编号
                                wrkMast.getWrkNo(),    // 工作号
@@ -3581,7 +3889,7 @@
                        }
                    }
                }
            // 无任务
                // 无任务
            } else {
                BasErrLog latest = basErrLogService.findLatest(crn.getId());
                // 有异常
@@ -3589,7 +3897,7 @@
                    // 记录新异常
                    if (latest == null || (latest.getErrCode() != crnProtocol.getAlarm().intValue())) {
                        BasCrnError crnError = basCrnErrorMapper.selectById(crnProtocol.getAlarm());
                        String errName = crnError==null? "未知异常":crnError.getErrName();
                        String errName = crnError == null ? "未知异常" : crnError.getErrName();
                        BasErrLog basErrLog = new BasErrLog(
                                null,    // 编号
                                null,    // 工作号
@@ -3604,7 +3912,7 @@
                                null,    // 源站
                                null,    // 源库位
                                null,    // 条码
                                (int)crnProtocol.getAlarm(),    // 异常码
                                (int) crnProtocol.getAlarm(),    // 异常码
                                errName,    // 异常
                                1,    // 异常情况
                                now,    // 添加时间
@@ -3617,7 +3925,7 @@
                            News.error("堆垛机plc异常记录失败 ===>> [id:{}] [error:{}]", crn.getId(), errName);
                        }
                    }
                // 无异常
                    // 无异常
                } else {
                    // 异常修复
                    if (latest != null && latest.getStatus() == 1) {
@@ -3636,7 +3944,7 @@
    /**
     * 穿梭车异常信息记录
     */
    private void recSteErr(){
    private void recSteErr() {
        Date now = new Date();
        for (SteSlave ste : slaveProperties.getSte()) {
            // 获取堆垛机信息
@@ -3656,7 +3964,7 @@
                            continue;
                        }
                        BasSteErr steErr = basSteErrService.selectById(steProtocol.getAlarm());
                        String errName = steErr==null? "未知异常":steErr.getErrName();
                        String errName = steErr == null ? "未知异常" : steErr.getErrName();
                        BasSteErrLog basSteErrLog = new BasSteErrLog(
                                null,    // 编号
                                wrkMast.getWrkNo(),    // 工作号
@@ -3703,7 +4011,7 @@
                    // 记录新异常
                    if (latest == null || (latest.getErrCode() != steProtocol.getAlarm().intValue())) {
                        BasSteErr steErr = basSteErrService.selectById(steProtocol.getAlarm());
                        String errName = steErr==null? "未知异常":steErr.getErrName();
                        String errName = steErr == null ? "未知异常" : steErr.getErrName();
                        BasSteErrLog basSteErrLog = new BasSteErrLog(
                                null,    // 编号
                                null,    // 工作号
@@ -3718,7 +4026,7 @@
                                null,    // 源站
                                null,    // 源库位
                                null,    // 条码
                                (int)steProtocol.getAlarm(),    // 异常码
                                (int) steProtocol.getAlarm(),    // 异常码
                                errName,    // 异常
                                1,    // 异常情况
                                now,    // 添加时间
@@ -3753,7 +4061,7 @@
    /**
     * 空栈板初始化入库,叉车入库站放货
     */
    public synchronized void storeEmptyPlt(){
    public synchronized void storeEmptyPlt() {
        for (DevpSlave devp : slaveProperties.getDevp()) {
            // 遍历空板入库口
            for (DevpSlave.Sta emptyInSta : devp.getEmptyInSta()) {
@@ -3768,22 +4076,40 @@
                //20230201. 2号堆垛机有出库任务时,禁止新板入库
                if (staProtocol.isLoading() && staProtocol.getWorkNo() == 9995) {
                    if ( emptyInSta.getStaNo()==103 && devpThread.ioModeOf1F == IoModeType.PAKOUT_MODE) {
                    if (emptyInSta.getStaNo() == 103 && devpThread.ioModeOf1F == IoModeType.PAKOUT_MODE) {
                        //有出库任务,退库到入库口
                        staProtocol.setWorkNo((short) 9999);
                        staProtocol.setStaNo((short)100);
                        staProtocol.setStaNo((short) 100);
                        devpThread.setPakMk(staProtocol.getSiteId(), false);
                        boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                        News.error("MainServiceImpl  storeEmptyPlt"+"103为出库模式,禁止入库,退回入库口。!!!");
                        News.error("MainServiceImpl  storeEmptyPlt" + "103为出库模式,禁止入库,退回入库口。!!!");
                        continue;
                    }
                    if ( emptyInSta.getStaNo()==203 && devpThread.ioModeOf2F == IoModeType.PAKOUT_MODE) {
                    if (emptyInSta.getStaNo() == 203 && devpThread.ioModeOf2F == IoModeType.PAKOUT_MODE) {
                        //有出库任务,退库到入库口
                        staProtocol.setWorkNo((short) 9999);
                        staProtocol.setStaNo((short)200);
                        staProtocol.setStaNo((short) 200);
                        devpThread.setPakMk(staProtocol.getSiteId(), false);
                        boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                        News.error("MainServiceImpl  storeEmptyPlt"+"203为出库模式,禁止入库,退回入库口。!!!");
                        News.error("MainServiceImpl  storeEmptyPlt" + "203为出库模式,禁止入库,退回入库口。!!!");
                        continue;
                    }
                    if (emptyInSta.getStaNo() == 113 && devpThread.ioModeOf3F == IoModeType.PAKOUT_MODE) {
                        //有出库任务,退库到入库口
                        staProtocol.setWorkNo((short) 9999);
                        staProtocol.setStaNo((short) 100);
                        devpThread.setPakMk(staProtocol.getSiteId(), false);
                        boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                        News.error("MainServiceImpl  storeEmptyPlt" + "113为出库模式,禁止入库,退回入库口。!!!");
                        continue;
                    }
                    if (emptyInSta.getStaNo() == 213 && devpThread.ioModeOf4F == IoModeType.PAKOUT_MODE) {
                        //有出库任务,退库到入库口
                        staProtocol.setWorkNo((short) 9999);
                        staProtocol.setStaNo((short) 200);
                        devpThread.setPakMk(staProtocol.getSiteId(), false);
                        boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                        News.error("MainServiceImpl  storeEmptyPlt" + "213为出库模式,禁止入库,退回入库口。!!!");
                        continue;
                    }
                }
@@ -3801,9 +4127,9 @@
                    BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, emptyInSta.getBarcode());
                    if (barcodeThread != null) {
                        String barcode0 = barcodeThread.getBarcode();
                        if(!Cools.isEmpty(barcode0)) {
                        if (!Cools.isEmpty(barcode0)) {
//                            News.info("{}号条码扫描器检测条码信息:{}", emptyInSta.getBarcode(), barcode0);
                            if(!"NG".endsWith(barcode0) && !"NoRead".equals(barcode0) && !"empty".equals(barcode0)) {
                            if (!"NG".endsWith(barcode0) && !"NoRead".equals(barcode0) && !"empty".equals(barcode0)) {
                                barcode = barcode0;
                            }
                        }
@@ -3868,109 +4194,118 @@
     */
    public synchronized void ledExecute() {
        for (LedSlave led : slaveProperties.getLed()) {
            // 获取输送线plc线程
            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, led.getDevpPlcId());
            // 命令集合
            List<LedCommand> commands = new ArrayList<>();
            // 工作档集合
            List<WrkMast> wrkMasts = new ArrayList<>();
            for (Integer staNo : led.getStaArr()) {
                // 获取叉车站点
                StaProtocol staProtocol = devpThread.getStation().get(staNo);
                if (null == staProtocol || null == staProtocol.getWorkNo() || 0 == staProtocol.getWorkNo() || !staProtocol.isLoading()) {
                    continue;
                } else {
                    staProtocol = staProtocol.clone();
                }
                // 获取工作档数据
                WrkMast wrkMast = wrkMastMapper.selectById(staProtocol.getWorkNo());
                if (null == wrkMast || wrkMast.getWrkSts() < 14 || wrkMast.getIoType() < 100) { continue; }
                wrkMasts.add(wrkMast);
                // 组装命令
                LedCommand ledCommand = new LedCommand();
                ledCommand.setWorkNo(wrkMast.getWrkNo());
                ledCommand.setIoType(wrkMast.getIoType());
                // 出库模式
                switch (wrkMast.getIoType()) {
                    case 101:
                        ledCommand.setTitle("全板出库");
                        break;
                    case 103:
                        ledCommand.setTitle("拣料出库");
                        break;
                    case 104:
                        ledCommand.setTitle("并板出库");
                        break;
                    case 107:
                        ledCommand.setTitle("盘点出库");
                        break;
                    case 110:
                        ledCommand.setTitle("空板出库");
                        ledCommand.setEmptyMk(true);
                        break;
                    default:
                        News.error("任务入出库类型错误!!![工作号:{}] [入出库类型:{}]", wrkMast.getWrkNo(), wrkMast.getIoType());
                        break;
                }
                ledCommand.setSourceLocNo(wrkMast.getSourceLocNo());
                ledCommand.setStaNo(wrkMast.getStaNo());
                ledCommand.setBarcode(wrkMast.getBarcode());
                if (wrkMast.getIoType() != 110) {
                    List<WrkDetl> wrkDetls = wrkDetlService.findByWorkNo(wrkMast.getWrkNo());
                    wrkDetls.forEach(wrkDetl -> {
                        Double total = 0.0;
                        EntityWrapper<LocDetl> wrapper = new EntityWrapper<>();
                        LocDetl locDetl = locDetlService.selectOne(wrapper.eq("zpallet", wrkDetl.getZpallet()).eq("matnr", wrkDetl.getMatnr()));
                        if (Cools.isEmpty(locDetl)) {
                            total = wrkDetl.getAnfme();
                        } else {
                            total = locDetl.getAnfme();
                        }
                        if (wrkMast.getIoType() == 101) {
                            ledCommand.getMatDtos().add(new MatDto(wrkDetl.getMatnr(), wrkDetl.getMaktx(), wrkDetl.getBatch(), wrkDetl.getSpecs(), wrkDetl.getManu(), wrkDetl.getMemo(), wrkDetl.getAnfme(),total));
                        }
                        if (wrkMast.getIoType() == 103 && (null == wrkDetl.getInspect() || 0 == wrkDetl.getInspect())) {
                            ledCommand.getMatDtos().add(new MatDto(wrkDetl.getMatnr(), wrkDetl.getMaktx(), wrkDetl.getBatch(), wrkDetl.getSpecs(), wrkDetl.getManu(), wrkDetl.getMemo(), wrkDetl.getAnfme(),total));
                        }
                        if (wrkMast.getIoType() == 107) {
                            ledCommand.getMatDtos().add(new MatDto(wrkDetl.getMatnr(), wrkDetl.getMaktx(), wrkDetl.getBatch(), wrkDetl.getSpecs(), wrkDetl.getManu(), wrkDetl.getMemo(), wrkDetl.getAnfme(),total));
                        }
                    });
                }
                commands.add(ledCommand);
            }
            Set<Integer> workNos = wrkMasts.stream().map(WrkMast::getWrkNo).collect(Collectors.toSet());
            // 获取LED线程
            LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, led.getId());
            // 相同工作号集合则过滤
            if (CollectionUtils.equals(ledThread.getWorkNos(), workNos)) {
                continue;
            }
            // 命令下发 -------------------------------------------------------------------------------
            if (!commands.isEmpty()) {
                if (!MessageQueue.offer(SlaveType.Led, led.getId(), new Task(1, commands))) {
                    News.error("{}号LED命令下发失败!!![ip:{}] [port:{}]", led.getId(), led.getIp(), led.getPort());
                    continue;
                }
            }
            try {
                // 修改主档led标记
                for (WrkMast wrkMast : wrkMasts) {
                    wrkMast.setOveMk("Y");
                    wrkMast.setModiTime(new Date());
                    if (wrkMastMapper.updateById(wrkMast) == 0) {
                        throw new CoolException("更新工作档失败");
                // 获取输送线plc线程
                DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, led.getDevpPlcId());
                // 命令集合
                List<LedCommand> commands = new ArrayList<>();
                // 工作档集合
                List<WrkMast> wrkMasts = new ArrayList<>();
                for (Integer staNo : led.getStaArr()) {
                    // 获取叉车站点
                    StaProtocol staProtocol = devpThread.getStation().get(staNo);
                    if (null == staProtocol || null == staProtocol.getWorkNo() || 0 == staProtocol.getWorkNo() || !staProtocol.isLoading()) {
                        continue;
                    } else {
                        staProtocol = staProtocol.clone();
                    }
                    // 获取工作档数据
                    WrkMast wrkMast = wrkMastMapper.selectById(staProtocol.getWorkNo());
                    if (null == wrkMast || wrkMast.getWrkSts() < 14 || wrkMast.getIoType() < 100) {
                        continue;
                    }
                    wrkMasts.add(wrkMast);
                    // 组装命令
                    LedCommand ledCommand = new LedCommand();
                    ledCommand.setWorkNo(wrkMast.getWrkNo());
                    ledCommand.setIoType(wrkMast.getIoType());
                    // 出库模式
                    switch (wrkMast.getIoType()) {
                        case 101:
                            ledCommand.setTitle("全板出库");
                            break;
                        case 103:
                            ledCommand.setTitle("拣料出库");
                            break;
                        case 104:
                            ledCommand.setTitle("并板出库");
                            break;
                        case 107:
                            ledCommand.setTitle("盘点出库");
                            break;
                        case 110:
                            ledCommand.setTitle("空板出库");
                            ledCommand.setEmptyMk(true);
                            break;
                        default:
                            News.error("任务入出库类型错误!!![工作号:{}] [入出库类型:{}]", wrkMast.getWrkNo(), wrkMast.getIoType());
                            break;
                    }
                    ledCommand.setSourceLocNo(wrkMast.getSourceLocNo());
                    ledCommand.setStaNo(wrkMast.getStaNo());
                    ledCommand.setBarcode(wrkMast.getBarcode());
                    if (wrkMast.getIoType() != 110) {
                        List<WrkDetl> wrkDetls = wrkDetlService.findByWorkNo(wrkMast.getWrkNo());
                        wrkDetls.forEach(wrkDetl -> {
                            Double total = 0.0;
                            EntityWrapper<LocDetl> wrapper = new EntityWrapper<>();
                            LocDetl locDetl = locDetlService.selectOne(wrapper.eq("zpallet", wrkDetl.getZpallet()).eq("matnr", wrkDetl.getMatnr()));
                            if (Cools.isEmpty(locDetl)) {
                                total = wrkDetl.getAnfme();
                            } else {
                                total = locDetl.getAnfme();
                            }
                            if (wrkMast.getIoType() == 101) {
                                ledCommand.getMatDtos().add(new MatDto(wrkDetl.getMatnr(), wrkDetl.getMaktx(), wrkDetl.getBatch(), wrkDetl.getSpecs(), wrkDetl.getManu(), wrkDetl.getMemo(), wrkDetl.getAnfme(), total));
                            }
                            if (wrkMast.getIoType() == 103 && (null == wrkDetl.getInspect() || 0 == wrkDetl.getInspect())) {
                                ledCommand.getMatDtos().add(new MatDto(wrkDetl.getMatnr(), wrkDetl.getMaktx(), wrkDetl.getBatch(), wrkDetl.getSpecs(), wrkDetl.getManu(), wrkDetl.getMemo(), wrkDetl.getAnfme(), total));
                            }
                            if (wrkMast.getIoType() == 107) {
                                ledCommand.getMatDtos().add(new MatDto(wrkDetl.getMatnr(), wrkDetl.getMaktx(), wrkDetl.getBatch(), wrkDetl.getSpecs(), wrkDetl.getManu(), wrkDetl.getMemo(), wrkDetl.getAnfme(), total));
                            }
                        });
                    }
                    commands.add(ledCommand);
                }
                Set<Integer> workNos = wrkMasts.stream().map(WrkMast::getWrkNo).collect(Collectors.toSet());
                // 获取LED线程
                LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, led.getId());
                // 相同工作号集合则过滤
                if (CollectionUtils.equals(ledThread.getWorkNos(), workNos)) {
                    continue;
                }
                // 命令下发 -------------------------------------------------------------------------------
                if (!commands.isEmpty()) {
                    if (!MessageQueue.offer(SlaveType.Led, led.getId(), new Task(1, commands))) {
                        News.error("{}号LED命令下发失败!!![ip:{}] [port:{}]", led.getId(), led.getIp(), led.getPort());
                        continue;
                    } else {
                        News.info("{}号LED命令下发成功!!![ip:{}] [port:{}]", led.getId(), led.getIp(), led.getPort());
                        News.info("{}号LED命令下发成功!!![commands:{}]", led.getId(), commands);
                    }
                }
                // 更新线程当前工作号集合
                ledThread.setWorkNos(workNos);
                try {
                    // 修改主档led标记
                    for (WrkMast wrkMast : wrkMasts) {
                        wrkMast.setOveMk("Y");
                        wrkMast.setModiTime(new Date());
                        if (wrkMastMapper.updateById(wrkMast) == 0) {
                            throw new CoolException("更新工作档失败");
                        }
                    }
                    // 更新线程当前工作号集合
                    ledThread.setWorkNos(workNos);
                } catch (Exception e) {
                    e.printStackTrace();
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                }
            } catch (Exception e) {
                e.printStackTrace();
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                News.error(e.getMessage());
            }
        }
@@ -3981,26 +4316,34 @@
     */
    public synchronized void ledReset() {
        for (LedSlave led : slaveProperties.getLed()) {
            // 获取输送线plc线程
            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, led.getDevpPlcId());
            // 命令集合
            boolean reset = true;
            for (Integer staNo : led.getStaArr()) {
                // 获取叉车站点
                StaProtocol staProtocol = devpThread.getStation().get(staNo);
                if (staProtocol == null) { continue; }
                if (staProtocol.getWorkNo() != 0) {
                    reset = false;
                    break;
            try {
                // 获取输送线plc线程
                DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, led.getDevpPlcId());
                // 命令集合
                boolean reset = true;
                for (Integer staNo : led.getStaArr()) {
                    // 获取叉车站点
                    StaProtocol staProtocol = devpThread.getStation().get(staNo);
                    if (staProtocol == null) {
                        continue;
                    }
                    if (staProtocol.getWorkNo() != 0) {
                        reset = false;
                        break;
                    }
                }
            }
            // 获取led线程
            LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, led.getDevpPlcId());
            // led显示默认内容
            if (reset) {
                if (!MessageQueue.offer(SlaveType.Led, led.getId(), new Task(2, new ArrayList<>()))) {
                    News.error("{}号LED命令下发失败!!![ip:{}] [port:{}]", led.getId(), led.getIp(), led.getPort());
                // 获取led线程
                LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, led.getDevpPlcId());
                // led显示默认内容
                if (reset) {
                    if (!MessageQueue.offer(SlaveType.Led, led.getId(), new Task(2, new ArrayList<>()))) {
                        News.error("{}号LED复位命令下发失败!!![ip:{}] [port:{}]", led.getId(), led.getIp(), led.getPort());
                    } else {
//                        News.info("{}号LED复位命令下发成功!!![ip:{}] [port:{}]", led.getId(), led.getIp(), led.getPort());
                    }
                }
            } catch (Exception e) {
                News.error("LED异常" + led.getId());
            }
        }
    }
@@ -4013,7 +4356,9 @@
            SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, ste.getId());
            SteProtocol steProtocol = steThread.getSteProtocol();
            BasSte basSte = basSteService.selectById(ste.getId());
            if (Cools.isEmpty(steProtocol, basSte)) { continue; }
            if (Cools.isEmpty(steProtocol, basSte)) {
                continue;
            }
            try {
                // 在线 空闲   无作业标记   不在充电
                if (steProtocol.getMode() == 0
@@ -4100,7 +4445,9 @@
                    } else if (wrkCharge.getWrkSts() == 24L) {
                        // 小车行驶至充电位
                        if (steProtocol.statusType.equals(SteStatusType.IDLE) && steProtocol.getPakMk().equals("N")) {
                            if (steProtocol.getChargeStatus() == 1) { continue; }
                            if (steProtocol.getChargeStatus() == 1) {
                                continue;
                            }
                            // 命令下发区 --------------------------------------------------------------------------
                            SteCommand steCommand = new SteCommand();
                            steCommand.setSteNo(wrkCharge.getSteNo()); // 穿梭车编号
@@ -4120,7 +4467,9 @@
                            }
                        }
                    } else if (wrkCharge.getWrkSts() == 26) {
                        if (steProtocol.getChargeStatus() == 0) { continue; }
                        if (steProtocol.getChargeStatus() == 0) {
                            continue;
                        }
                        // 给输送线下发充电任务
                        SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, 1);
                        SteChargeType steChargeType = SteChargeType.get(wrkCharge.getLocNo());
@@ -4147,9 +4496,13 @@
    }
    public List<String> crn1DemoLocs = new ArrayList<String>(); public String crn1LastLoc = "";
    public List<String> crn2DemoLocs = new ArrayList<String>(); public String crn2LastLoc = "";
    public List<String> crn3DemoLocs = new ArrayList<String>(); public String crn3LastLoc = "";
    public List<String> crn1DemoLocs = new ArrayList<String>();
    public String crn1LastLoc = "";
    public List<String> crn2DemoLocs = new ArrayList<String>();
    public String crn2LastLoc = "";
    public List<String> crn3DemoLocs = new ArrayList<String>();
    public String crn3LastLoc = "";
    public synchronized void demo() {
        if (Cools.isEmpty(crn1DemoLocs)) {
            crn1DemoLocs = locMastService.getDemoNextLoc(1);
@@ -4184,7 +4537,9 @@
                SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, steNo);
                SteProtocol steProtocol = steThread.getSteProtocol();
                BasSte basSte = basSteService.selectById(steNo);
                if (Cools.isEmpty(steProtocol, basSte)) { continue; }
                if (Cools.isEmpty(steProtocol, basSte)) {
                    continue;
                }
                // 只有当穿梭车空闲 并且 无任务时才继续执行
                if (steProtocol.isIdle()) {
@@ -4266,7 +4621,9 @@
        }
        SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, wrkCharge.getSteNo());
        SteProtocol steProtocol = steThread.getSteProtocol();
        if (null == steProtocol) { return; }
        if (null == steProtocol) {
            return;
        }
        if (steProtocol.isIdle()) {
            // 31.生成演示ID
            if (wrkCharge.getWrkSts() == 31L) {
@@ -4276,7 +4633,7 @@
                if (!wrkChargeService.updateById(wrkCharge)) {
                    News.error("修改演示任务{}工作档 31.生成演示ID ==>> 32.小车走行 失败!", wrkCharge.getWrkNo());
                }
            // 33.小车待搬
                // 33.小车待搬
            } else if (wrkCharge.getWrkSts() == 33L) {
                LocMast locMast = locMastService.selectById(wrkCharge.getLocNo());
                // 堆垛机命令下发区 --------------------------------------------------------------------------
@@ -4306,7 +4663,7 @@
                        News.error("修改演示任务{}工作档 33.小车待搬 => 34.吊车搬运 失败!", wrkCharge.getWrkNo());
                    }
                }
            // 35.小车就绪
                // 35.小车就绪
            } else if (wrkCharge.getWrkSts() == 35L) {
                int steNo = steProtocol.getSteNo().intValue();
@@ -4351,10 +4708,10 @@
    /**
     * 因深库位阻塞,对浅库位进行移转
     */
    private synchronized void moveLocForDeepLoc(CrnSlave crn, LocMast shallowLoc){
    private synchronized void moveLocForDeepLoc(CrnSlave crn, LocMast shallowLoc) {
        try {
            String rows = "";
            switch (crn.getId()){
            switch (crn.getId()) {
                case 1:
                    rows = "3,4";
                    break;
@@ -4366,15 +4723,92 @@
                    break;
            }
            LocMast loc = null;
            List<LocMast> locs = locMastService.selectList(new EntityWrapper<LocMast>().eq("crn_no",crn.getId())
                                                .eq("loc_type1",shallowLoc.getLocType1())
                                                .eq("loc_type2",shallowLoc.getLocType2())
                                                .eq("loc_sts","O")
                                                .last(" and row1 in (" + rows + ") order by bay1,lev1"));
            for (LocMast one : locs){
                if(Utils.getGroupRow(one.getLocNo()) != Utils.getGroupRow(shallowLoc.getLocNo())
                    || Utils.getBay(one.getLocNo()) != Utils.getBay(shallowLoc.getLocNo())
                    || Utils.getLev(one.getLocNo()) != Utils.getLev(shallowLoc.getLocNo())){
            if (shallowLoc.getLocType2() == 3 || shallowLoc.getLocType2() == 1) {
                //低频混直接出库
                // 获取工作号
                int workNo = commonService.getWorkNo(0);
                Date now = new Date();
                // 保存工作档
                WrkMast wrkMast = new WrkMast();
                wrkMast.setWrkNo(workNo);
                wrkMast.setIoTime(now);
                wrkMast.setWrkSts(11L); // 工作状态:11.生成出库ID
                wrkMast.setIoType(101); // 入出库状态: 101.全板出库
                wrkMast.setIoPri((double) 9999);
                wrkMast.setCrnNo(crn.getId());
                wrkMast.setSourceLocNo(shallowLoc.getLocNo()); // 源库位
                if (shallowLoc.getCrnNo() == 1) {
                    wrkMast.setStaNo(100);
                    wrkMast.setSourceStaNo(108);
                } else if (shallowLoc.getCrnNo() == 2) {
                    wrkMast.setStaNo(100);
                    wrkMast.setSourceStaNo(104);
                } else {
                    wrkMast.setStaNo(200);
                    wrkMast.setSourceStaNo(208);
                }
//                wrkMast.setLocNo(loc.getLocNo()); // 目标库位
                wrkMast.setFullPlt("Y"); // 满板
                wrkMast.setPicking("N"); // 拣料
                wrkMast.setExitMk("N"); // 退出
                wrkMast.setEmptyMk(shallowLoc.getLocSts().equals("D") ? "Y" : "N"); // 空板
                wrkMast.setBarcode(shallowLoc.getBarcode()); // 托盘码
                wrkMast.setLinkMis("N");
                wrkMast.setAppeTime(now);
                wrkMast.setModiTime(now);
                int res = wrkMastMapper.insert(wrkMast);
                if (res == 0) {
                    throw new CoolException("保存工作档失败");
                }
                // 工作档明细保存
                if (shallowLoc.getLocSts().equals("F")) {
                    List<LocDetl> locDetls = locDetlService.selectList(new EntityWrapper<LocDetl>().eq("loc_no", shallowLoc.getLocNo()));
                    for (LocDetl locDetl : locDetls) {
                        WrkDetl wrkDetl = new WrkDetl();
                        wrkDetl.sync(locDetl);
                        wrkDetl.setWrkNo(workNo);
                        wrkDetl.setIoTime(now);
                        wrkDetl.setAnfme(locDetl.getAnfme());
                        wrkDetl.setAppeTime(now);
                        wrkDetl.setModiTime(now);
                        if (!wrkDetlService.insert(wrkDetl)) {
                            throw new CoolException("保存工作档明细失败");
                        }
                        // 生成对应的组托档
                        WaitPakin waitPakin = new WaitPakin();
                        waitPakin.sync(wrkDetl);
                        waitPakin.setModiTime(now);
                        waitPakin.setAppeTime(now);
                        waitPakinMapper.insert(waitPakin);
                    }
                }
                // 修改源库位状态
                if (shallowLoc.getLocSts().equals("D") || shallowLoc.getLocSts().equals("F")) {
                    shallowLoc.setLocSts("R"); // R.出库预约
                    shallowLoc.setModiTime(now);
                    if (!locMastService.updateById(shallowLoc)) {
                        throw new CoolException("更新源库位状态失败");
                    }
                } else {
                    throw new CoolException("源库位出库失败");
                }
                return;
            }
            List<LocMast> locs = locMastService.selectList(new EntityWrapper<LocMast>().eq("crn_no", crn.getId())
                    .eq("loc_type1", shallowLoc.getLocType1())
                    .eq("loc_type2", shallowLoc.getLocType2())
                    .eq("loc_sts", "O")
                    .last(" and row1 in (" + rows + ") order by bay1,lev1"));
            for (LocMast one : locs) {
                if (Utils.getGroupRow(one.getLocNo()) != Utils.getGroupRow(shallowLoc.getLocNo())
                        || Utils.getBay(one.getLocNo()) != Utils.getBay(shallowLoc.getLocNo())
                        || Utils.getLev(one.getLocNo()) != Utils.getLev(shallowLoc.getLocNo())) {
                    Integer steNo = this.hasCar(one.getLocNo());
                    if (steNo != null) {
@@ -4401,7 +4835,7 @@
            if (null == loc) {
                News.error("深库位出库 --- 浅库位阻塞异常! 待移转浅库位:" + shallowLoc.getLocNo());
//                return;
                return;
//                throw new CoolException("深库位出库 --- 浅库位阻塞异常! 待移转浅库位:" + shallowLoc.getLocNo());
            }
@@ -4483,10 +4917,10 @@
                SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                for (DevpSlave.Sta inSta : devp.getInSta()) {
                    Integer sourceStaNo = inSta.getStaNo()==103 ? 104 : 204;
                    Integer sourceStaNo = inSta.getStaNo() == 103 ? 104 : inSta.getStaNo() == 113 ? 104 : 204;
                    WrkMast pakout = wrkMastMapper.selectWorkingPakout(sourceStaNo);
                    switch (inSta.getStaNo()) {
                        case 103://1F
                        case 103://1F1
                            if (pakout != null) {
                                if (devpThread.ioModeOf1F != IoModeType.PAKOUT_MODE) {
                                    // 出库切换中
@@ -4496,7 +4930,7 @@
//                                            && !devpThread.getStation().get(inSta.getStaNo()+1).isLoading()
//                                            && devpThread.getStation().get(inSta.getStaNo()+1).getWorkNo()==0) {
//                                        // 出库模式
                                        devpThread.ioModeOf1F = IoModeType.PAKOUT_MODE;
                                    devpThread.ioModeOf1F = IoModeType.PAKOUT_MODE;
//                                    }
                                }
                            } else {
@@ -4504,7 +4938,7 @@
                                devpThread.ioModeOf1F = IoModeType.PAKIN_MODE;
                            }
                            break;
                        case 203://2F
                        case 203://1F2
                            if (pakout != null) {
                                if (devpThread.ioModeOf2F != IoModeType.PAKOUT_MODE) {
                                    // 出库切换中
@@ -4514,12 +4948,165 @@
//                                            && !devpThread.getStation().get(inSta.getStaNo()-1).isLoading()
//                                            && devpThread.getStation().get(inSta.getStaNo()-1).getWorkNo()==0) {
//                                        // 出库模式
                                        devpThread.ioModeOf2F = IoModeType.PAKOUT_MODE;
                                    devpThread.ioModeOf2F = IoModeType.PAKOUT_MODE;
//                                    }
                                }
                            } else {
                                // 入库模式
                                devpThread.ioModeOf2F = IoModeType.PAKIN_MODE;
                            }
                            break;
//                        case 113://2F1
//                            if (pakout != null) {
//                                if (devpThread.ioModeOf3F != IoModeType.PAKOUT_MODE) {
//                                    // 出库切换中
////                                    devpThread.ioModeOf2F = IoModeType.PAKOUT_BOOTING;
////                                    WrkMast pakin = wrkMastMapper.selectWorkingPakin(inSta.getStaNo());
////                                    if (pakin == null && !devpThread.getStation().get(inSta.getStaNo()).isLoading()
////                                            && !devpThread.getStation().get(inSta.getStaNo()-1).isLoading()
////                                            && devpThread.getStation().get(inSta.getStaNo()-1).getWorkNo()==0) {
////                                        // 出库模式
//                                    devpThread.ioModeOf3F = IoModeType.PAKOUT_MODE;
////                                    }
//                                }
//                            } else {
//                                // 入库模式
//                                devpThread.ioModeOf3F = IoModeType.PAKIN_MODE;
//                            }
//                            break;
//                        case 213://2F2
//                            if (pakout != null) {
//                                if (devpThread.ioModeOf4F != IoModeType.PAKOUT_MODE) {
//                                    // 出库切换中
////                                    devpThread.ioModeOf2F = IoModeType.PAKOUT_BOOTING;
////                                    WrkMast pakin = wrkMastMapper.selectWorkingPakin(inSta.getStaNo());
////                                    if (pakin == null && !devpThread.getStation().get(inSta.getStaNo()).isLoading()
////                                            && !devpThread.getStation().get(inSta.getStaNo()-1).isLoading()
////                                            && devpThread.getStation().get(inSta.getStaNo()-1).getWorkNo()==0) {
////                                        // 出库模式
//                                    devpThread.ioModeOf4F = IoModeType.PAKOUT_MODE;
////                                    }
//                                }
//                            } else {
//                                // 入库模式
//                                devpThread.ioModeOf4F = IoModeType.PAKIN_MODE;
//                            }
//                            break;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public synchronized void ioConvert2F() {
        try {
            // 根据输送线plc遍历
            for (DevpSlave devp : slaveProperties.getDevp()) {
                if (devp.getId() == 1) {
                    continue;
                }
                SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                for (DevpSlave.Sta inSta : devp.getInSta()) {
                    Integer staNoEnd = inSta.getStaNo() == 113 ? 114 : 214;
                    WrkMast pakout = wrkMastMapper.selectWorkingPakoutTwoF(staNoEnd);
                    boolean sign = true;
                    int[] staNos = new int[3];
                    switch (inSta.getStaNo()) {
                        case 113://2F1
                            staNos = new int[]{112, 113, 114};
                            for (int staNo : staNos) {
                                StaProtocol staProtocol = devpThread.getStation().get(staNo);
                                if (Cools.isEmpty(staProtocol)) continue;
                                if (!staProtocol.isAutoing() || staProtocol.isLoading() || staProtocol.getWorkNo() > 0) {
                                    sign = false;
                                }
                            }
                            if (sign) {
                                if (pakout != null) {
                                    if (devpThread.ioModeOf3F != IoModeType.PAKOUT_MODE) {
                                        // 出库切换中
//                                    devpThread.ioModeOf2F = IoModeType.PAKOUT_BOOTING;
//                                    WrkMast pakin = wrkMastMapper.selectWorkingPakin(inSta.getStaNo());
//                                    if (pakin == null && !devpThread.getStation().get(inSta.getStaNo()).isLoading()
//                                            && !devpThread.getStation().get(inSta.getStaNo()-1).isLoading()
//                                            && devpThread.getStation().get(inSta.getStaNo()-1).getWorkNo()==0) {
//                                        // 出库模式
                                        devpThread.ioModeOf3F = IoModeType.PAKOUT_MODE;
//                                    }
                                    }
                                } else {
                                    CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, 1);
                                    CrnProtocol crnProtocol = crnThread.getCrnProtocol();
                                    if (crnProtocol != null) {
                                        if (crnProtocol.getTaskNo() != 0) {
                                            if (crnProtocol.isStatusEnd()) {
                                                // 出库模式
                                                devpThread.ioModeOf3F = IoModeType.PAKOUT_MODE;
                                            } else {
                                                // 入库模式
                                                devpThread.ioModeOf3F = IoModeType.PAKIN_MODE;
                                            }
                                        } else {
                                            // 入库模式
                                            devpThread.ioModeOf3F = IoModeType.PAKIN_MODE;
                                        }
                                    } else {
                                        // 入库模式
                                        devpThread.ioModeOf3F = IoModeType.PAKIN_MODE;
                                    }
                                }
                            }
                            break;
                        case 213://2F2
                            staNos = new int[]{212, 213, 214};
                            for (int staNo : staNos) {
                                StaProtocol staProtocol = devpThread.getStation().get(staNo);
                                if (Cools.isEmpty(staProtocol)) continue;
                                if (!staProtocol.isAutoing() || staProtocol.isLoading()) {
                                    sign = false;
                                }
                            }
                            if (sign) {
                                if (pakout != null) {
                                    if (devpThread.ioModeOf4F != IoModeType.PAKOUT_MODE) {
                                        // 出库切换中
//                                    devpThread.ioModeOf2F = IoModeType.PAKOUT_BOOTING;
//                                    WrkMast pakin = wrkMastMapper.selectWorkingPakin(inSta.getStaNo());
//                                    if (pakin == null && !devpThread.getStation().get(inSta.getStaNo()).isLoading()
//                                            && !devpThread.getStation().get(inSta.getStaNo()-1).isLoading()
//                                            && devpThread.getStation().get(inSta.getStaNo()-1).getWorkNo()==0) {
//                                        // 出库模式
                                        devpThread.ioModeOf4F = IoModeType.PAKOUT_MODE;
//                                    }
                                    }
                                } else {
                                    CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, 3);
                                    CrnProtocol crnProtocol = crnThread.getCrnProtocol();
                                    if (crnProtocol != null) {
                                        if (crnProtocol.getTaskNo() != 0) {
                                            if (crnProtocol.isStatusEnd()) {
                                                // 出库模式
                                                devpThread.ioModeOf3F = IoModeType.PAKOUT_MODE;
                                            } else {
                                                // 入库模式
                                                devpThread.ioModeOf3F = IoModeType.PAKIN_MODE;
                                            }
                                        } else {
                                            // 入库模式
                                            devpThread.ioModeOf3F = IoModeType.PAKIN_MODE;
                                        }
                                    } else {
                                        // 入库模式
                                        devpThread.ioModeOf3F = IoModeType.PAKIN_MODE;
                                    }
                                }
                            }
                            break;
                    }
@@ -4532,4 +5119,58 @@
        }
    }
    public synchronized void automaticallyTurnOffCharging() {
        // 获取当前时间戳
        long timestamp = System.currentTimeMillis();
        Date date = new Date(timestamp);
        TimeZone timeZone = TimeZone.getTimeZone("Asia/Shanghai");
        java.util.Calendar calendar = java.util.Calendar.getInstance(timeZone);
        calendar.setTime(date);
        int hour = calendar.get(java.util.Calendar.HOUR_OF_DAY);
        if (hour > 8 && hour < 18) {
            for (SteSlave ste : slaveProperties.getSte()) {
                SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, ste.getId());
                SteProtocol steProtocol = steThread.getSteProtocol();
                BasSte basSte = basSteService.selectById(ste.getId());
                if (Cools.isEmpty(steProtocol, basSte)) {
                    continue;
                }
                try {
                    // 在线 空闲   无作业标记   不在充电
                    if (steProtocol.getMode() == 0
                            || !steProtocol.statusType.equals(SteStatusType.IDLE)
                            || basSte.getPakMk().equals("Y")
                            || steProtocol.getChargeStatus() == 0
                    ) {
                        continue;
                    }
                    if (!steProtocol.isEnable()) {
                        continue;
                    }
                    if (steProtocol.getCharge() > Float.parseFloat(basSte.getChargeLine())) {
                        WrkCharge wrkCharge = wrkChargeService.selectWorking(steProtocol.getSteNo().intValue());
                        if (wrkCharge == null) {
                            if (steProtocol.getChargeStatus() == 1) {
                                SteCommand steCommand = new SteCommand();
                                steCommand.setSteNo(ste.getId()); // 穿梭车编号
                                steCommand.setTaskNo(9999); // 工作号
                                steCommand.setTaskMode(SteTaskModeType.CLOSE_CHARGE);
                                if (!MessageQueue.offer(SlaveType.Ste, ste.getId(), new Task(2, steCommand))) {
                                    News.error("穿梭车命令下发失败,穿梭车号={},任务数据={}", ste.getId(), JSON.toJSON(steCommand));
                                }
                                try {
                                    Thread.sleep(500);
                                } catch (Exception e) {
                                }
                            }
                        }
                    }
                } catch (Exception e) {
                    News.error("自动关闭充电出错,联系管理员!" + hour + "点;" + ste.getId() + "号小车;");
                }
            }
        }
    }
}