自动化立体仓库 - WCS系统
#
tzsk
2023-11-23 d460aca01c59e5df7de68545eb5cfc929ec87d03
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java
@@ -25,6 +25,8 @@
import com.zy.core.model.protocol.*;
import com.zy.core.properties.SlaveProperties;
import com.zy.core.thread.*;
import com.zy.system.entity.Config;
import com.zy.system.service.ConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@@ -102,6 +104,12 @@
    private RedisUtil redisUtil;
    @Autowired
    private WrkMastLocMapper wrkMastLocMapper;
    @Autowired
    private BasLiftOptService basLiftOptService;
    @Autowired
    private ConfigService configService;
    @Autowired
    private NavigateMapUtils navigateMapUtils;
    /**
@@ -465,116 +473,155 @@
                        continue;
                    }
                    try {
                        // 访问 WMS 获取入库库位
                        LocTypeDto locTypeDto = new LocTypeDto(staProtocol);
                        SearchLocParam param = new SearchLocParam();
                        param.setWrkNo(wrkMast.getWrkNo());
                        param.setIoType(wrkMast.getIoType());
                        param.setSourceStaNo(pickSta.getStaNo());
//                        param.setLocType1(locTypeDto.getLocType1());
                        String response = new HttpHandler.Builder()
                                .setUri(wmsUrl)
                                .setPath("/rpc/pakin/loc/v1")
                                .setJson(JSON.toJSONString(param))
                                .build()
                                .doPost();
                        JSONObject jsonObject = JSON.parseObject(response);
                        LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, pickSta.getLed());
                        Integer code = jsonObject.getInteger("code");
                        if (code.equals(200)) {
                            StartupDto dto = jsonObject.getObject("data", StartupDto.class);
                    // 保存工作主档历史档
                    if (wrkMastMapper.saveWrkMastLog(wrkMast.getWrkNo()) == 0) {
                        throw new CoolException(wrkMast.getWrkNo() + "保存工作主档历史档失败");
                    }
//                            // 获取目标站
//                            Wrapper<StaDesc> wrapper = new EntityWrapper<StaDesc>()
//                                    .eq("type_no", wrkMast.getIoType() - 50)
//                                    .eq("stn_no", pickSta.getStaNo()) // 作业站点 = 拣料出库的目标站
//                                    .eq("crn_no", dto.getCrnNo()); // 堆垛机号
//                            StaDesc staDesc = staDescService.selectOne(wrapper);
//                            if (Cools.isEmpty(staDesc)) {
//                                News.error("入库路径不存在!type_no={},stn_no={},crn_no={}", wrkMast.getIoType(), pickSta.getStaNo(), wrkMast.getCrnNo());
//                                continue;
//                            }
//                            // 堆垛机站点(目标站)
//                            Integer staNo = staDesc.getCrnStn();
                    String sourceLocNo = wrkMast.getSourceLocNo().trim();
                    LiftStaProtocol liftStaProtocol = NyLiftUtils.getLiftStaByLev(pickSta.getLiftNo(), Utils.getLev(sourceLocNo));//获取回库提升机目标站
                    if (liftStaProtocol == null) {
                        continue;
                    }
                            // 保存工作明细档历史档
//                        if (wrkMastMapper.saveWrkDetlLog(wrkMast.getWrkNo()) == 0) {
//                            throw new CoolException("保存工作明细档历史档失败");
//                        }
                            // 保存工作主档历史档
                            if (wrkMastMapper.saveWrkMastLog(wrkMast.getWrkNo()) == 0) {
                                throw new CoolException(wrkMast.getWrkNo() + "保存工作主档历史档失败");
                            }
                            String sourceLocNo = wrkMast.getSourceLocNo().trim();
                            LiftStaProtocol liftStaProtocol = NyLiftUtils.getLiftStaByLev(pickSta.getLiftNo(), Utils.getLev(sourceLocNo));//获取回库提升机目标站
                            if (liftStaProtocol == null) {
                                continue;
                            }
                            // 更新工作档数据状态
                            wrkMast.setIoType(wrkMast.getIoType() - 50); // 入出库类型: 103->53,104->54,107->57
                            wrkMast.setWrkSts(2L); // 工作状态: 2.设备上走
                            wrkMast.setSourceStaNo(pickSta.getStaNo()); // 源站
                    // 更新工作档数据状态
                    wrkMast.setIoType(wrkMast.getIoType() - 50); // 入出库类型: 103->53,104->54,107->57
                    wrkMast.setWrkSts(2L); // 工作状态: 2.设备上走
                    wrkMast.setSourceStaNo(pickSta.getStaNo()); // 源站
//                            wrkMast.setStaNo(dto.getStaNo()); // 目标站
//                            wrkMast.setCrnNo(dto.getCrnNo());
                            wrkMast.setStaNo(liftStaProtocol.getStaNo());//目标站
                            wrkMast.setLocNo(sourceLocNo); // 目标库位 = 出库时的源库位
                            wrkMast.setShuttleNo(null); // 穿梭车清空
                            wrkMast.setModiTime(new Date());
                            if (wrkMastMapper.updateById(wrkMast) == 0) {
                                throw new CoolException(wrkMast.getWrkNo() + "更新工作档数据状态失败");
                            }
                            if (wrkMastMapper.setSteEmpty(wrkMast.getWrkNo()) == 0) {
                                throw new CoolException(wrkMast.getWrkNo() + "更新工作档数据状态失败");
                            }
                            // 修改库位状态 Q.拣料/盘点/并板再入库
                            LocMast locMast = locMastService.selectById(sourceLocNo);
                            locMast.setLocSts("Q");
                            locMast.setModiTime(new Date());
                            if (!locMastService.updateById(locMast)) {
                                throw new CoolException("修改库位状态失败");
                            }
//                            // 更新站点信息 且 下发plc命令
//                            staProtocol.setWorkNo(wrkMast.getWrkNo().shortValue());
//                            staProtocol.setStaNo(wrkMast.getStaNo().shortValue());
//                            devpThread.setPakMk(staProtocol.getSiteId(), false);
//                            boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                            if (!result) {
//                                News.error("发布命令至输送线队列失败!!! [plc编号:{}]", devp.getId());
//                            }
                            barcodeThread.setBarcode("");//清理条码
                        } else if (code == 500){
                            if (ledThread != null) {
                                String errorMsg = jsonObject.getString("msg");
                                if (!Cools.isEmpty(errorMsg)) {
                                    MessageQueue.offer(SlaveType.Led, pickSta.getLed(), new Task(3, errorMsg));
                                }
                            }
                            News.error("请求接口失败!!!url:{};request:{};response:{}", wmsUrl + "/rpc/pakin/loc/v1", JSON.toJSONString(param), response);
                        } else {
//                            staProtocol.setWorkNo((short) 32002);
//                            staProtocol.setStaNo(pickSta.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");
//                                String errorMsg = barcode + "托盘识别异常,请先进行组托!";
                                MessageQueue.offer(SlaveType.Led, pickSta.getLed(), new Task(3, errorMsg));
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    wrkMast.setStaNo(liftStaProtocol.getStaNo());//目标站
                    wrkMast.setLocNo(sourceLocNo); // 目标库位 = 出库时的源库位
                    wrkMast.setShuttleNo(null); // 穿梭车清空
                    wrkMast.setLiftNo(null);// 提升机清空
                    wrkMast.setModiTime(new Date());
                    if (wrkMastMapper.updateById(wrkMast) == 0) {
                        throw new CoolException(wrkMast.getWrkNo() + "更新工作档数据状态失败");
                    }
                    if (wrkMastMapper.setSteEmpty(wrkMast.getWrkNo()) == 0) {
                        throw new CoolException(wrkMast.getWrkNo() + "更新工作档数据状态失败");
                    }
                    // 修改库位状态 Q.拣料/盘点/并板再入库
                    LocMast locMast = locMastService.selectById(sourceLocNo);
                    locMast.setLocSts("Q");
                    locMast.setModiTime(new Date());
                    if (!locMastService.updateById(locMast)) {
                        throw new CoolException("修改库位状态失败");
                    }
                    barcodeThread.setBarcode("");//清理条码
//                    try {
//                        // 访问 WMS 获取入库库位
//                        LocTypeDto locTypeDto = new LocTypeDto(staProtocol);
//                        SearchLocParam param = new SearchLocParam();
//                        param.setWrkNo(wrkMast.getWrkNo());
//                        param.setIoType(wrkMast.getIoType());
//                        param.setSourceStaNo(pickSta.getStaNo());
////                        param.setLocType1(locTypeDto.getLocType1());
//                        String response = new HttpHandler.Builder()
//                                .setUri(wmsUrl)
//                                .setPath("/rpc/pakin/loc/v1")
//                                .setJson(JSON.toJSONString(param))
//                                .build()
//                                .doPost();
//                        JSONObject jsonObject = JSON.parseObject(response);
//                        LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, pickSta.getLed());
//                        Integer code = jsonObject.getInteger("code");
//                        if (code.equals(200)) {
//                            StartupDto dto = jsonObject.getObject("data", StartupDto.class);
//
////                            // 获取目标站
////                            Wrapper<StaDesc> wrapper = new EntityWrapper<StaDesc>()
////                                    .eq("type_no", wrkMast.getIoType() - 50)
////                                    .eq("stn_no", pickSta.getStaNo()) // 作业站点 = 拣料出库的目标站
////                                    .eq("crn_no", dto.getCrnNo()); // 堆垛机号
////                            StaDesc staDesc = staDescService.selectOne(wrapper);
////                            if (Cools.isEmpty(staDesc)) {
////                                News.error("入库路径不存在!type_no={},stn_no={},crn_no={}", wrkMast.getIoType(), pickSta.getStaNo(), wrkMast.getCrnNo());
////                                continue;
////                            }
////                            // 堆垛机站点(目标站)
////                            Integer staNo = staDesc.getCrnStn();
//
//                            // 保存工作明细档历史档
////                        if (wrkMastMapper.saveWrkDetlLog(wrkMast.getWrkNo()) == 0) {
////                            throw new CoolException("保存工作明细档历史档失败");
////                        }
//                            // 保存工作主档历史档
//                            if (wrkMastMapper.saveWrkMastLog(wrkMast.getWrkNo()) == 0) {
//                                throw new CoolException(wrkMast.getWrkNo() + "保存工作主档历史档失败");
//                            }
//
//                            String sourceLocNo = wrkMast.getSourceLocNo().trim();
//                            LiftStaProtocol liftStaProtocol = NyLiftUtils.getLiftStaByLev(pickSta.getLiftNo(), Utils.getLev(sourceLocNo));//获取回库提升机目标站
//                            if (liftStaProtocol == null) {
//                                continue;
//                            }
//
//                            // 更新工作档数据状态
//                            wrkMast.setIoType(wrkMast.getIoType() - 50); // 入出库类型: 103->53,104->54,107->57
//                            wrkMast.setWrkSts(2L); // 工作状态: 2.设备上走
//                            wrkMast.setSourceStaNo(pickSta.getStaNo()); // 源站
////                            wrkMast.setStaNo(dto.getStaNo()); // 目标站
////                            wrkMast.setCrnNo(dto.getCrnNo());
//                            wrkMast.setStaNo(liftStaProtocol.getStaNo());//目标站
//                            wrkMast.setLocNo(sourceLocNo); // 目标库位 = 出库时的源库位
//                            wrkMast.setShuttleNo(null); // 穿梭车清空
//                            wrkMast.setLiftNo(null);// 提升机清空
//                            wrkMast.setModiTime(new Date());
//                            if (wrkMastMapper.updateById(wrkMast) == 0) {
//                                throw new CoolException(wrkMast.getWrkNo() + "更新工作档数据状态失败");
//                            }
//                            if (wrkMastMapper.setSteEmpty(wrkMast.getWrkNo()) == 0) {
//                                throw new CoolException(wrkMast.getWrkNo() + "更新工作档数据状态失败");
//                            }
//
//                            // 修改库位状态 Q.拣料/盘点/并板再入库
//                            LocMast locMast = locMastService.selectById(sourceLocNo);
//                            locMast.setLocSts("Q");
//                            locMast.setModiTime(new Date());
//                            if (!locMastService.updateById(locMast)) {
//                                throw new CoolException("修改库位状态失败");
//                            }
//
////                            // 更新站点信息 且 下发plc命令
////                            staProtocol.setWorkNo(wrkMast.getWrkNo().shortValue());
////                            staProtocol.setStaNo(wrkMast.getStaNo().shortValue());
////                            devpThread.setPakMk(staProtocol.getSiteId(), false);
////                            boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
////                            if (!result) {
////                                News.error("发布命令至输送线队列失败!!! [plc编号:{}]", devp.getId());
////                            }
//
//                            barcodeThread.setBarcode("");//清理条码
//
//                        } else if (code == 500){
//                            if (ledThread != null) {
//                                String errorMsg = jsonObject.getString("msg");
//                                if (!Cools.isEmpty(errorMsg)) {
//                                    MessageQueue.offer(SlaveType.Led, pickSta.getLed(), new Task(3, errorMsg));
//                                }
//                            }
//                            News.error("请求接口失败!!!url:{};request:{};response:{}", wmsUrl + "/rpc/pakin/loc/v1", JSON.toJSONString(param), response);
//                        } else {
////                            staProtocol.setWorkNo((short) 32002);
////                            staProtocol.setStaNo(pickSta.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");
////                                String errorMsg = barcode + "托盘识别异常,请先进行组托!";
//                                MessageQueue.offer(SlaveType.Led, pickSta.getLed(), new Task(3, errorMsg));
//                            }
//                        }
//
//                    } catch (Exception e) {
//                        e.printStackTrace();
//                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//                    }
                }
            }
@@ -587,7 +634,7 @@
     */
    public synchronized void initRealtimeBasMap() {
        for (int i = 1; i <= 10; i++) {//总共四层楼
            Object data = redisUtil.get("realtimeBasMap_" + i);
            Object data = redisUtil.get(RedisKeyType.MAP.key + i);
            if (data == null) {//redis地图数据为空,从数据库中获取
                BasMap basMap = basMapService.selectLatestMap(i);
                if (basMap == null) {
@@ -609,7 +656,7 @@
                }
                //将数据库地图数据存入redis
                redisUtil.set("realtimeBasMap_" + i, JSON.toJSONString(basMap));
                redisUtil.set(RedisKeyType.MAP.key + i, JSON.toJSONString(basMap));
            }
        }
    }
