自动化立体仓库 - WCS系统
zjj
2024-01-22 7a806791fba46b27f4a8af6809c270f92be5f11c
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java
@@ -8,10 +8,9 @@
import com.core.common.DateUtils;
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.mapper.BasCrnErrorMapper;
import com.zy.asrs.mapper.WaitPakinMapper;
import com.zy.asrs.mapper.WrkMastMapper;
import com.zy.asrs.mapper.*;
import com.zy.asrs.service.*;
import com.zy.asrs.utils.RouteUtils;
import com.zy.asrs.utils.Utils;
import com.zy.asrs.utils.VersionUtils;
import com.zy.common.model.LocTypeDto;
@@ -21,27 +20,27 @@
import com.zy.common.service.CommonService;
import com.zy.common.utils.CollectionUtils;
import com.zy.common.utils.HttpHandler;
import com.zy.common.utils.News;
import com.zy.core.CrnThread;
import com.zy.core.DevpThread;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.*;
import com.zy.core.model.CrnSlave;
import com.zy.core.model.DevpSlave;
import com.zy.core.model.LedSlave;
import com.zy.core.model.Task;
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;
import com.zy.core.properties.SlaveProperties;
import com.zy.core.thread.BarcodeThread;
import com.zy.core.thread.LedThread;
import com.zy.core.thread.RgvThread;
import com.zy.core.thread.SiemensDevpThread;
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;
@@ -87,35 +86,33 @@
    private BasErrLogService basErrLogService;
    @Autowired
    private BasCrnErrorMapper basCrnErrorMapper;
    @Autowired
    private WrkMastStaMapper wrkMastStaMapper;
    @Autowired
    private BasRgvService basRgvService;
    @Autowired
    private BasRgvMapMapper basRgvMapMapper;
    @Autowired
    private WrkMastService wrkMastService;
    @Value("${wms.url}")
    private String wmsUrl;
    public Integer wrkNo = 10000;
    /**
     * 组托
     * 入库站,根据条码扫描生成入库工作档,工作状态 2
     */
    public void generateStoreWrkFile() {
    public synchronized void generateStoreWrkFile(Integer mark) {
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
        // 根据输送线plc遍历
        for (DevpSlave devp : slaveProperties.getDevp()) {
            // 遍历入库口
            for (DevpSlave.Sta inSta : devp.getInSta()) {
                // 获取条码扫描仪信息
                BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, inSta.getBarcode());
                if (barcodeThread == null) {
                    continue;
                }
                String barcode = barcodeThread.getBarcode();
                if(!Cools.isEmpty(barcode)) {
                    log.info("{}号条码扫描器检测条码信息:{}", inSta.getBarcode(), barcode);
                    if("NG".endsWith(barcode) || "NoRead".equals(barcode)) {
                        continue;
                    }
                } else {
                    continue;
                }
                // 获取入库站信息
                LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, inSta.getLed());
                SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                StaProtocol staProtocol = devpThread.getStation().get(inSta.getStaNo());
                if (staProtocol == null) {
@@ -124,44 +121,88 @@
                    staProtocol = staProtocol.clone();
                }
                // 入出库模式判断
//                if ( inSta.getStaNo()==203 && devpThread.ioModeOf2F != IoModeType.PAKIN_MODE) { continue; }
                if ( inSta.getStaNo()==203 && devpThread.ioModeOf2F == IoModeType.PAKOUT_MODE) { continue; }
                if (barcodeThread == null) {
                    continue;
                }
                String barcode = barcodeThread.getBarcode();
                // 尺寸检测异常
                boolean back = false;
                String errMsg = "";
                if (staProtocol.isFrontErr()) {
                    errMsg = "前超限";
                    back = true;
                }
                if (!back && staProtocol.isBackErr()) {
                    errMsg = "后超限";
                    back = true;
                }
                if (!back && staProtocol.isHighErr()) {
                    errMsg = "高超限";
                    back = true;
                }
                if (!back && staProtocol.isLeftErr()) {
                    errMsg = "左超限";
                    back = true;
                }
                if (!back && staProtocol.isRightErr()) {
                    errMsg = "右超限";
                    back = true;
                }
                if (!back && staProtocol.isWeightErr()) {
                    errMsg = "超重";
                    back = true;
                }
                if (!back && staProtocol.isBarcodeErr()) {
                    errMsg = "扫码失败";
                    back = true;
                }
                // 退回
                if (back) {
//                        News.warn("扫码入库失败,{}入库站因{}异常,托盘已被退回", inSta.getStaNo(), errMsg);
                    MessageQueue.offer(SlaveType.Led, inSta.getLed(), new Task(3, errMsg));
                    if (!staProtocol.isLoading()){
                        continue;
                    }
                    if (!staProtocol.isPakMk()) {
                        continue;
                    }
                    staProtocol.setWorkNo(wrkNo);
                    News.info("{}入库回退:{},任务号:{}", inSta.getStaNo(), errMsg,wrkNo);
                    wrkNo++;
                    staProtocol.setStaNo(inSta.getBackSta().shortValue());
                    devpThread.setPakMk(staProtocol.getSiteId(), false);
                    MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                }
                // 判断是否满足入库条件
                if (staProtocol.isAutoing() && staProtocol.isLoading()
                if (staProtocol.isAutoing()
                        && staProtocol.isLoading()
                        && staProtocol.isInEnable()
                        && !staProtocol.isEmptyMk() && (staProtocol.getWorkNo() == 0 || staProtocol.getWorkNo() > 9990)
                        && staProtocol.isPakMk()){// && !Cools.isEmpty(barcode)) {
                        && !staProtocol.isEmptyMk()
                        && staProtocol.isPakMk()) {
                    if(Cools.isEmpty(barcode) || "NG".endsWith(barcode) || "NoRead".equals(barcode) || "00000000".equals(barcode)) {
                        News.info("{}号条码扫描器检测条码信息:{}", inSta.getBarcode(), barcode);
//                    if(Cools.isEmpty(barcode) || "NG".endsWith(barcode) || "NoRead".equals(barcode)) {
//                        log.info("{}号条码扫描器检测条码信息:{}", inSta.getBarcode(), barcode);
//                        //条码为空或者不符合,退库到172站点
//                        staProtocol.setWorkNo((short)9999);
//                        staProtocol.setStaNo((short)172);
//                        devpThread.setPakMk(staProtocol.getSiteId(), false);
//                        boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                        if (!result) {
//                            throw new CoolException("更新plc站点信息失败");
//                        }
//                        continue;
//                    }
                        continue;
                    }
                    // 判断重复工作档
                    WrkMast wrkMast = wrkMastMapper.selectPakInStep1(inSta.getStaNo(), barcode);
                    if (wrkMast != null) {
                        log.error("工作档中已存在该站状态为( 2.设备上走 )的数据,工作号={}", wrkMast.getWrkNo());
                        News.error(methodName + ":工作档中已存在该站状态为( 2.设备上走 )的数据,工作号={}", wrkMast.getWrkNo());
                        if (ledThread != null) {
                            News.error(methodName + ":扫码失败,请重试");
                            MessageQueue.offer(SlaveType.Led, inSta.getLed(), new Task(3, "工作档中已存在该站状态为( 2.设备上走 )的数据,工作号={" + wrkMast.getWrkNo() + "}, 请手动取消已存在工作档"));
                        }
                        continue;
                    }
//                    // 获取入库通知档
//                    List<WaitPakin> waitPakins = waitPakinMapper.selectList(new EntityWrapper<WaitPakin>().eq("zpallet", barcode).eq("io_status", "N"));
//                    if (waitPakins.isEmpty()) {
//                        log.error("无此入库条码数据。条码号={}", barcode);
//                        continue;
//                    }
                    WrkMast checkPick = wrkMastService.selectOne(new EntityWrapper<WrkMast>()
                            .eq("barcode", barcode)
                            .in("io_type", 107,103));
                    if (!Cools.isEmpty(checkPick)) {
                        continue;
                    }
                    try {
                        LocTypeDto locTypeDto = new LocTypeDto(staProtocol);
                        SearchLocParam param = new SearchLocParam();
@@ -178,76 +219,32 @@
                        JSONObject jsonObject = JSON.parseObject(response);
                        if (jsonObject.getInteger("code").equals(200)) {
                            StartupDto dto = jsonObject.getObject("data", StartupDto.class);
                            barcodeThread.setBarcode("");
                            staProtocol.setWorkNo(dto.getWorkNo().shortValue());
                            staProtocol.setWorkNo(dto.getWorkNo());
                            staProtocol.setStaNo(dto.getStaNo().shortValue());
                            devpThread.setPakMk(staProtocol.getSiteId(), false);
                            boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                            if (!result) {
                                News.error(methodName + ":更新plc站点信息失败");
                                throw new CoolException("更新plc站点信息失败");
                            }
                        } else {
                            log.error("请求接口失败!!!url:{};request:{};response:{}", wmsUrl+"/rpc/pakin/loc/v1", JSON.toJSONString(param), response);
                            staProtocol.setWorkNo(wrkNo);
                            wrkNo++;
                            staProtocol.setStaNo(inSta.getBackSta().shortValue());
                            devpThread.setPakMk(staProtocol.getSiteId(), false);
                            MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                            if (ledThread != null) {
                                String errorMsg = jsonObject.getString("msg");
                                if (!Cools.isEmpty(errorMsg)) {
                                    MessageQueue.offer(SlaveType.Led, inSta.getLed(), new Task(3, errorMsg));
                                }
                            }
                            News.error(methodName + ":请求接口失败!!!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();
@@ -259,6 +256,7 @@
            }
        }
//        News.infoNoLog(""+mark+" - 0"+" - 组托  ===》执行完成");
    }
@@ -266,7 +264,7 @@
     * wms入库
     * 入库站,根据条码扫描生成入库工作档,工作状态 1 ==>> 2
     */
    public void generateStoreWrkFile0() {
    public synchronized void generateStoreWrkFile0(Integer mark) {
        // 根据输送线plc遍历
        for (DevpSlave devp : slaveProperties.getDevp()) {
            // 遍历入库口
@@ -281,20 +279,28 @@
                }
//                // 入出库模式判断
                if ( inSta.getStaNo()==203 && devpThread.ioModeOf2F != IoModeType.PAKIN_MODE) { continue; }
                if (inSta.getStaNo() == 203 && devpThread.ioModeOf2F != IoModeType.PAKIN_MODE) {
                    continue;
                }
                // 判断是否满足入库条件
                if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.isInEnable()
                if (!staProtocol.isLoading()){
                    continue;
                }
                if (staProtocol.isAutoing() && staProtocol.isInEnable()
                        && !staProtocol.isEmptyMk() && (staProtocol.getWorkNo() == 0 || staProtocol.getWorkNo() == 9999)
                        && staProtocol.isPakMk()) {
                    News.warnNoLog(""+mark+" - 0"+" - 开始执行");
                    // 判断重复工作档
                    WrkMast wrkMast = wrkMastMapper.selectPakInStep11(inSta.getStaNo());
                    if (wrkMast == null) { continue; }
                    if (wrkMast == null) {
                        continue;
                    }
                    // 命令下发区 --------------------------------------------------------------------------
                    // 更新站点信息 且 下发plc命令
                    staProtocol.setWorkNo(wrkMast.getWrkNo().shortValue());
                    staProtocol.setWorkNo(wrkMast.getWrkNo());
                    staProtocol.setStaNo(wrkMast.getStaNo().shortValue());
                    devpThread.setPakMk(staProtocol.getSiteId(), false);
                    boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
@@ -303,41 +309,44 @@
                        wrkMast.setWrkSts(2L); // 工作状态:2.设备上走
                        wrkMast.setModiTime(new Date());
                        if (wrkMastMapper.updateById(wrkMast) == 0) {
                            log.error("更新工作档失败!!! [工作号:{}]", wrkMast.getWrkNo());
                            News.error(""+mark+" - 1"+" - 更新工作档失败!!! [工作号:{}]", wrkMast.getWrkNo());
                        }
                    } else {
                        log.error("发布命令至输送线队列失败!!! [plc编号:{}]", devp.getId());
                        News.error(""+mark+" - 2"+" - 发布命令至输送线队列失败!!! [plc编号:{}]", devp.getId());
                    }
                }else {
                    News.errorNoLog(""+mark+" - 6"+" - 站点信息不符合入库条件!!!"+" 自动信号:"+staProtocol.isLoading()+"、可入信号:" + staProtocol.isInEnable()
                            +"、空板信号:"+ staProtocol.isEmptyMk()+"、工作号:" + staProtocol.getWorkNo()
                            +"、锁定标记"+ staProtocol.isPakMk()+"、入库印记:" + staProtocol.getStamp());
                }
            }
        }
//        News.infoNoLog(""+mark+" - 0"+" - wms入库  ===》执行完成");
    }
    /**
     * 拣料、并板、盘点再入库
     */
    public synchronized void stnToCrnStnPick(){
    public synchronized void stnToCrnStnPick(Integer mark) {
        for (DevpSlave devp : slaveProperties.getDevp()) {
            // 遍历拣料入库口
            for (DevpSlave.Sta pickSta : devp.getPickSta()) {
//                // 获取条码扫描仪信息
//                BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, pickSta.getBarcode());
//                if (barcodeThread == null) {
//                    continue;
//                }
//                String barcode = barcodeThread.getBarcode();
//                if(!Cools.isEmpty(barcode)) {
//                    log.info("{}号条码扫描器检测条码信息:{}", pickSta.getBarcode(), barcode);
//                    if("NG".endsWith(barcode) || "NoRead".equals(barcode)) {
//                        continue;
//                    }
//                } else {
//                    continue;
//                }
                // 获取条码扫描仪信息
                BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, pickSta.getBarcode());
                if (barcodeThread == null) {
                    continue;
                }
                String barcode = barcodeThread.getBarcode();
                if(!Cools.isEmpty(barcode)) {
//                    News.info(""+mark+" - 1"+" - {}号条码扫描器检测条码信息:{}", pickSta.getBarcode(), barcode);
                    if("NG".endsWith(barcode) || "NoRead".equals(barcode)) {
                        continue;
                    }
                } else {
                    continue;
                }
                // 获取拣料入库站信息
                SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
@@ -351,15 +360,16 @@
//                // 入出库模式判断
//                if (devpThread.ioMode != IoModeType.PAKIN_MODE) { continue; }
                if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.isInEnable() && staProtocol.isPakMk()){
//                    WrkMast wrkMast = wrkMastMapper.selectPickStep(barcode);
                    WrkMast wrkMast = wrkMastMapper.selectPakInStep3(staProtocol.getWorkNo().intValue());
                if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.isInEnable() && staProtocol.isPakMk()) {
                    News.warnNoLog(""+mark+" - 0"+" - 开始执行");
                    WrkMast wrkMast = wrkMastMapper.selectPickStep(barcode);
//                    WrkMast wrkMast = wrkMastMapper.selectPakInStep3(staProtocol.getWorkNo().intValue());
                    if (wrkMast == null) {
                        // 无拣料数据
                        continue;
                    }
                    if ((wrkMast.getIoType() != 103 && wrkMast.getIoType() != 104 && wrkMast.getIoType() != 107)
                        || Cools.isEmpty(wrkMast.getStaNo()) || Cools.isEmpty(wrkMast.getSourceStaNo()) ) {
                            || Cools.isEmpty(wrkMast.getStaNo()) || Cools.isEmpty(wrkMast.getSourceStaNo())) {
                        continue;
                    }
@@ -379,7 +389,18 @@
                            .eq("crn_no", wrkMast.getCrnNo()); // 堆垛机号
                    StaDesc staDesc = staDescService.selectOne(wrapper);
                    if (Cools.isEmpty(staDesc)) {
                        log.error("入库路径不存在!type_no={},stn_no={},crn_no={}", wrkMast.getIoType(), pickSta.getStaNo(), wrkMast.getCrnNo());
                        News.error(""+mark+" - 2"+" - 入库路径不存在!type_no={},stn_no={},crn_no={}", wrkMast.getIoType(), pickSta.getStaNo(), wrkMast.getCrnNo());
                        staProtocol.setWorkNo(9989);
                        staProtocol.setStaNo((short) (pickSta.getStaNo().shortValue()-(short)1));
                        devpThread.setPakMk(staProtocol.getSiteId(), false);
                        MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                        //LED
                        LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, pickSta.getLed());
                        // led 异常显示
                        if (ledThread != null) {
                            String errorMsg = "此为拣料、并板、盘点再入库.请放在"+pickSta.getBackSta().shortValue()+"站点";
                            MessageQueue.offer(SlaveType.Led, pickSta.getLed(), new Task(5, errorMsg));
                        }
                        continue;
                    }
@@ -424,26 +445,30 @@
                    }
                    // 更新站点信息 且 下发plc命令
                    staProtocol.setWorkNo(wrkMast.getWrkNo().shortValue());
                    staProtocol.setWorkNo(wrkMast.getWrkNo());
                    staProtocol.setStaNo(wrkMast.getStaNo().shortValue());
                    devpThread.setPakMk(staProtocol.getSiteId(), false);
                    boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                    if (!result) {
                        log.error("发布命令至输送线队列失败!!! [plc编号:{}]", devp.getId());
                        News.error(""+mark+" - 3"+" - 发布命令至输送线队列失败!!! [plc编号:{}]", devp.getId());
                    }
                }else {
                    News.errorNoLog(""+mark+" - 6"+" - 站点信息不符合入库条件!!!"+" 自动信号:"+staProtocol.isLoading()+"、可入信号:" + staProtocol.isInEnable()
                            +"、空板信号:"+ staProtocol.isEmptyMk());
                }
            }
        }
