自动化立体仓库 - WCS系统
Junjie
2023-06-15 c1c6e4385c986ac63d7884cfaa818e05207005c9
出入库代码(暂)
1个文件已添加
21个文件已修改
1126 ■■■■ 已修改文件
src/main/java/com/zy/asrs/controller/SiteController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/vo/SiteTableVo.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/BasDevpMapper.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/WrkMastMapper.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/BasDevpService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/BasDevpServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java 390 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/utils/Utils.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/MainProcess.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/LiftLevType.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/ShuttleRunDirection.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/ShuttleTaskModeType.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/command/LiftCommand.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/LiftProtocol.java 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/ShuttleProtocol.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/StaProtocol.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/LiftThread.java 74 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/ShuttleThread.java 313 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/SiemensDevpThread.java 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/WrkMastMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/pipeline.html 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/shuttle.html 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/SiteController.java
@@ -151,6 +151,8 @@
            vo.setLoading(staProtocol.isLoading()?"Y":"N");     // 有物
            vo.setInEnable(staProtocol.isInEnable()?"Y":"N");   // 可入
            vo.setOutEnable(staProtocol.isOutEnable()?"Y":"N"); // 可出
            vo.setLiftArrival(staProtocol.isLiftArrival()?"Y":"N"); // 提升机到位信号
            vo.setShuttleTakeEnable(staProtocol.isShuttleTakeEnable()?"Y":"N"); // 穿梭车可取信号
            vo.setPakMk(staProtocol.isPakMk()?"Y":"N");       // 入库标记
            vo.setEmptyMk(staProtocol.isEmptyMk()?"Y":"N");     // 空板信号
            vo.setStaNo(staProtocol.getStaNo());                // 目标站
src/main/java/com/zy/asrs/domain/vo/SiteTableVo.java
@@ -35,4 +35,10 @@
    // 目标站
    private Short staNo = 0;
    //提升机到位信号
    private String liftArrival = "-";
    //四向穿梭车可取信号
    private String shuttleTakeEnable = "-";
}
src/main/java/com/zy/asrs/mapper/BasDevpMapper.java
@@ -20,5 +20,5 @@
    BasDevp queryByLocNo(String locNo);
    BasDevp queryByQrCode(String qrCodeValue);
    BasDevp queryByQrCode(Integer qrCodeValue);
}
src/main/java/com/zy/asrs/mapper/WrkMastMapper.java
@@ -96,7 +96,7 @@
    WrkMast selectAllC();
    WrkMast selectRackInStep48(Short workNo,Integer sourceStaNo);
    WrkMast selectRackInStep48(Short workNo,Integer staNo);
    WrkMast selectByWorkNo(Integer workNo);
src/main/java/com/zy/asrs/service/BasDevpService.java
@@ -48,6 +48,6 @@
    BasDevp queryByLocNo(String locNo);
    BasDevp queryByQrCode(String qrCodeValue);
    BasDevp queryByQrCode(Integer qrCodeValue);
}
src/main/java/com/zy/asrs/service/impl/BasDevpServiceImpl.java
@@ -76,7 +76,7 @@
    }
    @Override
    public BasDevp queryByQrCode(String qrCodeValue) {
    public BasDevp queryByQrCode(Integer qrCodeValue) {
        return this.baseMapper.queryByQrCode(qrCodeValue);
    }
}
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java
@@ -4,7 +4,6 @@
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.Cools;
import com.core.common.SpringUtils;
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.mapper.*;
@@ -60,13 +59,13 @@
    @Autowired
    private StaDescService staDescService;
    @Autowired
    private BasCrnpService basCrnpService;
    @Autowired
    private BasDevpService basDevpService;
    @Autowired
    private BasErrLogService basErrLogService;
    @Autowired
    private BasSteErrLogService basSteErrLogService;
    @Autowired
    private BasShuttleService basShuttleService;
    @Autowired
    private BasShuttleErrLogService basShuttleErrLogService;
    @Autowired
@@ -152,11 +151,12 @@
                    }
                    continue;
                }
                // 判断是否满足入库条件
                if (staProtocol.isAutoing() && staProtocol.isLoading()
                        && staProtocol.isInEnable()
                        && !staProtocol.isEmptyMk() && (workNo == 0 || (workNo >= 9990 && workNo <= 9999))
                        && staProtocol.isPakMk()) {
                        ) {
                    // 获取条码扫描仪信息
                    BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, inSta.getBarcode());
@@ -167,10 +167,10 @@
                    if(!Cools.isEmpty(barcode)) {
//                        News.info("{}号条码扫描器检测条码信息:{}", inSta.getBarcode(), barcode);
                        if("NG".endsWith(barcode) || "NoRead".equals(barcode) || "empty".equals(barcode)|| "00000000".equals(barcode)) {
                            staProtocol.setWorkNo((short) 32002);
                            staProtocol.setStaNo(inSta.getBackSta().shortValue());
                            devpThread.setPakMk(staProtocol.getSiteId(), false);
                            MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                            staProtocol.setWorkNo((short) 32002);
//                            staProtocol.setStaNo(inSta.getBackSta().shortValue());
//                            devpThread.setPakMk(staProtocol.getSiteId(), false);
//                            MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                            // led 异常显示
                            LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, inSta.getLed());
@@ -181,10 +181,10 @@
                            continue;
                        }
                    } else {
                        staProtocol.setWorkNo((short) 32002);
                        staProtocol.setStaNo(inSta.getBackSta().shortValue());
                        devpThread.setPakMk(staProtocol.getSiteId(), false);
                        MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                        staProtocol.setWorkNo((short) 32002);
//                        staProtocol.setStaNo(inSta.getBackSta().shortValue());
//                        devpThread.setPakMk(staProtocol.getSiteId(), false);
//                        MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                        // led 异常显示
                        LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, inSta.getLed());
@@ -235,6 +235,18 @@
                            if (!result) {
                                throw new CoolException("更新plc站点信息失败");
                            }
                            // 判断重复工作档
                            WrkMast wrkMast = wrkMastMapper.selectPakInStep11(inSta.getStaNo());
                            if (wrkMast == null) { continue; }
                            // 更新工作主档
                            wrkMast.setWrkSts(2L); // 工作状态:2.设备上走
                            wrkMast.setModiTime(new Date());
                            if (wrkMastMapper.updateById(wrkMast) == 0) {
                                News.error("更新工作档失败!!! [工作号:{}]", wrkMast.getWrkNo());
                            }
                        } else if (code == 500){
                            if (ledThread != null) {
                                String errorMsg = jsonObject.getString("msg");
@@ -595,6 +607,9 @@
                    continue;
                }
                LiftProtocol liftProtocol = liftThread.getLiftProtocol();
                if (liftProtocol == null) {
                    continue;
                }
                if (!liftProtocol.isIdle()) {
                    continue;
                }
@@ -602,7 +617,6 @@
                //提升机处于空闲状态,进行任务的恢复
                liftProtocol.setTaskNo(redisCommand.getWrkNo());//将提升机线程分配任务号
                liftProtocol.setProtocolStatus(LiftProtocolStatusType.WORKING);//工作状态
                liftProtocol.setLiftLock(true);//提升机锁定
            }else if(key.toString().contains("shuttle_wrk_no_")){//四向穿梭车任务
                ShuttleRedisCommand redisCommand = JSON.parseObject(map.get(key).toString(), ShuttleRedisCommand.class);
@@ -616,6 +630,9 @@
                    continue;
                }
                ShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
                if (shuttleProtocol == null) {
                    continue;
                }
                if (!shuttleProtocol.isIdle()) {
                    continue;
                }