@@ -620,7 +667,7 @@
    public synchronized void restartTaskFromRedis() {
        HashMap<Object, Object> map = redisUtil.getRedis();
        for (Object key : map.keySet()) {
            if (key.toString().contains("lift_wrk_no_")) {//提升机任务
            if (key.toString().contains(RedisKeyType.LIFT.key)) {//提升机任务
                LiftRedisCommand redisCommand = JSON.parseObject(map.get(key).toString(), LiftRedisCommand.class);
                if (redisCommand == null) {
                    continue;
@@ -643,7 +690,7 @@
                liftProtocol.setTaskNo(redisCommand.getWrkNo());//将提升机线程分配任务号
                liftProtocol.setProtocolStatus(LiftProtocolStatusType.WORKING);//工作状态
            }else if(key.toString().contains("shuttle_wrk_no_")){//四向穿梭车任务
            }else if(key.toString().contains(RedisKeyType.SHUTTLE.key)){//四向穿梭车任务
                ShuttleRedisCommand redisCommand = JSON.parseObject(map.get(key).toString(), ShuttleRedisCommand.class);
                if (redisCommand == null) {
                    continue;
@@ -690,6 +737,7 @@
            // 判断是否满足入库条件,自动、空闲、有物
            if (!(liftStaProtocol.getModel() && !liftStaProtocol.getBusy() && liftStaProtocol.getHasTray())) {
                News.info("{}任务,输送站点状态不满足入库。输送站点:{}", wrkMast.getWrkNo(), JSON.toJSONString(liftStaProtocol));
                continue;
            }
@@ -750,7 +798,8 @@
    public boolean shuttleInExecuteStep1(WrkMast wrkMast, LiftStaProtocol liftStaProtocol) {
        if (wrkMast.getWrkSts() == 4) {
            if (wrkMast.getShuttleNo() == null) {//没有绑定小车,进行调度
                shuttleDispatchUtils.dispatchShuttle(wrkMast.getWrkNo(), liftStaProtocol.getLocNo());//调度小车到货物所在输送站点进行取货
                boolean result = shuttleDispatchUtils.dispatchShuttle(wrkMast.getWrkNo(), liftStaProtocol.getLocNo());//调度小车到货物所在输送站点进行取货
                News.info("{}任务,调度小车{}系统等待中", wrkMast.getWrkNo(), result ? "成功" : "失败");
                return false;
            }
@@ -764,16 +813,19 @@
                return false;
            }
            if (!shuttleProtocol.isIdle()) {
                News.info("{}任务,{}小车忙碌中", wrkMast.getWrkNo(), shuttleProtocol.getShuttleNo());
                return false;
            }
            //判断小车令牌是否未被占领
            if (shuttleProtocol.getToken() != 0) {
                News.info("{}任务,{}小车,令牌已被独占,禁止派发任务", wrkMast.getWrkNo(), shuttleProtocol.getShuttleNo());
                return false;//小车已被独占,禁止再派发任务
            }
            //判断小车是否存在移动任务
            WrkMast hasMoveWorking = wrkMastMapper.selectShuttleHasMoveWorking(wrkMast.getShuttleNo());
            if (hasMoveWorking != null) {
                News.info("{}任务,{}小车,存在移动任务,禁止派发任务", wrkMast.getWrkNo(), shuttleProtocol.getShuttleNo());
                return false;//存在移动任务,禁止执行入库任务
            }
@@ -781,12 +833,14 @@
            if (!shuttleProtocol.getCurrentLocNo().equals(liftStaProtocol.getLocNo())) {
                //小车不在输送站点位置
                shuttleDispatchUtils.dispatchShuttle(wrkMast.getWrkNo(), liftStaProtocol.getLocNo(), wrkMast.getShuttleNo());//调度小车到货物所在输送站点进行取货
                News.info("{}任务,{}小车,未到达输送站点,系统等待中", wrkMast.getWrkNo(), shuttleProtocol.getShuttleNo());
                return false;
            }
            //小车已抵达输送站点位置,进行搬运货物
            NyShuttleOperaResult result = NyShuttleOperaUtils.getShuttleTransportCommands(wrkMast.getShuttleNo(), wrkMast.getWrkNo(), shuttleProtocol.getCurrentLocNo(), wrkMast.getLocNo());
            if (result == null) {//路径计算失败
                News.info("{}任务,{}小车,路径计算失败,系统等待中", wrkMast.getWrkNo(), shuttleProtocol.getShuttleNo());
                return false;
            }
@@ -837,6 +891,7 @@
            wrapper.eq("stn_no", wrkMast.getStaNo());//出库站点编号
            StaDesc staDesc = staDescService.selectOne(wrapper);
            if (staDesc == null) {
                News.info("{}任务,出库路径不存在", wrkMast.getWrkNo());
                return false;//出库路径不存在
            }
@@ -846,8 +901,29 @@
                return false;//出库站点不存在
            }
            if (!basDevp.getAutoing().equals("Y")) {
                News.info("{}任务,{}站点,不是自动状态",wrkMast.getWrkNo(),basDevp.getDevNo());
                return false;//不是自动状态
            }
            if (!basDevp.getOutEnable().equals("Y")) {
                News.info("{}任务,{}站点,没有可出信号", wrkMast.getWrkNo(), basDevp.getDevNo());
                return false;//出库站点不可出
            }
            Integer liftNo = basDevp.getLiftNo();//搜索出库提升机是否存在入库任务,如存在禁止出库
            List<WrkMast> liftWrkMasts = wrkMastMapper.selectInWrkMastByLiftNo(liftNo);
            if (!liftWrkMasts.isEmpty()) {
                News.info("{}任务,{}号提升机,存在入库任务,系统禁止出库", wrkMast.getWrkNo(), liftNo);
                return false;//存在入库任务,禁止出库
            }
            //同库位组校验
            List<String> outerLoc = Utils.getGroupOuterLoc(wrkMast.getSourceLocNo());
            List<LocMast> outerLocMasts = locMastService.selectNotEmptyLocNos(outerLoc);
            if (!outerLocMasts.isEmpty()) {
                News.info("{}任务,浅库位存在货物,系统等待中", wrkMast.getWrkNo());
                return false;//浅库位存在未执行任务
            }
            //获取源站
@@ -857,11 +933,13 @@
            }
            if (!(liftStaProtocol.getModel() && !liftStaProtocol.getBusy() && !liftStaProtocol.getHasTray())) {
                News.info("{}任务,{}内部输送站,不满足自动、空闲、无托盘状态", wrkMast.getWrkNo(), liftStaProtocol.getStaNo());
                return false;//站点必须自动、空闲、没有托盘
            }
            if (wrkMast.getShuttleNo() == null) {//没有绑定小车,进行调度
                shuttleDispatchUtils.dispatchShuttle(wrkMast.getWrkNo(), wrkMast.getSourceLocNo());//调度小车到货物所在库位进行取货
                boolean result = shuttleDispatchUtils.dispatchShuttle(wrkMast.getWrkNo(), wrkMast.getSourceLocNo());//调度小车到货物所在库位进行取货
                News.info("{}任务,调度小车{}系统等待中。", wrkMast.getWrkNo(), result ? "成功" : "失败");
                return false;
            }
@@ -875,10 +953,12 @@
                return false;
            }
            if (!shuttleProtocol.isIdle()) {
                News.info("{}任务,{}小车,忙碌中", wrkMast.getWrkNo(), shuttleProtocol.getShuttleNo());
                return false;
            }
            //判断小车令牌是否未被占领
            if (shuttleProtocol.getToken() != 0) {
                News.info("{}任务,{}小车,令牌已被独占,禁止派发任务", wrkMast.getWrkNo(), shuttleProtocol.getShuttleNo());
                return false;//小车已被独占,禁止再派发任务
            }
@@ -886,12 +966,14 @@
            if (!shuttleProtocol.getCurrentLocNo().equals(wrkMast.getSourceLocNo())) {
                //小车不在输送站点位置
                shuttleDispatchUtils.dispatchShuttle(wrkMast.getWrkNo(), wrkMast.getSourceLocNo(), wrkMast.getShuttleNo());//调度小车到货物所在库位进行取货
                News.info("{}任务,{}小车,未到达输送站点,系统等待中", wrkMast.getWrkNo(), shuttleProtocol.getShuttleNo());
                return false;
            }
            //小车已抵达货物位置,进行搬运货物
            NyShuttleOperaResult result = NyShuttleOperaUtils.getShuttleTransportCommands(wrkMast.getShuttleNo(), wrkMast.getWrkNo(), wrkMast.getSourceLocNo(), liftStaProtocol.getLocNo());//将货物搬运至提升机输送站点
            if (result == null) {//出库路径计算失败
                News.info("{}任务,{}小车,路径计算失败,系统等待中", wrkMast.getWrkNo(), shuttleProtocol.getShuttleNo());
                return false;
            }
@@ -929,8 +1011,6 @@
            }
            //四向穿梭车状态为等待确认、小车处于空闲状态
            if (shuttleProtocol.getProtocolStatus() == ShuttleProtocolStatusType.WAITING.id  //任务完成等待确认
                    && shuttleProtocol.getTaskNo() != 0
                    && shuttleProtocol.getFree() == ShuttleStatusType.IDLE.id
@@ -1040,11 +1120,13 @@
            }
            if (!liftProtocol.isIdle()) {
                News.info("{}号提升机,忙碌中", liftSlave.getId());
                continue;
            }
            //判断提升机令牌是否被占用
            if (liftProtocol.getToken() != 0) {
                News.info("{}号提升机,令牌已被独占", liftSlave.getId());
                continue;
            }
@@ -1058,6 +1140,7 @@
                //搜索是否有其他任务占用了提升机,如果占用提升机的任务和当前任务相同,则运行执行
                WrkMast wrkMast1 = wrkMastMapper.selectLiftWrkMast(liftProtocol.getLiftNo().intValue());
                if (wrkMast1 != null && wrkMast1.getWrkNo().intValue() != wrkMast.getWrkNo().intValue()) {
                    News.info("{}号提升机,被其他任务{}占用且和当前任务{}不相同,禁止派发", liftSlave.getId(), wrkMast1.getWrkNo(), wrkMast.getWrkNo());
                    continue;
                }
@@ -1093,7 +1176,22 @@
            }
            if (!sourceBasDevp.getInEnable().equals("Y")) {
                News.info("{}任务,{}源站,没有可入信号", wrkMast.getWrkNo(), sourceBasDevp.getDevNo());
                return false;//站点不可入
            }
            //判断提升机整个三楼是否都处于入库模式
            Integer outInModel1 = Utils.getOutInModelByLift(sourceBasDevp.getLiftNo(), 1);
            Integer outInModel2 = Utils.getOutInModelByLift(sourceBasDevp.getLiftNo(), 5);
            Integer outInModel3 = Utils.getOutInModelByLift(sourceBasDevp.getLiftNo(), 8);
            if (outInModel1 == null || outInModel2 == null || outInModel3 == null) {
                News.info("{}任务,没有出入库模式", wrkMast.getWrkNo());
                return false;//不存在出入库模式
            }
            if (outInModel1 == 2 || outInModel2 == 2 && outInModel3 == 2) {
                News.info("{}任务,有站点处于出库模式,禁止入库", wrkMast.getWrkNo());
                return false;//只要有一个处于出库模式,禁止入库
            }
            LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, sourceBasDevp.getLiftNo());
@@ -1105,26 +1203,31 @@
                return false;
            }
            if (!liftProtocol.isIdle()) {
                News.info("{}任务,{}号提升机,忙碌中", wrkMast.getWrkNo(), liftProtocol.getLiftNo());
                return false;
            }
            //判断提升机令牌是否未被占领
            if (liftProtocol.getToken() != 0) {
                News.info("{}任务,{}号提升机,令牌已被独占,禁止派发", wrkMast.getWrkNo(), liftProtocol.getLiftNo());
                return false;//提升机已被独占,禁止再派发任务
            }
            //判断提升机内是否有小车
            if (liftProtocol.getHasCar()) {
                News.info("{}任务,{}号提升机,提升机内部有小车,禁止派发", wrkMast.getWrkNo(), liftProtocol.getLiftNo());
                return false;//有小车,禁止派发
            }
            //判断提升机内是否有托盘
            if (liftProtocol.getHasTray()) {
                News.info("{}任务,{}号提升机,提升机内部有托盘,禁止派发", wrkMast.getWrkNo(), liftProtocol.getLiftNo());
                return false;//有托盘,禁止派发
            }
            //判断提升机是否有其他任务
            WrkMast liftWrkMast = wrkMastMapper.selectLiftWrkMast(liftThread.getSlave().getId());
            if (liftWrkMast != null) {
                News.info("{}任务,{}号提升机,当前提升机存在未完成任务,禁止派发", wrkMast.getWrkNo(), liftProtocol.getLiftNo());
                return false;//当前提升机存在未完成任务,等待下一次轮询
            }
