pjb
1 天以前 29e0a8a8f74a7155f7e6c0d854bb7566c655b0c8
src/main/java/com/zy/service/impl/MainServiceImpl.java
@@ -26,8 +26,11 @@
import com.zy.core.thread.LedThread;
import com.zy.core.thread.SiemensDevpThread;
import com.zy.entity.*;
import com.zy.entity.param.StockOutParam;
import com.zy.mapper.*;
import com.zy.service.*;
import com.zy.system.entity.Config;
import com.zy.system.service.ConfigService;
import com.zy.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@@ -36,6 +39,7 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
@@ -73,6 +77,7 @@
    // 成品库堆垛机出库站点到rgv接驳点
    public static final Map<Integer,Short>  crnOutSiteToRgvSite = new HashMap<>();
    public static final Map<Integer,Short>  crnOutSiteToRgvSite2 = new HashMap<>();
    static {
        emptyPalletSiteMap.put(1001,"M"); // emptyPalletSiteMap.put(1002,"M");
@@ -100,6 +105,9 @@
        outGzxSiteList.add(1081);outGzxSiteList.add(1084);outGzxSiteList.add(1087);
        crnOutSiteToRgvSite.put(1093, (short) 1091);crnOutSiteToRgvSite.put(1099, (short) 1097);crnOutSiteToRgvSite.put(1107, (short) 1105);
        crnOutSiteToRgvSite2.put(1087, (short) 1089);crnOutSiteToRgvSite2.put(1084, (short) 1086);crnOutSiteToRgvSite2.put(1081, (short) 1083);
        crnOutSiteToRgvSite2.put(1043, (short) 1041);crnOutSiteToRgvSite2.put(1016, (short) 1018);
    }
    @Autowired
@@ -114,6 +122,9 @@
    private WaitPakinMapper waitPakinMapper;
    @Autowired
    private LocMastService locMastService;
    @Resource
    private LocMastMapper locMastMapper;
    @Autowired
    private StaDescService staDescService;
    @Autowired
@@ -136,6 +147,12 @@
    private WrkMastService wrkMastService;
    @Autowired
    private BasRgvMapService basRgvMapService;
    @Resource
    private ConfigService configService;
    @Resource
    private BasDevpErrLogService basDevpErrLogService;
    @Value("${wms.url}")
    private String wmsUrl;