@@ -635,19 +652,10 @@
        // 根据输送线plc遍历
        for (DevpSlave devp : slaveProperties.getDevp()) {
            // 遍历入库站
            for (DevpSlave.StaRack rackInStn : devp.getRackInStn()) {
            for (DevpSlave.StaRack staRack : devp.getRackInStn()) {
                // 获取入库站信息
                DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                StaProtocol staProtocol = devpThread.getStation().get(rackInStn.getStaNo());
//                StaProtocol staProtocol105 = devpThread.getStation().get(105);
//                staProtocol105.setWorkNo((short) 752);
//                staProtocol105.setStaNo((short) 100);
//
//                StaProtocol staProtocol106 = devpThread.getStation().get(106);
//                staProtocol106.setWorkNo((short) 753);
//                staProtocol106.setStaNo((short) 100);
                StaProtocol staProtocol = devpThread.getStation().get(staRack.getStaNo());
                if (staProtocol == null) {
                    continue;
                } else {
@@ -655,8 +663,8 @@
                }
                Short workNo = staProtocol.getWorkNo();
                // 判断是否满足入库条件
                if (true || staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.isInEnable()) {
                // 判断是否满足入库条件,自动、有物、四向穿梭车可取信号
                if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.isShuttleTakeEnable()) {
                    WrkMast wrkMast = wrkMastMapper.selectRackInStep48(workNo, staProtocol.getSiteId());
                    if (wrkMast != null) {
                        if (wrkMast.getWrkSts() == 4 || wrkMast.getWrkSts() == 8) {
@@ -697,18 +705,15 @@
                            assignCommand.setSourceLocNo(currentLocNo);//源库位(小车当前位置)
                            String locNo = wrkMast.getLocNo();//当前工作档库位号
                            Integer lev = Integer.parseInt(locNo.substring(locNo.length() - 2, locNo.length()));//当前工作档库位层高
                            Integer currentLev = Integer.parseInt(currentLocNo.substring(currentLocNo.length() - 2, currentLocNo.length()));//小车当前层高
                            Integer currentLev = Utils.getLev(currentLocNo);//小车当前层高
                            //获取提升机
                            LiftSlave liftSlave = slaveProperties.getLift().get(0);
                            //提升机库位号
                            String liftLocNo = liftSlave.getLiftLocNo(currentLev);
                            //提升机口站点库位号
                            String liftSiteLocNo = Utils.levToOutInStaLocNo(currentLev);
                            if (wrkMast.getWrkSts() == 8 || Boolean.parseBoolean(searchIdleShuttle.get("sameLay").toString())) {
                                //同一层直接取货无需经过提升机
                                //直接计算车到提升机取货再到库位路径指令
                                List<ShuttleCommand> commands = this.shuttleAssignCommand(currentLocNo, liftLocNo, locNo, assignCommand,shuttleThread);
                                List<ShuttleCommand> commands = this.shuttleAssignCommand(currentLocNo, liftSiteLocNo, locNo, assignCommand,shuttleThread);
                                if (wrkMast.getWrkSts() == 8) {
                                    //此时车在提升机内部,需要多下达一步指令让车移动到提升机口
                                    BasDevp basDevp = basDevpService.selectById(109);//获取提升机信息
@@ -716,7 +721,7 @@
                                    Short distCode = commands.get(0).getStartCodeNum();//提升机口二维码
                                    Short runDirection = commands.get(0).getRunDirection();//运行方向
                                    //获取命令
                                    ShuttleCommand moveCommand = shuttleThread.getMoveCommand(startCode, distCode, 1300, runDirection);
                                    ShuttleCommand moveCommand = shuttleThread.getMoveCommand(startCode, distCode, 1300, runDirection, (short) 1, 0);
                                    commands.add(0, moveCommand);//将该指令添加到队头
                                }
                                assignCommand.setCommands(commands);
@@ -729,11 +734,11 @@
                                //不同层,将目标库位分配成提升机库位号
                                //小车移动到提升机口,计算路径
                                List<ShuttleCommand> commands = this.shuttleAssignCommand(currentLocNo, liftLocNo, ShuttleTaskModeType.PAK_IN.id, assignCommand, shuttleThread);
                                List<ShuttleCommand> commands = this.shuttleAssignCommand(currentLocNo, liftSiteLocNo, ShuttleTaskModeType.PAK_IN.id, assignCommand, shuttleThread);
                                //分配目标库位
                                shuttleProtocol.setLocNo(liftLocNo);
                                shuttleProtocol.setLocNo(liftSiteLocNo);
                                //目标库位
                                assignCommand.setLocNo(liftLocNo);
                                assignCommand.setLocNo(liftSiteLocNo);
                                assignCommand.setCommands(commands);
                                wrkMast.setWrkSts(5L);//小车迁移状态
                            }
@@ -752,8 +757,18 @@
    }
    //获取起点-终点指令。mapType:1=》无货地图,2=》有货地图
    //获取起点-终点指令。mapType:0=>无货物地图,1=》携带货物出入库地图
    public synchronized List<ShuttleCommand> shuttleAssignCommand(String startLocNo, String locNo, Integer mapType, ShuttleAssignCommand assignCommand, ShuttleThread shuttleThread) {
        //获取小车移动速度
        BasShuttle basShuttle = basShuttleService.selectById(assignCommand.getShuttleNo());
        Integer runSpeed = 1000;
        if (basShuttle != null) {
            Integer runSpeed1 = basShuttle.getRunSpeed();
            if (runSpeed1 != null) {
                runSpeed = runSpeed1;
            }
        }
        //计算小车起点到中点所需命令
        List<NavigateNode> calc = NavigateUtils.calc(startLocNo, locNo, mapType);
        List<ShuttleCommand> commands = new ArrayList<>();
@@ -770,15 +785,20 @@
        for (ArrayList<NavigateNode> nodes : data) {
            //开始路径
            NavigateNode startPath = nodes.get(0);
            //中间路径
            NavigateNode middlePath = nodes.get(nodes.size() - 2);
            //目标路径
            NavigateNode endPath = nodes.get(nodes.size() - 1);
            Integer allDistance = NavigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离
            Integer middleToDistDistance = NavigateUtils.getMiddleToDistDistance(nodes);//计算中间点到目标点行走距离
            //通过xy坐标小车二维码
            Short startCodeNum = NavigatePositionConvert.xyToPosition(startPath.getX(), startPath.getY(), startPath.getZ());
            //通过xy坐标小车二维码
            Short middleCodeNum = NavigatePositionConvert.xyToPosition(middlePath.getX(), middlePath.getY(), middlePath.getZ());
            //通过xy坐标小车二维码
            Short distCodeNum = NavigatePositionConvert.xyToPosition(endPath.getX(), endPath.getY(), endPath.getZ());
            //获取移动命令
            ShuttleCommand command = shuttleThread.getMoveCommand(startCodeNum, distCodeNum, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id);
            ShuttleCommand command = shuttleThread.getMoveCommand(startCodeNum, distCodeNum, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id, middleCodeNum, middleToDistDistance, runSpeed);
            commands.add(command);
        }
@@ -792,33 +812,47 @@
    //获取起点-中点-终点指令
    public synchronized List<ShuttleCommand> shuttleAssignCommand(String startLocNo, String middleLocNo, String locNo, ShuttleAssignCommand assignCommand, ShuttleThread shuttleThread) {
        //计算小车起点到中点所需命令
        List<NavigateNode> calc = NavigateUtils.calc(startLocNo, middleLocNo, 1);//小车无货,走入库地图
        List<ShuttleCommand> commands = new ArrayList<>();
        if (calc == null) {
            return null;
        //获取小车移动速度
        BasShuttle basShuttle = basShuttleService.selectById(assignCommand.getShuttleNo());
        Integer runSpeed = 1000;
        if (basShuttle != null) {
            Integer runSpeed1 = basShuttle.getRunSpeed();
            if (runSpeed1 != null) {
                runSpeed = runSpeed1;
            }
        }
        List<NavigateNode> allNode = new ArrayList<>();
        allNode.addAll(calc);
        //计算小车起点到中点所需命令
        List<NavigateNode> calc = NavigateUtils.calc(startLocNo, middleLocNo, 1);//小车无货,走入库地图
        List<ShuttleCommand> commands = new ArrayList<>();
        if (calc != null) {
            allNode.addAll(calc);
        //获取分段路径
        ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(calc);
        //将每一段路径分成command指令
        for (ArrayList<NavigateNode> nodes : data) {
            //开始路径
            NavigateNode startPath = nodes.get(0);
                //中间路径
                NavigateNode middlePath = nodes.get(nodes.size() - 2);
            //目标路径
            NavigateNode endPath = nodes.get(nodes.size() - 1);
            Integer allDistance = NavigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离
                Integer middleToDistDistance = NavigateUtils.getMiddleToDistDistance(nodes);//计算中间点到目标点行走距离
            //通过xy坐标小车二维码
            Short startCodeNum = NavigatePositionConvert.xyToPosition(startPath.getX(), startPath.getY(), startPath.getZ());
            //通过xy坐标小车二维码
                Short middleCodeNum = NavigatePositionConvert.xyToPosition(middlePath.getX(), middlePath.getY(), middlePath.getZ());
                //通过xy坐标小车二维码
            Short distCodeNum = NavigatePositionConvert.xyToPosition(endPath.getX(), endPath.getY(), endPath.getZ());
            //获取移动命令
            ShuttleCommand command = shuttleThread.getMoveCommand(startCodeNum, distCodeNum, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id);
                ShuttleCommand command = shuttleThread.getMoveCommand(startCodeNum, distCodeNum, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id, middleCodeNum, middleToDistDistance, runSpeed);
            commands.add(command);
            }
        }
        //小车指令到达目标位置后,再发出一条顶升指令
@@ -837,15 +871,20 @@
        for (ArrayList<NavigateNode> nodes : data2) {
            //开始路径
            NavigateNode startPath = nodes.get(0);
            //中间路径
            NavigateNode middlePath = nodes.get(nodes.size() - 2);
            //目标路径
            NavigateNode endPath = nodes.get(nodes.size() - 1);
            Integer allDistance = NavigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离
            Integer middleToDistDistance = NavigateUtils.getMiddleToDistDistance(nodes);//计算中间点到目标点行走距离
            //通过xy坐标小车二维码
            Short startCodeNum = NavigatePositionConvert.xyToPosition(startPath.getX(), startPath.getY(), startPath.getZ());
            //通过xy坐标小车二维码
            Short middleCodeNum = NavigatePositionConvert.xyToPosition(middlePath.getX(), middlePath.getY(), middlePath.getZ());
            //通过xy坐标小车二维码
            Short distCodeNum = NavigatePositionConvert.xyToPosition(endPath.getX(), endPath.getY(), endPath.getZ());
            ShuttleCommand moveCommand = shuttleThread.getMoveCommand(startCodeNum, distCodeNum, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id);
            ShuttleCommand moveCommand = shuttleThread.getMoveCommand(startCodeNum, distCodeNum, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id, middleCodeNum, middleToDistDistance, runSpeed);
            commands.add(moveCommand);
        }
@@ -915,11 +954,11 @@
                    String currentLocNo = shuttleProtocol.getCurrentLocNo();
                    //小车当前层高
                    Integer currentLev = Integer.parseInt(currentLocNo.substring(currentLocNo.length() - 2, currentLocNo.length()));
                    Integer currentLev = Utils.getLev(currentLocNo);
                    //获取提升机
                    LiftSlave liftSlave = slaveProperties.getLift().get(0);
                    //提升机库位号
                    String liftLocNo = liftSlave.getLiftLocNo(currentLev);
                    //当前楼层提升机输送站点库位号
                    String liftSiteLocNo = Utils.levToOutInStaLocNo(currentLev);
                    //分配任务号
                    shuttleProtocol.setTaskNo(wrkMast.getWrkNo().shortValue());
@@ -939,8 +978,11 @@
                        //判断小车和库位是否在同一层
                        if (Boolean.parseBoolean(searchIdleShuttle.get("sameLay").toString())) {
                            //同一层(将小车移动到货物位置)
                            List<ShuttleCommand> commands = this.shuttleAssignCommand(currentLocNo, wrkMast.getSourceLocNo(), liftLocNo, assignCommand, shuttleThread);
                            List<ShuttleCommand> commands = this.shuttleAssignCommand(currentLocNo, wrkMast.getSourceLocNo(), liftSiteLocNo, assignCommand, shuttleThread);
                            if (commands == null) {
                                //未找到路径,等待下一次
                                continue;
                            }
                            //分配目标库位
                            shuttleProtocol.setLocNo(wrkMast.getSourceLocNo());
                            //目标库位
@@ -951,21 +993,21 @@
                            //不同层,将目标库位分配成提升机库位号(将小车移动到提升机位置)
                            //小车到提升机口指令
                            List<ShuttleCommand> commands = this.shuttleAssignCommand(currentLocNo, liftLocNo, ShuttleTaskModeType.PAK_IN.id, assignCommand, shuttleThread);
                            shuttleProtocol.setLocNo(liftLocNo);
                            List<ShuttleCommand> commands = this.shuttleAssignCommand(currentLocNo, liftSiteLocNo, ShuttleTaskModeType.PAK_IN.id, assignCommand, shuttleThread);
                            shuttleProtocol.setLocNo(liftSiteLocNo);
                            //目标库位
                            assignCommand.setLocNo(liftLocNo);
                            assignCommand.setLocNo(liftSiteLocNo);
                            assignCommand.setCommands(commands);
                            wrkMast.setWrkSts(22L);//小车迁移状态
                        }
                    } else if (wrkMast.getWrkSts() == 25) {
                        List<ShuttleCommand> commands = this.shuttleAssignCommand(currentLocNo, wrkMast.getSourceLocNo(), liftLocNo, assignCommand, shuttleThread);
                        List<ShuttleCommand> commands = this.shuttleAssignCommand(currentLocNo, wrkMast.getSourceLocNo(), liftSiteLocNo, assignCommand, shuttleThread);
                        //此时车在提升机内部,需要多下达一步指令让车移动到提升机口
                        BasDevp basDevp = basDevpService.selectById(109);//获取提升机信息
                        short startCode = Short.parseShort(basDevp.getQrCodeValue());//提升机二维码
                        Short distCode = commands.get(0).getStartCodeNum();//目标二维码
                        //获取移动命令
                        ShuttleCommand moveCommand = shuttleThread.getMoveCommand(startCode, distCode, 1300, commands.get(0).getRunDirection());
                        ShuttleCommand moveCommand = shuttleThread.getMoveCommand(startCode, distCode, 1300, commands.get(0).getRunDirection(), (short) 1, 0);
                        commands.add(0, moveCommand);//将该指令添加到队头
                        //分配目标库位
@@ -992,7 +1034,7 @@
        HashMap<String, Object> map = new HashMap<>();
        String locNo = wrkMast.getWrkSts() < 10 ? wrkMast.getLocNo() : wrkMast.getSourceLocNo();//库位号
        LocMast locMast = locMastService.queryByLoc(locNo);//找到库位记录
        String lay = locNo.substring(locNo.length() - 2, locNo.length());//当前工作档库位层高
        int lev = Utils.getLev(locNo);//当前工作档库位层高
        ShuttleThread recentShuttle = null;//当前距离最近的四向穿梭车线程
        for (ShuttleSlave shuttle : slaveProperties.getShuttle()) {
@@ -1007,8 +1049,8 @@
            }
            String shuttleLocNo = shuttleProtocol.getCurrentLocNo();//二维码对应库位号
            String shuttleLocNoLay = shuttleLocNo.substring(shuttleLocNo.length() - 2, shuttleLocNo.length());//库位号对应层高
            if (lay.equals(shuttleLocNoLay)) {
            int shuttleLocNoLey = Utils.getLev(shuttleLocNo);//库位号对应层高
            if (lev == shuttleLocNoLey) {
                //当前四向穿梭车和工作档任务在同一层,则调配该车辆
                map.put("sameLay", true);//同一层
                map.put("result", shuttleThread);
@@ -1024,10 +1066,8 @@
                String recentShuttleLocNoLay = recentShuttleLocNo.substring(recentShuttleLocNo.length() - 2, recentShuttleLocNo.length());//库位号对应层高
                int recentShuttleLocNoLayInt = Integer.parseInt(recentShuttleLocNoLay);
                int layInt = Integer.parseInt(lay);
                int shuttleLocNoLayInt = Integer.parseInt(shuttleLocNoLay);
                int i = Math.abs(layInt - recentShuttleLocNoLayInt);//工作档楼层减最近穿梭车楼层,取绝对值
                int j = Math.abs(layInt - shuttleLocNoLayInt);//工作档楼层减当前穿梭车楼层,取绝对值
                int i = Math.abs(lev - recentShuttleLocNoLayInt);//工作档楼层减最近穿梭车楼层,取绝对值
                int j = Math.abs(lev - shuttleLocNoLey);//工作档楼层减当前穿梭车楼层,取绝对值
                if (i < j) {
                    //更新最近穿梭车
                    recentShuttle = shuttleThread;
@@ -1046,7 +1086,7 @@
                    LiftSlave liftSlave = slaveProperties.getLift().get(0);
                    //提升机库位号
                    String recentLiftLocNo = liftSlave.getLiftLocNo(recentShuttleLocNoLayInt);
                    String shuttleLiftLocNo = liftSlave.getLiftLocNo(shuttleLocNoLayInt);
                    String shuttleLiftLocNo = liftSlave.getLiftLocNo(shuttleLocNoLey);
                    //当前最近四向穿梭车到提升机路径
                    List<NavigateNode> recentShuttlePath = NavigateUtils.calc(recentShuttleLocNo, recentLiftLocNo, ShuttleTaskModeType.PAK_IN.id);
@@ -1078,9 +1118,11 @@
                continue;
            }
            //四向穿梭车状态为等待确认
            //四向穿梭车状态为等待确认、小车处于空闲状态
            if (shuttleProtocol.getProtocolStatus() == ShuttleProtocolStatusType.WAITING.id  //任务完成等待确认
                    && shuttleProtocol.getTaskNo() != 0) {
                    && shuttleProtocol.getTaskNo() != 0
                    && shuttleProtocol.getBusyStatus() == 0
            ) {
                //将任务档标记为完成
                WrkMast wrkMast = wrkMastMapper.selectByWorkNo(shuttleProtocol.getTaskNo().intValue());
                if (wrkMast != null) {
@@ -1198,33 +1240,60 @@
            //命令list
            ArrayList<LiftCommand> commands = new ArrayList<>();
            if (wrkMast.getWrkSts() == 2) {
            DevpThread devpThread = null;
            Integer devpId = null;
            for (DevpSlave devp : slaveProperties.getDevp()){
                // 获取入库站信息
                devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                devpId = devp.getId();
            }
            if (wrkMast.getWrkSts() == 2) {//2.设备上走
                //工作档目标库位号
                String wrkMastLocNo = wrkMast.getIoType() == 101 ? wrkMast.getSourceLocNo() : wrkMast.getLocNo();
                String wrkMastLocNo = wrkMast.getLocNo();
                //工作档目标库位楼层
                int wrkMastLocNoLey = Integer.parseInt(wrkMastLocNo.substring(wrkMastLocNo.length() - 2, wrkMastLocNo.length()));
                int wrkMastLocNoLey = Utils.getLev(wrkMastLocNo);
                //提升机当前楼层
                int liftLev = liftProtocol.getLev().intValue();
                if (liftLev != 1) {
                    //提升机不在1层,获取到1层的提升机命令
                    LiftCommand command1 = liftThread.getLiftUpDownCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), (short) 1);
                if (liftLev == 0) {//提升机当前楼层为0,提升机失去位置信息,让提升机前往一楼
                    LiftCommand command = liftThread.getLiftUpDownCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), LiftLevType.ONE.lev);
                    commands.add(command);//将命令添加进list
                }
                if (liftLev != LiftLevType.TWO.realLev) {
                    //提升机不在输送线楼层,获取到输送线层的提升机命令
                    LiftCommand command1 = liftThread.getLiftUpDownCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), LiftLevType.TWO.lev);
                    commands.add(command1);//将命令添加进list
                }
                //输送线将货物运进来(正转)
                LiftCommand command2 = liftThread.getLiftTurnCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), 1);
                //输送线将货物运进来(无货正转)
                LiftCommand command2 = liftThread.getLiftTurnCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), 3);
                command2.setOperaStaNo((short) 102);//操作102站
                command2.setRotationDire(1);//给输送线下发链条转动信号,正转
                command2.setDevpId(devpId);
                commands.add(command2);//将命令添加进list
                Integer levTmp = wrkMastLocNoLey;
                if (wrkMastLocNoLey >= 2) {
                    levTmp += 1;
                }
                //提升机前往目标楼层(工作档目标楼层)
                LiftCommand command3 = liftThread.getLiftUpDownCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), (short) wrkMastLocNoLey);
                LiftCommand command3 = liftThread.getLiftUpDownCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), levTmp);
                commands.add(command3);//将命令添加进list
                //提升机到达指定楼层,输送线将货物移出去(反转)
                //提升机到达指定楼层,输送线将货物移出去(正转)
                //输送线将货物移出去
                LiftCommand command4 = liftThread.getLiftTurnCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), 2);
                LiftCommand command4 = liftThread.getLiftTurnCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), 1);
                Integer distStaNo = Utils.levToOutInStaNo(levTmp);
                command4.setOperaStaNo(distStaNo.shortValue());//操作目标楼层站点
                command4.setRotationDire(1);//给输送线下发链条转动信号,正转
                command4.setDevpId(devpId);
                commands.add(command4);//将命令添加进list
            }else {
                wrkMast.setWrkSts(3L);//3.提升机搬运中
            }else if(wrkMast.getWrkSts() == 6 || wrkMast.getWrkSts() == 23) {//6.迁移小车至提升机口完成 => 7.提升机迁移小车中 || 23.迁移小车至提升机口完成 => 24.提升机迁移小车中
                liftProtocol.setShuttleNo(wrkMast.getShuttleNo().shortValue());//设置四向穿梭车号
                //找到四向穿梭车的线程
@@ -1240,51 +1309,93 @@
                //当前穿梭车库位号
                String currentLocNo = shuttleProtocol.getCurrentLocNo();
                //当前穿梭车楼层
                int currentLocNoLey = Integer.parseInt(currentLocNo.substring(currentLocNo.length() - 2, currentLocNo.length()));
                int currentLocNoLey = Utils.getLev(currentLocNo);
                //工作档目标库位号
                String wrkMastLocNo = wrkMast.getIoType() == 101 ? wrkMast.getSourceLocNo() : wrkMast.getLocNo();
                //工作档目标库位楼层
                int wrkMastLocNoLey = Integer.parseInt(wrkMastLocNo.substring(wrkMastLocNo.length() - 2, wrkMastLocNo.length()));
                int wrkMastLocNoLey = Utils.getLev(wrkMastLocNo);
                //提升机当前楼层
                int liftLev = liftProtocol.getLev().intValue();
                if (liftLev == 0) {//提升机当前楼层为0,提升机失去位置信息,让提升机前往一楼
                    LiftCommand command = liftThread.getLiftUpDownCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), LiftLevType.ONE.lev);
                    commands.add(command);//将命令添加进list
                }
                if (liftLev != currentLocNoLey) {
                    //不同楼层
                    //获取目标楼层(穿梭车所在楼层)命令
                    LiftCommand command1 = liftThread.getLiftUpDownCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), (short) currentLocNoLey);
                    LiftCommand command1 = liftThread.getLiftUpDownCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), currentLocNoLey);
                    commands.add(command1);//将命令添加进list
                }
                //输送线将四向穿梭车移动进来(正转)
                LiftCommand command2 = liftThread.getLiftTurnCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), 1);
                //输送线将四向穿梭车移动进来(反转)
                LiftCommand command2 = liftThread.getLiftTurnCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), 4);
                commands.add(command2);//将命令添加进list
                if (liftLev != currentLocNoLey) {
                    //提升机前往目标楼层(工作档目标楼层)
                    LiftCommand command3 = liftThread.getLiftUpDownCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), (short) wrkMastLocNoLey);
                    LiftCommand command3 = liftThread.getLiftUpDownCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), wrkMastLocNoLey);
                    commands.add(command3);//将命令添加进list
                }
                //提升机到达指定楼层,输送线将四向穿梭车移出去
                //输送线将四向穿梭车移动出去(反转)
                LiftCommand command4 = liftThread.getLiftTurnCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), 2);
                //输送线将四向穿梭车移动出去(正转)
                LiftCommand command4 = liftThread.getLiftTurnCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), 1);
                commands.add(command4);//将命令添加进list
                wrkMast.setWrkSts(wrkMast.getWrkSts() == 6 ? 7L : 24L);//6.迁移小车至提升机口完成 => 7.提升机迁移小车中 || 23.迁移小车至提升机口完成 => 24.提升机迁移小车中
            } else if (wrkMast.getWrkSts() == 27) {//27.小车出库搬运完成
                //工作档源库位号
                String wrkMastLocNo = wrkMast.getSourceLocNo();
                //工作档源库位楼层
                int wrkMastLocNoLey = Utils.getLev(wrkMastLocNo);
                //提升机当前楼层
                int liftLev = liftProtocol.getLev().intValue();
                if (liftLev == 0) {//提升机当前楼层为0,提升机失去位置信息,让提升机前往一楼
                    LiftCommand command = liftThread.getLiftUpDownCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), LiftLevType.ONE.lev);
                    commands.add(command);//将命令添加进list
            }
            switch (wrkMast.getWrkSts().intValue()) {
                case 2://2.设备上走
                    wrkMast.setWrkSts(3L);//3.提升机搬运中
                    break;//3.提升机搬运中
                case 6://6.迁移小车至提升机口完成
                    wrkMast.setWrkSts(7L);//7.提升机迁移小车中
                    break;
                case 23://23.迁移小车至提升机口完成
                    wrkMast.setWrkSts(24L);//24.提升机迁移小车中
                    break;
                case 27://27.小车出库搬运完成
                //判断提升机是否到位
                StaProtocol staProtocol = devpThread.getStation().get(Utils.levToOutInStaNo(wrkMastLocNoLey));//起始站点
                if (liftLev != wrkMastLocNoLey && wrkMastLocNoLey != 1 || !staProtocol.isLiftArrival()) {
                    //提升机不在工作档源库位楼层,调度提升机
                    LiftCommand command1 = liftThread.getLiftUpDownCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), wrkMastLocNoLey);
                    commands.add(command1);//将命令添加进list
                }
                //输送线将货物运进来(无货反转)
                LiftCommand command2 = liftThread.getLiftTurnCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), 4);
                command2.setOperaStaNo(staProtocol.getSiteId().shortValue());//输送线操作站点号
                command2.setRotationDire(2);//给输送线下发链条转动信号,反转
                command2.setDevpId(devpId);//输送线iD
                command2.setStaNo((short) 104);//写入出库目标站104
                commands.add(command2);//将命令添加进list
                //提升机前往出库口,输送线楼层
                LiftCommand command3 = liftThread.getLiftUpDownCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), LiftLevType.TWO.lev);
                commands.add(command3);//将命令添加进list
                //提升机到达指定楼层,输送线将货物移出去(反转)
                //输送线将货物移出去
                LiftCommand command4 = liftThread.getLiftTurnCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), 2);
                command4.setOperaStaNo((short) 102);//操作102站
                command4.setRotationDire(2);//给输送线下发链条转动信号,反转
                command4.setDevpId(devpId);
                commands.add(command4);//将命令添加进list
                //提升机链条执行完毕后,给102站写入资料
                LiftCommand command5 = liftThread.getResetCommand();
                command5.setDevpId(devpId);//输送线iD
                command5.setOperaStaNo((short) 102);//操作102站
                command5.setStaNo((short) 104);//写入出库目标站104
                command5.setRotationDire(0);//链条转动停止
                commands.add(command5);
                    wrkMast.setWrkSts(28L);//28.提升机搬运中
                    break;
            }
            //所需命令组合完毕,更新数据库,提交到线程去工作