@@ -1137,6 +1240,7 @@
            }
            if (targetStaProtocol.getHasTray()) {
                News.info("{}任务,{}号提升机,{}站点,提升机站点有托盘,禁止派发", wrkMast.getWrkNo(), liftProtocol.getLiftNo(), targetStaProtocol.getStaNo());
                return false;//提升机站点有托盘,禁止派发
            }
@@ -1144,7 +1248,7 @@
            //获取提升机命令
            NyLiftCommand liftCommand = NyLiftUtils.getLiftCommand(liftProtocol.getLiftNo().intValue(), NyLiftTaskModelType.MOVE_TRAY.id, startSta, targetSta, wrkMast.getWrkNo());
            if (wrkMast.getIoType() == 53) {
            if (wrkMast.getIoType() == 53 || wrkMast.getIoType() == 57) {
                //拣料再回库,重新分配设备工作号
                Random random = new Random();
                int deviceWrk = Math.abs((liftCommand.getTaskNo().intValue() + random.nextInt(9999)));//获取设备工作号
@@ -1193,10 +1297,31 @@
            //获取出库站点(目标站)
            BasDevp basDevp = basDevpService.selectById(wrkMast.getStaNo());
            if (basDevp == null) {
                News.info("{}任务,出库站点不存在,禁止派发", wrkMast.getWrkNo());
                return false;//出库站点不存在
            }
            //获取源站对应的牛眼提升机站点编号(起点编号)
            LiftStaProtocol liftStaProtocol = NyLiftUtils.getLiftStaByLev(basDevp.getLiftNo(), Utils.getLev(wrkMast.getSourceLocNo()));
            if (liftStaProtocol == null) {
                News.info("{}任务,找不到站点,禁止派发", wrkMast.getWrkNo());
                return false;//找不到站点
            }
            Integer startSta = liftStaProtocol.getStaNo();
            NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
            if (shuttleProtocol.getCurrentLocNo().equals(liftStaProtocol.getLocNo())) {
                //小车还在输送站点
                //调度小车避让
                boolean result = Utils.searchEmptyGroupToMoveShuttle(Utils.getLev(wrkMast.getSourceLocNo()), wrkMast.getShuttleNo(), shuttleThread);
                if (!result) {
                    News.info("{}任务,{}小车,小车在输送站点调度小车避让失败", wrkMast.getWrkNo(), shuttleProtocol.getShuttleNo());
                    return false;
                }
            }
            if (!basDevp.getOutEnable().equals("Y")) {
                News.info("{}任务,{}站点,没有可出信号,禁止派发", wrkMast.getWrkNo(), basDevp.getDevNo());
                return false;//出库站点不可出
            }
@@ -1210,38 +1335,25 @@
            }
            if (!liftProtocol.isIdle()) {
                News.info("{}任务,{}号提升机,忙碌中", wrkMast.getWrkNo(), liftProtocol.getLiftNo());
                return false;
            }
            //判断提升机令牌是否未被占领
            if (liftProtocol.getToken() != 0) {
                News.info("{}任务,{}号提升机,令牌已被独占,禁止派发", wrkMast.getWrkNo(), liftProtocol.getLiftNo());
                return false;//提升机已被独占,禁止再派发任务
            }
            //判断提升机是否有其他任务
            WrkMast liftWrkMast = wrkMastMapper.selectLiftWrkMast(liftThread.getSlave().getId());
            if (liftWrkMast != null) {
                News.info("{}任务,{}号提升机,当前提升机存在未完成任务,禁止派发", wrkMast.getWrkNo(), liftProtocol.getLiftNo());
                return false;//当前提升机存在未完成任务,等待下一次轮询
            }
            //获取源站对应的牛眼提升机站点编号(起点编号)
            LiftStaProtocol liftStaProtocol = NyLiftUtils.getLiftStaByLev(liftThread.getSlave().getId(), Utils.getLev(wrkMast.getSourceLocNo()));
            if (liftStaProtocol == null) {
                return false;//找不到站点
            }
            Integer startSta = liftStaProtocol.getStaNo();
            NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
            if (shuttleProtocol.getCurrentLocNo().equals(liftStaProtocol.getLocNo())) {
                //小车还在输送站点
                //调度小车避让
                boolean result = Utils.searchEmptyGroupToMoveShuttle(Utils.getLev(wrkMast.getSourceLocNo()), wrkMast.getShuttleNo(), shuttleThread);
                if (!result) {
                    return false;
                }
            }
            //获目标站源站对应的输送站点
            BasDevp targetBasDevp = basDevpService.selectById(wrkMast.getStaNo());
            if (targetBasDevp == null) {
                News.info("{}任务,{}站点,站点不存在,禁止派发", wrkMast.getWrkNo(), wrkMast.getStaNo());
                return false;//站点不存在
            }
            //获取牛眼提升机站点编号(目标编号)
@@ -1291,8 +1403,14 @@
                    && liftProtocol.getTaskNo() != 0
                    && !liftProtocol.getBusy()
            ) {
                BasLiftOpt basLiftOpt = basLiftOptService.selectByDeviceWrk(liftProtocol.getTaskNo().toString());
                int taskNo = liftProtocol.getTaskNo().intValue();
                if (basLiftOpt != null) {
                    taskNo = basLiftOpt.getWrkNo();
                }
                //将任务档标记为完成
                WrkMast wrkMast = wrkMastMapper.selectByWorkNo324104(liftProtocol.getTaskNo().intValue());
                WrkMast wrkMast = wrkMastMapper.selectByWorkNo324104(taskNo);
                if (wrkMast != null) {
                    switch (wrkMast.getWrkSts().intValue()) {
                        case 3://3.提升机搬运中 ==> 4.提升机搬运完成
@@ -1307,15 +1425,18 @@
                            wrkMast.setWrkSts(25L);
                            if (wrkMast.getIoType() == 11) {//库位移转
                                wrkMast.setWrkSts(4L);//4.提升机搬运完成
                            }else {
                                if (wrkMast.getMk() == null || !wrkMast.getMk().equals("Y")) {
                                    //不需要用到机械臂,直接转29.出库完成
                                    wrkMast.setWrkSts(29L);
                                    wrkMast.setShuttleNo(null);//释放小车
                                    wrkMast.setLiftNo(null);//释放提升机
                                }
                            }
                            if (liftProtocol.getToken().equals(wrkMast.getWrkNo())) {
                                //释放提升机令牌
                                liftProtocol.setToken(0);
                            }
                            if (wrkMast.getMk() == null || !wrkMast.getMk().equals("Y")) {
                                //不需要用到机械臂,直接转29.出库完成
                                wrkMast.setWrkSts(29L);
                            }
                            break;
@@ -1484,7 +1605,7 @@
            }
            //获取穿梭车最近且空闲的提升机输送站点
            LiftStaProtocol liftSta = shuttleDispatchUtils.getRecentLiftSta(shuttleThread.getSlave().getId());
            LiftStaProtocol liftSta = shuttleDispatchUtils.getRecentLiftSta(shuttleThread.getSlave().getId(), Utils.getLev(wrkMast.getLocNo()));
            if (liftSta == null) {
                return false;//没有可用且空闲的输送站点
            }
@@ -1530,14 +1651,47 @@
    private boolean locToLocExecuteStep3(WrkMast wrkMast) {
        Date now = new Date();
        if (wrkMast.getWrkSts() == 23) {//23.小车搬运完成
            //源站
            Integer sourceStaNo = wrkMast.getSourceStaNo();
            //目标站
            Integer staNo = wrkMast.getStaNo();
            if (sourceStaNo == null || staNo == null) {
                return false;//源站或目标站为空
            }
            int liftNo = staNo / 100;//获取提升机号
            //获取提升机线程
            LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, wrkMast.getLiftNo());
            LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, liftNo);
            if (liftThread == null) {
                return false;
            }
            LiftProtocol liftProtocol = liftThread.getLiftProtocol();
            if (liftProtocol == null) {
                return false;
            }
            //获取源站对应的输送站点
            LiftStaProtocol liftStaProtocol = NyLiftUtils.getLiftStaByLev(liftNo, Utils.getLev(wrkMast.getSourceLocNo()));
            if (liftStaProtocol == null) {
                return false;//找不到站点
            }
            if (!(liftStaProtocol.getModel() && !liftStaProtocol.getBusy() && liftStaProtocol.getHasTray())) {
                return false;//站点必须自动、空闲、有托盘
            }
            NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, wrkMast.getShuttleNo());
            if (shuttleThread == null) {
                return false;
            }
            NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
            if (shuttleProtocol.getCurrentLocNo().equals(liftStaProtocol.getLocNo())) {
                //小车还在输送站点
                //调度小车避让
                boolean result = Utils.searchEmptyGroupToMoveShuttle(Utils.getLev(wrkMast.getSourceLocNo()), wrkMast.getShuttleNo(), shuttleThread);
                if (!result) {
                    return false;
                }
            }
            if (!liftProtocol.isIdle()) {
@@ -1548,14 +1702,6 @@
            WrkMast wrkMast1 = wrkMastMapper.selectLiftWrkMast(liftProtocol.getLiftNo().intValue());
            if (wrkMast1 != null && wrkMast1.getWrkNo().intValue() != wrkMast.getWrkNo().intValue()) {
                return false;
            }
            //源站
            Integer sourceStaNo = wrkMast.getSourceStaNo();
            //目标站
            Integer staNo = wrkMast.getStaNo();
            if (sourceStaNo == null || staNo == null) {
                return false;//源站或目标站为空
            }
            //获取提升机命令
@@ -1592,13 +1738,17 @@
    private boolean locToLocExecuteStep4(WrkMast wrkMast) {
        if (wrkMast.getWrkSts() == 4) {//4.提升机搬运完成
            //获取目标站对应的输送站点
            BasDevp targetBasDevp = basDevpService.selectByLevAndLiftNo(Utils.getLev(wrkMast.getLocNo()), wrkMast.getLiftNo());
            if (targetBasDevp == null) {
                return false;//缺少站点信息
            LiftStaProtocol liftStaProtocol = NyLiftUtils.getLiftStaByLev(wrkMast.getLiftNo(), Utils.getLev(wrkMast.getLocNo()));
            if (liftStaProtocol == null) {
                return false;//找不到站点
            }
            if (!(liftStaProtocol.getModel() && !liftStaProtocol.getBusy() && liftStaProtocol.getHasTray())) {
                return false;//站点必须自动、空闲、有托盘
            }
            if (wrkMast.getShuttleNo() == null) {
                shuttleDispatchUtils.dispatchShuttle(wrkMast.getWrkNo(), targetBasDevp.getLocNo());//调度小车到目标输送站点进行取货
                shuttleDispatchUtils.dispatchShuttle(wrkMast.getWrkNo(), liftStaProtocol.getLocNo());//调度小车到目标输送站点进行取货
                return false;
            }
@@ -1616,14 +1766,14 @@
            }
            //判断小车是否到达目标输送站点
            if (!shuttleProtocol.getCurrentLocNo().equals(targetBasDevp.getLocNo())) {
            if (!shuttleProtocol.getCurrentLocNo().equals(liftStaProtocol.getLocNo())) {
                //小车不在目标输送站点
                shuttleDispatchUtils.dispatchShuttle(wrkMast.getWrkNo(), targetBasDevp.getLocNo(), wrkMast.getShuttleNo());//调度小车到目标输送站点进行取货
                shuttleDispatchUtils.dispatchShuttle(wrkMast.getWrkNo(), liftStaProtocol.getLocNo(), wrkMast.getShuttleNo());//调度小车到目标输送站点进行取货
                return false;
            }
            //小车已抵达目标输送站点,将货物搬运到目标库位
            NyShuttleOperaResult result = NyShuttleOperaUtils.getShuttleTransportCommands(wrkMast.getShuttleNo(), wrkMast.getWrkNo(), targetBasDevp.getLocNo(), wrkMast.getLocNo());
            NyShuttleOperaResult result = NyShuttleOperaUtils.getShuttleTransportCommands(wrkMast.getShuttleNo(), wrkMast.getWrkNo(), liftStaProtocol.getLocNo(), wrkMast.getLocNo());
            if (result == null) {//路径计算失败
                return false;
            }
@@ -1964,10 +2114,10 @@
    }
    /**
     * AGV补货 => 机械臂拣料
     * AGV补货 => 生成入库通知档
     */
    public void agvRestockByRobot() {
        //检测300站是否自动、有物、工作号
    public void robotGenerateAgvTask() {
//检测300站是否自动、有物、工作号
        for (DevpSlave devp : slaveProperties.getDevp()) {
            // 获取入库站信息
            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
@@ -1997,68 +2147,82 @@
                    } else if (staProtocol317.isAutoing() && !staProtocol317.isLoading()) {
                        //自动、无物
                        targetSta = (short) 317;
                    }else {
                    } else {
                        continue;//没有空闲站点
                    }
                    targetSta = (short) 317;
                    if (wrkMast.getStaNo() != 303 && wrkMast.getStaNo() != 317) {
                        //向AGV发起组托请求
//                        try {
//                            HashMap<String, Object> param = new HashMap<>();
//                            param.put("wrkNo", wrkMast.getWrkNo());
//                            String response = new HttpHandler.Builder()
//                                    .setUri(wmsUrl)
//                                    .setPath("/openAGV")
//                                    .setJson(JSON.toJSONString(param))
//                                    .build()
//                                    .doPost();
//                            JSONObject jsonObject = JSON.parseObject(response);
//                            Integer code = jsonObject.getInteger("code");
//                            if (code.equals(200)) {//AGV组托成功
//                                //覆盖工作档目标站
//                                wrkMast.setStaNo(targetSta.intValue());
//                                wrkMast.setShuttleNo(null);//释放小车
//                                if (wrkMastMapper.updateById(wrkMast) > 0) {
//                                    //向300站写入目标站
//                                    staProtocol = staProtocol.clone();
//                                    staProtocol.setStaNo(targetSta);//移动到目标站
//                                    boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                                    try {
//                                        Thread.sleep(500);
//                                    } catch (Exception e) {
//                                        e.printStackTrace();
//                                    }
//                                    continue;
//                                }
//                            }
//                        } catch (Exception e) {
//                            e.printStackTrace();
//                            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//                        }
                        //覆盖工作档目标站
                        wrkMast.setStaNo(targetSta.intValue());
                        wrkMast.setShuttleNo(null);//释放小车
                        if (wrkMastMapper.updateById(wrkMast) > 0) {
                            //向300站写入目标站
                            staProtocol = staProtocol.clone();
                            staProtocol.setStaNo(targetSta);//移动到目标站
                            boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                            try {
                                Thread.sleep(500);
                            } catch (Exception e) {
                                e.printStackTrace();
                        try {
                            HashMap<String, Object> param = new HashMap<>();
                            param.put("wrkNo", wrkMast.getWrkNo());
                            String response = new HttpHandler.Builder()
                                    .setUri(wmsUrl)
                                    .setPath("/rpc/replenishment")
                                    .setJson(JSON.toJSONString(param))
                                    .build()
                                    .doPost();
                            JSONObject jsonObject = JSON.parseObject(response);
                            Integer code = jsonObject.getInteger("code");
                            if (code.equals(200)) {//AGV组托成功
                                //覆盖工作档目标站
                                wrkMast.setStaNo(targetSta.intValue());
                                wrkMast.setShuttleNo(null);//释放小车
                                wrkMast.setLiftNo(null);//释放提升机
                                if (wrkMastMapper.updateById(wrkMast) > 0) {
                                    //向300站写入目标站
                                    staProtocol = staProtocol.clone();
                                    staProtocol.setStaNo(targetSta);//移动到目标站
                                    boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                                    try {
                                        Thread.sleep(500);
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                    continue;
                                }
                            }
                            continue;
                        } catch (Exception e) {
                            e.printStackTrace();
                            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        }
//                        //覆盖工作档目标站
//                        wrkMast.setStaNo(targetSta.intValue());
//                        wrkMast.setShuttleNo(null);//释放小车
//                        wrkMast.setLiftNo(null);//释放提升机
//                        if (wrkMastMapper.updateById(wrkMast) > 0) {
//                            //向300站写入目标站
//                            staProtocol = staProtocol.clone();
//                            staProtocol.setStaNo(targetSta);//移动到目标站
//                            boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                            try {
//                                Thread.sleep(500);
//                            } catch (Exception e) {
//                                e.printStackTrace();
//                            }
//                            continue;
//                        }
                    }
                }
            }
        }
    }
    /**
     * AGV补货 => 机械臂拣料
     */
    public void agvRestockByRobot() {
        //检测300站是否自动、有物、工作号
        for (DevpSlave devp : slaveProperties.getDevp()) {
            // 获取入库站信息
            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
            StaProtocol staProtocol303 = devpThread.getStation().get(303);
            StaProtocol staProtocol317 = devpThread.getStation().get(317);
            if (staProtocol303 == null || staProtocol317 == null) {
                continue;
            }
            if (staProtocol303.isAutoing() && staProtocol303.isLoading() && staProtocol303.getWorkNo() != 0) {
                //调度机械臂
                //查询是否有工作档
@@ -2112,27 +2276,31 @@
                continue;
            }
            if (staProtocol309.isAutoing() && staProtocol309.isLoading()) {
            if (staProtocol309.isAutoing() && staProtocol309.isLoading() && staProtocol309.isInEnable()) {
                // 获取条码扫描仪信息
                BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, 11);//308站条码器
                BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, 9);//308站条码器
                if (barcodeThread == null) {
                    continue;
                }
                String barcode = barcodeThread.getBarcode();
                if(!Cools.isEmpty(barcode)) {
                    //通知AGV取货
                    agvRestockCall("CS-301-001-01@3", barcode);
                    agvRestockCall("301-1", barcode);
                    log.info("通知AGV取货,条码号:" + barcode);
                }
            } else if (staProtocol312.isAutoing() && staProtocol312.isLoading()) {
            }
            if (staProtocol312.isAutoing() && staProtocol312.isLoading() && staProtocol312.isInEnable()) {
                // 获取条码扫描仪信息
                BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, 12);//311站条码器
                BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, 10);//311站条码器
                if (barcodeThread == null) {
                    continue;
                }
                String barcode = barcodeThread.getBarcode();
                if(!Cools.isEmpty(barcode)) {
                    //通知AGV取货
                    agvRestockCall("CS-302-001-01@3", barcode);
                    agvRestockCall("302-1", barcode);
                    log.info("通知AGV取货,条码号:" + barcode);
                }
            }
        }
@@ -2142,15 +2310,16 @@
    private boolean agvRestockCall(String staNo, String barcode) {
        try {
            HashMap<String, Object> param = new HashMap<>();
            param.put("staNo", staNo);
            param.put("barcode", barcode);
            param.put("devNo", staNo);
            param.put("containerCode", barcode);
            String response = new HttpHandler.Builder()
                    .setUri(wmsUrl)
                    .setPath("/callAGV")
                    .setPath("/rpc/start")
                    .setJson(JSON.toJSONString(param))
                    .build()
                    .doPost();
            JSONObject jsonObject = JSON.parseObject(response);
            log.info("悬挂线,wms返回结果:" + jsonObject);
            Integer code = jsonObject.getInteger("code");
            if (code.equals(200)) {//呼叫AGV
                return true;
@@ -2160,6 +2329,40 @@
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return false;
    }
    /**
     * AGV补货(悬挂线通知AGV取货)
     */
    public void agvRestockIntoByHangingWire() {
        //检测350和351扫码器
        int[] barcodeStaNo = {11, 12};//11 => 350站扫码器,12 => 351站扫码器
        for (int staNo : barcodeStaNo) {
            // 获取条码扫描仪信息
            BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, staNo);
            if (barcodeThread == null) {
                continue;
            }
            String barcode = barcodeThread.getBarcode();
            if(!Cools.isEmpty(barcode)) {
                if (barcode.contains("NoRead")) {
                    continue;
                }
                String agvStaNo = null;
                if (staNo == 11) {
                    agvStaNo = "303-1";
                }else {
                    agvStaNo = "304-1";
                }
                //通知AGV取货
                boolean result = agvRestockCall(agvStaNo, barcode);
                if (result) {
                    barcodeThread.setBarcode("");
                }
                log.info(barcodeThread.getSlave().getId() + "号扫码器,通知AGV取货,条码号:" + barcode);
            }
        }
    }
    // 300站拣料
@@ -2179,7 +2382,7 @@
                    continue;
                }
                if (wrkMast.getWrkSts() != 25) {//25.提升机搬运完成
                if (wrkMast.getWrkSts() != 29) {//29.出库完成
                    continue;
                }
@@ -2189,6 +2392,7 @@
                    //覆盖工作档目标站
                    wrkMast.setStaNo(sourceStaNo);
                    wrkMast.setSourceStaNo(staNo);
                    wrkMast.setMk("N");
                    if (wrkMastMapper.updateById(wrkMast) > 0) {
                        //向300站写入目标站
                        staProtocol = staProtocol.clone();
@@ -2258,8 +2462,65 @@
                ledCommand.setLocNo(wrkMast.getLocNo());
                ledCommand.setStaNo(wrkMast.getStaNo());
                if (wrkMast.getIoType() != 110 && wrkMast.getIoType() != 10) {
                    List<WrkDetl> wrkDetls = wrkDetlService.findByWorkNo(wrkMast.getWrkNo());
                    wrkDetls.forEach(wrkDetl -> ledCommand.getMatDtos().add(new MatDto(wrkDetl.getMatnr(), wrkDetl.getMaktx(), wrkDetl.getAnfme(),wrkDetl.getSpecs())));
                    //for (WrkDetl wrkDetl : wrkDetls) {
                    //    LocDetl locDetl = locDetlService.selectOne(new EntityWrapper<LocDetl>().eq("zpallet", wrkDetl.getZpallet()).eq("matnr", wrkDetl.getMatnr()));
                    //
                    //    locDetls.forEach(locDetl1 -> {
                    //        //工作档中存在该物料则跳过
                    //        String suppCode = "";
                    //
                    //        if (wrkDetl.getMatnr().equals(locDetl1.getMatnr())) {
                    //            Double anfme = 0D;
                    //            if (locDetl != null) {
                    //                anfme = locDetl.getAnfme();
                    //            }
                    //            if (wrkDetl.getSuppCode() != null) {
                    //                suppCode = wrkDetl.getSuppCode();
                    //            }
                    //            ledCommand.getMatDtos()
                    //                    .add(new MatDto(wrkDetl.getMatnr()
                    //                            , wrkDetl.getMaktx()
                    //                            , wrkDetl.getAnfme()
                    //                            , (wrkDetl.getAnfme()-anfme)
                    //                            , wrkDetl.getSpecs()
                    //                            , suppCode));
                    //        } else {
                    //            if (locDetl1.getSuppCode() != null) {
                    //                suppCode = locDetl1.getSuppCode();
                    //            }
                    //            ledCommand.getMatDtos()
                    //                    .add(new MatDto(locDetl1.getMatnr()
                    //                            , locDetl1.getMaktx()
                    //                            , 0D
                    //                            , locDetl1.getAnfme()
                    //                            , locDetl1.getSpecs()
                    //                            , suppCode));
                    //        }
                    //    });
                    //    //LocDetl locDetl = locDetlService.selectOne(new EntityWrapper<LocDetl>().eq("zpallet", wrkDetl.getZpallet()).eq("matnr", wrkDetl.getMatnr()));
                    //}
                    List<LocDetl> locDetls = locDetlService.selectList(new EntityWrapper<LocDetl>().eq("loc_no", wrkMast.getSourceLocNo()));
                    locDetls.forEach(locDetl -> {
                        Wrapper<WrkDetl> wrapper = new EntityWrapper<WrkDetl>().eq("matnr", locDetl.getMatnr()).eq("wrk_no",wrkMast.getWrkNo());
                        Utils.wapperSetCondition(wrapper,"batch",locDetl.getBatch());
                        Utils.wapperSetCondition(wrapper,"three_code",locDetl.getThreeCode());
                        Utils.wapperSetCondition(wrapper,"dead_time",locDetl.getDeadTime());
                        Utils.wapperSetCondition(wrapper,"supp_code",locDetl.getSuppCode());//料箱码
                        WrkDetl detl = wrkDetlService.selectOne(wrapper);
                        if (Cools.isEmpty(detl)) {
                            String suppCode = "";
                            if (locDetl.getSuppCode() != null) {
                                suppCode = locDetl.getSuppCode();
                            }
                            ledCommand.getMatDtos().add(new MatDto(locDetl.getMatnr(), locDetl.getMaktx(), 0D, locDetl.getAnfme(), locDetl.getSpecs(), suppCode));
                        } else {
                            String suppCode = "";
                            if (detl.getSuppCode() != null) {
                                suppCode = detl.getSuppCode();
                            }
                            ledCommand.getMatDtos().add(new MatDto(detl.getMatnr(), detl.getMaktx(), detl.getAnfme(), (locDetl.getAnfme() - detl.getAnfme()), detl.getSpecs(), suppCode));
                        }
                    });
                }
                commands.add(ledCommand);
            }
@@ -2272,20 +2533,11 @@
            }
            // 命令下发 -------------------------------------------------------------------------------
            if (!commands.isEmpty()) {
                if (led.getId()>3){
                    if (!MessageQueue.offer(SlaveType.Led, led.getId()-3, new Task(1, commands))) {
                        log.error("{}号LED命令下发失败!!![ip:{}] [port:{}]", led.getId()-3, led.getIp(), led.getPort());
                        continue;
                    }else {
                        ledThread.setLedMk(false);
                    }
                if (!MessageQueue.offer(SlaveType.Led, led.getId(), new Task(1, commands))) {
                    log.error("{}号LED命令下发失败!!![ip:{}] [port:{}]", led.getId(), led.getIp(), led.getPort());
                    continue;
                }else {
                    if (!MessageQueue.offer(SlaveType.Led, led.getId(), new Task(1, commands))) {
                        log.error("{}号LED命令下发失败!!![ip:{}] [port:{}]", led.getId(), led.getIp(), led.getPort());
                        continue;
                    }else {
                        ledThread.setLedMk(false);
                    }
                    ledThread.setLedMk(false);
                }
            }
@@ -2314,35 +2566,36 @@
     * 其他  ===>> LED显示器复位,显示默认信息
     */
    public 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 && staProtocol.isLoading()) {
                    reset = false;
                    break;
                }
            }
            // 获取led线程
            LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, led.getId());
            // led显示默认内容
            if (reset && !ledThread.isLedMk()) {
                ledThread.setLedMk(true);
                if (!MessageQueue.offer(SlaveType.Led, led.getId(), new Task(4, new ArrayList<>()))) {
                    News.error(" - {}号LED命令下发失败!!![ip:{}] [port:{}]", led.getId(), led.getIp(), led.getPort());
                } else {
                }
            }
        }