//        News.infoNoLog(""+mark+" - 0"+" - 拣料、并板、盘点再入库  ===》执行完成");
    }
    /**
     * 堆垛机站出库到出库站
     */
    @Async
    public void crnStnToOutStn() {
    public synchronized void crnStnToOutStn(Integer mark) {
        for (CrnSlave crnSlave : slaveProperties.getCrn()) {
            // 遍历堆垛机出库站
            for (CrnSlave.CrnStn crnStn : crnSlave.getCrnOutStn()) {
@@ -476,12 +501,13 @@
                    if (crnProtocol.modeType == CrnModeType.AUTO && crnProtocol.getTaskNo().equals(wrkMast.getWrkNo().shortValue())
                            && crnProtocol.statusType == CrnStatusType.WAITING
                            && crnProtocol.forkPosType == CrnForkPosType.HOME) {
                        News.warnNoLog(""+mark+" - 0"+" - 开始执行");
                        // 命令下发区 --------------------------------------------------------------------------
                        // 下发站点信息
                        staProtocol.setWorkNo(wrkMast.getWrkNo().shortValue());
                        staProtocol.setStaNo(wrkMast.getStaNo().shortValue());
                        staProtocol.setWorkNo(wrkMast.getWrkNo());
                        staProtocol.setStaNo(RouteUtils.CrnStaEnd(wrkMast.getStaNo(),wrkMast.getSourceStaNo()));
                        if (!MessageQueue.offer(SlaveType.Devp, crnStn.getDevpPlcId(), new Task(2, staProtocol))) {
                            continue;
                        }
@@ -493,28 +519,38 @@
                            // 复位堆垛机
                            crnThread.setResetFlag(true);
                        } else {
                            log.error("更新工作档的工作状态为14失败!!! [工作号:{}]", wrkMast.getWrkNo());
                            News.error(""+mark+" - 1"+" - 更新工作档的工作状态为14失败!!! [工作号:{}]", wrkMast.getWrkNo());
                        }
                    }else {
                        News.errorNoLog(""+mark+" - 6"+" - 堆垛机信息不符合入库条件!!!"
                                +" 堆垛机状态:"+crnProtocol.modeType+"==自动AUTO:" + CrnModeType.AUTO
                                +"、堆垛机任务号:"+crnProtocol.getTaskNo()+"==工作档任务号:" + wrkMast.getWrkNo().shortValue()
                                +"、状态枚举:"+crnProtocol.statusType+"==WAITING:90 //任务完成等待WCS确认):" + CrnStatusType.WAITING
                                +"、货叉位置:"+crnProtocol.forkPosType+"==HOME:0  // 货叉原位:" + CrnForkPosType.HOME);
                    }
                }
            }
        }
