#
TQS
2023-04-20 f1b654fc854bd0a88ef7ee9815f8cfaf33e30007
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java
@@ -105,7 +105,7 @@
            // 遍历入库口
            for (DevpSlave.Sta inSta : devp.getInSta()) {
                // 获取入库站信息
                DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                StaProtocol staProtocol = devpThread.getStation().get(inSta.getStaNo());
                if (staProtocol == null) {
                    continue;
@@ -113,11 +113,34 @@
                    staProtocol = staProtocol.clone();
                }
                Short workNo = staProtocol.getWorkNo();
                // 判断是否满足入库条件
                if (staProtocol.isAutoing() && staProtocol.isLoading()
                        && staProtocol.isInEnable()
                        && !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;
                        }
                    }
                    // 获取条码扫描仪信息
                    BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, inSta.getBarcode());
@@ -303,29 +326,59 @@
                        continue;
                    }
                    short staNo;
                    List<BasDevp> basDevps1 = basDevpMapper.getLoading(103);
                    List<BasDevp> basDevps2 = basDevpMapper.getLoading(203);
                    switch (wrkMast.getSourceStaNo()) {
                        case 104:
                        case 108:
                            staNo = 103;
                            List<BasDevp> basDevps1 = basDevpMapper.getLoading(103);
                            if (basDevps1.size()!=0){
                            if (basDevps1.size()!=0 && basDevps2.size()!=0){
                                continue;
                            } else if (basDevps1.size()!=0){
                                staNo = 203;
                            }
                            List<WrkMast> wrkMasts1 = wrkMastMapper.selectWrkStsAndIoType(103);
                            List<WrkMast> wrkMasts1 = wrkMastMapper.selectWrkStsAndIoType((int)staNo);
                            if (wrkMasts1.size()!=0){
                                continue;
                                boolean flag = false;
                                for (WrkMast wrkMast1:wrkMasts1){
                                    if (!wrkMast1.getWrkNo().equals(wrkMast.getWrkNo())){
                                        flag = true;
                                        break;
                                    }
                                }
                                if (flag)  {
                                    News.error("MainServiceImpl  324行"+"104站点存在货物,捡料盘点货物暂时不重新入库!!!");
                                    continue;
                                }
                            }
                            break;
                        case 204:
                        case 208:
                            staNo = 203;
                            List<BasDevp> basDevps2 = basDevpMapper.getLoading(203);
                            if (basDevps2.size()!=0){
                            if (basDevps1.size()!=0 && basDevps2.size()!=0){
                                continue;
                            } else if (basDevps2.size()!=0){
                                staNo = 103;
                            }
                            List<WrkMast> wrkMasts2 = wrkMastMapper.selectWrkStsAndIoType(203);
//                            if (basDevps2.size()!=0){
//                                continue;
//                            }
                            List<WrkMast> wrkMasts2 = wrkMastMapper.selectWrkStsAndIoType((int)staNo);
                            if (wrkMasts2.size()!=0){
                                continue;
                                boolean flag = false;
                                for (WrkMast wrkMast1:wrkMasts2){
                                    if (!wrkMast1.getWrkNo().equals(wrkMast.getWrkNo())){
                                        flag = true;
                                        break;
                                    }
                                }
                                if (flag)  {
                                    News.error("MainServiceImpl  346行"+"204站点存在货物,捡料盘点货物暂时不重新入库!!!");
                                    continue;
                                }
                            }
                            break;
                        default:
@@ -450,7 +503,7 @@
                        Integer code = jsonObject.getInteger("code");
                        if (code.equals(200)) {
                            StartupDto dto = jsonObject.getObject("data", StartupDto.class);
                            News.info("再入库获取新库位成功,返回数据===>>", JSON.toJSON(dto));
//                            // 获取目标站
//                            Wrapper<StaDesc> wrapper = new EntityWrapper<StaDesc>()
//                                    .eq("type_no", wrkMast.getIoType() - 50)
@@ -478,6 +531,7 @@
                            // 更新工作档数据状态
                            wrkMast.setIoType(wrkMast.getIoType() - 50); // 入出库类型: 103->53,104->54,107->57
                            wrkMast.setWrkSts(2L); // 工作状态: 2.设备上走
                            wrkMast.setIoPri(13D);
                            wrkMast.setSourceStaNo(pickSta.getStaNo()); // 源站
                            wrkMast.setStaNo(dto.getStaNo()); // 目标站
                            wrkMast.setCrnNo(dto.getCrnNo());
@@ -521,6 +575,9 @@
                            ledThread.errorReset();
                            if(wrkMast.getIoType()>100){
                                throw new CoolException("再入库更新工作档失败,不能给PLC下发任务===>>" + wrkMast.getWrkNo());
                            }
                            // 更新站点信息 且 下发plc命令
                            staProtocol.setWorkNo(wrkMast.getWrkNo().shortValue());
                            staProtocol.setStaNo(wrkMast.getStaNo().shortValue());
@@ -701,6 +758,7 @@
                        // 更新工作档状态为 17.出库完成
                        wrkMast.setWrkSts(17L);
                        wrkMast.setSteNo(0);
                        wrkMast.setIoPri(15D);
                        wrkMast.setCrnEndTime(new Date());
                        if (wrkMastMapper.updateById(wrkMast) != 0) {
                            // 复位堆垛机
@@ -791,18 +849,18 @@
                continue;
            }
            //加强判断,只要存在移库任务,说明出库任务未完全结束,不执行入库任务
            WrkMast one = wrkMastMapper.selectLocMoveData(slave.getId());
            if(!Cools.isEmpty(one)){
                News.error("入库 ===>> 存在移库未完成任务,不能入库。移库任务号={},堆垛机号={}", one.getWrkNo(), slave.getId());
                continue;
            }
            // 获取工作状态为 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());
                continue;
            }
            //加强判断,只要存在移库任务,说明出库任务未完全结束,不执行入库任务
            WrkMast one = wrkMastMapper.selectLocMoveData(slave.getId());
            if(!Cools.isEmpty(one)){
                News.error("入库 ===>> 存在移库未完成任务,不能入库。移库任务号={},堆垛机号={}", one.getWrkNo(), slave.getId());
//                continue;
            }
            // 判断是否已存在小车绑定任务
@@ -1006,11 +1064,54 @@
                continue;
            }
            if (wrkMast.getWrkSts() == 11 && (wrkMast.getIoType() == 103 || wrkMast.getIoType() == 107)){
                Integer sour = wrkMast.getStaNo();
                List<WrkMast> wrkMasts = wrkMastMapper.selectWrkStsAndIoType(sour);
                if (wrkMasts.size() > 0){
                    continue;
            // 获取堆垛机出库站信息
            SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, crnStn.getDevpPlcId());
            StaProtocol staProtocol = devpThread.getStation().get(crnStn.getStaNo());
            if (staProtocol == null) {
                continue;
            } else {
                staProtocol = staProtocol.clone();
            }
            if (wrkMast.getCrnNo().equals(2)){
                if (wrkMast.getStaNo() == 103 && devpThread.ioModeOf1F != IoModeType.PAKOUT_MODE) {
                    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());
                    return false;
                }
                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号堆垛机暂时禁止出库!!!");
                        return false;
                    }
                    //如果存在目标站300且正在执行的拣料/盘点任务,则2号堆垛机不允许做拣料/盘点出库
                    WrkMast one = wrkMastService.selectOne(new EntityWrapper<WrkMast>()
                            .eq("sta_no",300)
                            .last(" and wrk_sts>11 and io_type in (103,107) "));
                    if(!Cools.isEmpty(one)){
                        News.error("MainServiceImpl  1099行"+"存在捡料、盘点未入库货物,2号堆垛机暂时禁止出库!!!");
                        continue;
                    }
                }
                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号堆垛机暂时禁止全板出库!!!");
                                return false;
                            }
                        }
                    }
                }
            }