//        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 && staProtocol.isLoading()) {
//                    reset = false;
//                    break;
//                }
//            }
//            // 获取led线程
//            LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, led.getId());
//            // led显示默认内容
//            if (reset && !ledThread.isLedMk()) {
//                ledThread.setLedMk(true);
//                if (!MessageQueue.offer(SlaveType.Led, led.getId(), new Task(4, new ArrayList<>()))) {
//                    News.error(" - {}号LED命令下发失败!!![ip:{}] [port:{}]", led.getId(), led.getIp(), led.getPort());
//                } else {
//                    News.error("{}号LED命令下发成功!!![ip:{}] [port:{}]", led.getId(), led.getIp(), led.getPort());
//                    ledThread.setLedMk(false);
//                }
//            }
//        }
        for (LedSlave led : slaveProperties.getLed()) {
            // 获取输送线plc线程
            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, led.getDevpPlcId());
@@ -2361,9 +2614,13 @@
            LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, led.getId());
            // led显示默认内容
            if (reset && !ledThread.isLedMk()) {
                ledThread.setLedMk(true);
                ledThread.setLedMk(false);
                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.error("{}号LED命令下发成功!!![ip:{}] [port:{}]", led.getId(), led.getIp(), led.getPort());
                    MessageQueue.offer(SlaveType.Led, led.getId(), new Task(4, new ArrayList<>()));
                    ledThread.setLedMk(false);
                }
            }
        }