@@ -1311,13 +1422,58 @@
                continue;
            }
            //提升机为等待确认
            if (liftProtocol.getProtocolStatus() == LiftProtocolStatusType.WAITING.id && liftProtocol.getTaskNo() != 0) {
//            //当提升机状态处于工作中,但提升机实际为空闲状态,且时长超过30秒,自动复位
//            if (liftProtocol.getProtocolStatus() == LiftProtocolStatusType.WORKING.id
//                    && liftProtocol.getTaskNo() != 0
//                    && !liftProtocol.getRunning()
//            ) {
//                if (liftProtocol.getWrkTime() == null) {
//                    continue;
//                }
//
//                Date wrkTime = liftProtocol.getWrkTime();
//                Date now = new Date();
//                long interval = (now.getTime() - wrkTime.getTime()) / 1000;//计算时间差
//                if (interval >= 30) {//超过30秒自动复位
//                    //设置提升机为空闲状态
//                    liftProtocol.setProtocolStatus(LiftProtocolStatusType.IDLE);
//                    //任务号清零
//                    liftProtocol.setTaskNo((short) 0);
//                    //标记复位
//                    liftProtocol.setPakMk(true);
//                    //任务指令清零
//                    liftProtocol.setAssignCommand(null);
//                    News.info("提升机已确认且任务完成状态,复位。提升机号={}", liftProtocol.getLiftNo());
//                }
//            }
            //提升机为等待确认且空闲
            if (liftProtocol.getProtocolStatus() == LiftProtocolStatusType.WAITING.id
                    && liftProtocol.getTaskNo() != 0
                    && !liftProtocol.getRunning()
            ) {
                DevpThread devpThread = null;
                Integer devpId = null;
                for (DevpSlave devp : slaveProperties.getDevp()){
                    // 获取入库站信息
                    devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                    devpId = devp.getId();
                }
                //将任务档标记为完成
                WrkMast wrkMast = wrkMastMapper.selectByWorkNo372428(liftProtocol.getTaskNo().intValue());
                if (wrkMast != null) {
                    switch (wrkMast.getWrkSts().intValue()) {
                        case 3://3.提升机搬运中 ==> 4.提升机搬运完成
                            //给目标站设置工作号
                            StaProtocol staProtocol = devpThread.getStation().get(wrkMast.getStaNo());//目标站
                            staProtocol.setWorkNo(wrkMast.getWrkNo().shortValue());
                            staProtocol.setStaNo(wrkMast.getStaNo().shortValue());
                            boolean result = MessageQueue.offer(SlaveType.Devp, devpId, new Task(2, staProtocol));
                            if (!result) {
                                throw new CoolException("更新plc站点信息失败");
                            }
                            wrkMast.setWrkSts(4L);
                            break;
                        case 7://7.提升机迁移小车中 ==> 8.提升机迁移小车完成
@@ -1342,25 +1498,14 @@
                        liftProtocol.setPakMk(true);
                        //任务指令清零
                        liftProtocol.setAssignCommand(null);
                        //提升机解锁
                        liftProtocol.setLiftLock(false);
                        News.info("提升机已确认且任务完成状态,复位。提升机号={}", liftProtocol.getLiftNo());
                    } else {
                        News.error("提升机已确认且任务完成状态,复位失败,但未找到工作档。提升机号={},工作号={}", liftProtocol.getLiftNo(), liftProtocol.getTaskNo());
                    }
                }
                //查询是否有充电任务
                WrkCharge wrkCharge = wrkChargeMapper.selectByWorkNo(liftProtocol.getTaskNo().intValue());
                if (wrkCharge != null) {
                    switch (wrkCharge.getWrkSts().intValue()) {
                        case 54://提升机搬运中
                            wrkCharge.setWrkSts(55L);//提升机搬运完成
                            break;
                        default:
                    }
                    if (wrkChargeMapper.updateById(wrkCharge) > 0) {
                //不是入出库调度任务、工作档任务,进行提升机的复位
                if (liftProtocol.getAssignCommand() != null) {
                        //设置提升机为空闲状态
                        liftProtocol.setProtocolStatus(LiftProtocolStatusType.IDLE);
                        //任务号清零
@@ -1369,13 +1514,14 @@
                        liftProtocol.setPakMk(true);
                        //任务指令清零
                        liftProtocol.setAssignCommand(null);
                        //提升机解锁
                        liftProtocol.setLiftLock(false);
                        News.info("提升机已确认且任务完成状态,复位。提升机号={}", liftProtocol.getLiftNo());
                    } else {
                        News.error("提升机已确认且任务完成状态,复位失败,但未找到工作档。提升机号={},工作号={}", liftProtocol.getLiftNo(), liftProtocol.getTaskNo());
//                    LiftAssignCommand assignCommand = liftProtocol.getAssignCommand();
//                    if (!assignCommand.getAuto()) {
//                        //手动命令
//
//                    }
                    }
                }
            }
        }
    }