@@ -170,36 +187,36 @@
                // 尺寸检测异常
                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 (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 && staProtocol.isInEnable()) {
                if (back && staProtocol.isInEnable() && staProtocol.isLoading() && staProtocol.getWorkNo() == 0) {
                    MessageQueue.offer(SlaveType.Led, inSta.getLed(), new Task(3, errMsg));
                    if (!staProtocol.isLoading()){
@@ -258,9 +275,12 @@
                            barcodeThread.setBarcode("");
                            staProtocol.setWorkNo(dto.getWorkNo());
                            staProtocol.setStaNo(dto.getStaNo().shortValue());
                            if (dto.getStaNo() == 1071 || dto.getStaNo() == 1064 || dto.getStaNo() == 1078) {
                                decreaseWantBucketCount(dto.getStaNo(),1);
                            }
                            devpThread.setPakMk(staProtocol.getSiteId(), false);
                            boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                            log.error("输送线下发2:"+dto.getWorkNo()+","+dto.getStaNo());
                            log.info("输送线下发2:"+dto.getWorkNo()+","+dto.getStaNo());
                            if (!result) {
                                News.error(methodName + ":更新plc站点信息失败");
                                throw new CoolException("更新plc站点信息失败");
@@ -295,10 +315,52 @@
        StaProtocol staProtocol1084 = devpThread.getStation().get(1084);
        StaProtocol staProtocol1087 = devpThread.getStation().get(1087);
        List<SearchLocParam.WantBucket> wantBucketList = new ArrayList<>();
        wantBucketList.add(new SearchLocParam.WantBucket(1064,staProtocol1084.getWantBucketFlag()));
        wantBucketList.add(new SearchLocParam.WantBucket(1071,staProtocol1081.getWantBucketFlag()));
        wantBucketList.add(new SearchLocParam.WantBucket(1078,staProtocol1087.getWantBucketFlag()));
        wantBucketList.add(new SearchLocParam.WantBucket(1064,staProtocol1084.getWantBucketFlag(),staProtocol1084.getWantBucketCount()));
        wantBucketList.add(new SearchLocParam.WantBucket(1071,staProtocol1081.getWantBucketFlag(),staProtocol1081.getWantBucketCount()));
        wantBucketList.add(new SearchLocParam.WantBucket(1078,staProtocol1087.getWantBucketFlag(),staProtocol1087.getWantBucketCount()));
        return wantBucketList;
    }
    /**
     * 罐装线要桶数量减少
     */
    private void decreaseWantBucketCount(int site, int decrease) throws InterruptedException {
        int siteNew;
        switch (site) {
            case 1071: siteNew = 1081;break;
            case 1064: siteNew = 1084;break;
            case 1078: siteNew = 1087;break;
            default:
                return;
        }
        SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, 2);
        StaProtocol staProtocol = devpThread.getStation().get(siteNew);
        if(staProtocol == null) {
            return;
        } else {
            staProtocol = staProtocol.clone();
        }
        int count = staProtocol.getWantBucketCount();
        int remaining = count - decrease;
        if ( remaining < 0) {
            log.error("自动出空桶减少罐装线要桶数异常,站点:{},减少前:{},减少数:{},剩余要桶数:{}", site, count, decrease, remaining);
            return;
        }
        staProtocol.setWantBucketCount(remaining);
        boolean offer = MessageQueue.offer(SlaveType.Devp, inGzxSiteList.indexOf(site) + 4, new Task(6, staProtocol));
        if (offer) {
            log.info("自动出空桶减少罐装线要桶数命令推送队列成功:站点:{},剩余要桶数:{}" ,site, remaining);
        } else {
            log.error("自动出空桶减少罐装线要桶数命令推送队列失败:站点:{},剩余要桶数:{}" ,site, remaining);
        }
        log.info("自动出空桶减少罐装线要桶数成功,站点:{},减少前:{},减少数:{},剩余要桶数:{}", site, count, decrease, remaining);
    }
    /**
@@ -679,7 +741,7 @@
                        continue;
                    }
                } else if (shallowLoc.getLocSts().equals("F") || shallowLoc.getLocSts().equals("D")) {
                } else if (shallowLoc.getLocSts().equals("F") || shallowLoc.getLocSts().equals("M")|| shallowLoc.getLocSts().equals("Z")) {
                    News.warnNoLog(""+mark+" - 1"+" - 12"+" - // F、D  库位状态={}",shallowLoc.getLocSts());
                    // 此标记避免多次执行移库任务
                    if (Cools.isEmpty(wrkMast.getUpdMk()) || "N".equals(wrkMast.getUpdMk())) {
@@ -767,12 +829,30 @@
     */
    public synchronized void locToCrnStn(CrnSlave slave, CrnProtocol crnProtocol,Integer mark) {
        News.warnNoLog(""+mark+" - 2"+" - 0"+" - 堆垛机入出库作业下发:执行出库");
        boolean crnAvailableOut = false;
        Config config = configService.selectOne(new EntityWrapper<Config>().eq("code","removeCrnAvailableOut"));
        if (config != null && config.getStatus() == 1) {
            crnAvailableOut = true;
        }
        // 限制去捆绑机器任务数
        int kbWrks = wrkMastMapper.selectCountByKb();
        for (CrnSlave.CrnStn crnStn : slave.getCrnOutStn()) {
            // 获取工作状态为11(生成出库ID)的出库工作档
            List<WrkMast> wrkMasts = wrkMastMapper.selectPakOutStep11(slave.getId(), crnStn.getStaNo());
            for (WrkMast wrkMast : wrkMasts) {
                if (wrkMast == null) {
                    continue;
                }
                if (wrkMast.getStaNo() == 1031) {
                    // 获取1033无状态时任务数+1
                    SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, 1);
                    StaProtocol staProtocol = devpThread.getStation().get(1033);
                    if (staProtocol.isLoading() && staProtocol.getWorkNo() == 0) {
                        kbWrks ++;
                    }
                    if (kbWrks > 2) {
                        continue;
                    }
                }
                // 工作档状态判断
                if (wrkMast.getIoType() < 100 || wrkMast.getSourceStaNo() == null) {
@@ -803,8 +883,8 @@
                }
                // 判断堆垛机出库站状态
                if (staProtocol.isAutoing() && !staProtocol.isLoading() && staDetl.getCanouting() != null && staDetl.getCanouting().equals("Y")
                        && staProtocol.getWorkNo() == 0 && staProtocol.isOutEnable()) {
                if (staProtocol.isAutoing() && staDetl.getCanouting() != null && staDetl.getCanouting().equals("Y") &&
                        (crnAvailableOut || !staProtocol.isLoading() && staProtocol.getWorkNo() == 0 && staProtocol.isOutEnable())) {
                    // 堆垛机控制过滤
                    if (!crnProtocol.getStatusType().equals(CrnStatusType.IDLE) || crnProtocol.getTaskNo() != 0) {
                        break;
@@ -841,7 +921,7 @@
                                }
                            }
                        } else if (shallowLoc.getLocSts().equals("F") || shallowLoc.getLocSts().equals("D")) {
                        } else if (shallowLoc.getLocSts().equals("F") || shallowLoc.getLocSts().equals("M")|| shallowLoc.getLocSts().equals("Z")) {
                            News.warnNoLog(""+mark+" - 2"+" - 9"+" - // F、D  库位状态={}",shallowLoc.getLocSts());
//                            WrkMast waitWrkMast = wrkMastMapper.selectByLocNo(shallowLocNo);
                            //2022-08-16 modify,不根据updmk标记移库任务(容易被取消导致堵塞),查询工作档是否存在任务
@@ -884,7 +964,7 @@
                        }
                        newLocNo = newLocNo + locNo.substring(2);
                        // 对应库位有无任务
                        WrkMast wrkMast1 = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("source_loc_no", newLocNo));
                        WrkMast wrkMast1 = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("source_loc_no", newLocNo).eq("wrk_sts",11));
                        if(wrkMast1 == null) {
                             if(locNo.startsWith("10") || locNo.startsWith("11")){ // 浅库位
@@ -953,7 +1033,7 @@
                        // 修改空桶库对应库位任务状态
                        if(slave.getId() == 4 && crnStn.getStaNo() == 1056) {
                            String locNo2 = (wrkMast.getSourceLocNo().startsWith("09") ? "10" : "12") + wrkMast.getSourceLocNo().substring(2);
                            WrkMast wrkMast1 = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("source_loc_no", locNo2));
                            WrkMast wrkMast1 = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("source_loc_no", locNo2).eq("wrk_sts",11));
                            if (wrkMast1 != null) {
                                wrkMast1.setWrkSts(12L);
                                wrkMast1.setCrnStrTime(now);
@@ -1075,7 +1155,7 @@
            //  状态:等待确认 并且  任务完成位 = 1
            if (crnProtocol.statusType == CrnStatusType.WAITING && crnProtocol.getTaskNo() != 0) {
                News.warnNoLog(""+mark+" - 0"+" - 开始执行对工作档的完成操作");
                if (crnProtocol.getTaskNo() == 9999) {
                if (crnProtocol.getTaskNo() == 9999) { // 回原点任务号
                    // 堆垛机复位
                    crnThread.setResetFlag(true);
                } else {
@@ -1095,15 +1175,23 @@
                    // 空桶入库完成,先完成对应库位组任务
                    if(wrkMast.getWorkNoOther() != 0 ){
                        WrkMast wrkMast1 = wrkMastService.selectByWrkNo(wrkMast.getWorkNoOther());
                        // 交换库位号
                        String locNo = wrkMast.getLocNo();
                        wrkMast.setLocNo(wrkMast1.getLocNo());
                        wrkMast1.setLocNo(locNo);
                        wrkMast1.setCrnEndTime(now);
                        wrkMast1.setModiTime(now);
                        wrkMast1.setWrkSts(4L);
                        wrkMast1.setWorkNoOther(0);
                        wrkMastMapper.updateById(wrkMast1);
                        if (wrkMast1 != null) {
                            // 交换库位号
                            String locNo = wrkMast.getLocNo();
                            wrkMast.setLocNo(wrkMast1.getLocNo());
                            // 交换入库时间,提取库存时按顺序先浅后深
                            Date ioTime = wrkMast.getIoTime();
                            if(locNo.startsWith("10")) {
                                wrkMast.setIoTime(wrkMast1.getIoTime());
                                wrkMast1.setIoTime(ioTime);
                            }
                            wrkMast1.setLocNo(locNo);
                            wrkMast1.setCrnEndTime(now);
                            wrkMast1.setModiTime(now);
                            wrkMast1.setWrkSts(4L);
                            wrkMast1.setWorkNoOther(0);
                            wrkMastMapper.updateById(wrkMast1);
                        }
                    }
                    wrkMast.setCrnEndTime(now);
                    wrkMast.setModiTime(now);
@@ -1122,6 +1210,68 @@
    }
    /**
     * 堆垛机回原点
     */
    public synchronized void originGo() throws InterruptedException {
        for (CrnSlave crn : slaveProperties.getCrn()) {
            // 获取堆垛机信息
            CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crn.getId());
            CrnProtocol crnProtocol = crnThread.getCrnProtocol();
            if(crnProtocol == null) {
                continue;
            }
            if (crnProtocol.getStatusType() == CrnStatusType.IDLE && crnProtocol.getTaskNo() == 0 && crnProtocol.getModeType() == CrnModeType.AUTO
                    && crnProtocol.getLoaded() == 0 && crnProtocol.getForkPos() == 0) {
                // 判断是不是已在原点
                if(crnProtocol.getBay() == 0 && crnProtocol.getLevel() == 1) {
                    continue;
                }
                // 判断是不是空闲三分钟
                BasCrnp basCrnp = basCrnpService.selectById(crn.getId());
                if (basCrnp.getWrkNo() != 0) {
                    continue;
                }
                Date now = new Date();
                Date modiTime = basCrnp.getModiTime();
                long diffInMillis = now.getTime()-modiTime.getTime();
                if(diffInMillis < 10 * 1000) { // 空闲小于10秒则跳过
                    continue;
                } else {  // 有入库任务或大于2分钟,回原点
                    int count = wrkMastService.selectCount(new EntityWrapper<WrkMast>().eq("io_type", 1).eq("crn_no", crn.getId()).in("wrk_sts", 2, 9, 10));
                    if(count == 0 && diffInMillis < 2 * 60 * 1000) {
                        continue;
                    }
                }
                // 有吊车入库或吊车出库任务
                int count = wrkMastService.selectCount(new EntityWrapper<WrkMast>().eq("crn_no", crnProtocol.getCrnNo()).in("wrk_sts", 3, 12));
                if(count != 0) {
                    continue;
                }
                CrnCommand crnCommand = new CrnCommand();
                crnCommand.setCrnNo(crn.getId()); // 堆垛机编号
                crnCommand.setTaskNo((short) 9999); // 工作号
                crnCommand.setTaskMode(CrnTaskModeType.GO_ORIGIN); // 任务模式:  回原点
                crnCommand.setSourcePosX((short) (crn.getId() == 1 ? 4 : crn.getId() == 2 ? 6 : crn.getId() == 3 ? 7 : 11));     // 源库位排
                crnCommand.setSourcePosY((short) 0);     // 源库位列
                crnCommand.setSourcePosZ((short) 1);     // 源库位层
                crnCommand.setDestinationPosX((short) 0);     // 目标库位排
                crnCommand.setDestinationPosY((short) 0);     // 目标库位列
                crnCommand.setDestinationPosZ((short) 0);     // 目标库位层
                if (!MessageQueue.offer(SlaveType.Crn, crn.getId(), new Task(2, crnCommand))) {
                    News.error("回原点任务下发失败", crn.getId(), JSON.toJSON(crnCommand));
                } else {
                    basCrnp.setModiTime(new Date());
                    basCrnpService.updateById(basCrnp); // 设置更新时间,避免重复下发回原点
                    log.info("{}号堆垛机回原点任务下发成功:{}", crn.getId(), JSON.toJSON(crnCommand));
                }
                Thread.sleep(3000);
            }
        }
    }
    /**
     * 堆垛机异常信息记录
     */
    public synchronized void recCrnErr(Integer mark) {
@@ -1133,15 +1283,15 @@
            if (crnProtocol == null) {
                continue;
            }
            if (true) {
//            if (crnProtocol.getModeType() != CrnModeType.STOP) {
//            if (true) {
            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"+" - 开始执行:堆垛机异常信息记录 : 有任务,有异常");
//                        News.warnNoLog(""+mark+" - 1"+" - 开始执行:堆垛机异常信息记录 : 有任务,有异常");
                        if (crnProtocol.getAlarm() != null && crnProtocol.getAlarm() > 0) {
                            WrkMast wrkMast = wrkMastMapper.selectById(crnProtocol.getTaskNo());
                            if (wrkMast == null) {
@@ -1244,6 +1394,174 @@
    }
    /**
     * 输送线异常
     */
    public synchronized void recDevpErr() {
        Date now = new Date();
        for (DevpSlave devp : slaveProperties.getDevp()) {
            Integer devpId = devp.getId();
            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devpId);
            Map<Integer, StaProtocol> station = devpThread.getStation();
            for (Map.Entry<Integer, StaProtocol> entry : station.entrySet()) {
                Integer siteNo = entry.getKey();
                StaProtocol staProtocol = entry.getValue();
                Integer workNo = staProtocol.getWorkNo();
                // 输送线报警
                String plcErr = staPlcErr(staProtocol);
                if (staProtocol.isAutoing()) {
                    // 有任务
                    if (staProtocol.getWorkNo() != 0 && staProtocol.getWorkNo() <= 9000) {
                        // 获取输送线报警信息
                        BasDevpErrLog latestByTaskNo = basDevpErrLogService.findLatestByTaskNo(siteNo, workNo);
                        // 有异常
                        if (latestByTaskNo == null) {
                            if (!plcErr.equals("")) {
                                WrkMast wrkMast = wrkMastMapper.selectById(workNo);
                                if (wrkMast == null) {
                                    continue;
                                }
                                BasDevpErrLog basErrLog = new BasDevpErrLog(
                                        null,    // 编号
                                        wrkMast.getWrkNo(),    // 工作号
                                        now,    // 发生时间
                                        null,    // 结束时间
                                        wrkMast.getWrkSts(),    // 工作状态
                                        wrkMast.getIoType(),    // 入出库类型
                                        wrkMast.getCrnNo(),    // 堆垛机
                                        devpId,    // plc
                                        wrkMast.getLocNo(),    // 目标库位
                                        wrkMast.getStaNo(),    // 目标站
                                        siteNo,    // 源站
                                        wrkMast.getSourceLocNo(),    // 源库位
                                        wrkMast.getBarcode(),    // 条码
                                        0,    // 异常码
                                        plcErr,    // 异常
                                        1,    // 异常情况
                                        now,    // 添加时间
                                        null,    // 添加人员
                                        now,    // 修改时间
                                        null,    // 修改人员
                                        "任务中异常"    // 备注
                                );
                                if (!basDevpErrLogService.insert(basErrLog)) {
                                    log.error("输送线异常信息插入表asr_bas_devp_err_log异常:{}", basErrLog);
                                }
                            }
                        } else {
                            // 异常修复
                            if (plcErr.equals("")) {
                                latestByTaskNo.setEndTime(now);
                                latestByTaskNo.setUpdateTime(now);
                                latestByTaskNo.setStatus(2);
                                if (!basDevpErrLogService.updateById(latestByTaskNo)) {
                                    log.error("输送线异常记录修复失败asr_bas_devp_err_log异常:{}", latestByTaskNo);
                                }
                            }
                        }
                        // 无任务
                    } else {
                        BasDevpErrLog latest = basDevpErrLogService.findLatest(siteNo);
                        // 有异常
                        if (!plcErr.equals("")) {
                            // 记录新异常
                            if (latest == null || !latest.getError().equals(plcErr) || latest.getStatus() == 2 ) {
                                BasDevpErrLog basErrLog = new BasDevpErrLog(
                                        null,    // 编号
                                        null,    // 工作号
                                        now,    // 发生时间
                                        null,    // 结束时间
                                        null,    // 工作状态
                                        null,    // 入出库类型
                                        0,    // 堆垛机
                                        devpId,    // plc
                                        null,    // 目标库位
                                        null,    // 目标站
                                        siteNo,    // 源站
                                        null,    // 源库位
                                        null,    // 条码
                                        0,    // 异常码
                                        plcErr,    // 异常
                                        1,    // 异常情况
                                        now,    // 添加时间
                                        null,    // 添加人员
                                        now,    // 修改时间
                                        null,    // 修改人员
                                        "无任务异常"    // 备注
                                );
                                if (!basDevpErrLogService.insert(basErrLog)) {
                                    log.error("输送线异常记录asr_bas_devp_err_log异常:{}", basErrLog);
                                }
                            }
                            // 无异常
                        } else {
                            // 异常修复
                            if (latest != null && latest.getStatus() == 1) {
                                latest.setEndTime(now);
                                latest.setUpdateTime(now);
                                latest.setStatus(2);
                                if (!basDevpErrLogService.updateById(latest)) {
                                    log.error("输送线异常记录修复失败asr_bas_devp_err_log异常:{}", latest);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    // 获取输送线报警
    public String staPlcErr(StaProtocol staProtocol){
        Integer siteId = staProtocol.getSiteId();
        if (staProtocol.getBreakerErr()){
            return "断路器故障";
        }
        if (staProtocol.getInfraredErr()){
            return "光电异常";
        }
        if (staProtocol.getOutTimeErr()){
            return "运行超时";
        }
        if (staProtocol.getSeizeSeatErr()){
            return "占位超时";
        }
        if (staProtocol.getWrkYgoodsN()){
            return "有任务无货故障";
        }
        if (staProtocol.getInverterErr()){
            return "变频器故障";
        }
        if (staProtocol.getContactErr()){
            return "电机接触器故障";
        }
        if (staProtocol.getUpcontactErr()){
            return "顶升电机接触器故障";
        }
        if (staProtocol.isFrontErr()){
            return "前超限";
        }
        if (staProtocol.isBackErr()){
            return "后超限";
        }
        if (staProtocol.isHighErr()){
            return "高超限";
        }
        if (staProtocol.isLeftErr()){
            return "左超限";
        }
        if (staProtocol.isRightErr()){
            return "右超限";
        }
        if (staProtocol.isBarcodeErr() && siteId != 1083 && siteId != 1086 && siteId != 1089 ){
            return "扫码失败";
        }
        return "";
    }
    /**
     * 出库  ===>> 工作档信息写入led显示器
     */
    public synchronized void ledExecute(Integer mark) {
@@ -1296,6 +1614,9 @@
                    case 110:
                        ledCommand.setTitle("空板出库");
                        ledCommand.setEmptyMk(true);
                        break;
                    case 120:
                        ledCommand.setTitle("手动转移");
                        break;
                    default:
                        News.error("任务入出库类型错误!!![工作号:{}] [入出库类型:{}]", wrkMast.getWrkNo(), wrkMast.getIoType());
@@ -1401,13 +1722,25 @@
     */
    private synchronized void moveLocForDeepLoc(CrnSlave crn, LocMast shallowLoc,Integer mark) {
        // 只有208L能放11层
        String model = null;
        if(shallowLoc.getLocSts().equals("F")) {
            LocDetl locDetl = locDetlService.selectOne(new EntityWrapper<LocDetl>().eq("loc_no", shallowLoc.getLocNo()));
            if(locDetl != null && locDetl.getModel() != null) {
                String matModel = locMastMapper.selectMatMatnrByMaktx(locDetl.getModel());
                if(matModel != null && matModel.equals("208L")) {
                    model = "208L";
                }
            }
        }
        try {
            News.warnNoLog(""+mark+"moveLocForDeepLoc"+" - 0"+" - 开始执行:因双深库位阻塞,对浅库位进行移转(立即执行版)");
            List<Integer> rows = locMastService.queryDistinctRow(crn.getId());
            LocMast loc = null;
            for (Integer row : rows) {
                if (Utils.isDeepLoc(slaveProperties, row)) {
                    loc = locMastService.queryFreeLocMast(row, shallowLoc.getLocType2());
//                    loc = locMastService.queryFreeLocMast(row, shallowLoc.getLocType2());
                    loc = locMastMapper.queryFreeLocMastNew(row,model);
                    if (loc != null) {
                        if (Utils.isDeepLoc(slaveProperties, loc.getLocNo())) {
@@ -1426,12 +1759,12 @@
            if (null == loc) {
                for (Integer row : rows) {
                    if (Utils.isShallowLoc(slaveProperties, row)) {
                        loc = locMastService.queryFreeLocMast(row, shallowLoc.getLocType2());
//                        loc = locMastService.queryFreeLocMast(row, shallowLoc.getLocType2());
                        loc = locMastMapper.queryFreeLocMastNew(row,model);
                        if (null != loc) {//对应深库位非在库状态,不能移库
                            String deepLoc = Utils.getDeepLoc(slaveProperties, loc.getLocNo());
                            LocMast deepLoc1 = locMastService.selectById(deepLoc);
                            if (!deepLoc1.getLocSts().equals("F") && !deepLoc1.getLocSts().equals("D")) {
                            if (!deepLoc1.getLocSts().equals("F") && !deepLoc1.getLocSts().equals("M")&& !deepLoc1.getLocSts().equals("Z")) {
                                loc = null;
                            }
                        }
@@ -1463,7 +1796,7 @@
                wrkMast.setFullPlt(shallowLoc.getLocSts().equals("F") ? "Y" : "N"); // 满板
                wrkMast.setPicking("N"); // 拣料
                wrkMast.setExitMk("N"); // 退出
                wrkMast.setEmptyMk(shallowLoc.getLocSts().equals("D") ? "Y" : "N"); // 空板
                wrkMast.setEmptyMk(shallowLoc.getLocSts().equals("M") ? "M" : shallowLoc.getLocSts().equals("Z") ? "Z" : "N"); // 空板
                wrkMast.setBarcode(shallowLoc.getBarcode()); // 托盘码
                wrkMast.setLinkMis("N");
                wrkMast.setAppeTime(new Date());
@@ -1491,7 +1824,7 @@
                    }
                }
                // 修改源库位状态
                if (shallowLoc.getLocSts().equals("D") || shallowLoc.getLocSts().equals("F")) {
                if (shallowLoc.getLocSts().equals("F") || shallowLoc.getLocSts().equals("M") || shallowLoc.getLocSts().equals("Z")) {
                    shallowLoc.setLocSts("R"); // R.出库预约
                    shallowLoc.setModiTime(new Date());
                    if (!locMastService.updateById(shallowLoc)) {
@@ -1565,6 +1898,9 @@
                    case 1019:dismantlingMachine = 1020;break;
                    case 1034:dismantlingMachine = 1035;break;
                }
                if(staProtocol.getSiteId() == 1034 && staProtocol.isHigh()) {
                    continue;
                }
                if (wrkMastService.selectList(new EntityWrapper<WrkMast>().in("io_type", 110).eq("sta_no", dismantlingMachine)).size() > 0) {
//                    log.warn("{}站点已经存在两个空板出库任务", entry.getKey());
                    continue;
@@ -1584,7 +1920,7 @@
                    if (jsonObject.getInteger("code").equals(200)) {
                        log.info("空托出库请求成功:请求参数{},返回值:{}", map, response);
                    } else {
                        log.error("空拖出库请求接口失败!!!url:{};request:{};response:{}", wmsUrl + "/rpc/auto/emptyOut/v1", map, response);
//                        log.error("空拖出库请求接口失败!!!url:{};request:{};response:{}", wmsUrl + "/rpc/auto/emptyOut/v1", map, response);
                    }
                } catch (Exception e) {
                    log.error("空拖出库请求接口异常!!!url:{};request:{};response:{}", wmsUrl + "/rpc/auto/emptyOut/v1", map, response);
@@ -1608,17 +1944,63 @@
            } else {
                staProtocol = staProtocol.clone();
            }
            if (staProtocol.isAutoing() && staProtocol.isLoading() && (staProtocol.isInEnable() || staProtocol.isOutEnable() && site == 1090) && staProtocol.getWorkNo() != 0 && staProtocol.getWorkNo() < 9000) {
            if (staProtocol.isAutoing() && staProtocol.isLoading() && (staProtocol.isInEnable() || staProtocol.isOutEnable() && site == 1090) && staProtocol.getWorkNo() != 0 && (staProtocol.getWorkNo() <= 9000 || staProtocol.getWorkNo()>=30000)) {
                if (staProtocol.getSiteId() == 1034 && !staProtocol.isHigh()) { // 1034空母拖回流任务需要高信号
                    continue;
                }
                // 查询工作档
                WrkMast wrkMast = wrkMastMapper.selectByWrkNo(staProtocol.getWorkNo());
                if (wrkMast == null) {
                    log.error("呼叫rgv,任务号不存在:{}",staProtocol.getWorkNo());
                    continue;
                }
                if (staProtocol.getSiteId() == 1090 && wrkMast.getLocNo() == null) {
                // 1083,1086,1089 外形检测失败,不是去异常口的 停在原处
                if (staProtocol.getSiteId() == 1083 || staProtocol.getSiteId() == 1086 || staProtocol.getSiteId() == 1089 && wrkMast.getStaNo() != 1090) {
                    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) {
                        log.error("{}站点,外形检测失败:{}",site,errMsg);
                        continue;
                    }
                }
                if (staProtocol.getSiteId() == 1090 && wrkMast.getStaNo() == 1090) {
                    continue;
                }
                if ((wrkMast.getWrkSts() == 2 || wrkMast.getWrkSts() == 15) && wrkMast.getRgvNo() == null) {
                if ((wrkMast.getWrkSts() == 2 || wrkMast.getWrkSts() == 15 || (wrkMast.getIoType() == 120 && wrkMast.getWrkSts() == 52)) && (wrkMast.getRgvNo() == null || wrkMast.getRgvDstaNo() == 1090)) {
                    // 有1090的任务跳过rgv分配
                    if(wrkMast.getStaNo() == 1090) {
                        DevpThread devpThread2 = (DevpThread) SlaveConnection.get(SlaveType.Devp, 2);
                        StaProtocol staProtocol2 = devpThread2.getStation().get(1090);
                        if(!staProtocol2.isAutoing() || staProtocol2.isLoading() || staProtocol2.getWorkNo() != 0) {
                            log.info("{}去异常口目标站点,自动:{},有物:{},工作号为:{}",wrkMast.getWrkNo(),staProtocol2.isAutoing(),staProtocol2.isLoading(),staProtocol2.getWorkNo());
                            continue;
                        }
                        int count = wrkMastService.selectCount(new EntityWrapper<WrkMast>().where("sta_no = 1090 AND (wrk_sts IN (9,10) OR (wrk_sts = 2 AND rgv_finish_time IS NOT NULL))"));
                        if (count > 0) {
                            log.info("{}去异常口,但是前面有去异常口任务数:{}",wrkMast.getWrkNo(),count);
                            continue;
                        }
                    }
                    wrkMast.setRgvNo(0);
                    wrkMast.setRgvSstaNo(site);
                    wrkMast.setRgvDstaNo(taskStaNoToRgvStaNoMap.get(wrkMast.getStaNo()));
@@ -1634,7 +2016,7 @@
    /**
     * rgv放货完成,给输送线下发任务
     */
    public synchronized void rgvToDev() {
    public synchronized void rgvToDev() throws InterruptedException {
        for (Integer site : rgvConnectionSiteList) {
            // 输送线plc编号
            Integer devpPlcId = site < 1044 ? 1 : site <= 1090 ? 2 : 3;
@@ -1653,28 +2035,39 @@
                    continue;
                }
                if(wrkMast.getIoType() == 3 && (wrkMast.getStaNo() == 1024 || wrkMast.getStaNo() == 1016 || wrkMast.getStaNo() == 1043)) { // 到1024出库口,放到输送线后任务完成
                if(wrkMast.getIoType() == 3 && (wrkMast.getStaNo() == 1024 || wrkMast.getStaNo() == 1031 || wrkMast.getStaNo() == 1016 || wrkMast.getStaNo() == 1043)) {  // 到1024出库口,放到输送线后任务完成
                    if(wrkMast.getWrkSts() != 2 ){
                        log.warn("rgv放货完成,rgv未复位:rgv号{},任务号:{},任务状态{}",wrkMast.getRgvNo(),wrkMast.getWrkNo(),wrkMast.getWrkSts());
                        log.warn("rgv放货完成3,rgv未复位:rgv号{},任务号:{},任务状态{}",wrkMast.getRgvNo(),wrkMast.getWrkNo(),wrkMast.getWrkSts());
                        continue;
                    }
                    wrkMast.setWrkSts(5L);
//                    if(wrkMast.getStaNo() == 1090) {
//                        wrkMast.setWrkSts(3L);
//                    }
                    wrkMast.setModiTime(new Date());
                    wrkMastService.updateById(wrkMast);
                } else if(wrkMast.getIoType() == 101 && (wrkMast.getStaNo() == 1024 || wrkMast.getStaNo() == 1016 || wrkMast.getStaNo() == 1043)) {
                } else if(wrkMast.getIoType() == 101 && (wrkMast.getStaNo() == 1024 || wrkMast.getStaNo() == 1031 || wrkMast.getStaNo() == 1016 || wrkMast.getStaNo() == 1043)) {
                    if(wrkMast.getWrkSts() != 2 ) {
                        log.warn("rgv放货完成,rgv未复位:rgv号{},任务号:{},任务状态{}", wrkMast.getRgvNo(), wrkMast.getWrkNo(), wrkMast.getWrkSts());
                        log.warn("rgv放货完成101,rgv未复位:rgv号{},任务号:{},任务状态{}", wrkMast.getRgvNo(), wrkMast.getWrkNo(), wrkMast.getWrkSts());
                        continue;
                    }
                    wrkMast.setWrkSts(15L);
                    wrkMast.setModiTime(new Date());
                    wrkMastService.updateById(wrkMast);
                } else if(wrkMast.getIoType() == 110 && (wrkMast.getStaNo() == 1002 || wrkMast.getStaNo() == 1020 ||wrkMast.getStaNo() == 1035)) {
                } else if(wrkMast.getIoType() == 110 && (wrkMast.getStaNo() == 1002 || wrkMast.getStaNo() == 1020 ||wrkMast.getStaNo() == 1035 || wrkMast.getStaNo() == 1024)) {
                    if(wrkMast.getWrkSts() != 2 ){
                        log.warn("rgv放货完成,rgv未复位:rgv号{},任务号:{},任务状态{}",wrkMast.getRgvNo(),wrkMast.getWrkNo(),wrkMast.getWrkSts());
                        log.warn("rgv放货完成110,rgv未复位:rgv号{},任务号:{},任务状态{}",wrkMast.getRgvNo(),wrkMast.getWrkNo(),wrkMast.getWrkSts());
                        continue;
                    }
                    wrkMast.setWrkSts(15L);
                    wrkMast.setModiTime(new Date());
                    wrkMastService.updateById(wrkMast);
                } else if(wrkMast.getIoType() == 120) {
                    if(wrkMast.getWrkSts() != 53 ){
                        log.warn("rgv放货完成120,rgv未复位:rgv号{},任务号:{},任务状态{}",wrkMast.getRgvNo(),wrkMast.getWrkNo(),wrkMast.getWrkSts());
                        continue;
                    }
                    wrkMast.setWrkSts(54L);
                    wrkMast.setModiTime(new Date());
                    wrkMastService.updateById(wrkMast);
                }
@@ -1683,10 +2076,11 @@
                staProtocol.setWorkNo(staProtocol.getHideWorkNo());
                staProtocol.setStaNo(wrkMast.getStaNo().shortValue());
                if (!MessageQueue.offer(SlaveType.Devp, devpPlcId, new Task(2, staProtocol))) {
                    log.info("rgv搬运完成给输送线下发命令失败!,plc id:{},站点{},任务号:{},目标站:{}", devpPlcId,staProtocol.getStaNo(), staProtocol.getWorkNo(), staProtocol.getStaNo());
                    log.info("rgv搬运完成给输送线下发命令失败!,plc id:{},站点{},任务号:{},目标站:{}", devpPlcId,staProtocol.getSiteId(), staProtocol.getWorkNo(), staProtocol.getStaNo());
                } else {
                    log.info("rgv搬运完成给输送线下发命令成功plc id:{}!,站点{},任务号:{},目标站:{}", devpPlcId,staProtocol.getStaNo(), staProtocol.getWorkNo(), staProtocol.getStaNo());
                    log.info("rgv搬运完成给输送线下发命令成功plc id:{}!,站点{},任务号:{},目标站:{}", devpPlcId,staProtocol.getSiteId(), staProtocol.getWorkNo(), staProtocol.getStaNo());
                }
                Thread.sleep(300);
            }
        }
    }
@@ -1708,17 +2102,17 @@
            if (wrkMast == null) {
                log.error("异常口入库任务号无任务:{}", staProtocol.getWorkNo());
                return;
            } else if (wrkMast.getLocNo() != null) {
                log.info("异常口入库库位已分配:{}", wrkMast.getLocNo());
            } else if (wrkMast.getLocNo() != null && wrkMast.getLocNo().length() == 7) {
//                log.info("异常口入库库位已分配:{}", wrkMast.getLocNo());
                return;
            } else if(wrkMast.getStaNo() != 1090) {
                log.info("异常口入库入库目标站点已分配:{}", wrkMast.getStaNo());
//                log.info("异常口入库入库目标站点已分配:{}", wrkMast.getStaNo());
                return;
            }
            try {
                CanningLineInLocParam param = new CanningLineInLocParam();
                param.setWrkNo(staProtocol.getWrkNo());
                param.setWrkNo(staProtocol.getWorkNo());
                param.setSourceStaNo(1090);
                param.setTbFlag(staProtocol.isInEnable()); // true入成品库,false入空桶库
@@ -1731,19 +2125,7 @@
                log.info("异常口入库请求wms原始返回:" + response);
                JSONObject jsonObject = JSON.parseObject(response);
                if (jsonObject.getInteger("code").equals(200)) {
//                    StartupDto dto = jsonObject.getObject("data", StartupDto.class);
//                    staProtocol.setWorkNo(dto.getWorkNo());
//                    staProtocol.setStaNo(dto.getStaNo().shortValue());
//                    devpThread.setPakMk(staProtocol.getSiteId(), false);
//                    boolean result = MessageQueue.offer(SlaveType.Devp, 2, new Task(2, staProtocol));
//                    if (result) {
//                        log.info("异常口入库推送输送线命令成功:" + dto.getWorkNo() + "," + 1090 + "," + dto.getStaNo());
//                        News.info("异常口入库推送输送线命令成功:" + dto.getWorkNo() + "," + 1090 + "," + dto.getStaNo());
//                    } else {
//                        log.error("异常口入库推送输送线命令失败:" + dto.getWorkNo() + "," + 1090 + "," + dto.getStaNo());
//                        News.error("异常口入库推送输送线命令失败:" + dto.getWorkNo() + "," + 1090 + "," + dto.getStaNo());
//                        throw new CoolException("异常口入库推送输送线命令失败:" + 1090);
//                    }
                    log.error("异常口入库请求接口成功常,url:{},request:{},response:{}", wmsUrl + "/rpc/pakin/CanningLine/loc/v1", JSON.toJSONString(param), response);
                } else {
                    log.error("异常口入库请求接口异常,url:{},request:{},response:{}", wmsUrl + "/rpc/pakin/CanningLine/loc/v1", JSON.toJSONString(param), response);
                    News.error("异常口入库请求接口异常!!!url:{};request:{};response:{}", wmsUrl + "/rpc/pakin/CanningLine/loc/v1", JSON.toJSONString(param), response);
@@ -1821,7 +2203,12 @@
        }
        // 站点条件判断
        if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.isInEnable() && staProtocol.getWrkNo() == 0) {
        if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.isInEnable()
                 && staProtocol.getWorkNo() == 0 && staProtocol.isHigh()) {
            WrkMast wrkMast1 = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("io_type", 3).eq("source_sta_no", 1034).eq("sta_no", 1024));
            if (wrkMast1 != null) {
                return;
            }
            Date now = new Date();
            // 保存工作档
@@ -1830,6 +2217,7 @@
            wrkMast.setIoTime(now);
            wrkMast.setWrkSts(2L);
            wrkMast.setIoType(3);
            wrkMast.setIoPri(15D);
            wrkMast.setSourceStaNo(1034); // 源站
            wrkMast.setStaNo(1024); // 目标站
            wrkMast.setAppeTime(now);
@@ -1845,6 +2233,244 @@
                log.error("子托盘底座母托盘回流命令推送队列失败:" + wrkMast.getWrkNo() + "," + staProtocol.getSiteId());
            }
        }
    }
    public synchronized void autoOutEmptyBucket() {
        Config config = configService.selectOne(new EntityWrapper<Config>().eq("code", "autoOutEmptyBucket").eq("status", 1));
        if (config == null || Cools.isEmpty(config.getValue())) {
            return;
        }
        // 需要自动补空桶的站点
        String[] split = config.getValue().split("=");
        for (SearchLocParam.WantBucket wantBucket : getWantBucketFlag()) {
            if (wantBucket.getBucketType() != 0 && wantBucket.getWantBucketCount() > 0) { // 罐装线有要桶信号+要托数不为0
                boolean flag = true; // 是否需要自动补,true不需要,false需要
                for (String item : split) {
                    if (String.valueOf(wantBucket.getSite()).equals(item)) {
                        flag = false;
                        break;
                    }
                }
                if (flag) {
                    return;
                }
                // <4 < 2 < 4
                int count = wrkMastMapper.selectInGzxCount(wantBucket.getSite());
                if (wantBucket.getWantBucketCount() == 1) { // 最后剩一拖的时候
                    log.info("{}自动补空桶剩最后一托,罐装线要桶型信息:{},正在执行任务数:{}", wantBucket.getSite(), wantBucket.getBucketType(), count);
                    if (wantBucket.getSite() == 1071 && count <= 3 || wantBucket.getSite() == 1064 && count <= 1 || wantBucket.getSite() == 1078 && count <= 3) { // 可以出一个
                        List<LocDetl> locDetlList = locDetlService.selectListByMatnr(wantBucket.getBucketType());
                        if (locDetlList.size() == 0) {
                            log.warn("自动出空桶最后一个,库存无数据");
                            break;
                        }
                        Map<String, LocDetl> locDetlMap = locDetlList.stream().collect(Collectors.toMap(LocDetl::getLocNo, locDetl -> locDetl));
                        LocDetl locDetlSta = null;
                        for (LocDetl locDetl : locDetlList) {
                            String loc1 = locDetl.getLocNo(); // 当前库位
                            String row = loc1.substring(0, 2);
                            String rowNew = ""; // 对应库位
                            switch (row) {
                                case "09":
                                    rowNew = "10";
                                    break;
                                case "10":
                                    rowNew = "09";
                                    break;
                                case "11":
                                    rowNew = "12";
                                    break;
                                case "12":
                                    rowNew = "11";
                                    break;
                                default:
                            }
                            String locNoNew = rowNew + loc1.substring(2);
                            LocDetl locDetl1 = locDetlMap.get(locNoNew);
                            if (locDetl1 == null) {
                                locDetlSta = locDetl;
                                break;
                            }
                        }
                        // 没有单的,深浅库位都有,先取浅库位
                        if (locDetlSta == null) {
                            Optional<LocDetl> first = locDetlList.stream().filter(locDetl -> locDetl.getLocNo().startsWith("10") || locDetl.getLocNo().startsWith("11")).findFirst();
                            if (first.isPresent()) {
                                locDetlSta = first.get();
                            }
                        }
                        if (locDetlSta != null) {
                            try {
                                StockOutParam param = new StockOutParam();
                                param.setOutSite(wantBucket.getSite());
                                List<StockOutParam.LocDetl> locDetls = new ArrayList<>();
                                StockOutParam.LocDetl locDetl2 = new StockOutParam.LocDetl();
                                locDetl2.setLocNo(locDetlSta.getLocNo());
                                locDetl2.setMatnr(locDetlSta.getMatnr());
                                locDetl2.setBatch(locDetlSta.getBatch());
                                locDetl2.setBrand(locDetlSta.getBrand());
                                locDetl2.setCount(locDetlSta.getAnfme());
                                locDetl2.setBoxType1(locDetlSta.getBoxType1());
                                locDetl2.setBoxType2(locDetlSta.getBoxType2());
                                locDetl2.setBoxType3(locDetlSta.getBoxType3());
                                locDetl2.setStandby1(locDetlSta.getStandby1());
                                locDetl2.setStandby2(locDetlSta.getStandby2());
                                locDetl2.setStandby3(locDetlSta.getStandby3());
                                locDetls.add(locDetl2);
                                param.setLocDetls(locDetls);
                                String response = new HttpHandler.Builder()
                                        .setUri(wmsUrl)
                                        .setPath("/rpc/autoOutEmptyBucket")
                                        .setJson(JSON.toJSONString(param))
                                        .build()
                                        .doPost();
                                log.info("最后一个自动出空桶请求wms原始返回:" + response);
                                JSONObject jsonObject = JSON.parseObject(response);
                                if (jsonObject.getInteger("code").equals(200)) {
                                    decreaseWantBucketCount(wantBucket.getSite(), 1);
                                    log.info("最后一个自动出空桶成功:{}", wantBucket.getSite());
                                    return;
                                } else {
                                    News.error("最后一个自动空桶出库" + ":请求接口失败!!!url:{};request:{};response:{}", wmsUrl + "/rpc/autoOutEmptyBucket", JSON.toJSONString(param), response);
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                            }
                        }
                    }
                } else if (wantBucket.getSite() == 1071 && count <= 2 || wantBucket.getSite() == 1064 && count == 0 || wantBucket.getSite() == 1078 && count <= 2) { // 可以出两个
                    log.info("{}自动补空桶,罐装线要桶型信息:{},正在执行任务数:{}", wantBucket.getSite(), wantBucket.getBucketType(), count);
                    // 判断库里有无空桶组
                    List<LocDetl> locDetlList = locDetlService.selectListByMatnr(wantBucket.getBucketType());
                    for (int i = 0; i < locDetlList.size(); i++) {
                        LocDetl locDetl = locDetlList.get(i);
                        String loc1 = locDetl.getLocNo();
                        String aisle1 = loc1.substring(0, 2);
                        String column1 = loc1.substring(2, 5);
                        String level1 = loc1.substring(5, 7);
                        for (int j = i + 1; j < locDetlList.size(); j++) {
                            LocDetl locDetl1 = locDetlList.get(j);
                            String loc2 = locDetl1.getLocNo();
                            String aisle2 = loc2.substring(0, 2);
                            String column2 = loc2.substring(2, 5);
                            String level2 = loc2.substring(5, 7);
                            // 检查是否满足组队条件
                            if (isSameAisleGroup(aisle1, aisle2) && column1.equals(column2) && level1.equals(level2)) {
                                // 创建空桶出库任务
                                try {
                                    StockOutParam param = new StockOutParam();
                                    param.setOutSite(wantBucket.getSite());
                                    List<StockOutParam.LocDetl> locDetls = new ArrayList<>();
                                    StockOutParam.LocDetl locDetl2 = new StockOutParam.LocDetl();
                                    locDetl2.setLocNo(locDetl.getLocNo());
                                    locDetl2.setMatnr(locDetl.getMatnr());
                                    locDetl2.setBatch(locDetl.getBatch());
                                    locDetl2.setBrand(locDetl.getBrand());
                                    locDetl2.setCount(locDetl.getAnfme());
                                    locDetl2.setBoxType1(locDetl.getBoxType1());
                                    locDetl2.setBoxType2(locDetl.getBoxType2());
                                    locDetl2.setBoxType3(locDetl.getBoxType3());
                                    locDetl2.setStandby1(locDetl.getStandby1());
                                    locDetl2.setStandby2(locDetl.getStandby2());
                                    locDetl2.setStandby3(locDetl.getStandby3());
                                    locDetls.add(locDetl2);
                                    StockOutParam.LocDetl locDetl3 = new StockOutParam.LocDetl();
                                    locDetl3.setLocNo(locDetl1.getLocNo());
                                    locDetl3.setMatnr(locDetl1.getMatnr());
                                    locDetl3.setBatch(locDetl1.getBatch());
                                    locDetl3.setBrand(locDetl1.getBrand());
                                    locDetl3.setCount(locDetl1.getAnfme());
                                    locDetl3.setBoxType1(locDetl1.getBoxType1());
                                    locDetl3.setBoxType2(locDetl1.getBoxType2());
                                    locDetl3.setBoxType3(locDetl1.getBoxType3());
                                    locDetl3.setStandby1(locDetl1.getStandby1());
                                    locDetl3.setStandby2(locDetl1.getStandby2());
                                    locDetl3.setStandby3(locDetl1.getStandby3());
                                    locDetls.add(locDetl3);
                                    param.setLocDetls(locDetls);
                                    String response = new HttpHandler.Builder()
                                            .setUri(wmsUrl)
                                            .setPath("/rpc/autoOutEmptyBucket")
                                            .setJson(JSON.toJSONString(param))
                                            .build()
                                            .doPost();
                                    log.info("自动出空桶请求wms原始返回:" + response);
                                    JSONObject jsonObject = JSON.parseObject(response);
                                    if (jsonObject.getInteger("code").equals(200)) {
                                        decreaseWantBucketCount(wantBucket.getSite(), 2);
                                        log.info("自动出空桶成功:{}", wantBucket.getSite());
                                        return;
                                    } else {
                                        News.error("自动空桶出库" + ":请求接口失败!!!url:{};request:{};response:{}", wmsUrl + "/rpc/autoOutEmptyBucket", JSON.toJSONString(param), response);
                                    }
                                } catch (Exception e) {
                                    e.printStackTrace();
                                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                                }
                            }
                        }
                    }
                    if (locDetlList.size() > 0) {
                        log.info("没有成对的空桶组,只能一个一个出");
                        try {
                            LocDetl locDetl = locDetlList.get(0);
                            StockOutParam param = new StockOutParam();
                            param.setOutSite(wantBucket.getSite());
                            List<StockOutParam.LocDetl> locDetls = new ArrayList<>();
                            StockOutParam.LocDetl locDetl2 = new StockOutParam.LocDetl();
                            locDetl2.setLocNo(locDetl.getLocNo());
                            locDetl2.setMatnr(locDetl.getMatnr());
                            locDetl2.setBatch(locDetl.getBatch());
                            locDetl2.setBrand(locDetl.getBrand());
                            locDetl2.setCount(locDetl.getAnfme());
                            locDetl2.setBoxType1(locDetl.getBoxType1());
                            locDetl2.setBoxType2(locDetl.getBoxType2());
                            locDetl2.setBoxType3(locDetl.getBoxType3());
                            locDetl2.setStandby1(locDetl.getStandby1());
                            locDetl2.setStandby2(locDetl.getStandby2());
                            locDetl2.setStandby3(locDetl.getStandby3());
                            locDetls.add(locDetl2);
                            param.setLocDetls(locDetls);
                            String response = new HttpHandler.Builder()
                                    .setUri(wmsUrl)
                                    .setPath("/rpc/autoOutEmptyBucket")
                                    .setJson(JSON.toJSONString(param))
                                    .build()
                                    .doPost();
                            log.info("自动出空桶请求wms原始返回:" + response);
                            JSONObject jsonObject = JSON.parseObject(response);
                            if (jsonObject.getInteger("code").equals(200)) {
                                decreaseWantBucketCount(wantBucket.getSite(), 1);
                                log.info("自动出空桶成功:{}", wantBucket.getSite());
                                return;
                            } else {
                                News.error("自动空桶出库" + ":请求接口失败!!!url:{};request:{};response:{}", wmsUrl + "/rpc/autoOutEmptyBucket", JSON.toJSONString(param), response);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        }
                    }
                }
            }
        }
    }
    // 判断两个排是否属于同一组
    private static boolean isSameAisleGroup(String aisle1, String aisle2) {
        return (aisle1.equals("09") && aisle2.equals("10")) ||
                (aisle1.equals("10") && aisle2.equals("09")) ||
                (aisle1.equals("11") && aisle2.equals("12")) ||
                (aisle1.equals("12") && aisle2.equals("11"));
    }
    /**
@@ -1885,20 +2511,12 @@
                    param.setMatnr(staProtocol.getMatnr().trim());
                    param.setBatch(staProtocol.getBatch().trim());
                    param.setManuDate(staProtocol.getManuDate());
                    param.setWeight(staProtocol.getWeight());
                    param.setGrossWeight(staProtocol.getGrossWeight());
                    param.setWeight(Math.round(staProtocol.getWeight() * 100.0) / 100.0);
                    param.setGrossWeight(Math.round(staProtocol.getGrossWeight() * 100.0) / 100.0);
                    param.setReinspection(staProtocol.isReinspection());
                    param.setSourceStaNo(site + 2);
                    param.setTbFlag(staProtocol2.isBarcodeErr());
//                    param.setWrkNo(57);
//                    param.setMatnr("101");
//                    param.setBatch("tt1");
//                    param.setManuDate("2025-06-05");
//                    param.setWeight(100.0);
//                    param.setGrossWeight(100.0);
//                    param.setSourceStaNo(site);
//                    param.setTbFlag(true);
                    param.setCannedVolume(Math.round(staProtocol.getCannedVolume() * 100.0) / 100.0);
                    String response = new HttpHandler.Builder()
                            .setUri(wmsUrl)
@@ -1995,4 +2613,60 @@
            }
        }
    }
    /**
     * 手动站位转移
     */
    public synchronized void manualStationTransfer() {
        WrkMast wrkMast = wrkMastMapper.selectByIoTypeAndWrkSts(120, 51L);
        if (Cools.isEmpty(wrkMast)) {
            return;
        }
        int devpId;
        if (wrkMast.getSourceStaNo() < 1044) {
            devpId = 1;
        } else if (wrkMast.getSourceStaNo() < 1091) {
            devpId = 2;
        } else {
            devpId = 3;
        }
        SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devpId);
        try {
            StaProtocol staProtocol = devpThread.getStation().get(wrkMast.getSourceStaNo());
            if (staProtocol == null) {
                wrkMast.setIoTime(new Date());
                wrkMastService.updateById(wrkMast);
                return;
            } else {
                staProtocol = staProtocol.clone();
            }
            // 站点条件判断
            if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.getWorkNo() == 0 && staProtocol.isPakMk()) {
                // 更新站点信息 且 下发plc命令
                StaProtocol staProtocolNew = new StaProtocol();
                staProtocolNew.setSiteId(staProtocol.getSiteId());
                staProtocolNew.setWorkNo(wrkMast.getWrkNo());
                staProtocolNew.setStaNo(crnOutSiteToRgvSite2.get(wrkMast.getSourceStaNo()));
                devpThread.setPakMk(staProtocol.getSiteId(), false);
                boolean result = MessageQueue.offer(SlaveType.Devp, devpId, new Task(2, staProtocolNew));
                log.info("手动站位转移输送线下发:" + staProtocolNew.getWrkNo() + "," + staProtocolNew.getSiteId());
                if (!result) {
                    News.errorNoLog("" + " - 1" + " - 更新plc站点信息失败");
                    throw new CoolException("更新plc站点信息失败");
                }
                wrkMast.setIoTime(new Date());
                wrkMast.setWrkSts(52L);
                wrkMastService.updateById(wrkMast);
            } else {
                wrkMast.setIoTime(new Date());
                wrkMastService.updateById(wrkMast);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}