@@ -2436,7 +2693,7 @@
            wrkCharge.setShuttleNo(shuttle.getId());
            wrkCharge.setCharge(shuttleCharge.id);
            wrkCharge.setWrkNo(commonService.getChargeWorkNo(4));
            wrkCharge.setWrkSts(51L);   // 21.准备充电
            wrkCharge.setWrkSts(51L);   // 51.准备充电
            wrkCharge.setIoPri((double) 10);
            wrkCharge.setLocNo(chargeLocNo);
            wrkCharge.setMemo("charge");
@@ -2500,7 +2757,16 @@
                }
            } else if (wrkCharge.getWrkSts() == 52) {
                //检测小车是否满电
                //获取满电阈值
                int maxPower = 95;
                EntityWrapper<Config> wrapper = new EntityWrapper<>();
                wrapper.eq("code", "chargeMaxValue");
                Config config = configService.selectOne(wrapper);
                if (config != null) {
                    maxPower = Integer.parseInt(config.getValue());
                }
                if (shuttleProtocol.getPowerPercent() < maxPower) {
                    continue;
                }
@@ -2583,8 +2849,6 @@
                continue;
            }
//            this.shuttleMoveExecuteStepClearWrkMast(wrkMast);//清理111.小车移动完成
        }
    }
@@ -2611,11 +2875,13 @@
            //小车处于空闲状态
            if (!shuttleProtocol.isIdleNoCharge(wrkMast.getWrkNo())) {
                News.info("{}任务,{}小车,小车忙碌中", wrkMast.getWrkNo(), shuttleProtocol.getShuttleNo());
                return false;
            }
            //判断小车令牌是否未被占领
            if (shuttleProtocol.getToken() != 0) {
                News.info("{}任务,{}小车,令牌已被独占,禁止派发", wrkMast.getWrkNo(), shuttleProtocol.getShuttleNo());
                return false;//小车已被独占,禁止再派发任务
            }