@@ -2135,7 +2281,7 @@
        //当前穿梭车库位号
        String currentLocNo = shuttleProtocol.getCurrentLocNo();
        //小车当前层高
        Integer currentLev = Integer.parseInt(currentLocNo.substring(currentLocNo.length() - 2, currentLocNo.length()));
        Integer currentLev = currentLocNo == null ? 0 : Integer.parseInt(currentLocNo.substring(currentLocNo.length() - 2, currentLocNo.length()));
        //获取提升机
        LiftSlave liftSlave = slaveProperties.getLift().get(0);
        //提升机库位号
@@ -2231,7 +2377,7 @@
            if (liftLev != currentLev) {
                //穿梭车和提升机处于不同楼层
                //获取目标楼层(穿梭车所在楼层)命令
                LiftCommand command1 = liftThread.getLiftUpDownCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), currentLev.shortValue());
                LiftCommand command1 = liftThread.getLiftUpDownCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), currentLev);
                commands.add(command1);//将命令添加进list
            }
@@ -2241,7 +2387,7 @@
            //提升机前往目标楼层
            //获取充电库位目标楼层命令
            LiftCommand command3 = liftThread.getLiftUpDownCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), chargeLocNoLev.shortValue());
            LiftCommand command3 = liftThread.getLiftUpDownCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), chargeLocNoLev);
            commands.add(command3);//将命令添加进list
            //提升机到达指定楼层,输送线将四向穿梭车移出去
src/main/java/com/zy/asrs/utils/Utils.java
@@ -268,6 +268,70 @@
        return zerofill(String.valueOf(row), 2) + zerofill(String.valueOf(bay), 3) + zerofill(String.valueOf(lev), 2);
    }
    //出入库站点号转换对应楼层
    public static Integer outInStaNoToLev(Integer distSta) {
        Integer distLev = 1;//目标楼层
        switch (distSta) {
            case 102:
                distLev = 2;//输送线楼层
            case 105:
                distLev = 1;//一楼
            case 106:
                distLev = 3;//二楼
            case 107:
                distLev = 4;//三楼
            case 108:
                distLev = 5;//四楼
        }
        return distLev;
    }
    //楼层转换对应出入库站点号
    public static Integer levToOutInStaNo(Integer lev) {
        Integer staNo = null;//站点号
        switch (lev) {
            case 1:
                staNo = 105;
                break;
            case 2://输送线层
                staNo = 105;
                break;
            case 3:
                staNo = 106;
                break;
            case 4:
                staNo = 107;
                break;
            case 5:
                staNo = 108;
                break;
        }
        return staNo;
    }
    //楼层转换对应出入库站点库位号
    public static String levToOutInStaLocNo(Integer lev) {
        String locNo = null;
        if (lev >= 2) {
            lev++;
        }
        switch (lev) {
            case 1:
                locNo = "1800201";
                break;
            case 3:
                locNo = "1800202";
                break;
            case 4:
                locNo = "1800203";
                break;
            case 5:
                locNo = "1800204";
                break;
        }
        return locNo;
    }
    public static void main(String[] args) {
        System.out.println(JSON.toJSONString(getGroupOutsideLoc("0200101")));
    }
src/main/java/com/zy/core/MainProcess.java
@@ -74,21 +74,18 @@
                    // 其他  ===>> LED显示器复位,显示默认信息
                    mainService.ledReset();
                    // 穿梭车 ===>> 小车电量检测充电
                    mainService.loopShuttleCharge();
                    mainService.executeShuttleCharge();
                    //出入库模式
                    i++;
                    if (i > 1) {
                        mainService.outAndIn();
                        i = 0;
                    }
//                    mainService.loopShuttleCharge();
//                    mainService.executeShuttleCharge();
//                    //出入库模式
//                    i++;
//                    if (i > 1) {
//                        mainService.outAndIn();
//                        i = 0;
//                    }
                    // 间隔
                    Thread.sleep(200);
                    // 穿梭车 ===>> 小车复位至待机库位
//                    mainService.queryChargeLocOfComplete();
//                    mainService.steFromChargeToIdleLoc();
                } catch (Exception e) {
                    e.printStackTrace();
                }