@@ -1022,7 +1123,7 @@
                    .last(" and wrk_sts < 10"));
            if(one1 != null){
                News.error("{}出库任务无法作业,因入库任务已绑定小车!", wrkMast.getWrkNo());
                continue;
                return false;
            }
            //加强判断,确保因出库导致的移库整套任务全部结束后,才能执行下一笔出库任务。只有库位完成移库回去全部任务后,才认为当组出库任务完成
@@ -1044,63 +1145,81 @@
            //出库库位不是最外层库位,判断浅库位组是否都为空,或存在库位移转任务
            boolean flag = false;
            if(!locMastService.isOutMost(wrkMast.getSourceLocNo())){
            if(!locMastService.isOutMost(wrkMast.getSourceLocNo())) {
                WrkMast wrkMastMove = wrkMastMapper.selectLocMoveWorking(slave.getId());
                if(wrkMastMove != null && wrkMast.getWrkNo() == 11){
                if (wrkMastMove != null && wrkMast.getWrkNo() == 11) {
                    continue;
                }
                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 (null == waitWrkMast) {
                                News.error("{}库位异常,未检索到相应工作档!", shallowLocNo);
                            } else {
                                //iotype=11,wrksts=17,说明货物已经移库到暂存库位,等待回原库位,此时允许继续出库
                                if (waitWrkMast.getIoType()!=11 || waitWrkMast.getWrkSts()!=17) {
                                    waitWrkMast.setIoPri((double) 9999);
                                    waitWrkMast.setModiTime(new Date());
                                    if (wrkMastMapper.updateById(waitWrkMast) == 0) {
                                        News.error("调整工作档优先级失败!工作号={}", waitWrkMast.getWrkNo());
                WrkMast two = wrkMastMapper.selectWorking1(slave.getId(), wrkMast.getWrkNo());
                if (two != null) {//2号机有在执行任务时,禁止生成移库工作档
                    continue;
                } else {
                    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 (null == waitWrkMast) {
                                    News.error("{}库位异常,未检索到相应工作档!", shallowLocNo);
                                } else {
                                    //iotype=11,wrksts=17,说明货物已经移库到暂存库位,等待回原库位,此时允许继续出库
                                    if (waitWrkMast.getIoType() != 11 || waitWrkMast.getWrkSts() != 17) {
                                        waitWrkMast.setIoPri((double) 9999);
                                        waitWrkMast.setModiTime(new Date());
                                        if (wrkMastMapper.updateById(waitWrkMast) == 0) {
                                            News.error("调整工作档优先级失败!工作号={}", waitWrkMast.getWrkNo());
                                        }
                                        if (waitWrkMast.getWrkSts() != 17) {
                                            flag = true;
                                        }
                                        break;
                                    }
                                }
                            } else if (shallowLoc.getLocSts().equals("F") || shallowLoc.getLocSts().equals("D")) {
                                if (null == waitWrkMast) {
                                    // 生成一笔移库任务工作档、改变浅库位的源库/目标库 库位状态
                                    // 没有作业中的出库任务时,才能生成移库任务
                                    WrkMast one2 = wrkMastService.selectOne(new EntityWrapper<WrkMast>()
                                            .eq("crn_no", slave.getId())
                                            .last(" and wrk_sts in (12,13,14,15,16)"));
                                    if (one2 == null) {
                                        moveLocForDeepLoc(slave, shallowLoc);
                                        // 置顶任务
                                        wrkMast.setIoPri((double) 9999);
                                        wrkMastMapper.updateById(wrkMast);
                                    } else {
                                        News.error("浅库位阻塞时,且浅库位存在作业中出库任务!工作号={}", one2.getWrkNo());
                                    }
                                    flag = true;
                                    break;
                                } else {
                                    if (waitWrkMast.getWrkSts() != 18) {
                                        News.error("库位出库到堆垛机站 ===>> 库位状态在库,但是浅库位已存在工作档任务!出库库位={},浅库位号={}", shallowLoc.getLocNo());
                                        flag = true;
                                        break;
                                    }
                                }
                            }
                        } else if (shallowLoc.getLocSts().equals("F") || shallowLoc.getLocSts().equals("D")) {
                            if (null == waitWrkMast) {
                                // 生成一笔移库任务工作档、改变浅库位的源库/目标库 库位状态
                                // 没有作业中的出库任务时,才能生成移库任务
                                WrkMast one2 = wrkMastService.selectOne(new EntityWrapper<WrkMast>()
                                        .eq("crn_no",slave.getId())
                                        .last(" and wrk_sts in (12,13,14,15,16)"));
                                if(one2==null) {
                                    moveLocForDeepLoc(slave, shallowLoc);
                                }
                            } else if (shallowLoc.getLocSts().equals("Q") || shallowLoc.getLocSts().equals("S")) {
                                News.error("库位出库到堆垛机站 ===>> 浅库位库位状态为入库预约!出库库位={},浅库位号={}", shallowLoc.getLocNo());
                                flag = true;
                                break;
                            } else {
                                if (waitWrkMast.getWrkSts()!=18) {
                                    News.error("库位出库到堆垛机站 ===>> 库位状态在库,但是浅库位已存在工作档任务!出库库位={},浅库位号={}", shallowLoc.getLocNo());
                                    flag = true;
                                    break;
                                }
                            }
                        } else if (shallowLoc.getLocSts().equals("Q") || shallowLoc.getLocSts().equals("S")){
                            News.error("库位出库到堆垛机站 ===>> 浅库位库位状态为入库预约!出库库位={},浅库位号={}", shallowLoc.getLocNo());
                            flag = true;
                            break;
                        }
                            //20230307 ADD,再加一次判断,当浅库位状态不为O时,不执行当前出库任务
                            if (shallowLoc != null && !shallowLoc.getLocSts().equals("O")) {
                                News.error("做了浅库位阻塞处理后反复判断,浅库位状态不为O ===>> 浅库位库位状态为入库预约!出库库位={},浅库位号={}", wrkMast.getSourceLocNo(), shallowLoc.getLocNo());
                                flag = true;
                                break;
                            }
                        }
                    }
                }
            }
            if(flag){
                continue;
                return false;
            }
            // 工作档状态判断
@@ -1111,17 +1230,10 @@
            // 获取源库位信息
            LocMast sourceSta = locMastService.selectById(wrkMast.getSourceLocNo());
            if (!sourceSta.getLocSts().equals("R") &&!sourceSta.getLocSts().equals("P")) {
                News.error("出库操作库位状态不符合--状态, 库位号={},库位状态={}", wrkMast.getLocNo(), sourceSta.getLocSts());
                News.error("出库操作库位状态不符合--状态, 库位号={},库位状态={}", wrkMast.getSourceLocNo(), sourceSta.getLocSts());
                continue;
            }
            // 获取堆垛机出库站信息
            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, crnStn.getDevpPlcId());
            StaProtocol staProtocol = devpThread.getStation().get(crnStn.getStaNo());
            if (staProtocol == null) {
                continue;
            } else {
                staProtocol = staProtocol.clone();
            }
            // 查询站点详细信息
            BasDevp staDetl = basDevpService.selectById(crnStn.getStaNo());
            if (staDetl == null) {
@@ -1520,14 +1632,19 @@
            String locNo = Utils.append(row, bay, lev);
            String[] deeplocs  = Utils.getDeepLocs(locNo);
            if(!Cools.isEmpty(deeplocs)){
                boolean ret = false;
                for(String deepLocNo : deeplocs) {
                    LocMast deepLoc = locMastService.selectById(deepLocNo);
                    WrkMast waitWrkMast = wrkMastMapper.selectByLocNo1(deepLocNo);
                    if(deepLoc != null && !deepLoc.getLocSts().equals("F")
                            && !deepLoc.getLocSts().equals("D")
                            && !deepLoc.getLocSts().equals("O")
                            && (waitWrkMast!=null && waitWrkMast.getWrkSts()<17)){
                            && (waitWrkMast!=null && waitWrkMast.getWrkSts()<18)){
                        News.error("移库再回库时,深库位组深库位状态为作业中 ===>> deepLoc={},loc_sts={}", deepLoc.getLocNo(), deepLoc.getLocSts());
                        if(waitWrkMast.getIoPri()<9999) {//调高优先级
                            waitWrkMast.setIoPri(waitWrkMast.getIoPri() + 1);
                            wrkMastService.updateById(waitWrkMast);
                        }
                        flag = true;
                        break;
                    }
@@ -1552,14 +1669,47 @@
                            }
                        }
                        LocMast sourceLoc = locMastService.selectById(wrkMast.getSourceLocNo());
                        if(sourceLoc.getLocSts().equals("F") || 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)) {
                                throw new CoolException("更新移库回库目标库位状态失败");
                            }
                        }
                        ret = true;
                        break;
                    }
                }
                if(ret == false && !flag){//深库位都不为O
                    LocMast curLoc = locMastService.selectById(locNo);
                    if(curLoc != null && curLoc.getLocSts().equals("O")){
                        //修改移库工作档
                        wrkMast.setSourceLocNo(wrkMast.getLocNo());
                        wrkMast.setIoPri((double)9999);
                        wrkMast.setWrkSts(2L);
                        wrkMast.setLocNo(locNo);
                        wrkMast.setSteNo(0);
                        wrkMast.setModiTime(new Date());
                        if (wrkMastMapper.updateById(wrkMast) == 0) {
                            News.error("修改工作档状态 17.移库完成 => 2.移库再入库中 失败!!,工作号={}", wrkMast.getWrkNo());
                        }
                        if(curLoc.getLocSts().equals("O")){
                            curLoc.setLocSts("S"); // S.入库预约
                            curLoc.setModiTime(new Date());
                            if (!locMastService.updateById(curLoc)) {
                                News.error("双深库位 --- 更新目标库位状态失败! 待移转浅库位:" + curLoc.getLocNo());
                                throw new CoolException("更新移库回库目标库位状态失败");
                            }
                        }
                        LocMast sourceLoc = locMastService.selectById(wrkMast.getSourceLocNo());
                        if(sourceLoc.getLocSts().equals("R") || sourceLoc.getLocSts().equals("D")){
                            sourceLoc.setLocSts("R"); // R.出库预约
                            sourceLoc.setModiTime(new Date());
                            if (!locMastService.updateById(sourceLoc)) {
                                throw new CoolException("更新移库回库目标库位状态失败");
                            }
                        }
                    }
                }
            }