@@ -2640,8 +2906,27 @@
            //判断提升机是否有其他任务(该任务需要换层必须提前独占提升机)
            WrkMast liftWrkMast = wrkMastMapper.selectLiftWrkMast(liftSta.getLiftNo());
            if (liftWrkMast != null) {
                News.info("{}任务,{}号提升机,提升机存在未完成任务,禁止派发", wrkMast.getWrkNo(), liftSta.getLiftNo());
                return false;//当前提升机存在未完成任务,等待下一次轮询
            }
            //*************尝试锁定目标站路径***************
            List<NavigateNode> targetNodes = NyLiftUtils.getLiftStaNodes(wrkMast.getStaNo());
            if (targetNodes == null) {
                return false;//未获取到节点
            }
            boolean checkPathIsAvailable = NavigateUtils.checkPathIsAvailable(targetNodes, shuttleProtocol.getShuttleNo().intValue(), Utils.getLev(wrkMast.getLocNo()), null);
            if (!checkPathIsAvailable) {
                News.info("{}任务,{}小车,目标站点路径被占用,禁止派发", wrkMast.getWrkNo(), shuttleProtocol.getShuttleNo());
                return false;//检测目标站点路径是否未被占用
            }
            //尝试锁定目标站路径
            boolean result2 = navigateMapUtils.writeNavigateNodeToRedisMap(Utils.getLev(wrkMast.getLocNo()), targetNodes, true);//所使用的路径进行锁定禁用
            if (!result2) {
                News.info("{}任务,{}小车,路径锁定失败,禁止派发", wrkMast.getWrkNo(), shuttleProtocol.getShuttleNo());
                return false;//路径锁定失败
            }
            //*************尝试锁定目标站路径***************
            //获取小车到输送站点行走命令
            NyShuttleOperaResult result = NyShuttleOperaUtils.getStartToTargetCommands(shuttleThread.getSlave().getId(), wrkMast.getWrkNo(), shuttleProtocol.getCurrentLocNo(), liftSta.getLocNo(), NavigationMapType.NORMAL.id);