src/main/java/com/zy/core/enums/LiftLevType.java
New file
@@ -0,0 +1,71 @@
package com.zy.core.enums;
/**
 * 提升机楼层与实际楼层数值转换
 */
public enum LiftLevType {
    ONE(1, (short) 1),
    TWO(2, (short) 2),
    THREE(3, (short) 4),
    FOUR(4, (short) 8),
    FIVE(5, (short) 16),
    ;
    public Integer lev;
    public Short realLev;
    LiftLevType(Integer lev, Short realLev) {
        this.lev = lev;
        this.realLev = realLev;
    }
    public static LiftLevType get(Integer lev) {
        if (null == lev) {
            return null;
        }
        for (LiftLevType type : LiftLevType.values()) {
            if (type.lev.equals(lev)) {
                return type;
            }
        }
        return null;
    }
    public static LiftLevType get(LiftLevType type) {
        if (null == type) {
            return null;
        }
        for (LiftLevType type2 : LiftLevType.values()) {
            if (type2 == type) {
                return type2;
            }
        }
        return null;
    }
    public static Short getRealLev(Integer lev) {
        if (null == lev) {
            return null;
        }
        for (LiftLevType type : LiftLevType.values()) {
            if (type.lev.equals(lev)) {
                return type.realLev;
            }
        }
        return null;
    }
    public static Integer getLev(Short realLev) {
        if (null == realLev) {
            return null;
        }
        for (LiftLevType type : LiftLevType.values()) {
            if (type.realLev.equals(realLev)) {
                return type.lev;
            }
        }
        return null;
    }
}
src/main/java/com/zy/core/enums/ShuttleRunDirection.java
@@ -5,8 +5,8 @@
 */