@@ -1697,6 +1847,64 @@
                    if (wrkMast.getWrkSts() == 3L) {
                        this.carMoveIn(wrkMast, wrkMast.getSteNo(), crnProtocol);
                    }
                }
            } else { //2023-4-20, 最外层库位,搬走小车直接移库
                // 判断小车是否在最外层库位,如果是则搬走,如果不是,则直接堆垛机入库
                Integer steNo = this.hasCar(wrkMast.getLocNo());
                // 有小车
                if (steNo != null) {
                    // 小车行走到堆垛机待搬移点
                    if (wrkMast.getWrkSts() == 2L && wrkMast.getSteNo() == 0) {
                        // 没有其他任务
                        if (null == wrkMastMapper.selectPakin(slave.getId(), steNo)) {
                            this.letCarBeReady(wrkMast, steNo, wrkMast.getLocNo());
                        }
                    }
                    // 小车搬走
                    if (wrkMast.getWrkSts() == 3L) {
                        this.carMoveOut(wrkMast, steNo, crnProtocol);
                    }
                    // 没有小车
                } else {
                    // 当前入库库位组没有小车 堆垛机则去站点取货入库
                    // case 1:从始至终库位组都没有小车,没有迁出小车动作,所以工作状态 = 2
                    // case 2:堆垛机已经搬出小车,有迁出小车动作,所以工作状态 = 6
                    if (wrkMast.getWrkSts() == 2L && wrkMast.getSteNo() == 0) {
                        // 已经存在吊车执行任务时,则过滤
                        if (wrkMastMapper.selectWorking(slave.getId()) != null) {
                            return;
                        }
                        // 堆垛机入库 命令下发区 --------------------------------------------------------------------------
                        CrnCommand crnCommand = new CrnCommand();
                        crnCommand.setCrnNo(slave.getId()); // 堆垛机编号
                        crnCommand.setTaskNo(wrkMast.getWrkNo().shortValue()); // 工作号
                        crnCommand.setAckFinish((short) 0);  // 任务完成确认位
                        crnCommand.setCommand((short) 0);
                        crnCommand.setTaskMode(CrnTaskModeType.LOC_MOVE); // 任务模式:  库位移转
                        crnCommand.setSourcePosX(sourceLoc.getRow1().shortValue());     // 源库位排
                        crnCommand.setSourcePosY(sourceLoc.getBay1().shortValue());     // 源库位列
                        crnCommand.setSourcePosZ(sourceLoc.getLev1().shortValue());     // 源库位层
                        crnCommand.setDestinationPosX(Utils.getGroupRow(loc.getLocNo()).shortValue());     // 目标库位排
                        crnCommand.setDestinationPosY(loc.getBay1().shortValue());     // 目标库位列
                        crnCommand.setDestinationPosZ(loc.getLev1().shortValue());     // 目标库位层
                        if (!MessageQueue.offer(SlaveType.Crn, wrkMast.getCrnNo(), new Task(2, crnCommand))) {
                            News.error("堆垛机命令下发失败,堆垛机号={},任务数据={}", wrkMast.getCrnNo(), JSON.toJSON(crnCommand));
                        } else {
                            // 修改工作档状态  7.吊车入库中
                            Date now = new Date();
                            wrkMast.setWrkSts(7L);
                            wrkMast.setCrnStrTime(now);
                            wrkMast.setModiTime(now);
                            if (wrkMastMapper.updateById(wrkMast) == 0) {
                                News.error("修改工作档状态 {} => 7.吊车入库中 失败!!,工作号={}", wrkMast.getWrkSts$(), wrkMast.getWrkNo());
                            }
                            return;
                        }
                    }
                }
            }
        }