@@ -2699,6 +2984,7 @@
            }
            if (basLift.getPoint() == null) {
                News.info("{}任务,{}号提升机,没有提升机点位坐标,禁止派发", wrkMast.getWrkNo(), basLift.getLiftNo());
                return false;//没有设置提升机点位坐标
            }
@@ -2706,6 +2992,7 @@
            WrkMast liftWrkMast = wrkMastMapper.selectLiftWrkMast(basLift.getLiftNo());
            if (liftWrkMast != null) {
                if (!liftWrkMast.getWrkNo().equals(wrkMast.getWrkNo())) {//提升机任务和当前任务不相同
                    News.info("{}任务,{}号提升机,提升机存在未完成任务,禁止派发", wrkMast.getWrkNo(), basLift.getLiftNo());
                    return false;//当前提升机存在未完成任务,等待下一次轮询
                }
            }
@@ -2720,6 +3007,7 @@
            }
            if (!liftProtocol.isIdle(wrkMast.getWrkNo().shortValue())) {
                News.info("{}任务,{}号提升机,提升机忙碌中,禁止派发", wrkMast.getWrkNo(), basLift.getLiftNo());
                return false;
            }
@@ -2735,11 +3023,13 @@
            //小车处于空闲状态
            if (!shuttleProtocol.isIdleNoCharge(wrkMast.getWrkNo())) {
                News.info("{}任务,{}小车,小车忙碌中,禁止派发", wrkMast.getWrkNo(), shuttleProtocol.getShuttleNo());
                return false;
            }
            //小车令牌是否被任务独占
            if (!shuttleProtocol.getToken().equals(wrkMast.getWrkNo())) {
                News.info("{}任务,{}小车,小车令牌被独占,禁止派发", wrkMast.getWrkNo(), shuttleProtocol.getShuttleNo());
                return false;
            }
@@ -2749,6 +3039,7 @@
                //调度提升机
                if (liftProtocol.getToken() != 0) {
                    News.info("{}任务,{}号提升机,提升机令牌被独占,禁止派发", wrkMast.getWrkNo(), liftProtocol.getLiftNo());
                    return false;//提升机令牌被占用
                }
@@ -2788,11 +3079,13 @@
            //判断提升机令牌是否为当前小车
            if (!liftProtocol.getToken().equals(wrkMast.getShuttleNo())) {
                News.info("{}任务,{}号提升机,提升机令牌被独占,禁止派发", wrkMast.getWrkNo(), liftProtocol.getLiftNo());
                return false;//提升机已被独占,禁止再派发任务
            }
            //判断小车是否为当前任务独占
            if (!shuttleProtocol.getToken().equals(wrkMast.getWrkNo())) {
                News.info("{}任务,{}小车,小车令牌被独占,禁止派发", wrkMast.getWrkNo(), shuttleProtocol.getShuttleNo());
                return false;
            }
@@ -2855,23 +3148,27 @@
                return false;
            }
            if (!liftProtocol.isIdle(wrkMast.getWrkNo().shortValue())) {
                News.info("{}任务,{}号提升机,提升机忙碌中,禁止派发", wrkMast.getWrkNo(), liftProtocol.getLiftNo());
                return false;
            }
            //判断提升机是否有其他任务
            WrkMast liftWrkMast = wrkMastMapper.selectLiftWrkMast(liftThread.getSlave().getId());
            if (liftWrkMast != null) {
                if (!liftWrkMast.getWrkNo().equals(wrkMast.getWrkNo())) {//提升机任务和当前任务不相同
                    News.info("{}任务,{}号提升机,提升机存在未完成任务,禁止派发", wrkMast.getWrkNo(), liftProtocol.getLiftNo());
                    return false;//当前提升机存在未完成任务,等待下一次轮询
                }
            }
            //判断提升机令牌是否为当前小车
            if (!liftProtocol.getToken().equals(wrkMast.getShuttleNo())) {
                News.info("{}任务,{}号提升机,提升机令牌和当前小车不一致,禁止派发", wrkMast.getWrkNo(), liftProtocol.getLiftNo());
                return false;//提升机令牌和当前小车不一致,禁止派发
            }
            //判断提升机内是否有小车
            if (!liftProtocol.getHasCar()) {
                News.info("{}任务,{}号提升机,提升机内无小车,禁止派发", wrkMast.getWrkNo(), liftProtocol.getLiftNo());
                return false;//提升机内无小车
            }
@@ -2887,11 +3184,13 @@
            //小车处于空闲状态
            if (!shuttleProtocol.isIdleNoCharge()) {
                News.info("{}任务,{}号提升机,提升机忙碌中,禁止派发", wrkMast.getWrkNo(), liftProtocol.getLiftNo());
                return false;
            }
            //判断小车是否为当前任务独占
            if (!shuttleProtocol.getToken().equals(wrkMast.getWrkNo())) {
                News.info("{}任务,{}小车,小车当前任务未被独占,禁止派发", wrkMast.getWrkNo(), shuttleProtocol.getShuttleNo());
                return false;
            }
@@ -2900,6 +3199,7 @@
            //获取目标站
            LiftStaProtocol liftSta = NyLiftUtils.getLiftStaByStaNo(wrkMast.getStaNo());
            if (sourceLiftSta == null || liftSta == null) {
                News.info("{}任务,缺少站点信息,禁止派发", wrkMast.getWrkNo());
                return false;//缺少站点信息
            }
@@ -2948,6 +3248,7 @@
                return false;
            }
            if (!liftProtocol.isIdle(wrkMast.getWrkNo().shortValue())) {
                News.info("{}任务,{}号提升机,提升机忙碌中,禁止派发", wrkMast.getWrkNo(), liftProtocol.getLiftNo());
                return false;
            }