//        News.infoNoLog(""+mark+" - 0"+" - 堆垛机站出库到出库站  ===》执行完成");
    }
    /**
     * 入出库  ===>>  堆垛机入出库作业下发
     */
    public synchronized void crnIoExecute(){
    public synchronized void crnIoExecute(Integer mark) {
        for (CrnSlave crn : slaveProperties.getCrn()) {
            // 获取堆垛机信息
            CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crn.getId());
            CrnProtocol crnProtocol = crnThread.getCrnProtocol();
            if (crnProtocol == null) { continue; }
            if (crnProtocol == null) {
                continue;
            }
            BasCrnp basCrnp = basCrnpService.selectById(crn.getId());
            if (basCrnp == null) {
                log.error("{}号堆垛机尚未在数据库进行维护!", crn.getId());
                News.error(""+mark+" - 1"+" - {}号堆垛机尚未在数据库进行维护!", crn.getId());
                continue;
            }
@@ -526,38 +562,43 @@
            // 只有当堆垛机空闲 并且 无任务时才继续执行
            if (crnProtocol.getStatusType() == CrnStatusType.IDLE && crnProtocol.getTaskNo() == 0 && crnProtocol.getModeType() == CrnModeType.AUTO
                    && crnProtocol.getLoaded() == 0 && crnProtocol.getForkPos() == 0) {
                News.warnNoLog(""+mark+" - 0"+" - 开始执行堆垛机入出库作业下发");
                // 如果最近一次是入库模式
                if (crnProtocol.getLastIo().equals("I")) {
                    if (basCrnp.getInEnable().equals("Y")) {
                        this.crnStnToLoc(crn, crnProtocol); //  入库
                        //mark - 1 - ....
                        this.crnStnToLoc(crn, crnProtocol,mark); //  入库
                        crnProtocol.setLastIo("O");
                    } else if (basCrnp.getOutEnable().equals("Y")) {
                        this.locToCrnStn(crn, crnProtocol); //  出库
                        //mark - 2 - ....
                        this.locToCrnStn(crn, crnProtocol,mark); //  出库
                        crnProtocol.setLastIo("I");
                    }
                }
                // 如果最近一次是出库模式
                else if (crnProtocol.getLastIo().equals("O")) {
                    if (basCrnp.getOutEnable().equals("Y")) {
                        this.locToCrnStn(crn, crnProtocol); //  出库
                        this.locToCrnStn(crn, crnProtocol,mark); //  出库
                        crnProtocol.setLastIo("I");
                    } else if (basCrnp.getInEnable().equals("Y")) {
                        this.crnStnToLoc(crn, crnProtocol); //  入库
                        this.crnStnToLoc(crn, crnProtocol,mark); //  入库
                        crnProtocol.setLastIo("O");
                    }
                }
            }
            // 库位移转
            this.locToLoc(crn, crnProtocol);
            //mark - 3 - ....
            this.locToLoc(crn, crnProtocol,mark);
//            this.crnRebackHp(crnProtocol, crnThread);
        }
//        News.infoNoLog(""+mark+" - 0"+" - 堆垛机入出库作业下发执行完成");
    }
    /**
     * 回原点,堆垛机没有执行中任务,设备存在入库任务时叫回原点
     */
    public synchronized void crnRebackHp(CrnProtocol crnProtocol, CrnThread crnThread){
    public synchronized void crnRebackHp(CrnProtocol crnProtocol, CrnThread crnThread) {
//        for (CrnSlave crn : slaveProperties.getCrn()) {
//            // 获取堆垛机信息
//            CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crn.getId());
@@ -570,56 +611,58 @@
//                log.error("{}号堆垛机尚未在数据库进行维护!", crn.getId());
//                continue;
//            }
            if (crnProtocol.getStatusType() == CrnStatusType.IDLE && crnProtocol.getTaskNo() == 0 && crnProtocol.getModeType() == CrnModeType.AUTO) {
                if(crnProtocol.getBay() ==1 && crnProtocol.getLevel()==1){
                    return;
                }
                // 已经存在吊车执行任务时,则过滤3,12
                if (wrkMastMapper.selectWorking(crnProtocol.getCrnNo()) != null) {
                    return;
                }
                //堆垛机有执行中任务,过滤3,4,11,12
                if (wrkMastMapper.selectCrnWorking(crnProtocol.getCrnNo()) != null) {
                    return;
                }
                //输送线没有入库任务,过滤2
                if (wrkMastMapper.selectDevWorking(crnProtocol.getCrnNo()) == null) {
                    return;
                }
                log.info("堆垛机召回原点==>>" + crnProtocol.getCrnNo() + "号堆垛机有入库任务,召回原点");
                // 命令下发区 --------------------------------------------------------------------------
                CrnCommand crnCommand = new CrnCommand();
                crnCommand.setCrnNo(crnProtocol.getCrnNo()); // 堆垛机编号
                crnCommand.setTaskNo((short) 9999); // 工作号
                crnCommand.setAckFinish((short) 0);  // 任务完成确认位
                crnCommand.setTaskMode(CrnTaskModeType.GO_ORIGIN); // 任务模式:  回原点
                crnCommand.setSourcePosX((short) 0);     // 源库位排
                crnCommand.setSourcePosY((short) 0);     // 源库位列
                crnCommand.setSourcePosZ((short) 0);     // 源库位层
                crnCommand.setDestinationPosX((short) 0);     // 目标库位排
                crnCommand.setDestinationPosY((short) 0);     // 目标库位列
                crnCommand.setDestinationPosZ((short) 0);     // 目标库位层
                if (!MessageQueue.offer(SlaveType.Crn, crnProtocol.getCrnNo(), new Task(2, crnCommand))) {
                    log.error("堆垛机回原点命令下发失败,堆垛机号={},任务数据={}", crnProtocol.getCrnNo(), JSON.toJSON(crnCommand));
                }
                crnThread.setBackHpFlag(true);
        if (crnProtocol.getStatusType() == CrnStatusType.IDLE && crnProtocol.getTaskNo() == 0 && crnProtocol.getModeType() == CrnModeType.AUTO) {
            if (crnProtocol.getBay() == 1 && crnProtocol.getLevel() == 1) {
                return;
            }
            // 已经存在吊车执行任务时,则过滤3,12
            if (wrkMastMapper.selectWorking(crnProtocol.getCrnNo()) != null) {
                return;
            }
            //堆垛机有执行中任务,过滤3,4,11,12
            if (wrkMastMapper.selectCrnWorking(crnProtocol.getCrnNo()) != null) {
                return;
            }
            //输送线没有入库任务,过滤2
            if (wrkMastMapper.selectDevWorking(crnProtocol.getCrnNo()) == null) {
                return;
            }
            News.info("堆垛机召回原点==>>" + crnProtocol.getCrnNo() + "号堆垛机有入库任务,召回原点");
            // 命令下发区 --------------------------------------------------------------------------
            CrnCommand crnCommand = new CrnCommand();
            crnCommand.setCrnNo(crnProtocol.getCrnNo()); // 堆垛机编号
            crnCommand.setTaskNo((short) 9999); // 工作号
            crnCommand.setAckFinish((short) 0);  // 任务完成确认位
            crnCommand.setTaskMode(CrnTaskModeType.GO_ORIGIN); // 任务模式:  回原点
            crnCommand.setSourcePosX((short) 0);     // 源库位排
            crnCommand.setSourcePosY((short) 0);     // 源库位列
            crnCommand.setSourcePosZ((short) 0);     // 源库位层
            crnCommand.setDestinationPosX((short) 0);     // 目标库位排
            crnCommand.setDestinationPosY((short) 0);     // 目标库位列
            crnCommand.setDestinationPosZ((short) 0);     // 目标库位层
            if (!MessageQueue.offer(SlaveType.Crn, crnProtocol.getCrnNo(), new Task(2, crnCommand))) {
                News.error("堆垛机回原点命令下发失败,堆垛机号={},任务数据={}", crnProtocol.getCrnNo(), JSON.toJSON(crnCommand));
            }
            crnThread.setBackHpFlag(true);
        }
//        }
    }
    /**
     * 入库  ===>>  堆垛机站到库位
     */
    public void crnStnToLoc(CrnSlave slave, CrnProtocol crnProtocol){
    public synchronized void crnStnToLoc(CrnSlave slave, CrnProtocol crnProtocol,Integer mark) {
        News.warnNoLog(""+mark+" - 1"+" - 0"+" - 堆垛机入出库作业下发:执行入库");
        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) {
                News.infoNoLog(""+mark+" - 1"+" - 1"+" - 堆垛机入库站信息(staProtocol!=null继续执行):staProtocol="+staProtocol);
                continue;
            } else {
                staProtocol = staProtocol.clone();
@@ -627,35 +670,41 @@
            // 查询站点详细信息
            BasDevp staDetl = basDevpService.selectById(crnStn.getStaNo());
            if (staDetl == null) {
                log.error("入库 ===>> 堆垛机站点在数据库不存在, 站点编号={}", crnStn.getStaNo());
                News.error(""+mark+" - 1"+" - 2"+" - 入库 ===>> 堆垛机站点在数据库不存在, 站点编号={}", crnStn.getStaNo());
                continue;
            }
            if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.getWorkNo() > 0 && staProtocol.isInEnable()
                    && staDetl.getCanining()!=null && staDetl.getCanining().equals("Y")) {
                    && staDetl.getCanining() != null && staDetl.getCanining().equals("Y")) {
                flag = true;
            }
            if (!flag) {
                News.errorNoLog(""+mark+" - 1"+" - 3"+" - 堆垛机入库站信息(以下需要全true):"
                        +"自动信号"+staProtocol.isAutoing()+"有物信号"+staProtocol.isLoading()
                        +"工作号>0"+staProtocol.getWorkNo()+"可入信号"+staProtocol.isInEnable()
                        +"能入信号(wms设置).equals(\"Y\")"+staDetl.getCanining());
                continue;
            }
            // 获取工作状态为2(设备上走)的入库工作档
            WrkMast wrkMast = wrkMastMapper.selectPakInStep2(slave.getId(), staProtocol.getWorkNo().intValue(), crnStn.getStaNo());
            if(null == wrkMast) {
            if (null == wrkMast) {
                News.infoNoLog(""+mark+" - 1"+" - 4"+" - 查询无待入库数据--wrk_sts=2, 工作号={}", staProtocol.getWorkNo());
//                log.error("查询无待入库数据--wrk_sts=2, 工作号={}", staProtocol.getWorkNo());
                continue;
            }
            // 获取库位信息
            LocMast locMast = locMastService.selectById(wrkMast.getLocNo());
            if (locMast == null) {
                log.error("查询库存无数据--库位号{}", wrkMast.getLocNo());
                News.error(""+mark+" - 1"+" - 5"+" - 查询库存无数据--库位号{}", wrkMast.getLocNo());
                continue;
            }
            if (!locMast.getLocSts().equals("S") && !locMast.getLocSts().equals("Q")) {
                log.error("入库操作库位状态不符合--状态, 库位号={},库位状态={}", wrkMast.getLocNo(), locMast.getLocSts());
                News.error(""+mark+" - 1"+" - 6"+" - 入库操作库位状态不符合--状态, 库位号={},库位状态={}", wrkMast.getLocNo(), locMast.getLocSts());
                continue;
            }
            // 堆垛机控制过滤
            if (!crnProtocol.getStatusType().equals(CrnStatusType.IDLE) || crnProtocol.getTaskNo() != 0) {
//                News.infoNoLog(""+mark+" - 1"+" - 7"+" - 堆垛机控制过滤:堆垛机是否空闲={},任务号={}", crnProtocol.getStatusType(),crnProtocol.getTaskNo());
                continue;
            }
@@ -666,47 +715,55 @@
            // 双深库位且浅库位有货,则需先对浅库位进行库位移转
            if (Utils.isDeepLoc(slaveProperties, wrkMast.getLocNo())) {
                News.warnNoLog(""+mark+" - 1"+" - 8"+" - 双深库位且浅库位有货,则需先对浅库位进行库位移转 : 开始执行 任务号={}",wrkMast.getWrkNo());
                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")) {
                    News.warnNoLog(""+mark+" - 1"+" - 9"+" - // O.空库位、Q.拣料/盘点/并板再入库、S.入库预约、X.禁用 直接搬!库位状态={}",shallowLoc.getLocSts());
                    WrkMast waitWrkMast = wrkMastMapper.selectByLocNo(shallowLocNo);
                    if (null == waitWrkMast) {
                        log.error("{}库位异常,未检索到相应工作档!", shallowLocNo);
                        News.error(""+mark+" - 1"+" - 10"+" - {}库位异常,未检索到相应工作档!", shallowLocNo);
                    } else {
                        waitWrkMast.setIoPri(15D);
                        waitWrkMast.setModiTime(new Date());
                        if (wrkMastMapper.updateById(waitWrkMast) == 0) {
                            log.error("调整工作档优先级失败!工作号={}", waitWrkMast.getWrkNo());
                            News.error(""+mark+" - 1"+" - 11"+" - 调整工作档优先级失败!工作号={}", waitWrkMast.getWrkNo());
                        }
                        continue;
                    }
                } else if (shallowLoc.getLocSts().equals("F") || shallowLoc.getLocSts().equals("D")) {
                    News.warnNoLog(""+mark+" - 1"+" - 12"+" - // F、D  库位状态={}",shallowLoc.getLocSts());
                    // 此标记避免多次执行移库任务
                    if (Cools.isEmpty(wrkMast.getUpdMk()) || "N".equals(wrkMast.getUpdMk())) {
                        wrkMast.setUpdMk("Y");
                        wrkMast.setIoPri(14D);
                        wrkMastMapper.updateById(wrkMast);
                        // 生成工作档,将浅库位移转到新的库位中
                        moveLocForDeepLoc(slave, shallowLoc);
                        moveLocForDeepLoc(slave, shallowLoc,mark);
                        // 生成工作档、改变浅库位的源库/目标库 库位状态、下发堆垛机命令(立马执行)
//                        moveLocForDeepLocPakin(slave, shallowLoc, wrkMast);
                    }
                    continue;
                } else if (shallowLoc.getLocSts().equals("Q")){
                } else if (shallowLoc.getLocSts().equals("Q")) {
                    News.warnNoLog(""+mark+" - 1"+" - 13"+" - // Q  库位状态={}",shallowLoc.getLocSts());
                    WrkMast waitWrkMast = wrkMastMapper.selectByLocNo(shallowLocNo);
                    if (null != waitWrkMast && waitWrkMast.getWrkSts()==4) {
                    if (null != waitWrkMast && waitWrkMast.getWrkSts() == 4) {
                        News.infoNoLog(""+mark+" - 1"+" - 14"+" - // F、D  工作状态(判断条件为==4)={}",waitWrkMast.getWrkSts());
                        continue;
                    }
                }
            }
            News.warnNoLog(""+mark+" - 1"+" - 15"+" - 命令下发 : 工作号={},源排={},源列={},源层={},目标排={},目标列={},目标层={}",wrkMast.getWrkNo().shortValue()
                    ,crnStn.getRow().shortValue(),crnStn.getBay().shortValue(),crnStn.getLev().shortValue()
                    ,locMast.getRow1().shortValue(),locMast.getBay1().shortValue(),locMast.getLev1().shortValue());
            // 命令下发区 --------------------------------------------------------------------------
            CrnCommand crnCommand = new CrnCommand();
            crnCommand.setCrnNo(slave.getId()); // 堆垛机编号
            crnCommand.setTaskNo(wrkMast.getWrkNo().shortValue()); // 工作号
            crnCommand.setAckFinish((short) 0);  // 任务完成确认位
//            crnCommand.setAckFinish((short) 0);  // 任务完成确认位
            crnCommand.setTaskMode(CrnTaskModeType.LOC_MOVE); // 任务模式:  库位移转
            crnCommand.setSourcePosX(crnStn.getRow().shortValue());     // 源库位排
            crnCommand.setSourcePosY(crnStn.getBay().shortValue());     // 源库位列
@@ -714,8 +771,9 @@
            crnCommand.setDestinationPosX(locMast.getRow1().shortValue());     // 目标库位排
            crnCommand.setDestinationPosY(locMast.getBay1().shortValue());     // 目标库位列
            crnCommand.setDestinationPosZ(locMast.getLev1().shortValue());     // 目标库位层
            crnCommand.setTraySize(locMast.getLocType1() == 2);
            if (!MessageQueue.offer(SlaveType.Crn, wrkMast.getCrnNo(), new Task(2, crnCommand))) {
                log.error("堆垛机命令下发失败,堆垛机号={},任务数据={}", wrkMast.getCrnNo(), JSON.toJSON(crnCommand));
                News.error(""+mark+" - 1"+" - 16"+" - 堆垛机命令下发失败,堆垛机号={},任务数据={}", wrkMast.getCrnNo(), JSON.toJSON(crnCommand));
            } else {
//                long startTime = System.currentTimeMillis();
@@ -736,40 +794,43 @@
                wrkMast.setCrnStrTime(now);
                wrkMast.setModiTime(now);
                if (wrkMastMapper.updateById(wrkMast) == 0) {
                    log.error("修改工作档状态 2.设备上走 => 3.吊车入库中 失败!!,工作号={}", wrkMast.getWrkNo());
                    News.error(""+mark+" - 1"+" - 17"+" - 修改工作档状态 2.设备上走 => 3.吊车入库中 失败!!,工作号={}", wrkMast.getWrkNo());
                }
            }
        }
        News.infoNoLog(""+mark+" - 1"+" - 0"+" - 堆垛机入出库作业下发 : 入库执行完毕");
    }
    /**
     * 出库  ===>>  库位到堆垛机站
     * 2022-06-09 TQS修改,查询工作档LIST,遍历下发,防止第一个任务堵塞出库
     */
    public void locToCrnStn(CrnSlave slave, CrnProtocol crnProtocol){
    public synchronized void locToCrnStn(CrnSlave slave, CrnProtocol crnProtocol,Integer mark) {
        News.warnNoLog(""+mark+" - 2"+" - 0"+" - 堆垛机入出库作业下发:执行出库");
        for (CrnSlave.CrnStn crnStn : slave.getCrnOutStn()) {
            // 获取工作状态为11(生成出库ID)的出库工作档
//            WrkMast wrkMast = wrkMastMapper.selectPakOutStep1(slave.getId(), crnStn.getStaNo());
            List<WrkMast> wrkMasts = wrkMastMapper.selectPakOutStep11(slave.getId(), crnStn.getStaNo());
            for (WrkMast wrkMast : wrkMasts){
            for (WrkMast wrkMast : wrkMasts) {
                if (wrkMast == null) {
                    continue;
                }
                // 工作档状态判断
                if (wrkMast.getIoType() < 100 || wrkMast.getSourceStaNo() == null){
                    log.error("查询工作档数据不符合条件--入出类型/站点, 工作号={},源库位={},入出类型={}", wrkMast.getWrkNo(), wrkMast.getSourceLocNo(), wrkMast.getIoType());
                if (wrkMast.getIoType() < 100 || wrkMast.getSourceStaNo() == null) {
                    News.error(""+mark+" - 2"+" - 1"+" - 查询工作档数据不符合条件--入出类型/站点, 工作号={},源库位={},入出类型={}", wrkMast.getWrkNo(), wrkMast.getSourceLocNo(), wrkMast.getIoType());
                    continue;
                }
                // 获取源库位信息
                LocMast sourceSta = locMastService.selectById(wrkMast.getSourceLocNo());
                if (!sourceSta.getLocSts().equals("R") &&!sourceSta.getLocSts().equals("P")) {
                    log.error("出库操作库位状态不符合--状态, 库位号={},库位状态={}", wrkMast.getLocNo(), sourceSta.getLocSts());
                if (!sourceSta.getLocSts().equals("R") && !sourceSta.getLocSts().equals("P")) {
                    News.error(""+mark+" - 2"+" - 2"+" - 出库操作库位状态不符合--状态, 库位号={},库位状态={}", wrkMast.getLocNo(), sourceSta.getLocSts());
                    continue;
                }
                // 获取堆垛机出库站信息
                SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, crnStn.getDevpPlcId());
                StaProtocol staProtocol = devpThread.getStation().get(crnStn.getStaNo());
                if (staProtocol == null) {
                    News.infoNoLog(""+mark+" - 2"+" - 3"+" - 堆垛机出库站信息(staProtocol!=null继续执行,否则循环终止):staProtocol="+staProtocol);
                    break;
//                    continue;
                } else {
@@ -778,19 +839,20 @@
//            // 入出库模式判断
//            if (devpThread.ioMode != IoModeType.PAKOUT_MODE) { continue; }
                if (wrkMast.getStaNo() == 204 && devpThread.ioModeOf2F != IoModeType.PAKOUT_MODE) {
                    continue;
                }
//                if (wrkMast.getStaNo() == 204 && devpThread.ioModeOf2F != IoModeType.PAKOUT_MODE) {
//                    News.infoNoLog(""+mark+" - 2"+" - 4"+" - 入出库模式(此处出库方法,出库模式继续=="+devpThread.ioModeOf2F);
//                    continue;
//                }
                // 查询站点详细信息
                BasDevp staDetl = basDevpService.selectById(crnStn.getStaNo());
                if (staDetl == null) {
                    log.error("出库 ===>> 堆垛机站点在数据库不存在, 站点编号={}", crnStn.getStaNo());
                    News.error(""+mark+" - 2"+" - 5"+" - 出库 ===>> 堆垛机站点在数据库不存在, 站点编号={}", crnStn.getStaNo());
                    break;
//                    continue;
                }
                // 判断堆垛机出库站状态
                if (staProtocol.isAutoing() && !staProtocol.isLoading() && staDetl.getCanouting() !=null && staDetl.getCanouting().equals("Y")
                if (staProtocol.isAutoing() && !staProtocol.isLoading() && staDetl.getCanouting() != null && staDetl.getCanouting().equals("Y")
                        && staProtocol.getWorkNo() == 0 && staProtocol.isOutEnable()) {
                    // 命令下发区 --------------------------------------------------------------------------
@@ -802,19 +864,21 @@
                    // 双深库位且浅库位有货,则需先对浅库位进行库位移转
                    if (Utils.isDeepLoc(slaveProperties, wrkMast.getSourceLocNo())) {
                        News.warnNoLog(""+mark+" - 2"+" - 6"+" - 双深库位且浅库位有货,则需先对浅库位进行库位移转 : 开始执行 任务号={}",wrkMast.getWrkNo());
                        String shallowLocNo = Utils.getShallowLoc(slaveProperties, wrkMast.getSourceLocNo());
                        LocMast shallowLoc = locMastService.selectById(shallowLocNo);
                        // O.空库位、Q.拣料/盘点/并板再入库、S.入库预约、X.禁用 直接搬!
                        if (shallowLoc.getLocSts().equals("P") || shallowLoc.getLocSts().equals("R")) {
                            News.warnNoLog(""+mark+" - 2"+" - 7"+" - // O.空库位、Q.拣料/盘点/并板再入库、S.入库预约、X.禁用 直接搬!库位状态={}",shallowLoc.getLocSts());
                            WrkMast waitWrkMast = wrkMastMapper.selectByLocNo(shallowLocNo);
                            if (null == waitWrkMast) {
                                log.error("{}库位异常,未检索到相应工作档!", shallowLocNo);
                                News.error("{}库位异常,未检索到相应工作档!", shallowLocNo);
                            } else {
                                if(waitWrkMast.getWrkSts() == 11) {
                                if (waitWrkMast.getWrkSts() == 11) {
                                    waitWrkMast.setIoPri(15D);
                                    waitWrkMast.setModiTime(new Date());
                                    if (wrkMastMapper.updateById(waitWrkMast) == 0) {
                                        log.error("调整工作档优先级失败!工作号={}", waitWrkMast.getWrkNo());
                                        News.error(""+mark+" - 2"+" - 8"+" - 调整工作档优先级失败!工作号={}", waitWrkMast.getWrkNo());
                                    }
                                    continue;
                                } else {
@@ -822,6 +886,7 @@
                                }
                            }
                        } else if (shallowLoc.getLocSts().equals("F") || shallowLoc.getLocSts().equals("D")) {
                            News.warnNoLog(""+mark+" - 2"+" - 9"+" - // F、D  库位状态={}",shallowLoc.getLocSts());
//                            WrkMast waitWrkMast = wrkMastMapper.selectByLocNo(shallowLocNo);
                            //2022-08-16 modify,不根据updmk标记移库任务(容易被取消导致堵塞),查询工作档是否存在任务
                            WrkMast waitWrkMast = wrkMastMapper.selectByLocNo1(shallowLocNo);
@@ -832,13 +897,15 @@
                                wrkMast.setUpdMk("Y");
                                wrkMastMapper.updateById(wrkMast);
                                // 生成工作档,将浅库位移转到新的库位中
                                moveLocForDeepLoc(slave, shallowLoc);
                                moveLocForDeepLoc(slave, shallowLoc,mark);
                            }
                            log.error("{}任务出库失败,浅库位堵塞!浅库位号:{}", wrkMast.getWrkNo(),shallowLocNo);
                            News.error("{}任务出库失败,浅库位堵塞!浅库位号:{}", wrkMast.getWrkNo(), shallowLocNo);
                            continue;
                        } else if (shallowLoc.getLocSts().equals("Q") || shallowLoc.getLocSts().equals("S")){
                            WrkMast waitWrkMast = wrkMastMapper.selectByLocNo(shallowLocNo);
                            if (null != waitWrkMast && waitWrkMast.getWrkSts()==4) {
                        } else if (shallowLoc.getLocSts().equals("Q") || shallowLoc.getLocSts().equals("S")) {
                            News.warnNoLog(""+mark+" - 2"+" - 10"+" - // Q、S  库位状态={}",shallowLoc.getLocSts());
                            WrkMast waitWrkMast = wrkMastMapper.selectByLocNo1(shallowLocNo);
                            if (null != waitWrkMast && waitWrkMast.getWrkSts() == 4) {
                                News.infoNoLog(""+mark+" - 2"+" - 11"+" - // F、D  工作状态(判断条件为==4)={}",waitWrkMast.getWrkSts());
                                continue;
                            }
                        }
@@ -850,11 +917,15 @@
//                        return;
                    }
                    News.warnNoLog(""+mark+" - 2"+" - 12"+" - 命令下发 : 工作号={},源排={},源列={},源层={},目标排={},目标列={},目标层={}",wrkMast.getWrkNo().shortValue()
                            ,sourceSta.getRow1().shortValue(),sourceSta.getBay1().shortValue(),sourceSta.getLev1().shortValue()
                            ,crnStn.getRow().shortValue(),crnStn.getBay().shortValue(),crnStn.getLev().shortValue());
                    // 1.堆垛机开始移动
                    CrnCommand crnCommand = new CrnCommand();
                    crnCommand.setCrnNo(slave.getId()); // 堆垛机编号
                    crnCommand.setTaskNo(wrkMast.getWrkNo().shortValue()); // 工作号
                    crnCommand.setAckFinish((short) 0);  // 任务完成确认位
//                    crnCommand.setAckFinish((short) 0);  // 任务完成确认位
                    crnCommand.setTaskMode(CrnTaskModeType.LOC_MOVE); // 任务模式:  库位移转
                    crnCommand.setSourcePosX(sourceSta.getRow1().shortValue());     // 源库位排
                    crnCommand.setSourcePosY(sourceSta.getBay1().shortValue());     // 源库位列
@@ -862,8 +933,9 @@
                    crnCommand.setDestinationPosX(crnStn.getRow().shortValue());     // 目标库位排
                    crnCommand.setDestinationPosY(crnStn.getBay().shortValue());     // 目标库位列
                    crnCommand.setDestinationPosZ(crnStn.getLev().shortValue());     // 目标库位层
                    crnCommand.setTraySize(sourceSta.getLocType1() == 2);     //库位类型
                    if (!MessageQueue.offer(SlaveType.Crn, wrkMast.getCrnNo(), new Task(2, crnCommand))) {
                        log.error("堆垛机命令下发失败,堆垛机号={},任务数据={}", wrkMast.getCrnNo(), JSON.toJSON(crnCommand));
                        News.error(""+mark+" - 2"+" - 13"+" - 堆垛机命令下发失败,堆垛机号={},任务数据={}", wrkMast.getCrnNo(), JSON.toJSON(crnCommand));
                    } else {
                        // 修改工作档状态 11.生成出库ID => 12.吊车出库中
                        Date now = new Date();
@@ -871,13 +943,14 @@
                        wrkMast.setCrnStrTime(now);
                        wrkMast.setModiTime(now);
                        if (wrkMastMapper.updateById(wrkMast) == 0) {
                            log.error("修改工作档状态 11.生成出库ID => 12.吊车出库中 失败!!,工作号={}", wrkMast.getWrkNo());
                            News.error(""+mark+" - 2"+" - 14"+" - 修改工作档状态 11.生成出库ID => 12.吊车出库中 失败!!,工作号={}", wrkMast.getWrkNo());
                        }
                        break;
                    }
                }
            }
        }
        News.infoNoLog(""+mark+" - 2"+" - 0"+" - 堆垛机入出库作业下发 : 出库执行完毕");
    }
//    /**
@@ -1000,16 +1073,17 @@
    /**
     * 库位移转
     */
    public void locToLoc(CrnSlave slave, CrnProtocol crnProtocol){
    public synchronized void locToLoc(CrnSlave slave, CrnProtocol crnProtocol,Integer mark) {
        // 获取工作档信息
        WrkMast wrkMast = wrkMastMapper.selectLocMove(slave.getId());
        if (null == wrkMast) {
            return;
        }
        News.warnNoLog(""+mark+" - 3"+" - 0"+" - 堆垛机入出库作业下发:执行库位移转");
        // 获取源库位信息
        LocMast sourceSta = locMastService.selectById(wrkMast.getSourceLocNo());
        if (null == sourceSta) {
            log.error("工作档库位移转失败,原因:检索源库位失败!工作号={},源库位={}", wrkMast.getWrkNo(), wrkMast.getSourceLocNo());
            News.error(""+mark+" - 3"+" - 1"+" - 工作档库位移转失败,原因:检索源库位失败!工作号={},源库位={}", wrkMast.getWrkNo(), wrkMast.getSourceLocNo());
            return;
        }
        // 源库位  库位状态判断
@@ -1019,7 +1093,11 @@
        // 获取目标库位信息
        LocMast sta = locMastService.selectById(wrkMast.getLocNo());
        if (null == sta) {
            log.error("工作档库位移转失败,原因:检索目标库位失败!工作号={},源库位={}", wrkMast.getWrkNo(), wrkMast.getLocNo());
            News.error(""+mark+" - 3"+" - 2"+" - 工作档库位移转失败,原因:检索目标库位失败!工作号={},源库位={}", wrkMast.getWrkNo(), wrkMast.getLocNo());
            return;
        }
        if(sta.getLocType1() != sourceSta.getLocType1()){
            News.error("移库目标库位类型与源库位类型不符");
            return;
        }
        // 获取堆垛机信息 并 判断是否可入出
@@ -1038,6 +1116,10 @@
            return;
        }
        News.warnNoLog(""+mark+" - 3"+" - 3"+" - 命令下发 : 工作号={},源排={},源列={},源层={},目标排={},目标列={},目标层={}",wrkMast.getWrkNo().shortValue()
                ,sourceSta.getRow1().shortValue(),sourceSta.getBay1().shortValue(),sourceSta.getLev1().shortValue()
                ,sta.getRow1().shortValue(),sta.getBay1().shortValue(),sta.getLev1().shortValue());
        // 命令下发区 --------------------------------------------------------------------------
        CrnCommand crnCommand = new CrnCommand();
        crnCommand.setCrnNo(slave.getId()); // 堆垛机编号
@@ -1050,8 +1132,9 @@
        crnCommand.setDestinationPosX(sta.getRow1().shortValue());     // 目标库位排
        crnCommand.setDestinationPosY(sta.getBay1().shortValue());     // 目标库位列
        crnCommand.setDestinationPosZ(sta.getLev1().shortValue());     // 目标库位层
        crnCommand.setTraySize(sourceSta.getLocType1() == 2);     //库位类型
        if (!MessageQueue.offer(SlaveType.Crn, wrkMast.getCrnNo(), new Task(2, crnCommand))) {
            log.error("堆垛机命令下发失败,堆垛机号={},任务数据={}", wrkMast.getCrnNo(), JSON.toJSON(crnCommand));
            News.error(""+mark+" - 3"+" - 4"+" - 堆垛机命令下发失败,堆垛机号={},任务数据={}", wrkMast.getCrnNo(), JSON.toJSON(crnCommand));
        } else {
            // 修改工作档状态 11.生成出库ID => 12.吊车出库中
            Date now = new Date();
@@ -1059,32 +1142,36 @@
            wrkMast.setCrnStrTime(now);
            wrkMast.setModiTime(now);
            if (wrkMastMapper.updateById(wrkMast) == 0) {
                log.error("【库位移转】 修改工作档状态 11.生成出库ID => 12.吊车出库中 失败!!,工作号={}", wrkMast.getWrkNo());
                News.error(""+mark+" - 3"+" - 5"+" - 【库位移转】 修改工作档状态 11.生成出库ID => 12.吊车出库中 失败!!,工作号={}", wrkMast.getWrkNo());
            }
        }
        News.infoNoLog(""+mark+" - 3"+" - 0"+" - 堆垛机入出库作业下发:库位移转完成");
    }
    /**
     * 执行对工作档的完成操作
     */
    @Async
    public void storeFinished() {
    public synchronized void storeFinished(Integer mark) {
        for (CrnSlave crn : slaveProperties.getCrn()) {
            // 获取堆垛机信息
            CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crn.getId());
            CrnProtocol crnProtocol = crnThread.getCrnProtocol();
            if (crnProtocol == null) { continue; }
            if (crnProtocol == null) {
                continue;
            }
            //  状态:等待确认 并且  任务完成位 = 1
            if (crnProtocol.statusType == CrnStatusType.WAITING && crnProtocol.getTaskNo() != 0) {
                if(crnProtocol.getTaskNo()==9999){
                News.warnNoLog(""+mark+" - 0"+" - 开始执行对工作档的完成操作");
                if (crnProtocol.getTaskNo() == 9999) {
                    // 堆垛机复位
                    crnThread.setResetFlag(true);
                }else {
                } else {
                    // 获取入库待确认工作档
                    WrkMast wrkMast = wrkMastMapper.selectPakInStep3(crnProtocol.getTaskNo().intValue());
                    if (wrkMast == null) {
                        log.error("堆垛机处于等待确认且任务完成状态,但未找到工作档。堆垛机号={},工作号={}", crn.getId(), crnProtocol.getTaskNo());
                        News.error(""+mark+" - 1"+" - 堆垛机处于等待确认且任务完成状态,但未找到工作档。堆垛机号={},工作号={}", crn.getId(), crnProtocol.getTaskNo());
                        continue;
                    }
                    // 入库 + 库位转移  ==> 4.入库完成
@@ -1099,19 +1186,20 @@
                    // 修改成功后复位堆垛机
                    if (wrkMastMapper.updateById(wrkMast) > 0) {
                        // 堆垛机复位
                        News.warnNoLog(""+mark+" - 2"+" - 修改成功后复位堆垛机 : 堆垛机号={}",crnThread.getCrnProtocol().getCrnNo());
                        crnThread.setResetFlag(true);
                    }
                }
            }
        }
//        News.infoNoLog(""+mark+" - 0"+" - 对工作档的完成操作执行完成");
    }
    /**
     * 堆垛机异常信息记录
     */
    @Async
    public void recCrnErr(){
    public synchronized void recCrnErr(Integer mark) {
        Date now = new Date();
        for (CrnSlave crn : slaveProperties.getCrn()) {
            // 获取堆垛机信息
@@ -1124,16 +1212,18 @@
//            if (crnProtocol.getModeType() != CrnModeType.STOP) {
                // 有任务
                if (crnProtocol.getTaskNo() != 0) {
                    BasErrLog latest = basErrLogService.findLatestByTaskNo(crn.getId(), crnProtocol.getTaskNo().intValue());
                    // 有异常
                    if (latest == null) {
                        News.warnNoLog(""+mark+" - 1"+" - 开始执行:堆垛机异常信息记录 : 有任务,有异常");
                        if (crnProtocol.getAlarm() != null && crnProtocol.getAlarm() > 0) {
                            WrkMast wrkMast = wrkMastMapper.selectById(crnProtocol.getTaskNo());
                            if (wrkMast == null) {
                                continue;
                            }
                            BasCrnError crnError = basCrnErrorMapper.selectById(crnProtocol.getAlarm());
                            String errName = crnError==null? String.valueOf(crnProtocol.getAlarm()):crnError.getErrName();
                            String errName = crnError == null ? String.valueOf(crnProtocol.getAlarm()) : crnError.getErrName();
                            BasErrLog basErrLog = new BasErrLog(
                                    null,    // 编号
                                    wrkMast.getWrkNo(),    // 工作号
@@ -1158,7 +1248,7 @@
                                    "任务中异常"    // 备注
                            );
                            if (!basErrLogService.insert(basErrLog)) {
                                log.error("堆垛机plc异常记录失败 ===>> [id:{}] [error:{}]", crn.getId(), errName);
                                News.error(""+mark+" - 2"+" - 堆垛机plc异常记录失败 ===>> [id:{}] [error:{}]", crn.getId(), errName);
                            }
                        }
                    } else {
@@ -1168,19 +1258,20 @@
                            latest.setUpdateTime(now);
                            latest.setStatus(2);
                            if (!basErrLogService.updateById(latest)) {
                                log.error("堆垛机plc异常记录修复失败 ===>> [id:{}] [errLogId:{}]", crn.getId(), latest.getId());
                                News.error(""+mark+" - 3"+" - 堆垛机plc异常记录修复失败 ===>> [id:{}] [errLogId:{}]", crn.getId(), latest.getId());
                            }
                        }
                    }
                // 无任务
                    // 无任务
                } else {
                    BasErrLog latest = basErrLogService.findLatest(crn.getId());
                    // 有异常
                    if (crnProtocol.getAlarm() != null && crnProtocol.getAlarm() > 0) {
                        News.warnNoLog(""+mark+" - 4"+" - 开始执行:堆垛机异常信息记录 : 无任务,有异常");
                        // 记录新异常
                        if (latest == null || (latest.getErrCode() != crnProtocol.getAlarm().intValue())) {
                            BasCrnError crnError = basCrnErrorMapper.selectById(crnProtocol.getAlarm());
                            String errName = crnError==null? String.valueOf(crnProtocol.getAlarm()):crnError.getErrName();
                            String errName = crnError == null ? String.valueOf(crnProtocol.getAlarm()) : crnError.getErrName();
                            BasErrLog basErrLog = new BasErrLog(
                                    null,    // 编号
                                    null,    // 工作号
@@ -1195,7 +1286,7 @@
                                    null,    // 源站
                                    null,    // 源库位
                                    null,    // 条码
                                    (int)crnProtocol.getAlarm(),    // 异常码
                                    (int) crnProtocol.getAlarm(),    // 异常码
                                    errName,    // 异常
                                    1,    // 异常情况
                                    now,    // 添加时间
@@ -1205,10 +1296,10 @@
                                    "无任务异常"    // 备注
                            );
                            if (!basErrLogService.insert(basErrLog)) {
                                log.error("堆垛机plc异常记录失败 ===>> [id:{}] [error:{}]", crn.getId(), errName);
                                News.error(""+mark+" - 5"+" - 堆垛机plc异常记录失败 ===>> [id:{}] [error:{}]", crn.getId(), errName);
                            }
                        }
                    // 无异常
                        // 无异常
                    } else {
                        // 异常修复
                        if (latest != null && latest.getStatus() == 1) {
@@ -1216,7 +1307,7 @@
                            latest.setUpdateTime(now);
                            latest.setStatus(2);
                            if (!basErrLogService.updateById(latest)) {
                                log.error("堆垛机plc异常记录修复失败 ===>> [id:{}] [errLogId:{}]", crn.getId(), latest.getId());
                                News.error(""+mark+" - 6"+" - 堆垛机plc异常记录修复失败 ===>> [id:{}] [errLogId:{}]", crn.getId(), latest.getId());
                            }
                        }
                    }
@@ -1224,6 +1315,7 @@
            }
        }
//        News.infoNoLog(""+mark+" - 0"+" - 堆垛机异常信息记录执行完成");
    }
@@ -1232,8 +1324,8 @@
    /**
     * 空栈板初始化入库,叉车入库站放货
     */
    @Async
    public void storeEmptyPlt(){
    public synchronized void storeEmptyPlt(Integer mark) {
        for (DevpSlave devp : slaveProperties.getDevp()) {
            // 遍历空板入库口
            for (DevpSlave.Sta emptyInSta : devp.getEmptyInSta()) {
@@ -1246,13 +1338,23 @@
                    staProtocol = staProtocol.clone();
                }
//                // 入出库模式判断
//                if ( emptyInSta.getStaNo()==203 && devpThread.ioModeOf2F != IoModeType.PAKIN_MODE) { continue; }
                if ( emptyInSta.getStaNo()==203 && devpThread.ioModeOf2F == IoModeType.PAKOUT_MODE) { continue; }
                LedThread ledThread = null;
                if (!Cools.isEmpty(emptyInSta.getLed()))  {
                    ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, emptyInSta.getLed());
                }
                if (!staProtocol.isLoading()){
                    continue;
                }
                // 站点条件判断
                if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.isInEnable()
                        && staProtocol.isEmptyMk() && (staProtocol.getWorkNo() > 9990 && staProtocol.getWorkNo() <= 9999) && staProtocol.isPakMk()) {
                if (staProtocol.isAutoing()
                        && staProtocol.isLoading()
                        && staProtocol.isInEnable()
                        && staProtocol.isEmptyMk()
                        && staProtocol.isPakMk()
                        ) {
                    News.warnNoLog(""+mark+" - 0"+" - 开始执行:空栈板初始化入库,叉车入库站放货");
                    try {
                        LocTypeDto locTypeDto = new LocTypeDto(staProtocol);
@@ -1272,89 +1374,67 @@
                            StartupDto dto = jsonObject.getObject("data", StartupDto.class);
                            // 更新站点信息 且 下发plc命令
                            staProtocol.setWorkNo(dto.getWorkNo().shortValue());
                            staProtocol.setStaNo(dto.getStaNo().shortValue());
                            staProtocol.setWorkNo(dto.getWorkNo());
                            staProtocol.setStaNo(staProtocol.getSiteId().shortValue());
                            devpThread.setPakMk(staProtocol.getSiteId(), false);
                            boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                            if (!result) {
                                News.errorNoLog(""+mark+" - 1"+" - 更新plc站点信息失败");
                                throw new CoolException("更新plc站点信息失败");
                            }
                            if (ledThread != null) {
                                // 命令集合
                                List<LedCommand> commands = new ArrayList<>();
                                // 组装命令
                                LedCommand ledCommand = new LedCommand();
                                ledCommand.setWorkNo(dto.getWorkNo());
                                ledCommand.setIoType(1);
                                ledCommand.setTitle("全板入库");
                                ledCommand.setLocNo(dto.getLocNo());
                                ledCommand.setStaNo(dto.getStaNo());
                                commands.add(ledCommand);
                                MessageQueue.offer(SlaveType.Led, emptyInSta.getLed(), new Task(3, commands));
//                                ledThread.errorReset();
                            }
                        } else {
                            log.error("请求接口失败!!!url:{};request:{};response:{}", wmsUrl+"/rpc/pakin/loc/v1", JSON.toJSONString(param), response);
//                            staProtocol.setWorkNo(wrkNo++);
//                            staProtocol.setStaNo(emptyInSta.getBackSta().shortValue());
//                            devpThread.setPakMk(staProtocol.getSiteId(), false);
//                            boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                            if (!result) {
//                                News.errorNoLog(""+mark+" - 2"+" - 更新plc站点信息失败");
//                                throw new CoolException("更新plc站点信息失败");
//                            }
//
//                            if (ledThread != null) {
//                                String errorMsg = jsonObject.getString("msg");
//                                if (!Cools.isEmpty(errorMsg)) {
//                                    MessageQueue.offer(SlaveType.Led, emptyInSta.getLed(), new Task(5, errorMsg));
//                                }
//                            }
//                            News.error(""+mark+" - 3"+" - 请求接口失败!!!url:{};request:{};response:{}", wmsUrl + "/rpc/pakin/loc/v1", JSON.toJSONString(param), response);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    }
//                    // 检索库位
//                    LocTypeDto locTypeDto = new LocTypeDto(staProtocol);
//                    StartupDto startupDto = commonService.getLocNo(1, 10, emptyInSta.getStaNo(), null, locTypeDto, 0);
//                    // 工作号
//                    int workNo = startupDto.getWorkNo();
//
//                    try {
//                        // 插入工作主档
//                        WrkMast wrkMast = new WrkMast();
//                        wrkMast.setWrkNo(workNo);
//                        wrkMast.setIoTime(new Date());
//                        wrkMast.setWrkSts(2L); // 工作状态:2.设备上走
//                        wrkMast.setIoType(10); // 入出库状态:10.空板入库
//                        wrkMast.setIoPri(10D); // 优先级:10
//                        wrkMast.setCrnNo(startupDto.getCrnNo());
//                        wrkMast.setSourceStaNo(startupDto.getSourceStaNo());
//                        wrkMast.setStaNo(startupDto.getStaNo());
//                        wrkMast.setLocNo(startupDto.getLocNo());
//                        wrkMast.setFullPlt("N"); // 满板
//                        wrkMast.setPicking("N"); // 拣料
//                        wrkMast.setExitMk("N"); // 退出
//                        wrkMast.setEmptyMk("Y"); // 空板
//                        wrkMast.setLinkMis("N");
////                    wrkMast.setCtnType(sourceStaNo.getCtnType()); // 容器类型
//                        // 操作人员数据
//                        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("改变库位状态失败");
//                        }
//                        // 命令下发区 --------------------------------------------------------------------------
//
//                        // 更新站点信息 且 下发plc命令
//                        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();
//                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//                    }
                } else {
                    News.errorNoLog(""+mark+" - 4"+" - 站点信息不符合入库条件!!!"+" 自动信号:"+staProtocol.isAutoing()+"、可入信号:" + staProtocol.isInEnable()
                            +"、空板信号:"+ staProtocol.isEmptyMk()+"、工作号:" + staProtocol.getWorkNo()
                            +"、锁定标记"+ staProtocol.isPakMk());
                }
            }
        }
//        News.infoNoLog(""+mark+" - 0"+" - 空栈板初始化入库,叉车入库站放货执行完成");
    }
    /**
     * 出库  ===>> 工作档信息写入led显示器
     */
    @Async
    public void ledExecute() {
    public synchronized void ledExecute(Integer mark) {
        for (LedSlave led : slaveProperties.getLed()) {
            // 获取输送线plc线程
            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, led.getDevpPlcId());
@@ -1373,7 +1453,10 @@
                // 获取工作档数据
                WrkMast wrkMast = wrkMastMapper.selectById(staProtocol.getWorkNo());
//                if (null == wrkMast || wrkMast.getWrkSts() < 14 || wrkMast.getIoType() < 100) { continue; }
                if (null == wrkMast) { continue; }
                if (null == wrkMast) {
                    continue;
                }
                News.warnNoLog(""+mark+" - 0"+" - 开始执行:出库  ===>> 工作档信息写入led显示器");
                wrkMasts.add(wrkMast);
                // 组装命令
                LedCommand ledCommand = new LedCommand();
@@ -1404,16 +1487,16 @@
                        ledCommand.setEmptyMk(true);
                        break;
                    default:
                        log.error("任务入出库类型错误!!![工作号:{}] [入出库类型:{}]", wrkMast.getWrkNo(), wrkMast.getIoType());
                        News.error(""+mark+" - 1"+" - 任务入出库类型错误!!![工作号:{}] [入出库类型:{}]", wrkMast.getWrkNo(), wrkMast.getIoType());
                        break;
                }
                ledCommand.setSourceLocNo(wrkMast.getSourceLocNo());
                ledCommand.setLocNo(wrkMast.getLocNo());
                ledCommand.setStaNo(wrkMast.getStaNo());
//                ledCommand.setSourceStaNo(wrkMast.getSourceStaNo());
                if (wrkMast.getIoType() != 110 && wrkMast.getIoType() != 10 ) {
                if (wrkMast.getIoType() != 110 && wrkMast.getIoType() != 10) {
                    List<WrkDetl> wrkDetls = wrkDetlService.findByWorkNo(wrkMast.getWrkNo());
                    wrkDetls.forEach(wrkDetl -> ledCommand.getMatDtos().add(new MatDto(wrkDetl.getMatnr(), wrkDetl.getMaktx(), wrkDetl.getAnfme())));
                    wrkDetls.forEach(wrkDetl -> ledCommand.getMatDtos().add(new MatDto(wrkDetl.getMatnr(), wrkDetl.getMaktx(), wrkDetl.getAnfme(),wrkDetl.getSpecs())));
                }
                commands.add(ledCommand);
            }
@@ -1424,12 +1507,31 @@
            if (CollectionUtils.equals(ledThread.getWorkNos(), workNos)) {
                continue;
            }
//             命令下发 -------------------------------------------------------------------------------
//            if (!commands.isEmpty()) {
//                if (led.getId() < 7) {
//                    if (!MessageQueue.offer(SlaveType.Led, led.getId(), new Task(3, commands))) {
//                        News.error(""+mark+" - 2"+" - {}号LED命令下发失败!!![ip:{}] [port:{}]", led.getId(), led.getIp(), led.getPort());
//                        continue;
//                    } else {
//                        ledThread.setLedMk(false);
//                    }
//                } else {
//                    if (!MessageQueue.offer(SlaveType.Led, led.getId(), new Task(1, commands))) {
//                        News.error(""+mark+" - 3"+" - {}号LED命令下发失败!!![ip:{}] [port:{}]", led.getId(), led.getIp(), led.getPort());
//                        continue;
//                    } else {
//                        ledThread.setLedMk(false);
//                    }
//                }
//
//            }
            // 命令下发 -------------------------------------------------------------------------------
            if (!commands.isEmpty()) {
                if (!MessageQueue.offer(SlaveType.Led, led.getId(), new Task(1, commands))) {
                    log.error("{}号LED命令下发失败!!![ip:{}] [port:{}]", led.getId(), led.getIp(), led.getPort());
                if (!MessageQueue.offer(SlaveType.Led, led.getId(), new Task(3, commands))) {
                    News.error("{}号LED命令下发失败!!![ip:{}] [port:{}]", led.getId(), led.getIp(), led.getPort());
                    continue;
                } else {
                }else {
                    ledThread.setLedMk(false);
                }
            }
@@ -1440,6 +1542,7 @@
                    wrkMast.setOveMk("Y");
                    wrkMast.setModiTime(new Date());
                    if (wrkMastMapper.updateById(wrkMast) == 0) {
                        News.errorNoLog(""+mark+" - 4"+" - 更新工作档失败");
                        throw new CoolException("更新工作档失败");
                    }
                }
@@ -1453,41 +1556,17 @@
            }
        }
//        News.infoNoLog(""+mark+" - 0"+" - 出库  ===>> 工作档信息写入led显示器执行完成");
    }
    /**
     * 其他  ===>> 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(Integer mark) {
//        News.warnNoLog(""+mark+" - 0"+" - 开始执行:其他  ===>> LED显示器复位,显示默认信息");
        for (LedSlave led : slaveProperties.getLed()) {
            // 获取输送线plc线程
            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, led.getDevpPlcId());
            // 命令集合
@@ -1508,13 +1587,14 @@
            // led显示默认内容
            if (reset && !ledThread.isLedMk()) {
                ledThread.setLedMk(true);
                if (!MessageQueue.offer(SlaveType.Led, led.getId(), new Task(2, new ArrayList<>()))) {
                    log.error("{}号LED命令下发失败!!![ip:{}] [port:{}]", led.getId(), led.getIp(), led.getPort());
                if (!MessageQueue.offer(SlaveType.Led, led.getId(), new Task(4, new ArrayList<>()))) {
                    News.error(""+mark+" - 1"+" - {}号LED命令下发失败!!![ip:{}] [port:{}]", led.getId(), led.getIp(), led.getPort());
                } else {
                }
            }
        }
//        News.infoNoLog(""+mark+" - 0"+" - 执行完成:其他  ===>> LED显示器复位,显示默认信息");
    }
    /**
@@ -1522,7 +1602,7 @@
     * tip:同步
     */
    @Transactional
    public synchronized void moveLocForDeepLocPakin(CrnSlave crn, LocMast shallowLoc, WrkMast pakinWrkMast){
    public synchronized void moveLocForDeepLocPakin(CrnSlave crn, LocMast shallowLoc, WrkMast pakinWrkMast) {
        LocMast loc = locMastService.selectById(pakinWrkMast.getLocNo());
        // 获取工作号
@@ -1541,7 +1621,7 @@
        wrkMast.setFullPlt(shallowLoc.getFullPlt()); // 满板
        wrkMast.setPicking("N"); // 拣料
        wrkMast.setExitMk("N"); // 退出
        wrkMast.setEmptyMk(shallowLoc.getLocSts().equals("D")?"Y":"N"); // 空板
        wrkMast.setEmptyMk(shallowLoc.getLocSts().equals("D") ? "Y" : "N"); // 空板
        wrkMast.setBarcode(shallowLoc.getBarcode()); // 托盘码
        wrkMast.setLinkMis("N");
        wrkMast.setCtnNo("Y");  // 入库阻塞库位移转标记
@@ -1571,7 +1651,7 @@
        if (shallowLoc.getLocSts().equals("D") || shallowLoc.getLocSts().equals("F")) {
            shallowLoc.setLocSts("S"); // S.入库预约,入库阻塞库位移转
            shallowLoc.setModiTime(now);
            if (!locMastService.updateById(shallowLoc)){
            if (!locMastService.updateById(shallowLoc)) {
                throw new CoolException("更新源库位状态失败");
            }
        } else {
@@ -1597,8 +1677,10 @@
     * 因双深库位阻塞,对浅库位进行移转(立即执行版)
     * tip:同步
     */
    private void moveLocForDeepLoc(CrnSlave crn, LocMast shallowLoc){
    private synchronized void moveLocForDeepLoc(CrnSlave crn, LocMast shallowLoc,Integer mark) {
        try {
            News.warnNoLog(""+mark+"moveLocForDeepLoc"+" - 0"+" - 开始执行:因双深库位阻塞,对浅库位进行移转(立即执行版)");
            List<Integer> rows = locMastService.queryDistinctRow(crn.getId());
            LocMast loc = null;
            for (Integer row : rows) {
@@ -1640,7 +1722,7 @@
            }
            if (null == loc) {
                log.error("双深库位 --- 浅库位阻塞异常! 待移转浅库位:" + shallowLoc.getLocNo());
                News.error(""+mark+"moveLocForDeepLoc"+" - 1"+" - 双深库位 --- 浅库位阻塞异常! 待移转浅库位:" + shallowLoc.getLocNo());
                throw new CoolException("双深库位 --- 浅库位阻塞异常! 待移转浅库位:" + shallowLoc.getLocNo());
            }
@@ -1666,6 +1748,7 @@
            wrkMast.setModiTime(new Date());
            int res = wrkMastMapper.insert(wrkMast);
            if (res == 0) {
                News.errorNoLog(""+mark+"moveLocForDeepLoc"+" - 2"+" - 保存工作档失败");
                throw new CoolException("保存工作档失败");
            }
            // 工作档明细保存
@@ -1680,6 +1763,7 @@
                    wrkDetl.setAppeTime(new Date());
                    wrkDetl.setModiTime(new Date());
                    if (!wrkDetlService.insert(wrkDetl)) {
                        News.errorNoLog(""+mark+"moveLocForDeepLoc"+" - 3"+" - 保存工作档明细失败");
                        throw new CoolException("保存工作档明细失败");
                    }
                }
@@ -1689,9 +1773,11 @@
                shallowLoc.setLocSts("R"); // R.出库预约
                shallowLoc.setModiTime(new Date());
                if (!locMastService.updateById(shallowLoc)) {
                    News.errorNoLog(""+mark+"moveLocForDeepLoc"+" - 4"+" - 更新源库位状态失败");
                    throw new CoolException("更新源库位状态失败");
                }
            } else {
                News.errorNoLog(""+mark+"moveLocForDeepLoc"+" - 5"+" - 源库位出库失败");
                throw new CoolException("源库位出库失败");
            }
            // 修改目标库位状态
@@ -1699,13 +1785,15 @@
                loc.setLocSts("S"); // S.入库预约
                loc.setModiTime(new Date());
                if (!locMastService.updateById(loc)) {
                    News.errorNoLog(""+mark+"moveLocForDeepLoc"+" - 6"+" - 更新目标库位状态失败");
                    throw new CoolException("更新目标库位状态失败");
                }
            } else {
                News.errorNoLog(""+mark+"moveLocForDeepLoc"+" - 7"+" - 移转失败");
                throw new CoolException("移转失败");
            }
        } catch (Exception e) {
            log.error("双深库位阻塞,对浅库位进行移转失败", e);
            News.error(""+mark+"moveLocForDeepLoc"+" - 8"+" - 双深库位阻塞,对浅库位进行移转失败", e);
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
@@ -1714,7 +1802,7 @@
    /**
     * 堆垛机演示  ===>> 库位移转
     */
    public synchronized void crnDemoOfLocMove1(){
    public synchronized void crnDemoOfLocMove1() {
        try {
            for (CrnSlave crn : slaveProperties.getCrn()) {
                if (!crn.getDemo()) {
@@ -1806,7 +1894,7 @@
                }
            }
        } catch (Exception e) {
            log.error("堆垛机演示  ===>> 库位移转失败", e);
            News.error("堆垛机演示  ===>> 库位移转失败", e);
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
@@ -1815,7 +1903,7 @@
    /**
     * 堆垛机命令下发后,异步修改工作档状态
     */
    public synchronized void crnIoWrkMast(){
    public synchronized void crnIoWrkMast() {
        for (CrnSlave crn : slaveProperties.getCrn()) {
            // 获取堆垛机信息
            CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crn.getId());
@@ -1828,30 +1916,32 @@
            if (crnProtocol.getStatusType() != CrnStatusType.IDLE && crnProtocol.getTaskNo() != 0 && crnProtocol.getModeType() == CrnModeType.AUTO) {
                // 获取工作档
                WrkMast wrkMast = wrkMastMapper.selectById(crnProtocol.getTaskNo());
                if (wrkMast == null) { continue; }
                if (wrkMast == null) {
                    continue;
                }
                // 入库
                if (wrkMast.getWrkSts() == 1 || wrkMast.getWrkSts() == 2) {
                    log.warn("堆垛机非空闲情况下,开始修改工作档状态。[id:{},时间:{}] >>>>> 堆垛机当前状态为:{}。任务号:{}", crn.getId(), DateUtils.convert(now, DateUtils.yyyyMMddHHmmsssss_F), crnProtocol.getStatusType().desc, crnProtocol.getTaskNo());
                    News.warn("堆垛机非空闲情况下,开始修改工作档状态。[id:{},时间:{}] >>>>> 堆垛机当前状态为:{}。任务号:{}", crn.getId(), DateUtils.convert(now, DateUtils.yyyyMMddHHmmsssss_F), crnProtocol.getStatusType().desc, crnProtocol.getTaskNo());
                    // 修改工作档状态 2.设备上走 => 3.吊车入库中
                    wrkMast.setWrkSts(3L);
                    wrkMast.setCrnStrTime(now);
                    wrkMast.setModiTime(now);
                    if (wrkMastMapper.updateById(wrkMast) == 0) {
                        log.error("修改工作档状态 2.设备上走 => 3.吊车入库中 失败!!,工作号={}", wrkMast.getWrkNo());
                        News.error("修改工作档状态 2.设备上走 => 3.吊车入库中 失败!!,工作号={}", wrkMast.getWrkNo());
                    }
                    log.warn("修改工作档状态成功。[时间:{}] >>>>> 任务号:{}",  DateUtils.convert(now, DateUtils.yyyyMMddHHmmsssss_F),  wrkMast.getWrkNo());
                    News.warn("修改工作档状态成功。[时间:{}] >>>>> 任务号:{}", DateUtils.convert(now, DateUtils.yyyyMMddHHmmsssss_F), wrkMast.getWrkNo());
                }
                // 出库、移库
                if (wrkMast.getWrkSts() == 11) {
                    log.warn("堆垛机非空闲情况下,开始修改工作档状态。[id:{},时间:{}] >>>>> 堆垛机当前状态为:{}。任务号:{}", crn.getId(), DateUtils.convert(now, DateUtils.yyyyMMddHHmmsssss_F), crnProtocol.getStatusType().desc, crnProtocol.getTaskNo());
                    News.warn("堆垛机非空闲情况下,开始修改工作档状态。[id:{},时间:{}] >>>>> 堆垛机当前状态为:{}。任务号:{}", crn.getId(), DateUtils.convert(now, DateUtils.yyyyMMddHHmmsssss_F), crnProtocol.getStatusType().desc, crnProtocol.getTaskNo());
                    // 修改工作档状态 11.生成出库ID => 12.吊车出库中
                    wrkMast.setWrkSts(12L);
                    wrkMast.setCrnStrTime(now);
                    wrkMast.setModiTime(now);
                    if (wrkMastMapper.updateById(wrkMast) == 0) {
                        log.error("修改工作档状态 11.生成出库ID => 12.吊车出库中 失败!!,工作号={}", wrkMast.getWrkNo());
                        News.error("修改工作档状态 11.生成出库ID => 12.吊车出库中 失败!!,工作号={}", wrkMast.getWrkNo());
                    }
                    log.warn("修改工作档状态成功。[时间:{}] >>>>> 任务号:{}",  DateUtils.convert(now, DateUtils.yyyyMMddHHmmsssss_F),  wrkMast.getWrkNo());
                    News.warn("修改工作档状态成功。[时间:{}] >>>>> 任务号:{}", DateUtils.convert(now, DateUtils.yyyyMMddHHmmsssss_F), wrkMast.getWrkNo());
                }
@@ -1863,7 +1953,7 @@
    /**
     * 入出库模式切换函数
     */
    public void ioConvert() {
    public synchronized void ioConvert() {
        try {
            // 根据输送线plc遍历
            for (DevpSlave devp : slaveProperties.getDevp()) {
@@ -1882,8 +1972,8 @@
                                    devpThread.ioModeOf2F = IoModeType.PAKOUT_BOOTING;
                                    WrkMast pakin = wrkMastMapper.selectWorkingPakin(inSta.getStaNo());
                                    if (pakin == null && !devpThread.getStation().get(inSta.getStaNo()).isLoading()
                                            && !devpThread.getStation().get(inSta.getStaNo()+1).isLoading()
                                            && devpThread.getStation().get(inSta.getStaNo()+1).getWorkNo()==0) {
                                            && !devpThread.getStation().get(inSta.getStaNo() + 1).isLoading()
                                            && devpThread.getStation().get(inSta.getStaNo() + 1).getWorkNo() == 0) {
                                        // 出库模式
                                        devpThread.ioModeOf2F = IoModeType.PAKOUT_MODE;
                                    }
@@ -1891,6 +1981,24 @@
                            } else {
                                // 入库模式
                                devpThread.ioModeOf2F = IoModeType.PAKIN_MODE;
                            }
                            break;
                        case 401://1F
                            if (pakout != null) {
                                if (devpThread.ioModeOf4F != IoModeType.PAKOUT_MODE) {
                                    // 出库切换中
                                    devpThread.ioModeOf4F = IoModeType.PAKOUT_BOOTING;
                                    WrkMast pakin = wrkMastMapper.selectWorkingPakin(inSta.getStaNo());
                                    if (pakin == null && !devpThread.getStation().get(inSta.getStaNo()).isLoading()
                                            && !devpThread.getStation().get(inSta.getStaNo() + 1).isLoading()
                                            && devpThread.getStation().get(inSta.getStaNo() + 1).getWorkNo() == 0) {
                                        // 出库模式
                                        devpThread.ioModeOf4F = IoModeType.PAKOUT_MODE;
                                    }
                                }
                            } else {
                                // 入库模式
                                devpThread.ioModeOf4F = IoModeType.PAKIN_MODE;
                            }
                            break;
                    }
@@ -1905,18 +2013,672 @@
    }
    public void outOfDevp() {
    public synchronized void outOfDevp(Integer mark) {
        List<WrkMast> wrkMasts = wrkMastMapper.selectPick();
        if (wrkMasts.size()!=0){
            News.warnNoLog(""+mark+" - 0"+" - 开始执行outOfDevp");
        }
        for (WrkMast wrkMast : wrkMasts) {
            if (basDevpService.selectCount(new EntityWrapper<BasDevp>().eq("wrk_no", wrkMast.getWrkNo())) == 0) {
                wrkMast.setCtnNo("Y");
                if (wrkMastMapper.updateById(wrkMast) == 0) {
                    log.error("修改{}工作档失败,ctn_no", wrkMast.getWrkNo());
                    News.error(""+mark+" - 1"+" - 修改{}工作档失败,ctn_no", wrkMast.getWrkNo());
                }
            }
        }
//        News.infoNoLog(""+mark+" - 0"+" - outOfDevp执行完成");
    }
    public synchronized void autoEmptyOut() {
        DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, 1);
        Integer autoOutSite = 12;
        //如果站点可出禁用,则不生成空盘出库任务
        StaProtocol staProtocol = devpThread.getStation().get(autoOutSite);
        if (staProtocol == null) {
            return;
        } else {
            staProtocol = staProtocol.clone();
        }
        if (staProtocol.isAutoing()  //自动
                && !staProtocol.isLoading()  //无物
                && staProtocol.isOutEnable()  //可出信号
                && staProtocol.getWorkNo() == 0
        ) {
            WrkMast pakoutEmpty = wrkMastMapper.selectPakoutEmpty(autoOutSite);
            if (null != pakoutEmpty) {
                return;
            }
            try {
                String response = new HttpHandler.Builder()
                        .setUri(wmsUrl)
                        .setPath("/rpc/auto/emptyOut/v1")
                        .build()
                        .doPost();
                JSONObject jsonObject = JSON.parseObject(response);
                if (jsonObject.getInteger("code").equals(200)) {
                    JSONObject data = (JSONObject) jsonObject.get("data");
                    News.info((String) data.get("msg"));
                } else {
                    News.error("请求接口失败!!!url:{};request:{};response:{}", wmsUrl + "/rpc/auto/emptyOut/v1","", response);
                }
            } catch (Exception e) {
                e.printStackTrace();
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            }
        }
    }
    public synchronized void autoEmptyIn() {
        DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, 1);
        Integer autoInSite = 12;
        StaProtocol staProtocol = devpThread.getStation().get(autoInSite);
        if (staProtocol == null) {
            return;
        } else {
            staProtocol = staProtocol.clone();
        }
        if (staProtocol.isAutoing()  //自动
                && staProtocol.isLoading()  //有物
                && staProtocol.isInEnable()  //可入信号
                && (staProtocol.getWorkNo() == 0 || staProtocol.getWorkNo() > 9990) //工作号为0或者工作号是9991~9999(输送机留用)
        ) {
            try {
                LocTypeDto locTypeDto = new LocTypeDto((short) 1, (short) 1, (short) 1);
                String response = new HttpHandler.Builder()
                        .setUri(wmsUrl)
                        .setPath("/rpc/auto/emptyIn/v1")
                        .setJson(JSON.toJSONString(locTypeDto))
                        .build()
                        .doPost();
                JSONObject jsonObject = JSON.parseObject(response);
                if (jsonObject.getInteger("code").equals(200)) {
                    News.info((String) jsonObject.get("msg"));
                } else {
                    News.error("请求接口失败!!!url:{};request:{};response:{}", wmsUrl + "/rpc/auto/emptyIn/v1", JSON.toJSONString(locTypeDto), response);
                }
            } catch (Exception e) {
                e.printStackTrace();
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            }
        }
    }
    /*
     * 小车地图更新  更新锁
     * */
    public synchronized boolean rgvMapUpdate(BasRgvMap basRgvMapCurrent,Integer staStart,Integer staEnd){
//        List<Integer> integers = RouteUtils.RouteMapCurrentFar(basRgvMapCurrent.getNowRoute(),staStart,staEnd, basRgvMapCurrent.getLockStartRoute());
        //更新当前小车锁
        try{
            Integer farCurrentStaNo = RouteUtils.RouteIndexFarMas(basRgvMapCurrent.getNowRoute(), staStart, staEnd, basRgvMapCurrent.getLockStartRoute());//获取最远站点
            Integer fallMerge = RouteUtils.RouteIndexFarMas(basRgvMapCurrent.getRgvNo(), farCurrentStaNo); //获取合并干涉项
            basRgvMapCurrent.setLockEndRoute(fallMerge);
            basRgvMapMapper.updateById(basRgvMapCurrent);
            //更新另一台小车地图
            Integer rgvNoOther = basRgvMapCurrent.getRgvNoOther();
            BasRgvMap basRgvMapOther = basRgvMapMapper.selectById(rgvNoOther);
            List<Integer> integers = RouteUtils.RouteMapCurrentFar(fallMerge, basRgvMapCurrent.getLockStartRoute());
            Integer lockEndRoute = RouteUtils.RouteMapOtherFarStnNo(integers, basRgvMapCurrent.getLockStartRoute());//另一台小车可活动最远位置
            basRgvMapOther.setEndRoute(lockEndRoute);
            basRgvMapMapper.updateById(basRgvMapOther);
            return true;
        }catch (Exception e){
            log.error("小车地图更新出错!");
            return false;
        }
    }
    /*
     * 刷新地图数据
     * */
    public synchronized void refreshRgvMap() {
        try{
            for (RgvSlave rgvSlave:slaveProperties.getRgv()) {
                RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, rgvSlave.getId());
                RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
                if (rgvProtocol == null) {
                    continue;
                }
                BasRgv basRgv = basRgvService.selectById(rgvSlave.getId());
                if (basRgv == null) {
                    log.error("{}号RGV尚未在数据库进行维护!2", rgvSlave.getId());
                    continue;
                }
                // 只有当RGV空闲、自动,工位一无物//rgv可用
                if (rgvProtocol.getStatusType() == RgvStatusType.IDLE
                        && rgvProtocol.getModeType() == RgvModeType.AUTO
                        && rgvProtocol.getLoaded1()==0  //现场修改:叠盘机,不满都算无物,怎么判断需要跟电控对接
                        && (rgvProtocol.getTaskNo1()==0 || rgvProtocol.getTaskNo1()==9999)
                ) {
                    BasRgvMap basRgvMap = basRgvMapMapper.selectById(rgvProtocol.getRgvNo());
                    basRgvMap.setNowRoute(rgvProtocol.getRgvPosI());
                    rgvMapUpdate(basRgvMap,basRgvMap.getStartRoute(),basRgvMap.getStartRoute());
                }
            }
        }catch (Exception e){
            log.error("4109行执行小车初始化任务下发失败");
            log.error("4109行"+e);
        }
    }
    /**
     *  完成小车任务
     */
    public synchronized void rgvCompleteWrkMastSta() {
        try{
            for (DevpSlave devp : slaveProperties.getDevp()) {
            for (RgvSlave rgvSlave:slaveProperties.getRgv()) {
                RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, rgvSlave.getId());
                RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
                if (rgvProtocol == null) {
                    continue;
                }
                BasRgv basRgv = basRgvService.selectById(rgvSlave.getId());
                if (basRgv == null) {
                    log.error("{}号RGV尚未在数据库进行维护!3", rgvSlave.getId());
                    continue;
                }
                // 只有当RGV等待WCS确认、自动
                if ((rgvProtocol.getStatusType1() == RgvStatusType.WAITING || rgvProtocol.getStatusType1()==RgvStatusType.FETCHWAITING)
                        && rgvProtocol.getModeType() == RgvModeType.AUTO
                        && (rgvProtocol.getStatusType() == RgvStatusType.WORKING1)
                ){
                    log.info("{}号小车等待wcs确认,状态{},参数{}",rgvProtocol.getRgvNo(),rgvProtocol.getStatusType(),rgvProtocol);
                    if (rgvProtocol.getTaskNo1()!=0){
                        if (rgvProtocol.getTaskNo1()==9999){
                            boolean rgvComplete = rgvComplete(rgvProtocol.getRgvNo());
                            if (!rgvComplete){
                                log.error("小车复位失败,小车号{}!",rgvProtocol.getRgvNo());
                            }
                            BasRgvMap basRgvMap = basRgvMapMapper.selectById(rgvProtocol.getRgvNo());
                            basRgvMap.setNowRoute(rgvProtocol.getRgvPosI());
                            rgvMapUpdate(basRgvMap,basRgvMap.getStartRoute(),basRgvMap.getStartRoute());
                            break;
                        }
                        WrkMastSta wrkMastSta = wrkMastStaMapper.selectByWrkNo(rgvProtocol.getTaskNo1().intValue());
                        if (Cools.isEmpty(wrkMastSta) || wrkMastSta.getWrkSts()!=1){
                            log.error("未查到小车执行任务或者执行任务状态不符合!"+wrkMastSta);
                            continue;
                        }
                        boolean rgvComplete = rgvComplete(rgvProtocol.getRgvNo());
//                        boolean rgvComplete = true;
                        if (!rgvComplete){
                            log.error("小车复位失败,小车号{}!",rgvProtocol.getRgvNo());
                            break;
                        }
                        DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                        StaProtocol staProtocol = devpThread.getStation().get(wrkMastSta.getStaEnd());
                        WrkMast wrkMast = wrkMastMapper.selectPakInStep3(wrkMastSta.getWrkNo().intValue());
                        if (!Cools.isEmpty(wrkMast)){
                            if (!staProtocol.isPakMk()){
                                continue;
                            }
                            // 下发站点信息
                            staProtocol.setWorkNo(wrkMast.getWrkNo());
                            staProtocol.setStaNo(wrkMast.getStaNo().shortValue());
                            devpThread.setPakMk(staProtocol.getSiteId(), false);
                            if (!MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol))) {
                                continue;
                            }
                        }
                        wrkMastSta.setWrkSts(3);
                        wrkMastStaMapper.updateById(wrkMastSta);
                        BasRgvMap basRgvMap = basRgvMapMapper.selectById(rgvProtocol.getRgvNo());
                        basRgvMap.setNowRoute(rgvProtocol.getRgvPosI());
                        rgvMapUpdate(basRgvMap,basRgvMap.getStartRoute(),basRgvMap.getStartRoute());
                    }
                    else {
                        log.error("小车复位失败,小车号{},等待wcs确认但是没有工作号!",rgvProtocol.getRgvNo());
                    }
                }
            }
            }
        }catch (Exception e){
            log.error("小车复位线程报错!"+e);
        }
    }
    /**
     * 执行小车搬运任务
     */
    public synchronized void rgvRunWrkMastFullSta() {
        try{
            for (RgvSlave rgvSlave:slaveProperties.getRgv()) {
                RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, rgvSlave.getId());
                RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
                if (rgvProtocol == null) {
                    continue;
                }
                BasRgv basRgv = basRgvService.selectById(rgvSlave.getId());
                if (basRgv == null) {
                    log.error("{}号RGV尚未在数据库进行维护!4", rgvSlave.getId());
                    continue;
                }
                // 只有当RGV空闲、自动,工位一无物//rgv可用
                if (rgvProtocol.getStatusType() == RgvStatusType.IDLE
                        && rgvProtocol.getModeType() == RgvModeType.AUTO
                        && rgvProtocol.getLoaded1()==0
                ) {
                    BasRgvMap basRgvMap = basRgvMapMapper.selectById(rgvProtocol.getRgvNo());
                    if (basRgvMap == null) {
                        log.error("{}号RGV尚未在数据库地图中进行维护!", rgvProtocol.getRgvNo());
                        continue;
                    }
                    List<Integer> route = RouteUtils.getRoute(basRgvMap.getStartRoute(), basRgvMap.getEndRoute());
                    basRgvMap.setNowRoute(rgvProtocol.getRgvPosI()); //更新小车当前位置站点号
                    List<WrkMastSta> wrkMastStaList = wrkMastStaMapper.selectNoInterfereList(route, route);
                    for (WrkMastSta wrkMastSta : wrkMastStaList){
                        if (wrkMastSta.getType()!=0 || wrkMastSta.getWrkType()!=3){//1:满版   3:取放
                            continue;
                        }
                        boolean sign = rgvTakeFullAll(basRgvMap.getRgvNo(), wrkMastSta); //命令下发
                        if (sign){
                            boolean signMap = rgvMapUpdate(basRgvMap, wrkMastSta.getStaStart(), wrkMastSta.getStaEnd());
                            if (signMap){
                                wrkMastSta.setWrkSts(1);
                                try{
                                    wrkMastStaMapper.updateById(wrkMastSta);
                                }catch (Exception e){
                                    log.error("更新小车任务失败");
                                }
                                return;
                            }else {
                                log.error("3864行,货物搬运任务:工作号{}所属任务下发后地图同步失败",wrkMastSta.getWrkNo());
                            }
                        } else {
                            log.error("工作号{}所属任务下发失败",wrkMastSta.getWrkNo());
                        }
                        break;
                    }
                }
            }
        }catch (Exception e){
            log.error("3875行执行小车搬运任务下发失败");
            log.error("3875行"+e);
        }
    }
    /**
     * 执行小车搬运任务
     */
//    public synchronized void rgvRunWrkMastEmptyStaPut() {//放
//        try{
//            for (RgvSlave rgvSlave:slaveProperties.getRgv()) {
//                RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, rgvSlave.getId());
//                RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
//                if (rgvProtocol == null) {
//                    continue;
//                }
//                BasRgv basRgv = basRgvService.selectById(rgvSlave.getId());
//                if (basRgv == null) {
//                    log.error("{}号RGV尚未在数据库进行维护!5", rgvSlave.getId());
//                    continue;
//                }
//
//                // 只有当RGV空闲、自动,工位二有物//rgv可用
//                if (rgvProtocol.getStatusType() == RgvStatusType.IDLE
//                        && rgvProtocol.getModeType() == RgvModeType.AUTO
//                        && rgvProtocol.getLoaded1()==1  //现场修改:叠盘机,不满都算无物,怎么判断需要跟电控对接
//                ) {
//                    BasRgvMap basRgvMap = basRgvMapMapper.selectById(rgvProtocol.getRgvNo());
//                    if (basRgvMap == null) {
//                        log.error("{}号RGV尚未在数据库地图中进行维护!", rgvProtocol.getRgvNo());
//                        continue;
//                    }
//                    basRgvMap.setNowRoute(rgvProtocol.getRgvPosI()); //更新小车当前位置站点号
//                    List<Integer> route = RouteUtils.getRoute(basRgvMap.getStartRoute(), basRgvMap.getEndRoute());//获取活动范围
//                    List<WrkMastSta> wrkMastStaList = wrkMastStaMapper.selectNoInterfereList(route, route);//查询可执行任务
//                    for (WrkMastSta wrkMastSta : wrkMastStaList){
//                        if (wrkMastSta.getType()!=2 || (wrkMastSta.getWrkType()!=2 && wrkMastSta.getWrkType()!=4)){// 2:空板  2:放 4:拆盘
//                            continue;
//                        }
//                        boolean sign = false;
//                        if (wrkMastSta.getStaStart()==0 && wrkMastSta.getStaEnd()!=0){//放
//                            sign = rgvPutEmpty(rgvProtocol.getRgvNo(),wrkMastSta);
//                        }else {
//                            continue;
//                        }
//                        if (sign){
//                            boolean signMap = rgvMapUpdate(basRgvMap, basRgvMap.getStartRoute(), wrkMastSta.getStaEnd());
//                            if (signMap){
//                                wrkMastSta.setWrkSts(2);
//                                try{
//                                    wrkMastStaMapper.updateById(wrkMastSta);
//                                }catch (Exception e){
//                                    log.error("更新小车任务失败");
//                                }
//                                return;
//                            }else {
//                                log.error("3857行,货物搬运任务:工作号{}所属任务下发后地图同步失败",wrkMastSta.getWrkNo());
//                            }
//                        }else {
//                            log.error("工作号{}所属任务下发失败",wrkMastSta.getWrkNo());
//                        }
//                        break;
//                    }
//                }
//            }
//        }catch (Exception e){
//            log.error("3933行执行小车放空板任务下发失败");
//            log.error("3933行"+e);
//        }
//    }
//    public synchronized void rgvRunWrkMastEmptyStaTake() {//取
//        try{
//            for (RgvSlave rgvSlave:slaveProperties.getRgv()) {
//                RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, rgvSlave.getId());
//                RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
//                if (rgvProtocol == null) {
//                    continue;
//                }
//                BasRgv basRgv = basRgvService.selectById(rgvSlave.getId());
//                if (basRgv == null) {
//                    log.error("{}号RGV尚未在数据库进行维护!6", rgvSlave.getId());
//                    continue;
//                }
//
//                // 只有当RGV空闲、自动,工位二无物//rgv可用
//                if (rgvProtocol.getStatusType() == RgvStatusType.IDLE
//                        && rgvProtocol.getModeType() == RgvModeType.AUTO
//                        && rgvProtocol.getLoaded1()==0  //现场修改:叠盘机,不满都算无物,怎么判断需要跟电控对接
//                ) {
//                    BasRgvMap basRgvMap = basRgvMapMapper.selectById(rgvProtocol.getRgvNo());
//                    if (basRgvMap == null) {
//                        log.error("{}号RGV尚未在数据库地图中进行维护!", rgvProtocol.getRgvNo());
//                        continue;
//                    }
//                    List<Integer> route = RouteUtils.getRoute(basRgvMap.getStartRoute(), basRgvMap.getEndRoute());
//                    basRgvMap.setNowRoute(rgvProtocol.getRgvPosI()); //更新小车当前位置站点号
//                    List<WrkMastSta> wrkMastStaList = wrkMastStaMapper.selectNoInterfereList(route, route);
//                    for (WrkMastSta wrkMastSta : wrkMastStaList){
//                        if (wrkMastSta.getType()!=2 || wrkMastSta.getWrkType()!=1){// 2:空板  1:取
//                            continue;
//                        }
//                        boolean sign = false;
//                        if (wrkMastSta.getStaEnd()==0 && wrkMastSta.getStaStart()!=0){//取
//                            sign = rgvTakeEmpty(rgvProtocol.getRgvNo(),wrkMastSta);
//                        } else {
//                            continue;
//                        }
//                        if (sign){
//                            boolean signMap = rgvMapUpdate(basRgvMap, wrkMastSta.getStaStart(), basRgvMap.getStartRoute());
//                            if (signMap){
//                                wrkMastSta.setWrkSts(1);
//                                try{
//                                    wrkMastStaMapper.updateById(wrkMastSta);
//                                }catch (Exception e){
//                                    log.error("更新小车任务失败");
//                                }
//                                return;
//                            }else {
//                                log.error("3879行,货物搬运任务:工作号{}所属任务下发后地图同步失败",wrkMastSta.getWrkNo());
//                            }
//                        }else {
//                            log.error("工作号{}所属任务下发失败",wrkMastSta.getWrkNo());
//                        }
//                        break;
//                    }
//                }
//            }
//        }catch (Exception e){
//            log.error("3989行执行小车取空板任务下发失败");
//            log.error("3989行"+e);
//        }
//    }
    /*
     * 有任务但未执行  此时需要调整小车位置
     * */
    public synchronized void rgvRunWrkMastEmptyStaAvoidance() {
        try{
            Integer integer = wrkMastStaMapper.selectAllWrkStsCount(null,0);//查询状态为0的任务
            if (integer==0){
                return;
            }
            for (RgvSlave rgvSlave:slaveProperties.getRgv()) {
                RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, rgvSlave.getId());
                RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
                if (rgvProtocol == null) {
                    continue;
                }
                BasRgv basRgv = basRgvService.selectById(rgvSlave.getId());
                if (basRgv == null) {
                    log.error("{}号RGV尚未在数据库进行维护!1", rgvSlave.getId());
                    continue;
                }
                // 只有当RGV空闲、自动,工位一无物//rgv可用
                if (rgvProtocol.getStatusType() == RgvStatusType.IDLE
                        && rgvProtocol.getModeType() == RgvModeType.AUTO
//                        && rgvProtocol.getLoaded1()==0  //现场修改:叠盘机,不满都算无物,怎么判断需要跟电控对接
                        && rgvProtocol.getTaskNo1()==0
//                        && rgvProtocol.getTaskNo2()==0
                ) {
                    BasRgvMap basRgvMap = basRgvMapMapper.selectById(rgvProtocol.getRgvNo());
                    if (rgvProtocol.getRgvPosI().equals(basRgvMap.getStartRoute())){
                        continue;
                    }
                    rgvAvoidanceXY(rgvProtocol.getRgvNo());
                    rgvMapUpdate(basRgvMap,basRgvMap.getStartRoute(),basRgvMap.getStartRoute());
                }
            }
        }catch (Exception e){
            log.error("4109行执行小车初始化任务下发失败");
            log.error("4109行"+e);
        }
    }
    /*
     * 小车XY移动  避让
     * */
    public synchronized boolean rgvAvoidanceXY(Integer rgvId){
        if (rgvId==1){
            try{
                BasRgvMap basRgvMap = basRgvMapMapper.selectById(rgvId);
                //  命令下发区 --------------------------------------------------------------------------
                RgvCommand rgvCommand = new RgvCommand();
                rgvCommand.setRgvNo(rgvId); // RGV编号
                rgvCommand.setAckFinish1((short) 0);  // 工位1任务完成确认位
                rgvCommand.setTaskNo1((short)32222); // 工位1工作号
                rgvCommand.setTaskMode1(RgvTaskModeType.X_MOVE); // 工位1任务模式:  回原点
                //basRgvMap.getLockStartRoute().shortValue()
                rgvCommand.setSourceStaNo1( (short)100);
                rgvCommand.setCommand((short) 1);   //工位1任务确认
                if (!MessageQueue.offer(SlaveType.Rgv, rgvId, new Task(4, rgvCommand))) {
                    //step=2,工位1、2写任务;   step=4,工位1写任务;     step=5,工位2写任务   step=9,回原点 9999任务号
                    log.error("RGV命令下发失败,RGV号={},任务数据={}", rgvId, JSON.toJSON(rgvCommand));
                    return false;
                } else {
                    return true;
                }
            }catch (Exception e){
                return false;
            }
        }else {
            try{
                BasRgvMap basRgvMap = basRgvMapMapper.selectById(rgvId);
                //  命令下发区 --------------------------------------------------------------------------
                RgvCommand rgvCommand = new RgvCommand();
                rgvCommand.setRgvNo(rgvId); // RGV编号
                rgvCommand.setAckFinish1((short) 0);  // 工位1任务完成确认位
                rgvCommand.setTaskNo1((short)32222); // 工位1工作号
                rgvCommand.setTaskMode1(RgvTaskModeType.X_MOVE); // 工位1任务模式:  回原点
                //basRgvMap.getLockStartRoute().shortValue()
                rgvCommand.setSourceStaNo1( (short)161);
                rgvCommand.setCommand((short) 1);   //工位1任务确认
                if (!MessageQueue.offer(SlaveType.Rgv, rgvId, new Task(4, rgvCommand))) {
                    //step=2,工位1、2写任务;   step=4,工位1写任务;     step=5,工位2写任务   step=9,回原点 9999任务号
                    log.error("RGV命令下发失败,RGV号={},任务数据={}", rgvId, JSON.toJSON(rgvCommand));
                    return false;
                } else {
                    return true;
                }
            }catch (Exception e){
                return false;
            }
        }
    }
    /*
     * 小车取货至工位任务
     * */
    public synchronized boolean rgvTakeFullAll(Integer rgvId,WrkMastSta wrkMastSta){
        try{
            //  命令下发区 --------------------------------------------------------------------------
            RgvCommand rgvCommand = new RgvCommand();
            rgvCommand.setRgvNo(rgvId); // RGV编号
            rgvCommand.setAckFinish1((short) 0);  // 工位1任务完成确认位
            rgvCommand.setTaskNo1(wrkMastSta.getWrkNo().shortValue()); // 工位1工作号
            rgvCommand.setTaskMode1(RgvTaskModeType.FETCH_PUT); // 工位1任务模式:  取放货
            rgvCommand.setSourceStaNo1(wrkMastSta.getStaStart().shortValue());   //工位1起点
            rgvCommand.setDestinationStaNo1(wrkMastSta.getStaEnd().shortValue());   //工位1目标站点
            rgvCommand.setCommand((short) 1);   //工位1任务确认
            if (!MessageQueue.offer(SlaveType.Rgv, rgvId, new Task(4, rgvCommand))) {
                //step=2,工位1、2写任务;   step=4,工位1写任务;     step=5,工位2写任务
                log.error("RGV命令下发失败,RGV号={},任务数据={}", rgvId, JSON.toJSON(rgvCommand));
                return false;
            } else {
                return true;
            }
        }catch (Exception e){
            return false;
        }
    }
    /*
     * 小车取货至工位任务
     * */
//    public synchronized boolean rgvTakeFull(Integer rgvId,WrkMastSta wrkMastSta){
//        try{
//            //  命令下发区 --------------------------------------------------------------------------
//            RgvCommand rgvCommand = new RgvCommand();
//            rgvCommand.setRgvNo(rgvId); // RGV编号
//            rgvCommand.setAckFinish1((short) 0);  // 工位1任务完成确认位
//            rgvCommand.setTaskNo1(wrkMastSta.getWrkNo().shortValue()); // 工位1工作号
//            rgvCommand.setTaskMode1(RgvTaskModeType.FETCH); // 工位1任务模式:  取货
//            rgvCommand.setSourceStaNo1(wrkMastSta.getStaStart().shortValue());   //工位1起点
//            rgvCommand.setCommand((short) 1);   //工位1任务确认
//            if (!MessageQueue.offer(SlaveType.Rgv, rgvId, new Task(4, rgvCommand))) {
//                //step=2,工位1、2写任务;   step=4,工位1写任务;     step=5,工位2写任务
//                log.error("RGV命令下发失败,RGV号={},任务数据={}", rgvId, JSON.toJSON(rgvCommand));
//                return false;
//            } else {
//                return true;
//            }
//        }catch (Exception e){
//            return false;
//        }
//    }
    /*
     * 小车放货至输送线任务
     * */
//    public synchronized boolean rgvPutFull(Integer rgvId,WrkMastSta wrkMastSta){
//        try{
//            //  命令下发区 --------------------------------------------------------------------------
//            RgvCommand rgvCommand = new RgvCommand();
//            rgvCommand.setRgvNo(rgvId); // RGV编号
//            rgvCommand.setAckFinish1((short) 0);  // 工位1任务完成确认位
//            rgvCommand.setTaskNo1(wrkMastSta.getWrkNo().shortValue()); // 工位1工作号
//            rgvCommand.setTaskMode1(RgvTaskModeType.PUT); // 工位1任务模式:  放货
//            rgvCommand.setDestinationStaNo1(wrkMastSta.getStaEnd().shortValue());   //工位1目标站点
//            rgvCommand.setCommand((short) 1);   //工位1任务确认
//            if (!MessageQueue.offer(SlaveType.Rgv, rgvId, new Task(4, rgvCommand))) {
//                //step=2,工位1、2写任务;   step=4,工位1写任务;     step=5,工位2写任务
//                log.error("RGV命令下发失败,RGV号={},任务数据={}", rgvId, JSON.toJSON(rgvCommand));
//                return false;
//            } else {
//                return true;
//            }
//        }catch (Exception e){
//            return false;
//        }
//    }
    /*
     * 小车取空板至工位任务
     * */
//    public synchronized boolean rgvTakeEmpty(Integer rgvId,WrkMastSta wrkMastSta){
//        try{
//            //  命令下发区 --------------------------------------------------------------------------
//            RgvCommand rgvCommand = new RgvCommand();
//            rgvCommand.setRgvNo(rgvId); // RGV编号
//            rgvCommand.setAckFinish2((short) 0);  // 工位2任务完成确认位
//            rgvCommand.setTaskNo2(wrkMastSta.getWrkNo().shortValue()); // 工位2工作号
//            rgvCommand.setTaskMode2(RgvTaskModeType.FETCH); // 工位2任务模式:  取货
//            rgvCommand.setSourceStaNo2(wrkMastSta.getStaStart().shortValue());   //工位2起点
//            rgvCommand.setCommand((short) 2);   //工位2任务确认
//            if (!MessageQueue.offer(SlaveType.Crn, rgvId, new Task(5, rgvCommand))) {
//                //step=2,工位1、2写任务;   step=4,工位1写任务;     step=5,工位2写任务
//                log.error("RGV命令下发失败,RGV号={},任务数据={}", rgvId, JSON.toJSON(rgvCommand));
//                return false;
//            } else {
//                return true;
//            }
//        }catch (Exception e){
//            return false;
//        }
//    }
    /*
     * 小车放空板至输送线任务
     * */
//    public synchronized boolean rgvPutEmpty(Integer rgvId,WrkMastSta wrkMastSta){
//        try{
//            //  命令下发区 --------------------------------------------------------------------------
//            RgvCommand rgvCommand = new RgvCommand();
//            rgvCommand.setRgvNo(rgvId); // RGV编号
//            rgvCommand.setAckFinish2((short) 0);  // 工位2任务完成确认位
//            rgvCommand.setTaskNo2(wrkMastSta.getWrkNo().shortValue()); // 工位2工作号
//            rgvCommand.setTaskMode2(RgvTaskModeType.PUT); // 工位2任务模式:  放货
//            rgvCommand.setDestinationStaNo2(wrkMastSta.getStaEnd().shortValue());   //工位2目标站点
//            rgvCommand.setCommand((short) 2);   //工位2任务确认
//            if (!MessageQueue.offer(SlaveType.Crn, rgvId, new Task(5, rgvCommand))) {
//                //step=2,工位1、2写任务;   step=4,工位1写任务;     step=5,工位2写任务
//                log.error("RGV命令下发失败,RGV号={},任务数据={}", rgvId, JSON.toJSON(rgvCommand));
//                return false;
//            } else {
//                return true;
//            }
//        }catch (Exception e){
//            return false;
//        }
//    }
    /*
     * 小车复位
     * */
    public synchronized boolean rgvComplete(Integer rgvId){
        try{
            //  命令下发区 --------------------------------------------------------------------------
            if (!MessageQueue.offer(SlaveType.Rgv, rgvId, new Task(3, new RgvCommand()))) {
                //step=2,工位1、2写任务;   step=4,工位1写任务;     step=5,工位2写任务
                log.error("RGV命令下发失败,RGV号={}",rgvId);
                return false;
            } else {
                log.info("RGV命令下发成功,RGV号={}",rgvId);
                return true;
            }
        }catch (Exception e){
            log.error("RGV命令下发失败,RGV号={}。异常:"+e,rgvId);
            return false;
        }
    }
}