@@ -2226,6 +2434,10 @@
        SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, steNo);
        SteProtocol steProtocol = steThread.getSteProtocol();
        if (steProtocol == null) { return; }
        if(steProtocol.getLoad() == 1){
            News.error("小车上方有货,无法下发任务===>>{}", steNo);
            return;
        }
        if (steProtocol.isIdle() && steProtocol.getLoad() == 0) {
            // 堆垛机空闲
            if (crnProtocol.getStatusType().equals(CrnStatusType.IDLE) || crnProtocol.getTaskNo() == 0) {
@@ -2246,18 +2458,35 @@
                    crnCommand.setDestinationPosX(Utils.getGroupRow(locMast.getLocNo()).shortValue());     // 目标库位排
                    crnCommand.setDestinationPosY(locMast.getBay1().shortValue());     // 目标库位列
                    crnCommand.setDestinationPosZ(locMast.getLev1().shortValue());     // 目标库位层
                    if (!MessageQueue.offer(SlaveType.Crn, wrkMast.getCrnNo(), new Task(2, crnCommand))) {
                        News.error("堆垛机命令下发失败,堆垛机号={},任务数据={}", wrkMast.getCrnNo(), JSON.toJSON(crnCommand));
                    } else {
                    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());
                        // 修改工作档状态 3.小车待搬 => 4.迁入小车
                        // 修改工作档状态 3.小车待搬 => 6.小车待入
                        Date now = new Date();
                        wrkMast.setWrkSts(4L);
                        wrkMast.setWrkSts(6L);
                        wrkMast.setCrnStrTime(now);
                        wrkMast.setModiTime(now);
                        if (wrkMastMapper.updateById(wrkMast) == 0) {
                            News.error("修改工作档状态 3.小车待搬 => 4.迁入小车 失败!!,工作号={}", wrkMast.getWrkNo());
                            News.error("修改工作档状态 3.小车待搬 => 6.小车待入 失败!!,工作号={}", wrkMast.getWrkNo());
                        }
                    } else {
                        if (!MessageQueue.offer(SlaveType.Crn, wrkMast.getCrnNo(), new Task(2, crnCommand))) {
                            News.error("堆垛机命令下发失败,堆垛机号={},任务数据={}", wrkMast.getCrnNo(), JSON.toJSON(crnCommand));
                        } else {
                            // 修改穿梭车运行中排列层
                            steThread.modifyPos(Utils.getGroupRow(locMast.getLocNo()), locMast.getBay1(), locMast.getLev1());
                            // 修改工作档状态 3.小车待搬 => 4.迁入小车
                            Date now = new Date();
                            wrkMast.setWrkSts(4L);
                            wrkMast.setCrnStrTime(now);
                            wrkMast.setModiTime(now);
                            if (wrkMastMapper.updateById(wrkMast) == 0) {
                                News.error("修改工作档状态 3.小车待搬 => 4.迁入小车 失败!!,工作号={}", wrkMast.getWrkNo());
                            }
                        }
                    }
                // 出库搬
@@ -2367,7 +2596,7 @@
                    // 充电任务
                    WrkCharge wrkCharge = wrkChargeService.selectById(crnProtocol.getTaskNo());
                    if (wrkCharge == null) {
                        News.error("堆垛机处于等待确认且任务完成状态,但未找到工作档。堆垛机号={},工作号={}", crn.getId(), crnProtocol.getTaskNo());
                        News.error("堆垛机处于等待确认且任务完成状态,但未找到充电工作档。堆垛机号={},工作号={}", crn.getId(), crnProtocol.getTaskNo());
                        continue;
                    } else {
                        // 小车搬至指定库位完成
@@ -2616,7 +2845,7 @@
                            SteCommand steCommand = new SteCommand();
                            steCommand.setSteNo(wrkMast.getSteNo()); // 穿梭车编号
                            steCommand.setTaskNo(9999); // 工作号
                            steCommand.setTaskMode(SteTaskModeType.findWaiting(basSte.getRow())); // 任务模式:  去近点 等待堆垛机叉取
                            steCommand.setTaskMode(SteTaskModeType.findWaiting(basSte.getRow())); // 任务模式:  去待机位避让
//                        steCommand.setRow(Utils.getGroupRow(steProtocol.getRow().intValue()).shortValue());
//                        steCommand.setBay(steProtocol.getBay());
//                        steCommand.setLev(steProtocol.getLev());
@@ -2627,6 +2856,36 @@
                            News.error("修改工作档状态 4.迁入小车 => 6.小车待入 失败!!,工作号={}", wrkMast.getWrkNo());
                        }
                        // 入库 ===>> 迁出小车 完成
                    } else if (wrkMast.getWrkSts() == 5) {
                        // 5.迁出小车 ==> 6.小车待入
                        wrkMast.setWrkSts(6L);
                        Date now = new Date();
                        wrkMast.setCrnEndTime(now);
                        wrkMast.setModiTime(now);
                        // 修改成功后复位堆垛机
                        if (wrkMastMapper.updateById(wrkMast) > 0) {
                            // 堆垛机复位
                            crnThread.setResetFlag(true);
                            // 穿梭车重新定位排列层
                            SteThread steThread = (SteThread) SlaveConnection.get(SlaveType.Ste, wrkMast.getSteNo());
                            if (!steThread.confirmPos()) {
                                News.error("{}号穿梭车重新定位失败!作业工作档任务号:{}", wrkMast.getSteNo(), wrkMast.getWrkNo());
                            }
                            // 穿梭车去待机位
                            BasSte basSte = basSteService.selectById(wrkMast.getSteNo());
                            SteCommand steCommand = new SteCommand();
                            steCommand.setSteNo(wrkMast.getSteNo()); // 穿梭车编号
                            steCommand.setTaskNo(9999); // 工作号
                            steCommand.setTaskMode(SteTaskModeType.findWaiting(basSte.getRow())); // 任务模式:  去近点 等待堆垛机叉取
//                        steCommand.setRow(Utils.getGroupRow(steProtocol.getRow().intValue()).shortValue());
//                        steCommand.setBay(steProtocol.getBay());
//                        steCommand.setLev(steProtocol.getLev());
                            if (!MessageQueue.offer(SlaveType.Ste, wrkMast.getSteNo(), new Task(2, steCommand))) {
                                News.error("穿梭车待机位命令下发失败,穿梭车号={},任务数据={}", wrkMast.getSteNo(), JSON.toJSON(steCommand));
                            }
                        } else {
                            News.error("修改工作档状态 5.迁出小车 => 6.小车待入 失败!!,工作号={}", wrkMast.getWrkNo());
                        }
                    }
                    if (wrkMast.getWrkSts() == 16) {
                        Date now = new Date();
@@ -2645,7 +2904,7 @@
                            String locSts = "";
                            // 库位移转判断是否为空板移转
                            if (wrkMast.getEmptyMk().equals("N")) {
                                locSts = "F";
                                locSts = "R";
                                // 转移库存明细数据: 库存号 由工作档源库位变为目标库位
                                if (!locDetlService.updateLocNo(wrkMast.getLocNo(), wrkMast.getSourceLocNo())) {
                                    News.error("库位移转 ===>> 转移库存明细数据失败;[源库位={}],[目标库位={}]", wrkMast.getSourceLocNo(), wrkMast.getLocNo());
@@ -2812,10 +3071,11 @@
                News.info("ste[id={}] 收到等待WCS确认信号,但是任务号(地址V824)为0", steProtocol.getSteNo());
            }
            if (steProtocol.getWaiting() && steProtocol.getTaskNo() != 0 && steProtocol.getStatus() == 10) {
            if (steProtocol.getWaiting() && steProtocol.getTaskNo() != 0) {
                News.info("ste[id={}] 执行工作档完成,任务号={}, 穿梭车状态={}", steProtocol.getSteNo(), steProtocol.getTaskNo(), steProtocol.getStatus());
                if (steProtocol.getTaskNo() == 9999) {
                    steThread.setResetFlag(true);
                    News.info("ste[id={}]小车复位标记 9999 成功!!,工作号={}", steProtocol.getSteNo(), 9999);
                } else {
                    // 查询是否有待入库的任务
                    WrkMast wrkMast = wrkMastMapper.selectCarWaiting(steProtocol.getTaskNo().intValue());
@@ -2832,6 +3092,7 @@
                                    News.error("修改充电任务状态 21.准备充电 ===>> 22.小车待搬 失败!!,工作号={}", wrkCharge.getWrkNo());
                                } else {
                                    steThread.setResetFlag(true);
                                    News.info("ste[id={}]小车复位标记 21.准备充电 ===>> 22.小车待搬 成功!!,工作号={}", steProtocol.getSteNo(), wrkCharge.getWrkNo());
                                }
                            } else if (wrkCharge.getWrkSts() == 25) {
                                // 25.小车去充电 ===>> 26.等待充电
@@ -2840,6 +3101,7 @@
                                    News.error("修改充电任务状态 25.小车去充电 ===>> 26.等待充电 失败!!,工作号={}", wrkCharge.getWrkNo());
                                } else {
                                    steThread.setResetFlag(true);
                                    News.info("ste[id={}]小车复位标记 25.小车去充电 ===>> 26.等待充电 成功!!,工作号={}", steProtocol.getSteNo(), wrkCharge.getWrkNo());
                                }
                            }  else if (wrkCharge.getWrkSts() == 32) {
                                // 32.小车走行 ===>> 33.小车待搬
@@ -2848,6 +3110,7 @@
                                    News.error("修改演示任务状态 25.小车去充电 ===>> 26.等待充电 失败!!,工作号={}", wrkCharge.getWrkNo());
                                } else {
                                    steThread.setResetFlag(true);
                                    News.info("ste[id={}]小车复位标记 25.小车去充电 ===>> 26.等待充电 成功!!,工作号={}", steProtocol.getSteNo(), wrkCharge.getWrkNo());
                                }
                            } else if (wrkCharge.getWrkSts() == 36) {
                                // 36.小车走行 ===>> 37.演示完成
@@ -2856,9 +3119,13 @@
                                    News.error("修改演示任务状态 36.小车走行 ===>> 37.演示完成 失败!!,工作号={}", wrkCharge.getWrkNo());
                                } else {
                                    steThread.setResetFlag(true);
                                    News.info("ste[id={}]小车复位标记 36.小车走行 ===>> 37.演示完成 成功!!,工作号={}", steProtocol.getSteNo(), wrkCharge.getWrkNo());
                                }
                            }
                        }
                    }else{
                        News.info("ste[id={}] 执行工作档完成,任务号={}, 穿梭车状态={},工作档状态={}",
                                steProtocol.getSteNo(), steProtocol.getTaskNo(), steProtocol.getStatus(), wrkMast.getWrkSts());
                    }
                    if (wrkMast == null) { continue; }