@@ -2955,12 +3256,14 @@
            WrkMast liftWrkMast = wrkMastMapper.selectLiftWrkMast(liftThread.getSlave().getId());
            if (liftWrkMast != null) {
                if (!liftWrkMast.getWrkNo().equals(wrkMast.getWrkNo())) {//提升机任务和当前任务不相同
                    News.info("{}任务,{}号提升机,提升机存在未完成任务,禁止派发", wrkMast.getWrkNo(), liftProtocol.getLiftNo());
                    return false;//当前提升机存在未完成任务,等待下一次轮询
                }
            }
            //判断提升机令牌是否为当前小车
            if (!liftProtocol.getToken().equals(wrkMast.getShuttleNo())) {
                News.info("{}任务,{}号提升机,提升机令牌和当前小车不一致,禁止派发", wrkMast.getWrkNo(), liftProtocol.getLiftNo());
                return false;//提升机令牌和当前小车不一致,禁止派发
            }
@@ -2976,11 +3279,13 @@
            //小车处于空闲状态
            if (!shuttleProtocol.isIdleNoCharge()) {
                News.info("{}任务,{}小车,小车忙碌中,禁止派发", wrkMast.getWrkNo(), shuttleProtocol.getShuttleNo());
                return false;
            }
            //判断小车是否为当前任务独占
            if (!shuttleProtocol.getToken().equals(wrkMast.getWrkNo())) {
                News.info("{}任务,{}小车,小车令牌被独占,禁止派发", wrkMast.getWrkNo(), shuttleProtocol.getShuttleNo());
                return false;
            }
@@ -2996,8 +3301,10 @@
                return false;//没有提升机数据
            }
            if (basLift.getPoint() == null) {
                News.info("{}任务,{}号提升机,缺少提升机点位坐标,禁止派发", wrkMast.getWrkNo(), liftProtocol.getLiftNo());
                return false;//没有设置提升机点位坐标
            }
            NavigateNode liftNode = new NavigateNode(basLift.getPoint$().getX(), basLift.getPoint$().getY());
            liftNode.setZ(liftSta.getLev());
@@ -3054,30 +3361,36 @@
            //小车处于空闲状态
            if (!shuttleProtocol.isIdleNoCharge(wrkMast.getWrkNo())) {
                News.info("{}任务,{}小车,小车忙碌中,禁止派发", wrkMast.getWrkNo(), shuttleProtocol.getShuttleNo());
                return false;
            }
            //判断小车令牌是否为当前任务
            if (shuttleProtocol.getToken() != 0 && !shuttleProtocol.getToken().equals(wrkMast.getWrkNo())) {
                News.info("{}任务,{}小车,小车令牌被独占,禁止派发", wrkMast.getWrkNo(), shuttleProtocol.getShuttleNo());
                return false;
            }
//            //获取目标站对应的输送站点
//            BasDevp targetBasDevp = basDevpService.selectByLevAndLiftNo(Utils.getLev(wrkMast.getLocNo()), wrkMast.getLiftNo());
//            if (targetBasDevp == null) {
//                return false;//缺少站点信息
//            }
//            //跨楼层移动任务
//            if (Utils.getLev(wrkMast.getSourceLocNo()) != Utils.getLev(wrkMast.getLocNo())) {
//                //获取目标站
//                LiftStaProtocol liftSta = NyLiftUtils.getLiftStaByStaNo(wrkMast.getStaNo());
//                if (liftSta == null) {
//                    return false;//找不到站点
//                }
//
//            //获取提升机数据
//            BasLift basLift = basLiftService.selectById(targetBasDevp.getLiftNo());
//            if (basLift == null) {
//                return false;//没有提升机数据
//                //*************尝试解锁目标站路径***************
//                List<NavigateNode> targetNodes = NyLiftUtils.getLiftStaNodes(liftSta.getStaNo());
//                if (targetNodes == null) {
//                    return false;//未获取到节点
//                }
//                //尝试解锁目标站路径
//                boolean result = navigateMapUtils.writeNavigateNodeToRedisMap(Utils.getLev(wrkMast.getLocNo()), targetNodes, false);//所使用的路径进行解锁
//                if (!result) {
//                    return false;//路径解锁失败
//                }
//                //*************尝试解锁目标站路径***************
//            }
//            if (basLift.getPoint() == null) {
//                return false;//没有设置提升机点位坐标
//            }
//            NavigateNode liftNode = new NavigateNode(basLift.getPoint$().getX(), basLift.getPoint$().getY());
//            liftNode.setZ(basLift.getPoint$().getZ());
            //小车已经在目标库位,直接认定小车移动任务完成
            if (shuttleProtocol.getCurrentLocNo().equals(wrkMast.getLocNo())) {
@@ -3106,8 +3419,32 @@
                return false;
            }
            //获取小车到目标库位命令
            NyShuttleOperaResult result = NyShuttleOperaUtils.getStartToTargetCommands(shuttleThread.getSlave().getId(), wrkMast.getWrkNo(), shuttleProtocol.getCurrentLocNo(), wrkMast.getLocNo(), NavigationMapType.NORMAL.id);
            NyShuttleOperaResult result = null;
            //跨楼层移动任务
            if (Utils.getLev(wrkMast.getSourceLocNo()) != Utils.getLev(wrkMast.getLocNo())) {
                //需要将前两个节点作为白名单节点传入
                //获取目标站
                LiftStaProtocol liftSta = NyLiftUtils.getLiftStaByStaNo(wrkMast.getStaNo());
                if (liftSta == null) {
                    return false;//找不到站点
                }
                List<NavigateNode> targetNodes = NyLiftUtils.getLiftStaNodes(liftSta.getStaNo());
                if (targetNodes == null) {
                    return false;//未获取到节点
                }
                //设置计算节点的白名单
                ArrayList<int[]> whiteList = new ArrayList<>();//设置计算节点的白名单
                for (NavigateNode node : targetNodes) {
                    whiteList.add(new int[]{node.getX(), node.getY()});
                }
                result = NyShuttleOperaUtils.getStartToTargetCommandsByWhites(shuttleThread.getSlave().getId(), wrkMast.getWrkNo(), shuttleProtocol.getCurrentLocNo(), wrkMast.getLocNo(), NavigationMapType.NORMAL.id, whiteList);
            }else {
                //获取小车到目标库位命令
                result = NyShuttleOperaUtils.getStartToTargetCommands(shuttleThread.getSlave().getId(), wrkMast.getWrkNo(), shuttleProtocol.getCurrentLocNo(), wrkMast.getLocNo(), NavigationMapType.NORMAL.id);
            }
            if (result == null) {
                return false;//路径计算失败
            }
@@ -3146,69 +3483,6 @@
                MessageQueue.offer(SlaveType.Shuttle, assignCommand.getShuttleNo().intValue(), new Task(3, assignCommand));
            }
        }
        return true;
    }
    /**
     * 小车迁移-清理111.小车移动完成
     */
    private boolean shuttleMoveExecuteStepClearWrkMast(WrkMast wrkMast) {
        if (wrkMast.getWrkSts() == 111) {
            //获取四向穿梭车线程
            NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, wrkMast.getShuttleNo());
            if (shuttleThread == null) {
                return false;
            }
            NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
            if (shuttleProtocol == null) {
                return false;
            }
            //小车处于空闲状态
            if (!shuttleProtocol.isIdleNoCharge(wrkMast.getWrkNo())) {
                return false;
            }
            Object o = redisUtil.get("shuttle_wrk_no_" + shuttleProtocol.getTaskNo());
            if (o != null) {
                ShuttleRedisCommand redisCommand = JSON.parseObject(o.toString(), ShuttleRedisCommand.class);
                ShuttleAssignCommand assignCommand = redisCommand.getAssignCommand();
                int size = assignCommand.getCommands().size();
                NyShuttleHttpCommand command = assignCommand.getCommands().get(size - 1);//获取最后一段命令
                if (!command.getComplete()) {
                    return false;//最后一段命令还未完成,不做操作
                }
                NavigateMapData navigateMapData = new NavigateMapData(Utils.getLev(shuttleProtocol.getCurrentLocNo()));
                navigateMapData.writeNavigateNodeToRedisMap(assignCommand.getNodes(), false);//解锁路径
                //删除redis
                redisUtil.del("shuttle_wrk_no_" + redisCommand.getWrkNo());
            }
            // 保存工作主档历史档
            if (wrkMastLocMapper.save(wrkMast.getWrkNo()) <= 0) {
                log.info("保存工作历史档[workNo={0}]失败", wrkMast.getWrkNo());
            }
            // 删除工作主档
            if (!wrkMastService.deleteById(wrkMast)) {
                log.info("删除工作主档[workNo={0}]失败", wrkMast.getWrkNo());
            }
            //设置四向穿梭车为空闲状态
            shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
            //源库位清零
            shuttleProtocol.setSourceLocNo(null);
            //目标库位清零
            shuttleProtocol.setLocNo(null);
            //任务指令清零
            shuttleProtocol.setAssignCommand(null);
            //工作号清零
            shuttleProtocol.setTaskNo(0);
            //清除令牌
            shuttleProtocol.setToken(0);
            News.info("四向穿梭车已确认且移动任务完成状态,复位。四向穿梭车号={}", shuttleProtocol.getShuttleNo());
        }
        return true;
    }