自动化立体仓库 - WCS系统
#
tqs
2022-12-02 0dc1710c16ee9258018ca79a389efc6b2cc71375
#
9个文件已修改
1004 ■■■■ 已修改文件
src/main/java/com/zy/asrs/mapper/WrkMastMapper.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java 858 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/MainProcess.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/RgvStatusType.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/RgvSlave.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/RgvThread.java 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/SiemensCrnThread.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application.yml 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/WrkMastMapper.xml 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/WrkMastMapper.java
@@ -110,10 +110,53 @@
    Integer selectExistInEmpty();
    /**
     * 查找工作状态为2(设备上走),且货物在RGV入库接驳站的入库工作档,查找最多2笔
     * 查找工作状态为2(设备上走),且RGV入库接驳站符合的的入库工作档
     * @param rgvNo
     * @param staNos
     * @return
     */
    List<WrkMast> selectRgvInStep1(@Param("rgvNo")Integer rgvNo, @Param("staNos")List<Integer> staNos);
    /**
     * 查找是否存在RGV正在工作中的任务
     * @param rgvNo
     * @return
     */
    List<WrkMast> selectRgvInWorking(@Param("rgvNo")Integer rgvNo);
    /**
     * 指定RGV出库站,查找工作状态为7(RGV入库放货中)的入库工作档List
     * @param rgvInDStn
     * @return
     */
    List<WrkMast> selectRgvInStep2(@Param("rgvInDStn")Integer rgvInDStn);
    /**
     * 指定RGV出库站,查找工作状态为17(RGV出库放货中)的出库工作档List
     * @param rgvOutDStn
     * @return
     */
    List<WrkMast> selectRgvOutStep2(@Param("rgvOutDStn")Integer rgvOutDStn);
    /**
     * 指定RGV出库站,查找工作状态为7(RGV入库放货中)或 17(RGV出库放货中) 的工作档List
     * @param rgvDestStn
     * @return
     */
    List<WrkMast> selectRgvDestStep2(@Param("rgvDestStn")Integer rgvDestStn);
    /**
     * 查找工作状态为14(出库完成),且RGV出库接驳站符合的的入库工作档
     * @param rgvNo
     * @param staNos
     * @return
     */
    List<WrkMast> selectRgvOutStep1(@Param("rgvNo")Integer rgvNo, @Param("staNos")List<Integer> staNos);
    /**
     * 查找是否存在RGV正在出库工作中的任务
     * @param rgvNo
     * @return
     */
    List<WrkMast> selectRgvOutWorking(@Param("rgvNo")Integer rgvNo);
}
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java
@@ -29,6 +29,7 @@
import com.zy.core.model.*;
import com.zy.core.model.command.CrnCommand;
import com.zy.core.model.command.LedCommand;
import com.zy.core.model.command.RgvCommand;
import com.zy.core.model.protocol.CrnProtocol;
import com.zy.core.model.protocol.RgvProtocol;
import com.zy.core.model.protocol.StaProtocol;
@@ -40,7 +41,6 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
@@ -104,8 +104,6 @@
                    continue;
                }
                String barcode = barcodeThread.getBarcode();
                barcode = "80011105";
                if (!Cools.isEmpty(barcode)) {
                    log.info("{}号条码扫描器检测条码信息:{}", inSta.getBarcode(), barcode);
@@ -196,64 +194,6 @@
                        } else {
                            log.error("请求接口失败!!!url:{};request:{};response:{}", wmsUrl + "/rpc/pakin/loc/v1", JSON.toJSONString(param), response);
                        }