@@ -2868,9 +3135,10 @@
                            wrkMast.setWrkSts(3L);
                            wrkMast.setModiTime(now);
                            if (wrkMastMapper.updateById(wrkMast) == 0) {
                                News.error("修改工作档状态 2.设备上走 => 3.小车待搬 失败!!,工作号={}", wrkMast.getWrkNo());
                                News.error("ste[id={}] 修改工作档状态 2.设备上走 => 3.小车待搬 失败!!,工作号={}", steProtocol.getSteNo(), wrkMast.getWrkNo());
                            } else {
                                steThread.setResetFlag(true);
                                News.info("ste[id={}]小车复位标记 修改工作档状态 2.设备上走 => 3.小车待搬 成功!!,工作号={}", steProtocol.getSteNo(), wrkMast.getWrkNo());
                            }
                            break;
                        case 8:
@@ -2881,6 +3149,7 @@
                                News.error("修改工作档状态 8.小车搬入库 => 9.入库完成 失败!!,工作号={}", wrkMast.getWrkNo());
                            } else {
                                steThread.setResetFlag(true);
                                News.info("ste[id={}]小车复位标记 修改工作档状态 8.小车搬入库 => 9.入库完成 成功!!工作号={}", steProtocol.getSteNo(), wrkMast.getWrkNo());
                            }
                            break;
                        case 11:
@@ -2911,6 +3180,7 @@
                                News.error("修改工作档状态 11.生成出库ID => 12.小车待搬 失败!!,工作号={}", wrkMast.getWrkNo());
                            } else {
                                steThread.setResetFlag(true);
                                News.info("ste[id={}]小车复位标记 修改工作档状态 11.生成出库ID => 12.小车待搬 成功!!,工作号={}", steProtocol.getSteNo(), wrkMast.getWrkNo());
                            }
                            break;
                        case 14:
@@ -2921,6 +3191,7 @@
                                News.error("修改工作档状态 14.小车搬出库 => 15.等待吊车 失败!!,工作号={}", wrkMast.getWrkNo());
                            } else {
                                steThread.setResetFlag(true);
                                News.info("ste[id={}]小车复位标记 修改工作档状态 14.小车搬出库 => 15.等待吊车 成功!!,工作号={}", steProtocol.getSteNo(), wrkMast.getWrkNo());
                            }
                            break;
                    }
@@ -3180,13 +3451,36 @@
            // 遍历空板入库口
            for (DevpSlave.Sta emptyInSta : devp.getEmptyInSta()) {
                // 获取空板入库站信息
                DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                StaProtocol staProtocol = devpThread.getStation().get(emptyInSta.getStaNo());
                if (staProtocol == null) {
                    continue;
                } else {
                    staProtocol = staProtocol.clone();
                }
                //20230201. 2号堆垛机有出库任务时,禁止新板入库
                if (staProtocol.isLoading() && staProtocol.getWorkNo() == 9995) {
                    if ( emptyInSta.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  storeEmptyPlt"+"103为出库模式,禁止入库,退回入库口。!!!");
                        continue;
                    }
                    if ( emptyInSta.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  storeEmptyPlt"+"203为出库模式,禁止入库,退回入库口。!!!");
                        continue;
                    }
                }
                // 站点条件判断
                if (staProtocol.isAutoing()
                        && staProtocol.isLoading()
@@ -3313,6 +3607,7 @@
                }
                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 -> {
@@ -3521,6 +3816,7 @@
                                    News.error("修改充电任务状态 26.等待充电 ===> 28.完成充电 失败!!,工作号={}", wrkCharge.getWrkNo());
                                } else {
                                    steThread.setResetFlag(true);
                                    News.info("修改充电任务状态 26.等待充电 ===> 28.完成充电 成功!!,工作号={}", wrkCharge.getWrkNo());
                                }
                            }
                        } else {
@@ -3762,8 +4058,31 @@
                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())){
                    loc = one;
                    break;
                    boolean success = true;
                    List<String> insideLoc = Utils.getGroupInsideLoc(one.getLocNo());
                    for (String inside : insideLoc) {
                        LocMast locMast = locMastService.selectById(inside);
                        if(Cools.isEmpty(locMast)){
                            continue;
                        }
                        if (locMast.getLocSts().equals("P")
                                || locMastService.selectById(inside).getLocSts().equals("R")
                                || locMastService.selectById(inside).getLocSts().equals("S")
                                || locMastService.selectById(inside).getLocSts().equals("Q")) {
                            success = false; break;
                        }
                    }
                    Integer steNo = this.hasCar(one.getLocNo());
                    if (steNo != null) {
                        continue;
                    }
                    if (success) {
                        loc = one;
                        break;
                    }
                }
            }