public enum ShuttleRunDirection {
    TOP((short)2, "货物方向+"),
    BOTTOM((short)1, "货物方向-"),
    TOP((short)2, "货物方向-"),
    BOTTOM((short)1, "货物方向+"),
    LEFT((short)3, "过道方向-"),
    RIGHT((short)4, "过道方向+"),
    ;
src/main/java/com/zy/core/enums/ShuttleTaskModeType.java
@@ -18,6 +18,7 @@
    SEARCH_BOTTOM(13, "负方向(后)寻库位"),
    MOVE_LOC_NO(14, "移动到目标库位"),
    CHARGE(15, "充电"),
    MOVE_LIFT(16, "移动到提升机"),
    ;
    public Integer id;
src/main/java/com/zy/core/model/command/LiftCommand.java
@@ -1,5 +1,6 @@
package com.zy.core.model.command;
import com.zy.core.model.protocol.StaProtocol;
import lombok.Data;
@@ -59,6 +60,26 @@
     */
    private Boolean liftLock;
    /**
     * 操作输送站点号
     */
    private Short operaStaNo;
    /**
     * 输送线联动转动方向,0:停止转动,1:正向转动,2:反向转动
     */
    private Integer rotationDire;
    /**
     * 输送线ID
     */
    private Integer devpId;
    /**
     * 目标站
     */
    private Short staNo;
    public Short getLiftLockShortValue() {
        if (liftLock == null) {
            return (short) 0;
src/main/java/com/zy/core/model/protocol/LiftProtocol.java
@@ -1,15 +1,11 @@
package com.zy.core.model.protocol;
import com.core.common.SpringUtils;
import com.zy.asrs.service.BasShuttleService;
import com.zy.core.News;
import com.zy.core.enums.LiftProtocolStatusType;
import com.zy.core.enums.ShuttleErrorCodeType;
import com.zy.core.enums.ShuttleProtocolStatusType;
import com.zy.core.enums.ShuttleStatusType;
import com.zy.core.model.command.LiftAssignCommand;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
/**
 * 提升机
@@ -22,6 +18,11 @@
     * 提升机号
     */
    private Short liftNo;
    /**
     * 提升机内部二维码
     */
    private Short barcode = 1699;
    /**
     * 任务号
@@ -199,6 +200,31 @@
     */
    private LiftAssignCommand assignCommand;
    /**
     * 出入库模式,1:入库,2:出库
     */
    private Integer outInModel;
    /**
     * 出入库模式起始站点
     */
    private Integer startSta;
    /**
     * 出入库模式目标站点
     */
    private Integer distSta;
    /**
     * 出入库模式步数
     */
    private Integer outInModelStep;
    /**
     * 工作时间
     */
    private Date wrkTime;
    public Short getLiftLockShortValue() {
        return liftLock ? (short) 1 : (short) 0;
    }
@@ -233,7 +259,7 @@
        boolean res = this.taskNo == 0
                && !this.liftLock
                && this.ready
//                && this.ready
                && !this.running
                && this.mode
                && this.pakMk.equals(true)
src/main/java/com/zy/core/model/protocol/ShuttleProtocol.java
@@ -54,7 +54,7 @@
    private String sourceLocNo;
    /**
     * 目标库位f
     * 目标库位
     */
    private String locNo;
@@ -246,6 +246,9 @@
            // 电量
            try {
                Integer chargeLine = SpringUtils.getBean(BasShuttleService.class).selectById(this.shuttleNo).getChargeLine();
                if (chargeLine == null) {
                    return false;
                }
                return this.getBatteryPower$() > chargeLine;
            } catch (Exception e) {
                News.error("fail", e);
src/main/java/com/zy/core/model/protocol/StaProtocol.java
@@ -40,6 +40,12 @@
    // 满托盘
    private boolean fullPlt;
    //提升机到位信号
    private boolean liftArrival;
    //四向穿梭车可取信号
    private boolean shuttleTakeEnable;
    // 高
    private boolean high;
@@ -75,6 +81,9 @@
    //出入库模式
    private Short outInModel;
    //输送线联动转动方向,0:停止转动,1:正向转动,2:反向转动
    private Integer rotationDire;
    public BasDevp toSqlModel(){
        BasDevp basDevp = new BasDevp();
        basDevp.setDevNo(siteId);
src/main/java/com/zy/core/thread/LiftThread.java
@@ -14,15 +14,19 @@
import com.zy.asrs.service.BasLiftService;
import com.zy.common.utils.CommonUtils;
import com.zy.common.utils.RedisUtil;
import com.zy.core.DevpThread;
import com.zy.core.News;
import com.zy.core.ThreadHandler;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.OutputQueue;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.*;
import com.zy.core.model.DevpSlave;
import com.zy.core.model.LiftSlave;
import com.zy.core.model.Task;
import com.zy.core.model.command.*;
import com.zy.core.model.protocol.LiftProtocol;
import com.zy.core.model.protocol.StaProtocol;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@@ -169,15 +173,13 @@
                ///读取提升机状态-end
                //小车处于运行状态,将标记置为true
                //提升机处于运行状态,将标记置为true
                if (liftProtocol.getRunning()) {
                    liftProtocol.setPakMk(true);
                }
                //提升机处于锁定、未运行、就绪、标记true、有任务号
                if (liftProtocol.getLiftLock()
                        && !liftProtocol.getRunning()
                        && liftProtocol.getReady()
                //提升机处于未运行、就绪、标记true、有任务号
                if (!liftProtocol.getRunning()
                        && liftProtocol.getPakMk()
                        && liftProtocol.getTaskNo() != 0) {
                    //还有未完成的命令
@@ -362,12 +364,33 @@
        //取出命令
        LiftCommand command = commands.get(commandStep);
        if (command.getOperaStaNo() != null && command.getDevpId() != null) {
            //站点和输送线ID不为null,需要下发站点指令调度指定站点进行链条转动
            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, command.getDevpId());
            StaProtocol staProtocol = devpThread.getStation().get(command.getOperaStaNo().intValue());
            if (!staProtocol.isLiftArrival()) {//链条转动条件,需要有提升机到位信号
                liftProtocol.setPakMk(true);
                return false;
            }
            staProtocol.setWorkNo(wrkNo);//设置任务号
            if (command.getStaNo() != null) {
                staProtocol.setStaNo(command.getStaNo());//设置目标站
            }
            if (command.getRotationDire() != null) {
                staProtocol.setRotationDire(command.getRotationDire());//站点链条转动信号
            }
            Integer devpId = command.getDevpId();
            boolean result1 = MessageQueue.offer(SlaveType.Devp, devpId, new Task(3, staProtocol));//下发命令使输送线链条运转
        }
        //下发命令
        if (!write(command)) {
            News.error("提升机命令下发失败,提升机号={},任务数据={}", command.getLiftNo(), JSON.toJSON(command));
            return false;
        }else {
            News.info("提升机命令下发成功,提升机号={},任务数据={}", command.getLiftNo(), JSON.toJSON(command));
            liftProtocol.setWrkTime(new Date());//更新工作时间
            //判断数据是否执行完成
            if (commandStep < size - 1) {
@@ -396,19 +419,9 @@
                //删除redis
                redisUtil.del("lift_wrk_no_" + redisCommand.getWrkNo());
                if (assignCommand.getAuto()) {
                    //对主线程抛出等待确认状态waiting
                    liftProtocol.setProtocolStatus(LiftProtocolStatusType.WAITING);
                    News.info("提升机任务执行完成等待确认中,提升机号={},任务数据={}", command.getLiftNo(), JSON.toJSON(command));
                }else {
                    //手动模式不抛出等待状态
                    liftProtocol.setTaskNo((short) 0);
                    liftProtocol.setShuttleNo((short) 0);
                    liftProtocol.setProtocolStatus(LiftProtocolStatusType.IDLE);
                    liftProtocol.setPakMk(true);
                    liftProtocol.setSecurityMk(false);
                    News.info("提升机手动任务执行完成,提升机号={},任务数据={}", command.getLiftNo(), JSON.toJSON(command));
                }
            }
        }
@@ -443,26 +456,7 @@
    public LiftCommand getLiftUpDownCommand(Integer lev) {
        LiftCommand command = new LiftCommand();
        command.setRun((short) 1);//升降
        Short position = 1;
        switch (lev) {
            case 1:
                position = 1;
                break;
            case 2:
                position = 2;
                break;
            case 3:
                position = 4;
                break;
            case 4:
                position = 8;
                break;
            case 5:
                position = 16;
                break;
            default:
                position = 1;
        }
        Short position = LiftLevType.getRealLev(lev);//获取提升机实际楼层数值
        command.setDistPosition(position);
        command.setSpeed((short) 200);
        command.setHeight2((short) 180);
@@ -475,12 +469,18 @@
    /**
     * 获取提升机上升下降命令
     */
    public LiftCommand getLiftUpDownCommand(Short liftNo, Short taskNo, Short lev) {
    public LiftCommand getLiftUpDownCommand(Short liftNo, Short taskNo, Integer lev) {
        LiftCommand command = new LiftCommand();
        Short position = LiftLevType.getRealLev(lev);//获取提升机实际楼层数值
        command.setRun((short) 1);//升降
        command.setLiftNo(liftNo);//提升机号
        command.setTaskNo(taskNo);//任务号
        command.setDistPosition(lev);//目标楼层1层
        command.setDistPosition(position);//目标楼层
        command.setSpeed((short) 200);
        command.setHeight2((short) 180);
        command.setHeight3((short) 1645);
        command.setHeight4((short) 3290);
        command.setHeight5((short) 4945);
        return command;
    }
src/main/java/com/zy/core/thread/ShuttleThread.java
@@ -8,14 +8,8 @@
import com.core.common.DateUtils;
import com.core.common.SpringUtils;
import com.core.exception.CoolException;
import com.zy.asrs.entity.BasDevp;
import com.zy.asrs.entity.BasShuttle;
import com.zy.asrs.entity.BasShuttleOpt;
import com.zy.asrs.entity.LocMast;
import com.zy.asrs.service.BasDevpService;
import com.zy.asrs.service.BasShuttleOptService;
import com.zy.asrs.service.BasShuttleService;
import com.zy.asrs.service.LocMastService;
import com.zy.asrs.entity.*;
import com.zy.asrs.service.*;
import com.zy.asrs.utils.Utils;
import com.zy.common.model.NavigateNode;
import com.zy.common.utils.*;
@@ -30,6 +24,7 @@
import com.zy.core.model.command.*;
import com.zy.core.model.protocol.LiftProtocol;
import com.zy.core.model.protocol.ShuttleProtocol;
import com.zy.core.model.protocol.StaProtocol;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@@ -174,18 +169,18 @@
                    shuttleProtocol.setPakMk(true);
                }
                if (shuttleProtocol.getErrorCode() != 0 && shuttleProtocol.getProtocolStatusType() == ShuttleProtocolStatusType.WORKING) {
                    //出现错误
                    resetAndTryFix(shuttleProtocol.getTaskNo());
                }
                if(shuttleProtocol.getProtocolStatusType() == ShuttleProtocolStatusType.FIXING
                        && shuttleProtocol.getTaskNo() != 0
                        && shuttleProtocol.getBusyStatusType() == ShuttleStatusType.IDLE){
                    //处于故障修复状态
                    //执行下一步指令
                    executeWork(shuttleProtocol.getTaskNo());
                }
//                if (shuttleProtocol.getErrorCode() != 0 && shuttleProtocol.getProtocolStatusType() == ShuttleProtocolStatusType.WORKING) {
//                    //出现错误
//                    resetAndTryFix(shuttleProtocol.getTaskNo());
//                }
//
//                if(shuttleProtocol.getProtocolStatusType() == ShuttleProtocolStatusType.FIXING
//                        && shuttleProtocol.getTaskNo() != 0
//                        && shuttleProtocol.getBusyStatusType() == ShuttleStatusType.IDLE){
//                    //处于故障修复状态
//                    //执行下一步指令
//                    executeWork(shuttleProtocol.getTaskNo());
//                }
                //四向穿梭车空闲、有任务、标记为true、存在任务指令,需要执行任务的下一条指令
                if (shuttleProtocol.getBusyStatusType() == ShuttleStatusType.IDLE
@@ -195,18 +190,18 @@
                    executeWork(shuttleProtocol.getTaskNo());
                }
                //检测是否有提升机锁定标记,有则检测提升机是否到位,是否能走下一步命令
                if (shuttleProtocol.getBusyStatusType() == ShuttleStatusType.IDLE
                        && shuttleProtocol.getTaskNo() != 0) {
                    Object o = redisUtil.get("shuttle_wrk_no_" + shuttleProtocol.getTaskNo());
                    if (o != null) {
                        ShuttleRedisCommand redisCommand = JSON.parseObject(o.toString(), ShuttleRedisCommand.class);
                        if (redisCommand.getLiftSecurityMk()) {
                            //执行下一步指令
                            executeWork(shuttleProtocol.getTaskNo());
                        }
                    }
                }
//                //检测是否有提升机锁定标记,有则检测提升机是否到位,是否能走下一步命令
//                if (shuttleProtocol.getBusyStatusType() == ShuttleStatusType.IDLE
//                        && shuttleProtocol.getTaskNo() != 0) {
//                    Object o = redisUtil.get("shuttle_wrk_no_" + shuttleProtocol.getTaskNo());
//                    if (o != null) {
//                        ShuttleRedisCommand redisCommand = JSON.parseObject(o.toString(), ShuttleRedisCommand.class);
//                        if (redisCommand.getLiftSecurityMk()) {
//                            //执行下一步指令
//                            executeWork(shuttleProtocol.getTaskNo());
//                        }
//                    }
//                }
                //将四向穿梭车状态保存至数据库
                BasShuttleService shuttleService = SpringUtils.getBean(BasShuttleService.class);
@@ -391,11 +386,28 @@
    //分配任务
    private void assignWork(ShuttleAssignCommand assignCommand) {
        ShuttleRedisCommand redisCommand = new ShuttleRedisCommand();
        if (!assignCommand.getAuto()) {
            List<NavigateNode> allNode = new ArrayList<>();
            List<ShuttleCommand> commands = new ArrayList<>();
            LocMastService locMastService = SpringUtils.getBean(LocMastService.class);
            BasShuttleService shuttleService = SpringUtils.getBean(BasShuttleService.class);
            NavigateMapData navigateMapData;
            //获取小车移动速度
            BasShuttle basShuttle = shuttleService.selectById(slave.getId());
            Integer runSpeed = 1000;
            if (basShuttle != null) {
                Integer runSpeed1 = basShuttle.getRunSpeed();
                if (runSpeed1 != null) {
                    runSpeed = runSpeed1;
                }
            }
            LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, 1);
            LiftProtocol liftProtocol = liftThread.getLiftProtocol();
            switch (assignCommand.getTaskMode()) {
                case 1://入库
                case 2://出库
@@ -403,9 +415,6 @@
                    //计算小车起点到中点所需命令
                    LocMast currentLocMast = locMastService.queryByQrCode(shuttleProtocol.getCurrentCode().toString());
                    List<NavigateNode> firstMastResult = NavigateUtils.calc(currentLocMast.getLocNo(), assignCommand.getSourceLocNo(), ShuttleTaskModeType.PAK_IN.id);
                    //所使用的路径进行锁定禁用
                    navigateMapData = new NavigateMapData(Utils.getLev(currentLocMast.getLocNo()));
                    navigateMapData.writeNavigateNodeToRedisMap(firstMastResult, true);////所使用的路径进行锁定禁用
                    if (firstMastResult != null) {
                        allNode.addAll(firstMastResult);//将节点进行保存
@@ -415,14 +424,18 @@
                        for (ArrayList<NavigateNode> nodes : data) {
                            //开始路径
                            NavigateNode startPath = nodes.get(0);
                            //中间路径
                            NavigateNode middlePath = nodes.get(nodes.size() - 2);
                            //目标路径
                            NavigateNode endPath = nodes.get(nodes.size() - 1);
                            Integer allDistance = NavigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离
                            Integer middleToDistDistance = NavigateUtils.getMiddleToDistDistance(nodes);//计算中间点到目标点行走距离
                            //正常移动命令
                            Short startCode = NavigatePositionConvert.xyToPosition(startPath.getX(), startPath.getY(), 1);//开始二维码
                            Short distCode = NavigatePositionConvert.xyToPosition(endPath.getX(), endPath.getY(), 1);//目标二维码
                            commands.add(getMoveCommand(startCode,distCode,allDistance,ShuttleRunDirection.get(startPath.getDirection()).id));
                            Short startCode = NavigatePositionConvert.xyToPosition(startPath.getX(), startPath.getY(), startPath.getZ());//开始二维码
                            Short middleCode = NavigatePositionConvert.xyToPosition(middlePath.getX(), middlePath.getY(), middlePath.getZ());//目标二维码
                            Short distCode = NavigatePositionConvert.xyToPosition(endPath.getX(), endPath.getY(), endPath.getZ());//目标二维码
                            commands.add(getMoveCommand(startCode, distCode, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id, middleCode, middleToDistDistance, runSpeed));
                        }
                        //托盘顶升
@@ -438,7 +451,6 @@
                    //计算中点到终点路径
                    List<NavigateNode> secMastResult = NavigateUtils.calc(assignCommand.getSourceLocNo(), assignCommand.getLocNo(), ShuttleTaskModeType.PAK_IN.id);
                    navigateMapData.writeNavigateNodeToRedisMap(firstMastResult, true);////所使用的路径进行锁定禁用
                    if (secMastResult != null) {
                        allNode.addAll(secMastResult);//将节点进行保存
@@ -448,18 +460,32 @@
                        for (ArrayList<NavigateNode> nodes : data) {
                            //开始路径
                            NavigateNode startPath = nodes.get(0);
                            //中间路径
                            NavigateNode middlePath = nodes.get(nodes.size() - 2);
                            //目标路径
                            NavigateNode endPath = nodes.get(nodes.size() - 1);
                            Integer allDistance = NavigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离
                            Integer middleToDistDistance = NavigateUtils.getMiddleToDistDistance(nodes);//计算中间点到目标点行走距离
                            //正常移动命令
                            Short startCode = NavigatePositionConvert.xyToPosition(startPath.getX(), startPath.getY(), 1);//开始二维码
                            Short distCode = NavigatePositionConvert.xyToPosition(endPath.getX(), endPath.getY(), 1);//目标二维码
                            commands.add(getMoveCommand(startCode, distCode, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id));
                            Short startCode = NavigatePositionConvert.xyToPosition(startPath.getX(), startPath.getY(), startPath.getZ());//开始二维码
                            Short middleCode = NavigatePositionConvert.xyToPosition(middlePath.getX(), middlePath.getY(), middlePath.getZ());//中间二维码
                            Short distCode = NavigatePositionConvert.xyToPosition(endPath.getX(), endPath.getY(), endPath.getZ());//目标二维码
                            commands.add(getMoveCommand(startCode, distCode, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id, middleCode, middleToDistDistance, runSpeed));
                        }
                        //托盘下降
                        commands.add(getPalletCommand((short) 2));
                    }
                    navigateMapData = new NavigateMapData(Utils.getLev(currentLocMast.getLocNo()));
                    if (firstMastResult != null) {
                        //所使用的路径进行锁定禁用
                        navigateMapData.writeNavigateNodeToRedisMap(firstMastResult, true);////所使用的路径进行锁定禁用
                    }
                    if (secMastResult != null) {
                        navigateMapData.writeNavigateNodeToRedisMap(secMastResult, true);////所使用的路径进行锁定禁用
                    }
                    break;
                case 3://托盘顶升
@@ -482,10 +508,10 @@
                    ShuttleCommand reset = getResetCommand();
                    commands.add(reset);
                    break;
                case 10://向正方向(左)寻库位
                case 10://正方向(右)寻库位
                    commands.add(getFindLocCommand((short) 1));
                    break;
                case 11://向负方向(右)寻库位
                case 11://负方向(左)寻库位
                    commands.add(getFindLocCommand((short) 2));
                    break;
                case 12://向正方向(前)寻库位
@@ -495,13 +521,28 @@
                    commands.add(getFindLocCommand((short) 3));
                    break;
                case 14://移动到目标库位
                    LocMast locMast = locMastService.queryByQrCode(shuttleProtocol.getCurrentCode().toString());
                    String startQr = shuttleProtocol.getCurrentCode().toString();//起始位置
                    //如果穿梭车在提升机内,移动时需要先下发出提升机命令
                    if (liftProtocol.getBarcode().intValue() == shuttleProtocol.getCurrentCode().intValue()) {
                        //穿梭车出提升机
                        Short liftLev = liftProtocol.getPositionArrivalFeedback();//提升机位置
                        String liftSiteLocNo = Utils.levToOutInStaLocNo(liftLev.intValue());
                        LocMast locMast1 = locMastService.selectById(liftSiteLocNo);
                        ShuttleCommand moveCommand = getMoveCommand(liftProtocol.getBarcode(), Short.parseShort(locMast1.getQrCodeValue()), 1400, ShuttleRunDirection.BOTTOM.id, liftProtocol.getBarcode(), 1400, runSpeed);
                        commands.add(moveCommand);
                        //起始位置修改为提升机口站点位置
                        startQr = locMast1.getQrCodeValue();
                    }
                    LocMast locMast = locMastService.queryByQrCode(startQr);
                    List<NavigateNode> result = NavigateUtils.calc(locMast.getLocNo(), assignCommand.getLocNo(), ShuttleTaskModeType.PAK_IN.id);
                    if (result != null) {
                    //所使用的路径进行锁定禁用
                    navigateMapData = new NavigateMapData(Utils.getLev(locMast.getLocNo()));
                    navigateMapData.writeNavigateNodeToRedisMap(result, true);////所使用的路径进行锁定禁用
                    if (result != null) {
                        allNode.addAll(result);//将节点进行保存
                        //获取分段路径
                        ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(result);
@@ -509,20 +550,66 @@
                        for (ArrayList<NavigateNode> nodes : data) {
                            //开始路径
                            NavigateNode startPath = nodes.get(0);
                            //中间路径
                            NavigateNode middlePath = nodes.get(nodes.size() - 2);
                            //目标路径
                            NavigateNode endPath = nodes.get(nodes.size() - 1);
                            Integer allDistance = NavigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离
                            LocMast distLocMast = locMastService.queryByLoc(assignCommand.getLocNo());
                            String qrCodeValue = distLocMast.getQrCodeValue();
                            Integer middleToDistDistance = NavigateUtils.getMiddleToDistDistance(nodes);//计算中间点到目标点行走距离
                            Short startCode = NavigatePositionConvert.xyToPosition(startPath.getX(), startPath.getY(), startPath.getZ());//开始二维码
                            Short middleCode = NavigatePositionConvert.xyToPosition(middlePath.getX(), middlePath.getY(), middlePath.getZ());//中间二维码
                            Short distCode = NavigatePositionConvert.xyToPosition(endPath.getX(), endPath.getY(), endPath.getZ());//目标二维码
                            //正常移动命令
                            commands.add(getMoveCommand(shuttleProtocol.getCurrentCode(),(short) Integer.parseInt(qrCodeValue),allDistance,ShuttleRunDirection.get(startPath.getDirection()).id));
                            commands.add(getMoveCommand(startCode, distCode, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id, middleCode, middleToDistDistance, runSpeed));
                        }
                    }
                    break;
                case 15://充电开关
                    commands.add(getChargeSwitchCommand());
                    break;
                case 16://移动到提升机
                    LocMast locMast1 = locMastService.queryByQrCode(shuttleProtocol.getCurrentCode().toString());
                    int lev = Utils.getLev(locMast1.getLocNo());//穿梭车当前高度
                    String liftSiteLocNo = Utils.levToOutInStaLocNo(lev);//当前楼层站点库位号
                    LocMast liftSitelocMast = locMastService.selectById(liftSiteLocNo);
                    List<NavigateNode> result1 = NavigateUtils.calc(locMast1.getLocNo(), liftSiteLocNo, ShuttleTaskModeType.PAK_IN.id);
                    Short endStartCode = null;
                    if (result1 != null) {
                        //所使用的路径进行锁定禁用
                        navigateMapData = new NavigateMapData(Utils.getLev(locMast1.getLocNo()));
                        navigateMapData.writeNavigateNodeToRedisMap(result1, true);////所使用的路径进行锁定禁用
                        allNode.addAll(result1);//将节点进行保存
                        //获取分段路径
                        ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(result1);
                        //将每一段路径分成command指令
                        for (ArrayList<NavigateNode> nodes : data) {
                            //开始路径
                            NavigateNode startPath = nodes.get(0);
                            //中间路径
                            NavigateNode middlePath = nodes.get(nodes.size() - 2);
                            //目标路径
                            NavigateNode endPath = nodes.get(nodes.size() - 1);
                            Integer allDistance = NavigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离
                            Integer middleToDistDistance = NavigateUtils.getMiddleToDistDistance(nodes);//计算中间点到目标点行走距离
                            Short startCode = NavigatePositionConvert.xyToPosition(startPath.getX(), startPath.getY(), startPath.getZ());//开始二维码
                            Short middleCode = NavigatePositionConvert.xyToPosition(middlePath.getX(), middlePath.getY(), middlePath.getZ());//中间二维码
                            Short distCode = NavigatePositionConvert.xyToPosition(endPath.getX(), endPath.getY(), endPath.getZ());//目标二维码
                            endStartCode = distCode;
                            //正常移动命令
                            commands.add(getMoveCommand(startCode, distCode, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id, middleCode, middleToDistDistance, runSpeed));
                        }
                    }
                    if (endStartCode == null && shuttleProtocol.getCurrentCode() == Short.parseShort(liftSitelocMast.getQrCodeValue())) {
                        //穿梭车已经在提升机站点口
                        endStartCode = shuttleProtocol.getCurrentCode();
                    }
                    //增加移动进提升机命令
                    ShuttleCommand moveCommand = getMoveCommand(endStartCode, liftProtocol.getBarcode(), 1400, ShuttleRunDirection.TOP.id, endStartCode, 1400, runSpeed);
                    commands.add(moveCommand);
                    break;
                default:
            }
@@ -530,7 +617,6 @@
            assignCommand.setNodes(allNode);//当前任务所占用的节点list
        }
        ShuttleRedisCommand redisCommand = new ShuttleRedisCommand();
        redisCommand.setShuttleNo(assignCommand.getShuttleNo());//四向穿梭车号
        redisCommand.setWrkNo(assignCommand.getTaskNo());//工作号
        redisCommand.setCommandStep(0);//命令执行步序
@@ -657,6 +743,9 @@
            }
        }
        LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, 1);
        LiftProtocol liftProtocol = liftThread.getLiftProtocol();
        //下发命令
        if (!write(command)) {
            News.error("四向穿梭车命令下发失败,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
@@ -694,17 +783,17 @@
                if (redisCommand.getLiftSecurityMk()) {
                    //曾锁定过提升机,需要进行解锁
                    LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, 1);
                    LiftProtocol liftProtocol = liftThread.getLiftProtocol();
                    if (liftProtocol != null) {
                        liftProtocol.setSecurityMk(false);
                    }
                }
                String locNo = shuttleProtocol.getLocNo() == null ? shuttleProtocol.getSourceLocNo() : shuttleProtocol.getLocNo();
                if (locNo != null) {
                //解除锁定的库位路径
                NavigateMapData navigateMapData = new NavigateMapData(Utils.getLev(locNo));
                navigateMapData.writeNavigateNodeToRedisMap(redisCommand.getAssignCommand().getNodes(), false);
                }
                //删除redis
                redisUtil.del("shuttle_wrk_no_" + redisCommand.getWrkNo());
@@ -743,6 +832,16 @@
            return false;
        }
        //拿到提升机线程
        LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, 1);
        if (liftThread == null) {
            return false;
        }
        LiftProtocol liftProtocol = liftThread.getLiftProtocol();
        if (liftProtocol == null) {
            return false;
        }
        Object o = redisUtil.get("shuttle_wrk_no_" + wrkNo);
        if (o == null) {
            return false;
@@ -753,6 +852,21 @@
        //检测是否存在提升机口的指令
        List<ShuttleCommand> commands = redisCommand.getAssignCommand().getCommands();
        if (commands.size() > 0) {
            if (commands.get(commandStep).getCommandWord() != 1) {
                //不是行走命令,直接放行
                return true;
            }
            if (commands.get(0).getStartCodeNum() == null) {
                return false;
            }
            //命令起始位置就是提升机二维码,则不进行校验
            if (commands.get(0).getStartCodeNum().intValue() == liftProtocol.getBarcode().intValue()) {
                return true;
            }
        }
        BasDevpService basDevpService = SpringUtils.getBean(BasDevpService.class);
        ArrayList<Short> qrCodeValues = new ArrayList<>();
        for (BasDevp basDevp : basDevpService.selectList(null)) {
@@ -762,13 +876,18 @@
        //遍历所有指令,判断是否有到提升机口的指令,并获取到达该提升机口所需步序
        int step = 0;
        Integer siteNo = null;//站点号
        ShuttleCommand command = null;
        for (int i = 1; i < commands.size(); i++) {
        for (int i = 0; i < commands.size(); i++) {
            command = commands.get(i);
            if (qrCodeValues.contains(command.getDistCodeNum())) {
            for (Short qrCodeValue : qrCodeValues) {
                if (qrCodeValue.intValue() == command.getDistCodeNum().intValue()) {
                //存在
                step = i + 1;
                    BasDevp basDevp = basDevpService.queryByQrCode(qrCodeValue.intValue());
                    siteNo = basDevp.getDevNo();
                break;
                }
            }
        }
@@ -783,49 +902,37 @@
            return true;
        }
        //拿到提升机线程
        LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, 1);
        if (liftThread == null) {
            return false;
        }
        LiftProtocol liftProtocol = liftThread.getLiftProtocol();
        if (liftProtocol == null) {
            return false;
        }
        //获取四向穿梭车当前楼层
        String shuttleLocNo = shuttleProtocol.getCurrentLocNo();//二维码对应库位号
        Integer shuttleLocNoLev = Integer.parseInt(shuttleLocNo.substring(shuttleLocNo.length() - 2, shuttleLocNo.length()));//库位号对应层高
        //程序走到这,表示提升机可能一直就在当前层,可能经过了移动到达了该层
        if (liftProtocol.getProtocolStatusType() == LiftProtocolStatusType.WAITING) {
            //提升机等待确认
            //设置提升机为空闲状态
            liftProtocol.setProtocolStatus(LiftProtocolStatusType.IDLE);
            //任务号清零
            liftProtocol.setTaskNo((short) 0);
            //标记复位
            liftProtocol.setPakMk(true);
            //任务指令清零
            liftProtocol.setAssignCommand(null);
            //提升机解锁
            liftProtocol.setLiftLock(false);
        }
        Integer shuttleLocNoLev = shuttleLocNo == null ? 0 : Utils.getLev(shuttleLocNo);//库位号对应层高
        //判断提升机是否在目标楼层
        if (liftProtocol.getLev().intValue() == shuttleLocNoLev) {
            //同一层,直接放行
            return true;
        if (shuttleLocNoLev >= 2) {
            shuttleLocNoLev++;
        }
        //提升机和穿梭车处于不同楼层,需要进行调度
        if (!liftProtocol.isIdle()) {
            //提升机不是空闲
        //判断输送线站点是否给出提升机到位信号
        if (siteNo != null) {
            SiemensDevpThread siemensDevpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, 1);
            StaProtocol staProtocol = siemensDevpThread.getStation().get(siteNo);
            if (staProtocol.isLiftArrival()
                && liftProtocol.getPositionArrivalFeedback().intValue() == shuttleLocNoLev) {
                //输送线反馈提升机到位且提升机楼层反馈为同一层,直接放行
                return true;
            }
        }
        if (liftProtocol.getRunning()) {
            //提升机运行中,禁止下发
            return false;
        }
        if (redisCommand.getLiftSecurityMk()) {
            //已经执行过提升机命令,禁止下发
            return false;
        }
        //给提升机分配任务
        liftProtocol.setLiftLock(true);//锁定提升机
        liftProtocol.setTaskNo(shuttleProtocol.getTaskNo());//设置任务号
        liftProtocol.setShuttleNo(shuttleProtocol.getShuttleNo());//设置四向穿梭车号
        liftProtocol.setProtocolStatus(LiftProtocolStatusType.WORKING);//设置提升机状态为工作中
@@ -836,12 +943,7 @@
        //命令list
        ArrayList<LiftCommand> liftCommands = new ArrayList<>();
        LiftCommand liftCommand = new LiftCommand();
        liftCommand.setLiftNo(liftProtocol.getLiftNo());//提升机号
        liftCommand.setTaskNo(liftProtocol.getTaskNo());//任务号
        liftCommand.setRun((short) 1);//升降
        liftCommand.setDistPosition(shuttleLocNoLev.shortValue());//目标楼层(穿梭车所在楼层)
        liftCommand.setLiftLock(true);//锁定提升机
        LiftCommand liftCommand = liftThread.getLiftUpDownCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), shuttleLocNoLev);
        liftCommands.add(liftCommand);//将命令添加进list
        LiftAssignCommand liftAssignCommand = new LiftAssignCommand();
@@ -941,20 +1043,27 @@
    }
    /**
     * 正常移动命令
     * @return
     * 正常移动命令,默认移动速度1000
     */
    public ShuttleCommand getMoveCommand(Short startCodeNum, Short distCodeNum, Integer startToDistDistance, Short runDirection) {
    public ShuttleCommand getMoveCommand(Short startCodeNum, Short distCodeNum, Integer startToDistDistance, Short runDirection, Short middleCodeNum, Integer middleToDistDistance) {
        return getMoveCommand(startCodeNum, distCodeNum, startToDistDistance, runDirection, middleCodeNum, middleToDistDistance, 1000);
    }
    /**
     * 正常移动命令
     */
    public ShuttleCommand getMoveCommand(Short startCodeNum, Short distCodeNum, Integer startToDistDistance, Short runDirection, Short middleCodeNum, Integer middleToDistDistance, Integer runSpeed) {
        ShuttleCommand command = new ShuttleCommand();
        command.setCommandWord((short) 1);
        command.setStartCodeNum(startCodeNum);
        command.setMiddleCodeNum((short) 1);
        command.setMiddleCodeNum(middleCodeNum);
        command.setDistCodeNum(distCodeNum);
        command.setStartToDistDistance(startToDistDistance);
        command.setMiddleToDistDistance(middleToDistDistance);
        command.setRunDirection(runDirection);
        command.setForceMoveDistance(0);
        command.setIOControl((short) 0);
        command.setRunSpeed((short) 1000);
        command.setRunSpeed(runSpeed.shortValue());
        command.setCommandEnd((short) 1);
        return command;
    }
@@ -1027,8 +1136,8 @@
     */
    public ShuttleCommand getChargeSwitchCommand() {
        ShuttleCommand command = new ShuttleCommand();
        command.setCommandWord((short) 8);
        command.setIOControl((short) 4);
        command.setCommandWord((short) 5);
        command.setChargeSwitch((short) 1);
        command.setCommandEnd((short) 1);
        return command;
    }
src/main/java/com/zy/core/thread/SiemensDevpThread.java
@@ -10,7 +10,6 @@
import com.core.common.SpringUtils;
import com.zy.asrs.entity.BasDevp;
import com.zy.asrs.service.BasDevpService;
import com.zy.common.utils.CommonUtils;
import com.zy.core.DevpThread;
import com.zy.core.News;
import com.zy.core.cache.MessageQueue;
@@ -47,6 +46,11 @@
        add(100);add(101);add(102);
        add(103);add(104);add(105);
        add(106);add(107);add(108);
    }};
    public static final ArrayList<Integer> outInStaNos = new ArrayList<Integer>() {{
        add(102);add(105);add(106);
        add(107);add(108);
    }};
    public boolean charge0;
@@ -144,8 +148,8 @@
                staProtocol.setOutEnable(status[3]);// 可出
                staProtocol.setEmptyMk(status[4]);  // 空板信号
                staProtocol.setFullPlt(status[5]);  // 满托盘
                staProtocol.setHigh(status[6]);     // 高库位
                staProtocol.setLow(status[7]);      // 低库位
                staProtocol.setLiftArrival(status[6]);     // 提升机到位信号
                staProtocol.setShuttleTakeEnable(status[7]);      // 提升机可取信号
                if (!staProtocol.isPakMk() && !staProtocol.isLoading()) {
                    staProtocol.setPakMk(true);
@@ -158,9 +162,9 @@
        OperateResultExOne<byte[]> result2 = siemensS7Net.Read("DB100.200",(short)24);
        if (result2.IsSuccess) {
            for (int i = 0; i <= barcodeSize; i++) {
                byte[] bytes = siemensS7Net.getByteTransform().TransByte(result2.Content, i * 8, 8);
                String barcode = CommonUtils.bytesToBarcode(bytes);
//                String barcode = siemensS7Net.getByteTransform().TransString(result2.Content,i*8,8, "UTF-8");
//                byte[] bytes = siemensS7Net.getByteTransform().TransByte(result2.Content, i * 8, 8);
//                String barcode = CommonUtils.bytesToBarcode(bytes);
                String barcode = siemensS7Net.getByteTransform().TransString(result2.Content,i*8,8, "UTF-8");
                BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, i + 1);
                if(!Cools.isEmpty(barcodeThread) && !barcodeThread.getBarcode().equals(barcode)) {
                    barcodeThread.setBarcode(barcode);
@@ -192,35 +196,39 @@
            StaProtocol staProtocol = station.get(102);
            staProtocol.setOutInModel(outInModel);
        }
//        // 外形检测 - 201
//        Thread.sleep(50);
//        OperateResultExOne<byte[]> result201 = siemensS7Net.Read("DB102.112", (short)1);
//        if (result201.IsSuccess) {
//            boolean[] status = siemensS7Net.getByteTransform().TransBool(result201.Content, 0, 1);
//            StaProtocol staProtocol = station.get(201);
//            staProtocol.setFrontErr(status[0]);
//            staProtocol.setBackErr(status[1]);
//            staProtocol.setHighErr(status[2]);
//            staProtocol.setLeftErr(status[3]);
//            staProtocol.setRightErr(status[4]);
//            staProtocol.setWeightErr(status[5]);
//            staProtocol.setBarcodeErr(status[6]);
//        }
//        // 外形检测 - 301
//        Thread.sleep(50);
//        OperateResultExOne<byte[]> result301 = siemensS7Net.Read("DB102.114", (short)1);
//        if (result301.IsSuccess) {
//            boolean[] status = siemensS7Net.getByteTransform().TransBool(result301.Content, 0, 1);
//            StaProtocol staProtocol = station.get(301);
//            staProtocol.setFrontErr(status[0]);
//            staProtocol.setBackErr(status[1]);
//            staProtocol.setHighErr(status[2]);
//            staProtocol.setLeftErr(status[3]);
//            staProtocol.setRightErr(status[4]);
//            staProtocol.setWeightErr(status[5]);
//            staProtocol.setBarcodeErr(status[6]);
//        }
        Thread.sleep(50);
        for (Integer siteId : outInStaNos) {
            String dbAddress = "DB100.300";
            switch (siteId) {
                case 102:
                    dbAddress = "DB100.300";
                    break;
                case 105:
                    dbAddress = "DB100.302";
                    break;
                case 106:
                    dbAddress = "DB100.304";
                    break;
                case 107:
                    dbAddress = "DB100.306";
                    break;
                case 108:
                    dbAddress = "DB100.308";
                    break;
            }
            OperateResultExOne<byte[]> resultRead = siemensS7Net.Read(dbAddress, (short) 2);
            if (resultRead.IsSuccess) {
                //链条转动情况
                short direction = siemensS7Net.getByteTransform().TransInt16(resultRead.Content, 0);
                StaProtocol staProtocol = station.get(siteId);
                if (direction != 0 && !staProtocol.isLoading()) {
                    //状态为正转或反转且无物时,将链条转动信号位复位
                    write4(siteId, 0);
                }
            }
        }
        if (result.IsSuccess && result1.IsSuccess) {
            OutputQueue.DEVP.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
@@ -282,11 +290,9 @@
        }
        Short outAndIn = staProtocol.getOutInModel();
        Integer siteId = staProtocol.getSiteId();
        Short run = 1;//正转
        if (outAndIn == 1) {//入库
            run = 1;//正转
        } else {
            run = 2;//反转
        Short run = 0;//停止转动
        if (staProtocol.getRotationDire() != null) {
            run = staProtocol.getRotationDire().shortValue();//转动方向
        }
        switch (siteId) {
            case 102:
@@ -306,6 +312,10 @@
                break;
        }
        if (staProtocol.getStaNo() != null && staProtocol.getWorkNo() != null) {
            write(staProtocol);//写入工作号和目标站
        }
    }
    /**
src/main/resources/mapper/WrkMastMapper.xml
@@ -241,7 +241,7 @@
        from dbo.asr_wrk_mast
        where 1=1
        and ((wrk_sts = 4 and shuttle_no is null) or (wrk_sts = 8 and shuttle_no is not null))
        and source_sta_no = #{sourceStaNo}
        and sta_no = #{staNo}
        and wrk_no=#{workNo}
        order by io_pri desc,wrk_sts desc
    </select>
src/main/webapp/views/pipeline.html
@@ -102,6 +102,8 @@
                        <th>入库标记</th>
                        <th>空板信号</th>
                        <th>目标站</th>
                        <th>提升机到位信号</th>
                        <th>穿梭车可取信号</th>
                    </tr>
                    </thead>
                    <!-- 表格内容 -->
@@ -287,6 +289,8 @@
                        setVal(tr.children("td").eq(6), table[i-1].pakMk);
                        setVal(tr.children("td").eq(7), table[i-1].emptyMk);
                        setVal(tr.children("td").eq(8), table[i-1].staNo);
                        setVal(tr.children("td").eq(9), table[i-1].liftArrival);
                        setVal(tr.children("td").eq(10), table[i-1].shuttleTakeEnable);
                    }
                } else if (res.code === 403){
                    window.location.href = baseUrl+"/login";
@@ -372,6 +376,8 @@
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "     </tr>\n";
        }
        $('#site-table tbody').after(html);
src/main/webapp/views/shuttle.html
@@ -121,6 +121,7 @@
                                            <button class="item" onclick="shuttleOperator(1)">入库</button>
                                            <button class="item" onclick="shuttleOperator(2)">出库</button>
                                            <button class="item" onclick="shuttleOperator(14)">移动到目标库位</button>
                                            <button class="item" onclick="shuttleOperator(16)">移动到提升机</button>
                                        </div>
                                    </div>
                                </div>