//                        // 检索库位
//                        LocTypeDto locTypeDto = new LocTypeDto(staProtocol);
//                        List<String> matNos = waitPakins.stream().map(WaitPakin::getMatnr).distinct().collect(Collectors.toList());
//                        StartupDto startupDto = commonService.getLocNo(1, 1, inSta.getStaNo(), matNos, locTypeDto, 0);
//                        // 工作号
//                        int workNo = startupDto.getWorkNo();
//                        // 插入工作明细档
//                        wrkDetlService.createWorkDetail(workNo, waitPakins, barcode);
//
//                        // 插入工作主档
//                        wrkMast = new WrkMast();
//                        wrkMast.setWrkNo(workNo);
//                        wrkMast.setIoTime(new Date());
//                        wrkMast.setWrkSts(2L); // 工作状态:2.设备上走
//                        wrkMast.setIoType(1); // 入出库状态:1.入库
//                        wrkMast.setIoPri(10D); // 优先级:10
//                        wrkMast.setCrnNo(startupDto.getCrnNo());
//                        wrkMast.setSourceStaNo(startupDto.getSourceStaNo());
//                        wrkMast.setStaNo(startupDto.getStaNo());
//                        wrkMast.setLocNo(startupDto.getLocNo());
//                        wrkMast.setBarcode(barcode); // 托盘码
//                        wrkMast.setFullPlt("Y"); // 满板:Y
//                        wrkMast.setPicking("N"); // 拣料
//                        wrkMast.setExitMk("N"); // 退出
//                        wrkMast.setEmptyMk("N"); // 空板
//                        wrkMast.setLinkMis("N");
//                        // 操作人员数据
//                        wrkMast.setAppeTime(new Date());
//                        wrkMast.setModiTime(new Date());
//                        Integer insert = wrkMastMapper.insert(wrkMast);
//                        if (insert == 0) {
//                            throw new CoolException("保存工作档失败");
//                        }
//                        // 更新目标库位状态
//                        LocMast locMast = locMastService.selectById(startupDto.getLocNo());
//                        locMast.setLocSts("S"); // S.入库预约
//                        locMast.setModiTime(new Date());
//                        if (!locMastService.updateById(locMast)){
//                            throw new CoolException("改变库位状态失败");
//                        }
//                        // 将入库通知档修改为已启动
//                        if (wrkMastMapper.updateWaitPakInStep1(barcode) == 0) {
//                            throw new CoolException("修改入库通知档状态为已启动失败");
//                        }
//
//                        // 命令下发区 --------------------------------------------------------------------------
//
//                        // 更新站点信息 且 下发plc命令
//                        barcodeThread.setBarcode("");
//                        staProtocol.setWorkNo((short) workNo);
//                        staProtocol.setStaNo(startupDto.getStaNo().shortValue());
//                        devpThread.setPakMk(staProtocol.getSiteId(), false);
//                        boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                        if (!result) {
//                            throw new CoolException("更新plc站点信息失败");
//                        }
                    } catch (Exception e) {
                        e.printStackTrace();
@@ -452,7 +392,6 @@
    /**
     * 堆垛机站出库到出库站
     */
    @Async
    public synchronized void crnStnToOutStn() {
        for (CrnSlave crnSlave : slaveProperties.getCrn()) {
            // 遍历堆垛机出库站
@@ -590,20 +529,20 @@
                // 如果最近一次是入库模式
                if (rgvProtocol.getLastIo().equals("I")) {
                    if (basRgv.getInEnable().equals("Y")) {
//                        this.rgvInStnToLoc(rgv, rgvProtocol); //  入库
                        this.rgvInStn(rgv, rgvProtocol); //  入库
                        rgvProtocol.setLastIo("O");
                    } else if (basRgv.getOutEnable().equals("Y")) {
//                        this.locToCrnStn(rgv, crnProtocol); //  出库
                        this.rgvOutStn(rgv, rgvProtocol); //  出库
                        rgvProtocol.setLastIo("I");
                    }
                }
                // 如果最近一次是出库模式
                else if (rgvProtocol.getLastIo().equals("O")) {
                    if (basRgv.getOutEnable().equals("Y")) {
//                        this.locToCrnStn(rgv, crnProtocol); //  出库
                        this.rgvOutStn(rgv, rgvProtocol); //  出库
                        rgvProtocol.setLastIo("I");
                    } else if (basRgv.getInEnable().equals("Y")) {
//                        this.rgvInStnToLoc(rgv, rgvProtocol); //  入库
                        this.rgvInStn(rgv, rgvProtocol); //  入库
                        rgvProtocol.setLastIo("O");
                    }
                }
@@ -1055,19 +994,23 @@
//    }
    /**
     * 入库  ===>>  RGV入库站到站
     * 查找工作状态为2(设备上走),且RGV入库接驳站符合的的入库工作档,提取出最多2笔
     * @param slave
     * @return
     */
    public synchronized void rgvInStn(RgvSlave slave, RgvProtocol rgvProtocol) {
        // 获取工作状态为2(设备上走),且货物在RGV入库接驳站的入库工作档,查找最多2笔
    public synchronized List<WrkMast> getRgvInTask(RgvSlave slave){
        List<WrkMast> wrkMastTask = new ArrayList<>();
        List<Integer> staNos = new ArrayList<>();
        for (RgvSlave.RgvStn rgvStn : slave.getRgvInStn()) {
        for (RgvSlave.RgvStn rgvStn : slave.getRgvInSStn()) {
            staNos.add(rgvStn.getStaNo());
        }
        List<WrkMast> wrkMasts1 = new ArrayList<>();
        if(staNos.size() < 1){
            return null;
        }
        List<WrkMast> wrkMasts = wrkMastMapper.selectRgvInStep1(slave.getId(), staNos);
        for(WrkMast wrkMast : wrkMasts){
            Integer plcId = 0;
            for (RgvSlave.RgvStn rgvStn : slave.getRgvInStn()) {
            for (RgvSlave.RgvStn rgvStn : slave.getRgvInSStn()) {
                if(rgvStn.getStaNo() == wrkMast.getRgvSstaNo()){
                    plcId = rgvStn.getDevpPlcId();
                    break;
@@ -1075,141 +1018,610 @@
            }
            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, plcId);
            StaProtocol staProtocol = devpThread.getStation().get(wrkMast.getRgvSstaNo());
            if (staProtocol == null) {
            //判断RGV入库源站点,自动、有物,有任务号,可出
            boolean flag1 = false;
            StaProtocol staProtocol1 = devpThread.getStation().get(wrkMast.getRgvSstaNo());
            if (staProtocol1 == null) {
                continue;
            } else {
                staProtocol = staProtocol.clone();
                staProtocol1 = staProtocol1.clone();
            }
            // 查询站点详细信息
            BasDevp staDetl1 = basDevpService.selectById(wrkMast.getRgvSstaNo());
            if (staDetl1 == null) {
                log.error("RGV入库 ===>> 输送机源站点在数据库不存在, 站点编号={}", wrkMast.getRgvSstaNo());
                continue;
            }
            if (staProtocol1.isAutoing() && staProtocol1.isLoading() && staProtocol1.getWorkNo().intValue() == wrkMast.getWrkNo()
                    && staProtocol1.isOutEnable() && staDetl1.getOutEnable() != null && staDetl1.getOutEnable().equals("Y")) {
                flag1 = true;
            }
            //判断RGV入库目标站点,自动、无物,没有任务号,可入
            boolean flag2 = false;
            StaProtocol staProtocol2 = devpThread.getStation().get(wrkMast.getRgvDstaNo());
            if (staProtocol2 == null) {
                continue;
            } else {
                staProtocol2 = staProtocol2.clone();
            }
            // 查询站点详细信息
            BasDevp staDetl2 = basDevpService.selectById(wrkMast.getRgvSstaNo());
            if (staDetl2 == null) {
                log.error("RGV入库 ===>> 输送机源站点在数据库不存在, 站点编号={}", wrkMast.getRgvSstaNo());
                continue;
            }
            if (staProtocol2.isAutoing() && staProtocol2.isLoading() && staProtocol2.getWorkNo().intValue() == wrkMast.getWrkNo()
                    && staProtocol2.isInEnable() && staDetl2.getCanining() != null && staDetl2.getCanining().equals("Y")) {
                flag2 = true;
            }
            if(flag1 && flag2){
                wrkMastTask.add(wrkMast);
                if(wrkMastTask.size() >= 2) break;
            }
        }
        return wrkMastTask;
    }
//        WrkMast wrkMast = wrkMastMapper.selectPakInStep2(slave.getId(), staProtocol.getWorkNo().intValue(), crnStn.getStaNo());
//        for (CrnSlave.CrnStn crnStn : slave.getCrnInStn()) {
//            boolean flag = false;
//            // 获取堆垛机入库站信息
//            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, crnStn.getDevpPlcId());
//            StaProtocol staProtocol = devpThread.getStation().get(crnStn.getStaNo());
//            if (staProtocol == null) {
//                continue;
//            } else {
//                staProtocol = staProtocol.clone();
//            }
//            // 查询站点详细信息
//            BasDevp staDetl = basDevpService.selectById(crnStn.getStaNo());
//            if (staDetl == null) {
//                log.error("入库 ===>> 堆垛机站点在数据库不存在, 站点编号={}", crnStn.getStaNo());
//                continue;
//            }
//            if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.getWorkNo() > 0 && staProtocol.isInEnable()
//                    && staDetl.getCanining() != null && staDetl.getCanining().equals("Y")) {
//                flag = true;
//            }
//            if (!flag) {
//                continue;
//            }
//            // 获取工作状态为2(设备上走)的入库工作档
//            WrkMast wrkMast = wrkMastMapper.selectPakInStep2(slave.getId(), staProtocol.getWorkNo().intValue(), crnStn.getStaNo());
//            if (null == wrkMast) {
////                log.error("查询无待入库数据--wrk_sts=2, 工作号={}", staProtocol.getWorkNo());
//                continue;
//            }
//            // 获取库位信息
//            LocMast locMast = locMastService.selectById(wrkMast.getLocNo());
//            if (locMast == null) {
//                log.error("查询库存无数据--库位号{}", wrkMast.getLocNo());
//                continue;
//            }
//            if (!locMast.getLocSts().equals("S") && !locMast.getLocSts().equals("Q")) {
//                log.error("入库操作库位状态不符合--状态, 库位号={},库位状态={}", wrkMast.getLocNo(), locMast.getLocSts());
//                continue;
//            }
//
//            // 堆垛机控制过滤
//            if (!crnProtocol.getStatusType().equals(CrnStatusType.IDLE) || crnProtocol.getTaskNo() != 0) {
//                continue;
//            }
//
//            // 已经存在吊车执行任务时,则过滤
//            if (wrkMastMapper.selectWorking(slave.getId()) != null) {
//                continue;
//            }
//
//            // 双深库位且浅库位有货,则需先对浅库位进行库位移转
//            if (Utils.isDeepLoc(slaveProperties, wrkMast.getLocNo())) {
//                String shallowLocNo = Utils.getShallowLoc(slaveProperties, wrkMast.getLocNo());
//                LocMast shallowLoc = locMastService.selectById(shallowLocNo);
//                // O.空库位、Q.拣料/盘点/并板再入库、S.入库预约、X.禁用 直接搬!
//                if (shallowLoc.getLocSts().equals("P") || shallowLoc.getLocSts().equals("R")) {
//                    WrkMast waitWrkMast = wrkMastMapper.selectByLocNo(shallowLocNo);
//                    if (null == waitWrkMast) {
//                        log.error("{}库位异常,未检索到相应工作档!", shallowLocNo);
//                    } else {
//                        waitWrkMast.setIoPri(15D);
//                        waitWrkMast.setModiTime(new Date());
//                        if (wrkMastMapper.updateById(waitWrkMast) == 0) {
//                            log.error("调整工作档优先级失败!工作号={}", waitWrkMast.getWrkNo());
//                        }
//                        continue;
//                    }
//
//                } else if (shallowLoc.getLocSts().equals("F") || shallowLoc.getLocSts().equals("D")) {
//                    // 此标记避免多次执行移库任务
//                    if (Cools.isEmpty(wrkMast.getUpdMk()) || "N".equals(wrkMast.getUpdMk())) {
//                        wrkMast.setUpdMk("Y");
//                        wrkMast.setIoPri(14D);
//                        wrkMastMapper.updateById(wrkMast);
//                        // 生成工作档,将浅库位移转到新的库位中
//                        moveLocForDeepLoc(slave, shallowLoc);
//                        // 生成工作档、改变浅库位的源库/目标库 库位状态、下发堆垛机命令(立马执行)
////                        moveLocForDeepLocPakin(slave, shallowLoc, wrkMast);
//                    }
//                    continue;
//                } else if (shallowLoc.getLocSts().equals("Q")) {
//                    WrkMast waitWrkMast = wrkMastMapper.selectByLocNo(shallowLocNo);
//                    if (null != waitWrkMast && waitWrkMast.getWrkSts() == 4) {
//                        continue;
//                    }
//                }
//            }
//
//            // 命令下发区 --------------------------------------------------------------------------
//            CrnCommand crnCommand = new CrnCommand();
//            crnCommand.setCrnNo(slave.getId()); // 堆垛机编号
//            crnCommand.setTaskNo(wrkMast.getWrkNo().shortValue()); // 工作号
//            crnCommand.setAckFinish((short) 0);  // 任务完成确认位
//            crnCommand.setTaskMode(CrnTaskModeType.LOC_MOVE); // 任务模式:  库位移转
//            crnCommand.setSourcePosX(crnStn.getRow().shortValue());     // 源库位排
//            crnCommand.setSourcePosY(crnStn.getBay().shortValue());     // 源库位列
//            crnCommand.setSourcePosZ(crnStn.getLev().shortValue());     // 源库位层
//            crnCommand.setDestinationPosX(locMast.getRow1().shortValue());     // 目标库位排
//            crnCommand.setDestinationPosY(locMast.getBay1().shortValue());     // 目标库位列
//            crnCommand.setDestinationPosZ(locMast.getLev1().shortValue());     // 目标库位层
//            if (!MessageQueue.offer(SlaveType.Crn, wrkMast.getCrnNo(), new Task(2, crnCommand))) {
//                log.error("堆垛机命令下发失败,堆垛机号={},任务数据={}", wrkMast.getCrnNo(), JSON.toJSON(crnCommand));
//            } else {
//
////                long startTime = System.currentTimeMillis();
////                while ((System.currentTimeMillis() - startTime) < COMMAND_TIMEOUT) {
////
////                    if (true) {
////                        break;
////                    }
////
////                    try{
////                        Thread.sleep(500);
////                    }catch(Exception ignore){}
////                }
//
//                // 修改工作档状态 2.设备上走 => 3.吊车入库中
//                Date now = new Date();
//                wrkMast.setWrkSts(3L);
//                wrkMast.setCrnStrTime(now);
//                wrkMast.setModiTime(now);
//                if (wrkMastMapper.updateById(wrkMast) == 0) {
//                    log.error("修改工作档状态 2.设备上走 => 3.吊车入库中 失败!!,工作号={}", wrkMast.getWrkNo());
//                }
//            }
//        }
    /**
     * 入库  ===>>  RGV入库站到站
     */
    public synchronized void rgvInStn(RgvSlave slave, RgvProtocol rgvProtocol) {
        //查找工作状态为2(设备上走),且RGV入库接驳站符合的的入库工作档,提取出最多2笔
        List<WrkMast> wrkMastTask = getRgvInTask(slave);
        if(wrkMastTask.size() <= 0){
            return;
        }
        // RGV控制过滤, 必须满足自动、空闲,没有任务号
        if (!rgvProtocol.getStatusType().equals(CrnStatusType.IDLE)
                || rgvProtocol.getModeType() != RgvModeType.AUTO
                || rgvProtocol.getTaskNo1() != 0 || rgvProtocol.getTaskNo2() != 0) {
            return;
        }
        // 已经存在RGV执行任务时,则过滤
        if(wrkMastMapper.selectRgvInWorking(slave.getId()).size() > 0){
            return;
        }
        if(wrkMastTask.size() == 2){
            //有2笔RGV待入库任务,2个工位,取货、放货任务同时下发
            WrkMast wrkMast1 = wrkMastTask.get(0);
            WrkMast wrkMast2 = wrkMastTask.get(1);
            if(Cools.isEmpty(wrkMast1) || Cools.isEmpty(wrkMast2)){
                log.error("工作档RGV入库数据为空");
                return;
            }
            //  命令下发区 --------------------------------------------------------------------------
            RgvCommand rgvCommand = new RgvCommand();
            rgvCommand.setRgvNo(slave.getId()); // RGV编号
            rgvCommand.setAckFinish1((short) 0);  // 工位1任务完成确认位
            rgvCommand.setTaskNo1(wrkMast1.getWrkNo().shortValue()); // 工位1工作号
            rgvCommand.setTaskMode1(RgvTaskModeType.FETCH_PUT); // 工位1任务模式:  取放货
            rgvCommand.setSourceStaNo1(wrkMast1.getRgvSstaNo().shortValue());   //工位1源站点
            rgvCommand.setDestinationStaNo1(wrkMast1.getRgvDstaNo().shortValue());   //工位1目标站点
            rgvCommand.setAckFinish2((short) 0);  // 工位2任务完成确认位
            rgvCommand.setTaskNo2(wrkMast2.getWrkNo().shortValue()); // 工位2工作号
            rgvCommand.setTaskMode2(RgvTaskModeType.FETCH_PUT); // 工位2任务模式:  取放货
            rgvCommand.setSourceStaNo2(wrkMast2.getRgvSstaNo().shortValue());   //工位2源站点
            rgvCommand.setDestinationStaNo2(wrkMast2.getRgvDstaNo().shortValue());   //工位2目标站点
            rgvCommand.setCommand((short) 0);   //工位1、2任务确认
            if (!MessageQueue.offer(SlaveType.Crn, wrkMast1.getRgvNo(), new Task(2, rgvCommand))) {
                //step=2,工位1、2写任务;   step=4,工位1写任务;     step=5,工位2写任务
                log.error("RGV命令下发失败,RGV号={},任务数据={}", slave.getId(), JSON.toJSON(rgvCommand));
            } else {
                // 修改工作档状态 2.设备上走 => 6.RGV入库取货中
                Date now = new Date();
                wrkMast1.setWrkSts(6L);
                wrkMast1.setCrnStrTime(now);
                wrkMast1.setModiTime(now);
                if (wrkMastMapper.updateById(wrkMast1) == 0) {
                    log.error("修改工作档状态 2.设备上走 => 6.RGV入库取货中 失败!!,工作号={}", wrkMast1.getWrkNo());
                }
                wrkMast2.setWrkSts(6L);
                wrkMast2.setCrnStrTime(now);
                wrkMast2.setModiTime(now);
                if (wrkMastMapper.updateById(wrkMast2) == 0) {
                    log.error("修改工作档状态 2.设备上走 => 6.RGV入库取货中 失败!!,工作号={}", wrkMast2.getWrkNo());
                }
            }
        } else if(wrkMastTask.size() == 1){
            //只有1笔RGV待入库任务,先下发取货任务,取货后再判断是否有下一笔待入库任务
            WrkMast wrkMast1 = wrkMastTask.get(0);
            if(Cools.isEmpty(wrkMast1)){
                log.error("工作档RGV入库数据为空");
                return;
            }
            //  命令下发区 --------------------------------------------------------------------------
            RgvCommand rgvCommand = new RgvCommand();
            rgvCommand.setRgvNo(slave.getId()); // RGV编号
            rgvCommand.setAckFinish1((short) 0);  // 工位1任务完成确认位
            rgvCommand.setTaskNo1(wrkMast1.getWrkNo().shortValue()); // 工位1工作号
            rgvCommand.setTaskMode1(RgvTaskModeType.FETCH); // 工位1任务模式:  取货
            rgvCommand.setSourceStaNo1(wrkMast1.getRgvSstaNo().shortValue());   //工位1源站点
            rgvCommand.setDestinationStaNo1(wrkMast1.getRgvDstaNo().shortValue());   //工位1目标站点
            rgvCommand.setCommand((short) 0);   //工位1、2任务确认
            if (!MessageQueue.offer(SlaveType.Crn, wrkMast1.getRgvNo(), new Task(4, rgvCommand))) {
                //step=2,工位1、2任务确认;   step=4,工位1确认;     step=5,工位2任务确认
                log.error("RGV命令下发失败,RGV号={},任务数据={}", slave.getId(), JSON.toJSON(rgvCommand));
            } else {
                // 修改工作档状态 2.设备上走 => 6.RGV入库取货中
                Date now = new Date();
                wrkMast1.setWrkSts(6L);
                wrkMast1.setCrnStrTime(now);
                wrkMast1.setModiTime(now);
                if (wrkMastMapper.updateById(wrkMast1) == 0) {
                    log.error("修改工作档状态 2.设备上走 => 6.RGV入库取货中 失败!!,工作号={}", wrkMast1.getWrkNo());
                }
            }
        }
    }
    /**
     * 出库  ===>>  RGV出库站到站
     */
    public synchronized void rgvOutStn(RgvSlave slave, RgvProtocol rgvProtocol) {
        //查找工作状态为14(出库完成),且RGV出库接驳站符合的的出库工作档,提取出最多2笔
        List<WrkMast> wrkMastTask = getRgvOutTask(slave);
        if(wrkMastTask.size() <= 0){
            return;
        }
        // RGV控制过滤, 必须满足自动、空闲,没有任务号
        if (!rgvProtocol.getStatusType().equals(CrnStatusType.IDLE)
                || rgvProtocol.getModeType() != RgvModeType.AUTO
                || rgvProtocol.getTaskNo1() != 0 || rgvProtocol.getTaskNo2() != 0) {
            return;
        }
        // 已经存在RGV执行任务时,则过滤
        if(wrkMastMapper.selectRgvOutWorking(slave.getId()).size() > 0){
            return;
        }
        if(wrkMastTask.size() == 2){
            //有2笔RGV待入库任务,2个工位,取货、放货任务同时下发
            WrkMast wrkMast1 = wrkMastTask.get(0);
            WrkMast wrkMast2 = wrkMastTask.get(1);
            if(Cools.isEmpty(wrkMast1) || Cools.isEmpty(wrkMast2)){
                log.error("工作档RGV入库数据为空");
                return;
            }
            //  命令下发区 --------------------------------------------------------------------------
            RgvCommand rgvCommand = new RgvCommand();
            rgvCommand.setRgvNo(slave.getId()); // RGV编号
            rgvCommand.setAckFinish1((short) 0);  // 工位1任务完成确认位
            rgvCommand.setTaskNo1(wrkMast1.getWrkNo().shortValue()); // 工位1工作号
            rgvCommand.setTaskMode1(RgvTaskModeType.FETCH_PUT); // 工位1任务模式:  取放货
            rgvCommand.setSourceStaNo1(wrkMast1.getRgvSstaNo().shortValue());   //工位1源站点
            rgvCommand.setDestinationStaNo1(wrkMast1.getRgvDstaNo().shortValue());   //工位1目标站点
            rgvCommand.setAckFinish2((short) 0);  // 工位2任务完成确认位
            rgvCommand.setTaskNo2(wrkMast2.getWrkNo().shortValue()); // 工位2工作号
            rgvCommand.setTaskMode2(RgvTaskModeType.FETCH_PUT); // 工位2任务模式:  取放货
            rgvCommand.setSourceStaNo2(wrkMast2.getRgvSstaNo().shortValue());   //工位2源站点
            rgvCommand.setDestinationStaNo2(wrkMast2.getRgvDstaNo().shortValue());   //工位2目标站点
            rgvCommand.setCommand((short) 0);   //工位1、2任务确认
            if (!MessageQueue.offer(SlaveType.Crn, wrkMast1.getRgvNo(), new Task(2, rgvCommand))) {
                //step=2,工位1、2写任务;   step=4,工位1写任务;     step=5,工位2写任务
                log.error("RGV命令下发失败,RGV号={},任务数据={}", slave.getId(), JSON.toJSON(rgvCommand));
            } else {
                // 修改工作档状态 14.出库完成 => 16.RGV出库取货中
                Date now = new Date();
                wrkMast1.setWrkSts(16L);
                wrkMast1.setCrnStrTime(now);
                wrkMast1.setModiTime(now);
                if (wrkMastMapper.updateById(wrkMast1) == 0) {
                    log.error("修改工作档状态 14.出库完成 => 16.RGV出库取货中 失败!!,工作号={}", wrkMast1.getWrkNo());
                }
                wrkMast2.setWrkSts(16L);
                wrkMast2.setCrnStrTime(now);
                wrkMast2.setModiTime(now);
                if (wrkMastMapper.updateById(wrkMast2) == 0) {
                    log.error("修改工作档状态 14.出库完成 => 16.RGV出库取货中 失败!!,工作号={}", wrkMast2.getWrkNo());
                }
            }
        } else if(wrkMastTask.size() == 1){
            //只有1笔RGV待入库任务,先下发取货任务,取货后再判断是否有下一笔待入库任务
            WrkMast wrkMast1 = wrkMastTask.get(0);
            if(Cools.isEmpty(wrkMast1)){
                log.error("工作档RGV入库数据为空");
                return;
            }
            //  命令下发区 --------------------------------------------------------------------------
            RgvCommand rgvCommand = new RgvCommand();
            rgvCommand.setRgvNo(slave.getId()); // RGV编号
            rgvCommand.setAckFinish1((short) 0);  // 工位1任务完成确认位
            rgvCommand.setTaskNo1(wrkMast1.getWrkNo().shortValue()); // 工位1工作号
            rgvCommand.setTaskMode1(RgvTaskModeType.FETCH); // 工位1任务模式:  取货
            rgvCommand.setSourceStaNo1(wrkMast1.getRgvSstaNo().shortValue());   //工位1源站点
            rgvCommand.setDestinationStaNo1(wrkMast1.getRgvDstaNo().shortValue());   //工位1目标站点
            rgvCommand.setCommand((short) 0);   //工位1、2任务确认
            if (!MessageQueue.offer(SlaveType.Crn, wrkMast1.getRgvNo(), new Task(4, rgvCommand))) {
                //step=2,工位1、2任务确认;   step=4,工位1确认;     step=5,工位2任务确认
                log.error("RGV命令下发失败,RGV号={},任务数据={}", slave.getId(), JSON.toJSON(rgvCommand));
            } else {
                // 修改工作档状态 14.出库完成 => 16.RGV出库取货中
                Date now = new Date();
                wrkMast1.setWrkSts(16L);
                wrkMast1.setCrnStrTime(now);
                wrkMast1.setModiTime(now);
                if (wrkMastMapper.updateById(wrkMast1) == 0) {
                    log.error("修改工作档状态 14.出库完成 => 16.RGV出库取货中 失败!!,工作号={}", wrkMast1.getWrkNo());
                }
            }
        }
    }
    /**
     * 查找工作状态为14(出库完成),且RGV出库接驳站符合的的出库工作档,提取出最多2笔
     * @param slave
     * @return
     */
    public synchronized List<WrkMast> getRgvOutTask(RgvSlave slave){
        List<WrkMast> wrkMastTask = new ArrayList<>();
        List<Integer> staNos = new ArrayList<>();
        for (RgvSlave.RgvStn rgvStn : slave.getRgvOutSStn()) {
            staNos.add(rgvStn.getStaNo());
        }
        if(staNos.size() < 1){
            return null;
        }
        List<WrkMast> wrkMasts = wrkMastMapper.selectRgvOutStep1(slave.getId(), staNos);
        for(WrkMast wrkMast : wrkMasts){
            Integer plcId = 0;
            for (RgvSlave.RgvStn rgvStn : slave.getRgvOutSStn()) {
                if(rgvStn.getStaNo() == wrkMast.getRgvSstaNo()){
                    plcId = rgvStn.getDevpPlcId();
                    break;
                }
            }
            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, plcId);
            //判断RGV出库源站点,自动、有物,有任务号,可出
            boolean flag1 = false;
            StaProtocol staProtocol1 = devpThread.getStation().get(wrkMast.getRgvSstaNo());
            if (staProtocol1 == null) {
                continue;
            } else {
                staProtocol1 = staProtocol1.clone();
            }
            // 查询站点详细信息
            BasDevp staDetl1 = basDevpService.selectById(wrkMast.getRgvSstaNo());
            if (staDetl1 == null) {
                log.error("RGV出库 ===>> 输送机源站点在数据库不存在, 站点编号={}", wrkMast.getRgvSstaNo());
                continue;
            }
            if (staProtocol1.isAutoing() && staProtocol1.isLoading() && staProtocol1.getWorkNo().intValue() == wrkMast.getWrkNo()
                    && staProtocol1.isOutEnable() && staDetl1.getOutEnable() != null && staDetl1.getOutEnable().equals("Y")) {
                flag1 = true;
            }
            //判断RGV出库目标站点,自动、无物,没有任务号,可入
            boolean flag2 = false;
            StaProtocol staProtocol2 = devpThread.getStation().get(wrkMast.getRgvDstaNo());
            if (staProtocol2 == null) {
                continue;
            } else {
                staProtocol2 = staProtocol2.clone();
            }
            // 查询站点详细信息
            BasDevp staDetl2 = basDevpService.selectById(wrkMast.getRgvSstaNo());
            if (staDetl2 == null) {
                log.error("RGV出库 ===>> 输送机源站点在数据库不存在, 站点编号={}", wrkMast.getRgvSstaNo());
                continue;
            }
            if (staProtocol2.isAutoing() && staProtocol2.isLoading() && staProtocol2.getWorkNo().intValue() == wrkMast.getWrkNo()
                    && staProtocol2.isInEnable() && staDetl2.getCanining() != null && staDetl2.getCanining().equals("Y")) {
                flag2 = true;
            }
            if(flag1 && flag2){
                wrkMastTask.add(wrkMast);
                if(wrkMastTask.size() >= 2) break;
            }
        }
        return wrkMastTask;
    }
    /**
     * 根据RGV完成信号,执行对工作档的完成操作,和RGV的任务下发
     */
    public synchronized void rgvFinished() {
        for (RgvSlave rgv : slaveProperties.getRgv()) {
            // 获取RGV信息
            RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, rgv.getId());
            RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
            if (rgvProtocol == null) {
                continue;
            }
            //  工位1状态:取货完成等待确认91 并且  任务完成位 = 1
            if (rgvProtocol.statusType1 == RgvStatusType.FETCHWAITING && rgvProtocol.getTaskNo1() != 0) {
                //工位1取货完成后,工位2是无货空闲状态时,准备给工位2发任务,确认是否有待执行RGV任务
                if (rgvProtocol.getModeType() == RgvModeType.AUTO
                        && rgvProtocol.getTaskNo1() > 0 && rgvProtocol.getTaskNo2() == 0
                        && rgvProtocol.getLoaded1() > 0 && rgvProtocol.getLoaded2() == 0
                        && rgvProtocol.getStatusType2() == RgvStatusType.IDLE
                ) {
                    WrkMast wrkMast1 = wrkMastMapper.selectPakInStep3(rgvProtocol.getTaskNo1().intValue());
                    if (wrkMast1 == null) {
                        log.error("RGV工位1处于等待确认且取货任务完成状态,但未找到工作档。RGV号={},工作号={}", rgv.getId(), rgvProtocol.getTaskNo1());
                        continue;
                    }
                    List<WrkMast> wrkMastTask = new ArrayList<>();
                    List<WrkMast> list = new ArrayList<>();
                    Integer type = 0;//1入库,2出库
                    if(wrkMast1.getWrkSts()==6L){
                        wrkMastTask = getRgvInTask(rgv);
                        list = wrkMastMapper.selectRgvInWorking(rgv.getId());
                        type = 1;
                    } else if(wrkMast1.getWrkSts()==16L){
                        wrkMastTask = getRgvOutTask(rgv);
                        list = wrkMastMapper.selectRgvOutWorking(rgv.getId());
                        type = 2;
                    }
                    if(wrkMastTask.size() > 0){//有继续执行任务,下发取货任务给工位2
                        // 已经存在RGV执行任务时,则过滤
                        if (list.size() > 1) {
                            continue;
                        }
                        WrkMast wrkMast2 = wrkMastTask.get(0);
                        //  命令下发区 --------------------------------------------------------------------------
                        RgvCommand rgvCommand = new RgvCommand();
                        rgvCommand.setRgvNo(rgv.getId()); // RGV编号
                        rgvCommand.setAckFinish2((short) 0);  // 工位2任务完成确认位
                        rgvCommand.setTaskNo2(wrkMast2.getWrkNo().shortValue()); // 工位2工作号
                        rgvCommand.setTaskMode2(RgvTaskModeType.FETCH); // 工位2任务模式:  取货
                        rgvCommand.setSourceStaNo2(wrkMast2.getRgvSstaNo().shortValue());   //工位2源站点
                        rgvCommand.setDestinationStaNo2(wrkMast2.getRgvDstaNo().shortValue());   //工位2目标站点
                        rgvCommand.setCommand((short) 0);   //工位1、2任务确认
                        if (!MessageQueue.offer(SlaveType.Crn, wrkMast2.getRgvNo(), new Task(5, rgvCommand))) {
                            //step=2,工位1、2写任务;   step=4,工位1写任务;     step=5,工位2写任务
                            log.error("RGV命令下发失败,RGV号={},任务数据={}", rgv.getId(), JSON.toJSON(rgvCommand));
                        } else {
                            // 修改工作档状态 2.设备上走 => 6.RGV入库取货中
                            Date now = new Date();
                            wrkMast2.setWrkSts(type==1 ? 6L : 16L);
                            wrkMast2.setCrnStrTime(now);
                            wrkMast2.setModiTime(now);
                            if (wrkMastMapper.updateById(wrkMast2) == 0) {
                                log.error("工位2修改工作档状态 2/14.设备上走 => 6/16.RGV入库取货中 失败!!,工作号={}", wrkMast2.getWrkNo());
                            }
                        }
                    } else {//没有继续执行任务,下发放货任务给工位1
                        if(type == 1 && wrkMast1.getWrkSts() != 6L){//RGV入库取货中
                            continue;
                        }
                        if(type == 2 && wrkMast1.getWrkSts() != 16L){//RGV出库取货中
                            continue;
                        }
                        //  命令下发区 --------------------------------------------------------------------------
                        RgvCommand rgvCommand = new RgvCommand();
                        rgvCommand.setRgvNo(rgv.getId()); // RGV编号
                        rgvCommand.setAckFinish1((short) 0);  // 工位1任务完成确认位
                        rgvCommand.setTaskNo1(wrkMast1.getWrkNo().shortValue()); // 工位1工作号
                        rgvCommand.setTaskMode1(RgvTaskModeType.PUT); // 工位1任务模式:  放货
                        rgvCommand.setSourceStaNo1(wrkMast1.getRgvSstaNo().shortValue());   //工位1源站点
                        rgvCommand.setDestinationStaNo1(wrkMast1.getRgvDstaNo().shortValue());   //工位1目标站点
                        rgvCommand.setCommand((short) 0);   //工位1、2任务确认
                        if (!MessageQueue.offer(SlaveType.Crn, wrkMast1.getRgvNo(), new Task(4, rgvCommand))) {
                            //step=2,工位1、2任务确认;   step=4,工位1确认;     step=5,工位2任务确认
                            log.error("RGV命令下发失败,RGV号={},任务数据={}", rgv.getId(), JSON.toJSON(rgvCommand));
                        } else {
                            // 修改工作档状态 6.RGV入库取货中 => 7.RGV入库放货中
                            Date now = new Date();
                            wrkMast1.setWrkSts(type==1 ? 7L : 17L);
                            wrkMast1.setCrnEndTime(now);
                            wrkMast1.setModiTime(now);
                            if (wrkMastMapper.updateById(wrkMast1) == 0) {
                                log.error("修改工作档状态 6/16.RGV入库取货中 => 7/17.RGV入库放货中 失败!!,工作号={}", wrkMast1.getWrkNo());
                            }
                            log.error("RGV命令下发成功,RGV号={},任务数据={}", rgv.getId(), JSON.toJSON(rgvCommand));
                        }
                    }
                } else if (rgvProtocol.getModeType() == RgvModeType.AUTO
                        && rgvProtocol.getTaskNo1() > 0 && rgvProtocol.getTaskNo2() > 0
                        && rgvProtocol.getLoaded1() > 0 && rgvProtocol.getLoaded2() > 0
                        && rgvProtocol.statusType2 == RgvStatusType.FETCHWAITING){
                    //  工位2状态:也是取货完成等待确认91 并且  任务完成位 = 1,  工位1、2同时下发放货任务
                    WrkMast wrkMast1 = wrkMastMapper.selectPakInStep3(rgvProtocol.getTaskNo1().intValue());
                    WrkMast wrkMast2 = wrkMastMapper.selectPakInStep3(rgvProtocol.getTaskNo2().intValue());
                    //  命令下发区 --------------------------------------------------------------------------
                    RgvCommand rgvCommand = new RgvCommand();
                    rgvCommand.setRgvNo(rgv.getId()); // RGV编号
                    rgvCommand.setAckFinish1((short) 0);  // 工位1任务完成确认位
                    rgvCommand.setTaskNo1(wrkMast1.getWrkNo().shortValue()); // 工位1工作号
                    rgvCommand.setTaskMode1(RgvTaskModeType.PUT); // 工位1任务模式:  放货
                    rgvCommand.setSourceStaNo1(wrkMast1.getRgvSstaNo().shortValue());   //工位1源站点
                    rgvCommand.setDestinationStaNo1(wrkMast1.getRgvDstaNo().shortValue());   //工位1目标站点
                    rgvCommand.setAckFinish2((short) 0);  // 工位2任务完成确认位
                    rgvCommand.setTaskNo2(wrkMast2.getWrkNo().shortValue()); // 工位2工作号
                    rgvCommand.setTaskMode2(RgvTaskModeType.PUT); // 工位2任务模式:  放货
                    rgvCommand.setSourceStaNo2(wrkMast2.getRgvSstaNo().shortValue());   //工位2源站点
                    rgvCommand.setDestinationStaNo2(wrkMast2.getRgvDstaNo().shortValue());   //工位2目标站点
                    rgvCommand.setCommand((short) 0);   //工位1、2任务确认
                    if (!MessageQueue.offer(SlaveType.Crn, wrkMast1.getRgvNo(), new Task(2, rgvCommand))) {
                        //step=2,工位1、2任务确认;   step=4,工位1确认;     step=5,工位2任务确认
                        log.error("RGV命令下发失败,RGV号={},任务数据={}", rgv.getId(), JSON.toJSON(rgvCommand));
                    } else {
                        // 修改工作档状态 2.设备上走 => 6.RGV入库取货中
                        Date now = new Date();
                        wrkMast1.setWrkSts(wrkMast1.getWrkSts()==6L ? 7L : 17L);
                        wrkMast1.setCrnStrTime(now);
                        wrkMast1.setModiTime(now);
                        if (wrkMastMapper.updateById(wrkMast1) == 0) {
                            log.error("修改工作档状态 6/16.RGV入库取货中 => 7/17.RGV入库放货中 失败!!,工作号={}", wrkMast1.getWrkNo());
                        }
                        wrkMast2.setWrkSts(wrkMast2.getWrkSts()==6L ? 7L : 17L);
                        wrkMast2.setCrnStrTime(now);
                        wrkMast2.setModiTime(now);
                        if (wrkMastMapper.updateById(wrkMast2) == 0) {
                            log.error("修改工作档状态 6/16.RGV入库取货中 => 7/17.RGV入库放货中 失败!!,工作号={}", wrkMast2.getWrkNo());
                        }
                    }
                }
            }
        }
    }
    /**
     * 入库  ===>>  RGV出库站到堆垛机入库站
     * rgvInDStnToCrnStn
     */
    public synchronized void rgvDestStnToCrnStn() {
        for (RgvSlave rgvSlave : slaveProperties.getRgv()) {
            // 遍历入库任务的RGV出库站
            for (RgvSlave.RgvStn rgvStn : rgvSlave.getRgvDestStn()) {
                // 获取RGV出库站信息
                DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, rgvStn.getDevpPlcId());
                StaProtocol staProtocol = devpThread.getStation().get(rgvStn.getStaNo());
                if (staProtocol == null) {
                    continue;
                } else {
                    staProtocol = staProtocol.clone();
                }
                if (staProtocol.isAutoing() && staProtocol.isLoading() && (staProtocol.getWorkNo() == 0 || staProtocol.getStaNo() == null)) {
                    // 查询工作档List
//                    List<WrkMast> wrkMasts = wrkMastMapper.selectRgvInStep2(staProtocol.getSiteId());
                    List<WrkMast> wrkMasts = wrkMastMapper.selectRgvDestStep2(staProtocol.getSiteId());
                    for(WrkMast wrkMast : wrkMasts){
                        // 判断工作档条件
                        if (wrkMast.getStaNo() == null || wrkMast.getSourceStaNo() == null
                            || wrkMast.getRgvSstaNo() == null || wrkMast.getRgvDstaNo() == null) {
                            continue;
                        }
                        RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, wrkMast.getRgvNo());
                        RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
                        //  判断RGV状态等待确认,工位1
                        if (rgvProtocol.modeType == RgvModeType.AUTO && rgvProtocol.getTaskNo1().equals(wrkMast.getWrkNo().shortValue())
                                && rgvProtocol.statusType1 == RgvStatusType.WAITING) {
                            // 命令下发区 --------------------------------------------------------------------------
                            // 下发站点信息
                            staProtocol.setWorkNo(wrkMast.getWrkNo().shortValue());
                            staProtocol.setStaNo(wrkMast.getStaNo().shortValue());
                            if (!MessageQueue.offer(SlaveType.Devp, rgvStn.getDevpPlcId(), new Task(2, staProtocol))) {
                                continue;
                            }
                            // 更新工作档状态为2,14
                            wrkMast.setWrkSts(wrkMast.getWrkSts()==7L ? 2L : 14L);
                            wrkMast.setOnlineYn("Y");
                            wrkMast.setCrnEndTime(new Date());
                            if (wrkMastMapper.updateById(wrkMast) != 0) {
                                // 复位RGV工位1
                                rgvThread.setResetFlag1(true);
                            } else {
                                log.error("RGV工位1接驳,更新工作档的工作状态为{}失败!!! [工作号:{}]", wrkMast.getWrkSts()==7L ? 2L : 14L, wrkMast.getWrkNo());
                            }
                        }
                        //  判断RGV状态等待确认,工位2
                        if (rgvProtocol.modeType == RgvModeType.AUTO && rgvProtocol.getTaskNo2().equals(wrkMast.getWrkNo().shortValue())
                                && rgvProtocol.statusType2 == RgvStatusType.WAITING) {
                            // 命令下发区 --------------------------------------------------------------------------
                            // 下发站点信息
                            staProtocol.setWorkNo(wrkMast.getWrkNo().shortValue());
                            staProtocol.setStaNo(wrkMast.getStaNo().shortValue());
                            if (!MessageQueue.offer(SlaveType.Devp, rgvStn.getDevpPlcId(), new Task(2, staProtocol))) {
                                continue;
                            }
                            // 更新工作档状态为2,14
                            wrkMast.setWrkSts(wrkMast.getWrkSts()==7L ? 2L : 14L);
                            wrkMast.setOnlineYn("Y");
                            wrkMast.setCrnEndTime(new Date());
                            if (wrkMastMapper.updateById(wrkMast) != 0) {
                                // 复位RGV工位2
                                rgvThread.setResetFlag2(true);
                            } else {
                                log.error("RGV工位2接驳,更新工作档的工作状态为{}失败!!! [工作号:{}]", wrkMast.getWrkSts()==7L ? 2L : 14L, wrkMast.getWrkNo());
                            }
                        }
                    }
                }
            }
        }
    }
    /**
     * 出库  ===>>  RGV出库站到系统出库站
     */
    public synchronized void rgvOutDStnToOutStn() {
        for (RgvSlave rgvSlave : slaveProperties.getRgv()) {
            // 遍历出库任务的RGV出库站
            for (RgvSlave.RgvStn rgvStn : rgvSlave.getRgvDestStn()) {
                // 获取RGV出库站信息
                DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, rgvStn.getDevpPlcId());
                StaProtocol staProtocol = devpThread.getStation().get(rgvStn.getStaNo());
                if (staProtocol == null) {
                    continue;
                } else {
                    staProtocol = staProtocol.clone();
                }
                if (staProtocol.isAutoing() && staProtocol.isLoading() && (staProtocol.getWorkNo() == 0 || staProtocol.getStaNo() == null)) {
                    // 查询工作档List
                    List<WrkMast> wrkMasts = wrkMastMapper.selectRgvOutStep2(staProtocol.getSiteId());
                    for(WrkMast wrkMast : wrkMasts){
                        // 判断工作档条件
                        if (wrkMast.getIoType() < 100 || wrkMast.getStaNo() == null || wrkMast.getSourceStaNo() == null
                                || wrkMast.getRgvSstaNo() == null || wrkMast.getRgvDstaNo() == null) {
                            continue;
                        }
                        RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, wrkMast.getRgvNo());
                        RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
                        //  判断RGV状态等待确认,工位1
                        if (rgvProtocol.modeType == RgvModeType.AUTO && rgvProtocol.getTaskNo1().equals(wrkMast.getWrkNo().shortValue())
                                && rgvProtocol.statusType1 == RgvStatusType.WAITING) {
                            // 命令下发区 --------------------------------------------------------------------------
                            // 下发站点信息
                            staProtocol.setWorkNo(wrkMast.getWrkNo().shortValue());
                            staProtocol.setStaNo(wrkMast.getStaNo().shortValue());
                            if (!MessageQueue.offer(SlaveType.Devp, rgvStn.getDevpPlcId(), new Task(2, staProtocol))) {
                                continue;
                            }
                            // 更新工作档状态为14
                            wrkMast.setWrkSts(14L);
                            wrkMast.setOnlineYn("Y");   //控制WMS将工作状态14转15的时机,只有RGV运搬完成后才可以转
                            wrkMast.setCrnEndTime(new Date());
                            if (wrkMastMapper.updateById(wrkMast) != 0) {
                                // 复位RGV工位1
                                rgvThread.setResetFlag1(true);
                            } else {
                                log.error("RGV工位1接驳,更新工作档的工作状态为2失败!!! [工作号:{}]", wrkMast.getWrkNo());
                            }
                        }
                        //  判断RGV状态等待确认,工位2
                        if (rgvProtocol.modeType == RgvModeType.AUTO && rgvProtocol.getTaskNo2().equals(wrkMast.getWrkNo().shortValue())
                                && rgvProtocol.statusType2 == RgvStatusType.WAITING) {
                            // 命令下发区 --------------------------------------------------------------------------
                            // 下发站点信息
                            staProtocol.setWorkNo(wrkMast.getWrkNo().shortValue());
                            staProtocol.setStaNo(wrkMast.getStaNo().shortValue());
                            if (!MessageQueue.offer(SlaveType.Devp, rgvStn.getDevpPlcId(), new Task(2, staProtocol))) {
                                continue;
                            }
                            // 更新工作档状态为14
                            wrkMast.setWrkSts(14L);
                            wrkMast.setOnlineYn("Y");   //控制WMS将工作状态14转15的时机,只有RGV运搬完成后才可以转
                            wrkMast.setCrnEndTime(new Date());
                            if (wrkMastMapper.updateById(wrkMast) != 0) {
                                // 复位RGV工位2
                                rgvThread.setResetFlag2(true);
                            } else {
                                log.error("RGV工位2接驳,更新工作档的工作状态为2失败!!! [工作号:{}]", wrkMast.getWrkNo());
                            }
                        }
                    }
                }
            }
        }
    }
    /**
@@ -1283,8 +1695,7 @@
    /**
     * 执行对工作档的完成操作
     */
    @Async
    public void storeFinished() {
    public synchronized void storeFinished() {
        for (CrnSlave crn : slaveProperties.getCrn()) {
            // 获取堆垛机信息
            CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crn.getId());
@@ -1327,8 +1738,7 @@
    /**
     * 堆垛机异常信息记录
     */
    @Async
    public void recCrnErr() {
    public synchronized void recCrnErr() {
        Date now = new Date();
        for (CrnSlave crn : slaveProperties.getCrn()) {
            // 获取堆垛机信息
@@ -1449,8 +1859,7 @@
    /**
     * 空栈板初始化入库,叉车入库站放货
     */
    @Async
    public void storeEmptyPlt() {
    public synchronized void storeEmptyPlt() {
        for (DevpSlave devp : slaveProperties.getDevp()) {
            // 遍历空板入库口
            for (DevpSlave.Sta emptyInSta : devp.getEmptyInSta()) {
@@ -1564,8 +1973,7 @@
    /**
     * 出库  ===>> 工作档信息写入led显示器
     */
    @Async
    public void ledExecute() {
    public synchronized void ledExecute() {
        for (LedSlave led : slaveProperties.getLed()) {
            // 获取输送线plc线程
            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, led.getDevpPlcId());
@@ -1681,35 +2089,7 @@
    /**
     * 其他  ===>> LED显示器复位,显示默认信息
     */
    @Async
    public void ledReset() {
//        for (LedSlave led : slaveProperties.getLed()) {
//            // 获取输送线plc线程
//            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, led.getDevpPlcId());
//            // 命令集合
//            boolean reset = true;
//            for (Integer staNo : led.getStaArr()) {
//                // 获取叉车站点
//                StaProtocol staProtocol = devpThread.getStation().get(staNo);
//                if (staProtocol == null) {
//                    continue;
//                } else {
//                    staProtocol = staProtocol.clone();
//                }
//                if (staProtocol.getWorkNo() != 0) {
//                    reset = false;
//                    break;
//                }
//            }
//            // 获取led线程
//            LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, led.getDevpPlcId());
//            // led显示默认内容
//            if (reset) {
//                if (!MessageQueue.offer(SlaveType.Led, led.getId(), new Task(2, new ArrayList<>()))) {
//                    log.error("{}号LED命令下发失败!!![ip:{}] [port:{}]", led.getId(), led.getIp(), led.getPort());
//                }
//            }
//        }
    public synchronized void ledReset() {
        for (LedSlave led : slaveProperties.getLed()) {
            // 获取输送线plc线程
            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, led.getDevpPlcId());
src/main/java/com/zy/core/MainProcess.java
@@ -56,12 +56,22 @@
                    mainService.crnStnToOutStn();
                    // 入出库  ===>>  堆垛机入出库作业下发
                    mainService.crnIoExecute();
                        // 入出库  ===>>  RGV入出库作业下发
                    mainService.rgvIoExecute();
                    // 入出库增强 ===>> 堆垛机命令下发后,异步修改工作档状态
//                    mainService.crnIoWrkMast();
                    // 入库  ===>> 执行对工作档的完成操作
                    mainService.storeFinished();
                    ///////////////////////RGV调度/////////////////////////////////////
                    // 入出库  ===>>  RGV入出库作业下发
                    mainService.rgvIoExecute();
                    // RGV入库  ===>> 根据RGV完成信号,执行对工作档的完成操作
                    mainService.rgvFinished();
                    // 入出库  ===>>  RGV出库站到系统入出库站
                    mainService.rgvDestStnToCrnStn();
//                    // 出库  ===>>  RGV出库站到系统出库站
//                    mainService.rgvOutDStnToOutStn();
                    //////////////////////////////////////////////////////////////////
                    // 堆垛机异常信息记录
                    mainService.recCrnErr();
                    // 入库  ===>> 空栈板初始化入库,叉车入库站放货
src/main/java/com/zy/core/enums/RgvStatusType.java
@@ -8,7 +8,8 @@
    SOS(2, "报警"),
    FETCHING(11, "取货中"),
    PUTTING(12, "放货中"),
    WAITING(10, "任务完成等待WCS确认"),
    WAITING(90, "任务完成等待WCS确认"),
    FETCHWAITING(91, "取货任务完成等待WCS确认"),
    ;
    public Integer id;
src/main/java/com/zy/core/model/RgvSlave.java
@@ -22,11 +22,14 @@
    private Boolean demo;
    // 堆垛机入库站点
    private List<RgvStn> rgvInStn = new ArrayList<>();
    // RGV入库源站点
    private List<RgvStn> rgvInSStn = new ArrayList<>();
    // 堆垛机出库站点
    private List<RgvStn> rgvOutStn = new ArrayList<>();
    // RGV出库源站点
    private List<RgvStn> rgvOutSStn = new ArrayList<>();
    // RGV出库目标站点
    private List<RgvStn> rgvDestStn = new ArrayList<>();
    @Data
    public static class RgvStn {
src/main/java/com/zy/core/thread/RgvThread.java
@@ -67,9 +67,17 @@
                    case 1:
                        readStatus();
                        break;
                    // 写入数据
                    // 工位1、2写入数据
                    case 2:
                        write((RgvCommand) task.getData());
                        break;
                    //工位1写入数据
                    case 4:
                        write1((RgvCommand) task.getData());
                        break;
                    //工位2写入数据
                    case 5:
                        write2((RgvCommand) task.getData());
                        break;
                    // 复位
                    case 3:
@@ -180,7 +188,8 @@
                OutputQueue.RGV.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
                // 工位1复位信号
                if (rgvProtocol.getStatusType1().equals(RgvStatusType.WAITING)) {
                if (rgvProtocol.getStatusType1().equals(RgvStatusType.WAITING)
                        || rgvProtocol.getStatusType1().equals(RgvStatusType.FETCHWAITING)) {
                    if (resetFlag1) {
                        RgvCommand rgvCommand = new RgvCommand();
                        rgvCommand.setAckFinish1((short)1);
@@ -191,7 +200,8 @@
                }
                // 工位2复位信号
                if (rgvProtocol.getStatusType2().equals(RgvStatusType.WAITING)) {
                if (rgvProtocol.getStatusType2().equals(RgvStatusType.WAITING)
                        || rgvProtocol.getStatusType2().equals(RgvStatusType.FETCHWAITING)) {
                    if (resetFlag2) {
                        RgvCommand rgvCommand = new RgvCommand();
                        rgvCommand.setAckFinish2((short)1);
@@ -306,6 +316,7 @@
        array[2] = command.getTaskMode1();
        array[3] = command.getSourceStaNo1();
        array[4] = command.getDestinationStaNo1();
        siemensNet.Write("DB100.20", command.getCommand());
        OperateResult result = siemensNet.Write("DB100.0", array);
@@ -357,15 +368,14 @@
            return false;
        }
        siemensNet.Write("DB100.20", command.getCommand());
        command.setRgvNo(slave.getId());
        short[] array = new short[5];
        short[] array = new short[6];
        array[0] = command.getAckFinish2();
        array[1] = command.getTaskNo2();
        array[2] = command.getTaskMode2();
        array[3] = command.getSourceStaNo2();
        array[4] = command.getDestinationStaNo2();
        array[5] = command.getCommand();
        OperateResult result = siemensNet.Write("DB100.10", array);
src/main/java/com/zy/core/thread/SiemensCrnThread.java
@@ -179,6 +179,8 @@
                // 复位信号
                if (crnProtocol.getStatusType().equals(CrnStatusType.WAITING)) {
                    log.error("-------------------------------------------第一步、[堆垛机号:{}, 工作号:{}, 载货台:{}]==>> 状态为10,等待确认!!",
                            slave.getId(),crnProtocol.getTaskNo(), crnProtocol.getLoaded()==1 ? "有物" : "无物");
                    if (resetFlag) {
                        if(crnProtocol.getTaskNo()==9999){
                            backHpFlag = false;
src/main/resources/application.yml
@@ -150,18 +150,24 @@
    port: 502
    rack: 0
    slot: 0
    rgvInStn[0]:
    rgvInSStn[0]:
      devpPlcId: ${wcs-slave.devp[0].id}
      staNo: 100
    rgvInSStn[1]:
      devpPlcId: ${wcs-slave.devp[0].id}
      staNo: 101
    rgvInStn[1]:
      devpPlcId: ${wcs-slave.devp[0].id}
      staNo: 102
    rgvOutStn[0]:
    rgvOutSStn[0]:
      devpPlcId: ${wcs-slave.devp[0].id}
      staNo: 110
    rgvOutStn[1]:
    rgvOutSStn[1]:
      devpPlcId: ${wcs-slave.devp[0].id}
      staNo: 112
    rgvDestStn[0]:
      devpPlcId: ${wcs-slave.devp[0].id}
      staNo: 102
    rgvDestStn[1]:
      devpPlcId: ${wcs-slave.devp[0].id}
      staNo: 103
  # RGV穿梭车2
  rgv[1]:
    id: 2
src/main/resources/mapper/WrkMastMapper.xml
@@ -200,4 +200,35 @@
        order by io_pri desc,io_time,wrk_no asc
    </select>
    <select id="selectRgvInStep2" resultMap="BaseResultMap">
        select * from dbo.asr_wrk_mast where rgv_dsta_no=#{rgvInDStn} and wrk_sts=7 and (io_type=1 or io_type=10 or io_type=53 or io_type=54 or io_type=57) order by io_pri desc,io_time desc,wrk_no ASC
    </select>
    <select id="selectRgvInWorking" resultMap="BaseResultMap">
        select * from dbo.asr_wrk_mast where 1=1 and wrk_sts in (6,7) and rgv_no=#{rgvNo} order by io_time,wrk_no
    </select>
    <select id="selectRgvOutStep2" resultMap="BaseResultMap">
        select * from dbo.asr_wrk_mast where rgv_dsta_no=#{rgvOutDStn} and wrk_sts=17 and io_type > 100 order by io_pri desc,io_time desc,wrk_no ASC
    </select>
    <select id="selectRgvDestStep2" resultMap="BaseResultMap">
        select * from dbo.asr_wrk_mast where rgv_dsta_no=#{rgvDestStn} and wrk_sts in (7,17) order by io_pri desc,io_time desc,wrk_no ASC
    </select>
    <select id="selectRgvOutStep1" resultMap="BaseResultMap">
        select * from dbo.asr_wrk_mast
        where rgv_no=#{rgvNo} and rgv_ssta_no in
        <foreach item="item" collection="staNos" index="index"  separator="," open="(" close=")">
            #{item}
        </foreach>
        and wrk_sts=14 and io_type>100 and online_yn='N'
        order by io_pri desc,io_time,wrk_no asc
    </select>
    <select id="selectRgvOutWorking" resultMap="BaseResultMap">
        select * from dbo.asr_wrk_mast where 1=1 and wrk_sts in (16,17) and rgv_no=#{rgvNo} order by io_time,wrk_no
    </select>
    <!--                                       RGV调度入出库相关                                      -->
</mapper>