@@ -3840,4 +4159,63 @@
        }
    }
    /**
     * 入出库模式切换函数
     */
    public synchronized void ioConvert() {
        try {
            // 根据输送线plc遍历
            for (DevpSlave devp : slaveProperties.getDevp()) {
                SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                for (DevpSlave.Sta inSta : devp.getInSta()) {
                    Integer sourceStaNo = inSta.getStaNo()==103 ? 104 : 204;
                    WrkMast pakout = wrkMastMapper.selectWorkingPakout(sourceStaNo);
                    switch (inSta.getStaNo()) {
                        case 103://1F
                            if (pakout != null) {
                                if (devpThread.ioModeOf1F != IoModeType.PAKOUT_MODE) {
                                    // 出库切换中
//                                    devpThread.ioModeOf1F = 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.ioModeOf1F = IoModeType.PAKOUT_MODE;
//                                    }
                                }
                            } else {
                                // 入库模式
                                devpThread.ioModeOf1F = IoModeType.PAKIN_MODE;
                            }
                            break;
                        case 203://2F
                            if (pakout != null) {
                                if (devpThread.ioModeOf2F != 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.ioModeOf2F = IoModeType.PAKOUT_MODE;
//                                    }
                                }
                            } else {
                                // 入库模式
                                devpThread.ioModeOf2F = IoModeType.PAKIN_MODE;
                            }
                            break;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}