lsh
2025-11-20 a98f92c9bb825deb54752ccac3c9b7b8ed20695d
*废弃啦
11个文件已添加
6个文件已修改
3666 ■■■■ 已修改文件
pom.xml 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java 2490 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/MainProcess.java 126 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/entity/license/AbstractServerInfos.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/entity/license/CustomKeyStoreParam.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/entity/license/CustomLicenseManager.java 241 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/entity/license/LicenseCheck.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/entity/license/LicenseCheckListener.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/entity/license/LicenseCreator.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/entity/license/LicenseCreatorParam.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/entity/license/LicenseManagerHolder.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/entity/license/LicenseVerify.java 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/entity/license/LicenseVerifyParam.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/entity/license/WindowsServerInfos.java 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application.yml 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/common.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/console.map.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml
@@ -182,10 +182,15 @@
            <version>1.1.3.3</version>
            <systemPath>${project.basedir}/src/main/resources/lib/xpp3-1.1.3.3.jar</systemPath>
        </dependency>
        <dependency>
            <groupId>de.schlichtherle.truelicense</groupId>
            <artifactId>truelicense-core</artifactId>
            <version>1.33</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>jshdwcs</finalName>
        <finalName>zzgtwcs</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java
@@ -7,20 +7,11 @@
import com.core.common.*;
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.param.AgvTaskAssignmentParam;
import com.zy.asrs.entity.param.ArmOrderAssignmentParam;
import com.zy.asrs.entity.param.ArmTaskAssignmentParam;
import com.zy.asrs.entity.param.CombParam;
import com.zy.asrs.entity.result.OrderDetlValueResultUtil;
import com.zy.asrs.mapper.*;
import com.zy.asrs.service.*;
import com.zy.asrs.utils.PostMesDataUtils;
import com.zy.asrs.utils.RouteUtils;
import com.zy.asrs.utils.Utils;
import com.zy.asrs.utils.VersionUtils;
import com.zy.asrs.utils.core.ReturnT;
import com.zy.common.constant.AgvConstant;
import com.zy.common.constant.ArmConstant;
import com.zy.common.model.LocTypeDto;
import com.zy.common.model.MatDto;
import com.zy.common.model.SearchLocParam;
@@ -37,15 +28,13 @@
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 com.zy.system.entity.license.LicenseVerify;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@@ -76,8 +65,6 @@
    @Autowired
    private WrkDetlService wrkDetlService;
    @Autowired
    private WaitPakinMapper waitPakinMapper;
    @Autowired
    private LocMastService locMastService;
    @Autowired
    private StaDescService staDescService;
@@ -92,36 +79,30 @@
    @Autowired
    private BasCrnErrorMapper basCrnErrorMapper;
    @Autowired
    private WrkMastStaMapper wrkMastStaMapper;
    @Autowired
    private BasRgvService basRgvService;
    @Autowired
    private BasRgvMapMapper basRgvMapMapper;
    @Autowired
    private WrkMastService wrkMastService;
    @Autowired
    private WrkMastStaService wrkMastStaService;
    @Autowired
    private BasRgvMapService basRgvMapService;
    @Autowired
    private BasArmService basArmService;
    @Autowired
    private BasAgvMastService basAgvMastService;
    @Autowired
    private BasArmMastService basArmMastService;
    @Autowired
    private ApiLogService apiLogService;
    @Value("${wms.url}")
    private String wmsUrl;
    @Value("${wms.comb}")
    private String wmsComb;
    @Value("${inventory.number}")
    private Integer inventoryNumber;
    public Integer wrkNo = 10001;
    public static final List<Integer> LEFT_POSITION = Arrays.asList(1004,1014,1018,1028,1035,2006,2012,2018,2024,2030);
    /*
     * 验证许可证是否有效
     * */
    public synchronized boolean licenseVerify() {
        try{
//            if (true) {
//                return true;
//            }
            return new LicenseVerify().verify();
        } catch (Exception e){
            log.info("许可证验证失败!!异常:{}",e.getMessage());
        }
        return false;
    }
    /**
     * 组托
     * 入库站,根据条码扫描生成入库工作档,工作状态 2
@@ -1750,90 +1731,6 @@
//
////            // 入出库模式判断
////            if (devpThread.ioMode != IoModeType.PAKOUT_MODE) { continue; }
//
//
//            // 查询站点详细信息
//            BasDevp staDetl = basDevpService.selectById(crnStn.getStaNo());
//            if (staDetl == null) {
//                log.error("出库 ===>> 堆垛机站点在数据库不存在, 站点编号={}", crnStn.getStaNo());
//                continue;
//            }
//            // 判断堆垛机出库站状态
//            if (staProtocol.isAutoing() && !staProtocol.isLoading() && staDetl.getCanouting() !=null && staDetl.getCanouting().equals("Y")
//                    && staProtocol.getWorkNo() == 0 && staProtocol.isOutEnable()) {
//                // 命令下发区 --------------------------------------------------------------------------
//
//                // 堆垛机控制过滤
//                if (!crnProtocol.getStatusType().equals(CrnStatusType.IDLE) || crnProtocol.getTaskNo() != 0) {
//                    continue;
//                }
//
//                // 双深库位且浅库位有货,则需先对浅库位进行库位移转
//                if (Utils.isDeepLoc(slaveProperties, wrkMast.getSourceLocNo())) {
//                    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")) {
//                        WrkMast waitWrkMast = wrkMastMapper.selectByLocNo(shallowLocNo);
//                        if (null == waitWrkMast) {
//                            log.error("{}库位异常,未检索到相应工作档!", shallowLocNo);
//                        } else {
//                            if(waitWrkMast.getWrkSts() == 11) {
//                                waitWrkMast.setIoPri(15D);
//                                waitWrkMast.setModiTime(new Date());
//                                if (wrkMastMapper.updateById(waitWrkMast) == 0) {
//                                    log.error("调整工作档优先级失败!工作号={}", waitWrkMast.getWrkNo());
//                                }
//                                continue;
//                            } else {
//
//                            }
//                        }
//                    } else if (shallowLoc.getLocSts().equals("F") || shallowLoc.getLocSts().equals("D")) {
//                        // 此标记避免多次执行移库任务
//                        if (Cools.isEmpty(wrkMast.getUpdMk()) || "N".equals(wrkMast.getUpdMk())) {
//                            wrkMast.setUpdMk("Y");
//                            wrkMastMapper.updateById(wrkMast);
//                            // 生成工作档、改变浅库位的源库/目标库 库位状态、下发堆垛机命令(立马执行)
//                            moveLocForDeepLoc(slave, shallowLoc);
//                        }
//                        log.error("{}任务出库失败,浅库位堵塞!", wrkMast.getWrkNo());
//                        continue;
//                    }
//                }
//
//                // 已经存在吊车执行任务时,则过滤
//                if (wrkMastMapper.selectWorking(slave.getId()) != null) {
//                    return;
//                }
//
//                // 1.堆垛机开始移动
//                CrnCommand crnCommand = new CrnCommand();
//                crnCommand.setCrnNo(slave.getId()); // 堆垛机编号
//                crnCommand.setTaskNo(wrkMast.getWrkNo().shortValue()); // 工作号
//                crnCommand.setAckFinish((short) 0);  // 任务完成确认位
//                crnCommand.setTaskMode(CrnTaskModeType.LOC_MOVE); // 任务模式:  库位移转
//                crnCommand.setSourcePosX(sourceSta.getRow1().shortValue());     // 源库位排
//                crnCommand.setSourcePosY(sourceSta.getBay1().shortValue());     // 源库位列
//                crnCommand.setSourcePosZ(sourceSta.getLev1().shortValue());     // 源库位层
//                crnCommand.setDestinationPosX(crnStn.getRow().shortValue());     // 目标库位排
//                crnCommand.setDestinationPosY(crnStn.getBay().shortValue());     // 目标库位列
//                crnCommand.setDestinationPosZ(crnStn.getLev().shortValue());     // 目标库位层
//                if (!MessageQueue.offer(SlaveType.Crn, wrkMast.getCrnNo(), new Task(2, crnCommand))) {
//                    log.error("堆垛机命令下发失败,堆垛机号={},任务数据={}", wrkMast.getCrnNo(), JSON.toJSON(crnCommand));
//                } else {
//                    // 修改工作档状态 11.生成出库ID => 12.吊车出库中
//                    Date now = new Date();
//                    wrkMast.setWrkSts(12L);
//                    wrkMast.setCrnStrTime(now);
//                    wrkMast.setModiTime(now);
//                    if (wrkMastMapper.updateById(wrkMast) == 0) {
//                        log.error("修改工作档状态 11.生成出库ID => 12.吊车出库中 失败!!,工作号={}", wrkMast.getWrkNo());
//                    }
//                }
//            }
//        }
//    }
    /**
     * 库位移转
@@ -2618,157 +2515,6 @@
    }
    /**
     * 堆垛机演示  ===>> 库位移转
     */
    public synchronized void crnDemoOfLocMove1() {
        try {
            for (CrnSlave crn : slaveProperties.getCrn()) {
                if (!crn.getDemo()) {
                    continue;
                }   // 必须为演示状态
                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) {
                    // 获取移库工作档信息
                    WrkMast wrkMast = wrkMastMapper.selectLocMove(crn.getId());
                    if (null != wrkMast) {
                        continue;
                    }
                    LocMast sourceLoc = locMastService.queryDemoSourceLoc(crn.getId());
                    LocMast loc = locMastService.queryDemoLoc(crn.getId());
                    if (null == sourceLoc || null == loc) {
                        continue;
                    }
                    String sourceLocNo = sourceLoc.getLocNo();
                    String locNo = loc.getLocNo();
                    // 获取工作号
                    int workNo = commonService.getWorkNo(0);
                    // 保存工作档
                    wrkMast = new WrkMast();
                    wrkMast.setWrkNo(workNo);
                    wrkMast.setIoTime(new Date());
                    wrkMast.setWrkSts(11L); // 工作状态:11.生成出库ID
                    wrkMast.setIoType(11); // 入出库状态: 11.库格移载
                    wrkMast.setIoPri(13D);
                    wrkMast.setCrnNo(crn.getId());
                    wrkMast.setSourceLocNo(sourceLocNo); // 源库位
                    wrkMast.setLocNo(locNo); // 目标库位
                    wrkMast.setFullPlt("N"); // 满板:Y
                    wrkMast.setPicking("N"); // 拣料
                    wrkMast.setExitMk("N"); // 退出
                    wrkMast.setEmptyMk(sourceLoc.getLocSts().equals("D") ? "Y" : "N"); // 空板
                    wrkMast.setBarcode(sourceLoc.getBarcode()); // 托盘码
                    wrkMast.setLinkMis("N");
                    wrkMast.setAppeTime(new Date());
                    wrkMast.setModiTime(new Date());
                    int res = wrkMastMapper.insert(wrkMast);
                    if (res == 0) {
                        throw new CoolException("保存工作档失败");
                    }
                    // 工作档明细保存
//                List<LocDetl> locDetls = locDetlService.selectList(new EntityWrapper<LocDetl>().eq("loc_no", sourceLocNo));
//                for (LocDetl locDetl : locDetls) {
//                    WrkDetl wrkDetl = new WrkDetl();
//                    wrkDetl.setWrkNo(workNo);
//                    wrkDetl.setIoTime(new Date());
//                    wrkDetl.setAnfme(locDetl.getAnfme());
//                    VersionUtils.setWrkDetl(wrkDetl, locDetl); // 版本控制
//                    wrkDetl.setAppeTime(new Date());
//                    wrkDetl.setModiTime(new Date());
//                    if (!wrkDetlService.insert(wrkDetl)) {
//                        throw new CoolException("保存工作档明细失败");
//                    }
//                }
                    // 修改源库位状态
                    if (sourceLoc.getLocSts().equals("D")) {
                        sourceLoc.setLocSts("R"); // R.出库预约
                        sourceLoc.setModiTime(new Date());
                        if (!locMastService.updateById(sourceLoc)) {
                            throw new CoolException("更新源库位状态失败");
                        }
                    } else {
                        throw new CoolException("源库位出库失败");
                    }
                    // 修改目标库位状态
                    if (loc.getLocSts().equals("O")) {
                        loc.setLocSts("S"); // S.入库预约
                        loc.setModiTime(new Date());
                        if (!locMastService.updateById(loc)) {
                            throw new CoolException("更新目标库位状态失败");
                        }
                    } else {
                        throw new CoolException("移转失败");
                    }
                }
            }
        } catch (Exception e) {
            News.error("堆垛机演示  ===>> 库位移转失败", e);
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }
    /**
     * 堆垛机命令下发后,异步修改工作档状态
     */
    public synchronized void crnIoWrkMast() {
        for (CrnSlave crn : slaveProperties.getCrn()) {
            // 获取堆垛机信息
            CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crn.getId());
            CrnProtocol crnProtocol = crnThread.getCrnProtocol();
            if (crnProtocol == null) {
                continue;
            }
            Date now = new Date();
            // 堆垛机正在运行
            if (crnProtocol.getStatusType() != CrnStatusType.IDLE && crnProtocol.getTaskNo() != 0 && crnProtocol.getModeType() == CrnModeType.AUTO) {
                // 获取工作档
                WrkMast wrkMast = wrkMastMapper.selectById(crnProtocol.getTaskNo());
                if (wrkMast == null) {
                    continue;
                }
                // 入库
                if (wrkMast.getWrkSts() == 1 || wrkMast.getWrkSts() == 2) {
                    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) {
                        News.error("修改工作档状态 2.设备上走 => 3.吊车入库中 失败!!,工作号={}", wrkMast.getWrkNo());
                    }
                    News.warn("修改工作档状态成功。[时间:{}] >>>>> 任务号:{}", DateUtils.convert(now, DateUtils.yyyyMMddHHmmsssss_F), wrkMast.getWrkNo());
                }
                // 出库、移库
                if (wrkMast.getWrkSts() == 11) {
                    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) {
                        News.error("修改工作档状态 11.生成出库ID => 12.吊车出库中 失败!!,工作号={}", wrkMast.getWrkNo());
                    }
                    News.warn("修改工作档状态成功。[时间:{}] >>>>> 任务号:{}", DateUtils.convert(now, DateUtils.yyyyMMddHHmmsssss_F), wrkMast.getWrkNo());
                }
            }
        }
    }
    /**
     * 入出库模式切换函数
     */
    public synchronized void ioConvert() {
@@ -2845,2208 +2591,6 @@
                }
            }
        }
//        News.infoNoLog(""+mark+" - 0"+" - outOfDevp执行完成");
    }
    public synchronized void autoEmptyOut() {
        SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, 1);
        List<Integer> list = new ArrayList<>();
        list.add(1108);list.add(2031);
        for (Integer site:list){
            Integer emptyCount = wrkMastMapper.countPakOutEmpty(site);
            StaProtocol staProtocol = null;
            if(emptyCount >= 1 && site == 1108){
                continue;
            }else if(emptyCount == 1 && site == 2031){
                continue;
            }
            //如果站点可出禁用,则不生成空盘出库任务
            switch (site){
                case 1108:staProtocol = devpThread.getStation().get(site - 2);break;
                case 2031:staProtocol = devpThread.getStation().get(site);break;
            }
            if (staProtocol == null) {
                return;
            } else {
                staProtocol = staProtocol.clone();
            }
            if (staProtocol.isAutoing()  //自动
                    && !staProtocol.isLoading()  //无物
//                    && staProtocol.isOutEnable()  //可出信号
                    && staProtocol.getWorkNo() == 0
            ) {
                Short loctype1 = 1;
                LocTypeDto locTypeDto = new LocTypeDto(loctype1, (short) 1, (short) 1);
                locTypeDto.setSiteId(site);
                try {
                    String response = new HttpHandler.Builder()
                            .setUri(wmsUrl)
                            .setPath("/rpc/auto/emptyOut/v1")
                            .setJson(JSON.toJSONString(locTypeDto))
                            .build()
                            .doPost();
                    JSONObject jsonObject = JSON.parseObject(response);
                    if (jsonObject.getInteger("code").equals(200)) {
                        String data = jsonObject.get("data").toString();
                        News.info((String) jsonObject.get("msg")+","+data);
                    } else {
                        News.warnNoLog("请求接口失败!!!url:{};request:{};response:{}", wmsUrl + "/rpc/auto/emptyOut/v1","", response);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                }
            }
        }
    }
    public synchronized void autoEmptyIn() {
         SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, 1);
        List<Integer> list = new ArrayList<>();
        list.add(1038);
        for (Integer site:list){
            StaProtocol staProtocol = devpThread.getStation().get(site);
            StaProtocol staProtocol1 = devpThread.getStation().get(1040);
            if (staProtocol == null) {
                return;
            } else {
                staProtocol = staProtocol.clone();
            }
            if (staProtocol.isAutoing()  //自动
                    && staProtocol.isLoading()  //有物
                    && staProtocol.isInEnable()  //可入信号
                    && staProtocol.isPakMk()
                    && staProtocol1.isFull() //叠满信号
                    && (staProtocol.getWorkNo() == 0 || staProtocol.getWorkNo() > 9990 ) //工作号为0或者工作号是9991~9999(输送机留用)
            ) {
                System.out.println(staProtocol);
                try {
                    Short loctype1 = 1;
                    LocTypeDto locTypeDto = new LocTypeDto(loctype1, (short) 1, (short) 1);
                    locTypeDto.setSiteId(site);
                    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"));
                        staProtocol.setWorkNo(jsonObject.get("data").hashCode());
                        staProtocol.setStaNo(site.shortValue());
                        devpThread.setPakMk(site,false);
                        MessageQueue.offer(SlaveType.Devp, 1, new Task(2, staProtocol));
                    } 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,String sign){
//        log.info("小车地图更新![标记:{}];[BasRgvMap:{}];[staStart:{}];[staEnd:{}];",sign,JSON.toJSONString(basRgvMapCurrent),staStart,staEnd);
//        List<Integer> integers = RouteUtils.RouteMapCurrentFar(basRgvMapCurrent.getNowRoute(),staStart,staEnd, basRgvMapCurrent.getLockStartRoute());
        //更新当前小车锁
        try{
            Integer farCurrentStaNo = RouteUtils.RouteIndexFarMas(basRgvMapCurrent.getNowRoute(), staStart, staEnd, basRgvMapCurrent.getLockStartRoute());//获取最远站点
//            log.info("小车地图更新!获取最远站点;[farCurrentStaNo:{}]",farCurrentStaNo);
            Integer fallMerge = RouteUtils.RouteIndexFarMas(basRgvMapCurrent.getRgvNo(), farCurrentStaNo); //获取合并干涉项
//            log.info("小车地图更新!获取合并干涉项;[fallMerge:{}]",fallMerge);
            basRgvMapCurrent.setLockEndRoute(fallMerge);
            Integer i = basRgvMapMapper.updateById(basRgvMapCurrent);
//            if (i>0){
//                log.error("{}:==>{}:{}号车更新结束锁,{}",sign,new Date(),basRgvMapCurrent.getRgvNo(),JSON.toJSONString(basRgvMapCurrent));
//            }
            //更新另一台小车地图
            Integer rgvNoOther = basRgvMapCurrent.getRgvNoOther(basRgvMapCurrent.getRgvNo());
//            log.info("小车地图更新!另一台小车号;[rgvNoOther:{}]",rgvNoOther);
            BasRgvMap basRgvMapOther = basRgvMapMapper.selectById(rgvNoOther);
//            log.info("小车地图更新!另一台小车;[basRgvMapOther:{}]",JSON.toJSONString(basRgvMapOther));
            List<Integer> integers = RouteUtils.RouteMapCurrentFar(fallMerge, basRgvMapCurrent.getLockStartRoute());
            Integer lockEndRoute = RouteUtils.RouteMapOtherFarStnNo(integers, basRgvMapCurrent.getLockStartRoute());//另一台小车可活动最远位置
//            log.info("小车地图更新!另一台小车可活动最远位置;[lockEndRoute:{}]",lockEndRoute);
            basRgvMapOther.setEndRoute(lockEndRoute);
            Integer i1 = basRgvMapMapper.updateById(basRgvMapOther);
//            if (i1>0){
//                log.error("{}:==>{}:{}号车更新结束位置,{}",sign,new Date(),basRgvMapOther.getRgvNo(),JSON.toJSONString(basRgvMapOther));
//            }
            return true;
        }catch (Exception e){
            log.error("小车地图更新出错!异常原因:"+e);
            return false;
        }
    }
    /*
     * 刷新地图数据
     * */
    public synchronized void refreshRgvMap() {
        try{
            List<BasRgvMap> basRgvMaps = basRgvMapService.selectList(new EntityWrapper<>());
            for (BasRgvMap rgvSlave:basRgvMaps) {
                RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, rgvSlave.getRgvNo());
                RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
                if (rgvProtocol == null) {
                    continue;
                }else {
                    rgvProtocol = rgvProtocol.clone();
                }
                BasRgv basRgv = basRgvService.selectById(rgvSlave.getRgvNo());
                if (basRgv == null) {
                    log.error("{}号RGV尚未在数据库进行维护!2", rgvSlave.getRgvNo());
                    continue;
                }
                Integer site = rgvProtocol.getRgvNo() == 1 ? rgvProtocol.getRgvPosI1() : rgvProtocol.getRgvPosI2();
                if (site == 0) {
                    continue;
                }
                rgvSlave.setNowRoute(site); // 更新小车当前位置站点号
                if (!basRgvMapService.updateById(rgvSlave)) {
                    log.error("小车更新地图失败");
                }
            }
        }catch (Exception e){
            log.error("小车更新地图失败");
        }
    }
    /**
     *  自动生成RGV接驳任务(检索出入口任务,生成对应RGV任务,检索4楼任务,非3号堆垛机,则生成对应接驳任务)
     */
//    public synchronized  void rgvCreateWrkMastSta(){
//        try{
//            for (DevpSlave devp : slaveProperties.getDevp()) {
//                SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
//                StaProtocol staProtocol = devpThread.getStation().get(1105);
//                if (staProtocol == null) {
//                    continue;
//                } else {
//                    staProtocol = staProtocol.clone();
//                }
//                if (!staProtocol.isAutoing() || !staProtocol.isLoading()){
//                    continue;
//                }
//            }
//        }
//    }
    /**
     * 小车上工位左右移动
     *
     */
//    public synchronized boolean rgvStaMove(Long workNo) {
//        try {
//            for (RgvSlave rgv : slaveProperties.getRgv()) {
//                RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, rgv.getId());
//                RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
//                if (rgvProtocol == null) {
//                    continue;
//                } else {
//                    rgvProtocol = rgvProtocol.clone();
//                }
//                if (rgvProtocol.isLoaded2ing() && rgvProtocol.isLoaded1ing()) {
//                    continue;
//                }
//                if (rgvProtocol.isLoaded1ing() && !rgvProtocol.isLoaded2ing() && rgvProtocol.getTaskNo1() != 0) {
//                    WrkMastSta wrkMastSta = wrkMastStaMapper.selectByWrkNo(rgvProtocol.getTaskNo1());
//                    Short moveSta = 0;
//
//                    if (wrkMastSta.getStaEnd() < 1036 || (2000 < wrkMastSta.getStaEnd() && wrkMastSta.getStaEnd() < 2031)) {
//                        moveSta = 2;
//                        boolean rgvComplete = rgvComplete3((int) rgvProtocol.getRgvNo(), 7, wrkMastSta.getWrkNo(), moveSta);
//                        if (!rgvComplete) {
//                            log.error("小车工位移动失败,小车号{}!", rgvProtocol.getRgvNo());
//                            break;
//                        }
//                    }
//                }
//                if (!rgvProtocol.isLoaded1ing() && rgvProtocol.isLoaded2ing() && rgvProtocol.getTaskNo2() != 0) {
//                    WrkMastSta wrkMastSta = wrkMastStaMapper.selectByWrkNo(rgvProtocol.getTaskNo2());
//                    Short moveSta = 0;
//
//                    if (wrkMastSta.getStaEnd() > 2030 || (1036 < wrkMastSta.getStaEnd() && wrkMastSta.getStaEnd() < 2000)) {
//                        moveSta = 1;
//                        boolean rgvComplete = rgvComplete3((int) rgvProtocol.getRgvNo(), 8, wrkMastSta.getWrkNo(), moveSta);
//                        if (!rgvComplete) {
//                            log.error("小车工位移动失败,小车号{}!", rgvProtocol.getRgvNo());
//                            break;
//                        }
//                    }
//                }
//
//
//            }
//        } catch (Exception e) {
//            log.error("小车复位线程报错!" + e);
//        }
//    }
    /**
     *  完成小车任务
     */
//    public synchronized void rgvCompleteWrkMastSta() {
//        try{
//            for (DevpSlave devp : slaveProperties.getDevp()) {
//                List<BasRgvMap> basRgvMaps = basRgvMapService.selectList(new EntityWrapper<>());
//            for (RgvSlave rgv : slaveProperties.getRgv()) {
//                RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, rgv.getId());
//                RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
//                if (rgvProtocol == null) {
//                    continue;
//                }else {
//                    rgvProtocol = rgvProtocol.clone();
//                }
//                BasRgv basRgv = basRgvService.selectById(rgv.getId());
//                if (basRgv == null) {
//                    log.error("{}号RGV尚未在数据库进行维护!3", rgv.getId());
//                    continue;
//                }
//                //放货确认
//                if(rgvProtocol.getStatusType1()==RgvStatusType.FETCHWAITING && rgvProtocol.getModeType() == RgvModeType.AUTO){
//                    boolean rgvComplete = rgvComplete((int) rgvProtocol.getRgvNo(), 3);
//                    if (!rgvComplete){
//                        log.error("小车放货复位失败,小车号{}!", rgvProtocol.getRgvNo());
//                    }
//                }
//                if(rgvProtocol.getStatusType2()==RgvStatusType.FETCHWAITING && rgvProtocol.getModeType() == RgvModeType.AUTO){
//                    boolean rgvComplete = rgvComplete((int) rgvProtocol.getRgvNo(), 6);
//                    if (!rgvComplete){
//                        log.error("小车放货复位失败,小车号{}!", rgvProtocol.getRgvNo());
//                    }
//                }
//
//                // 只有当RGV工位1等待WCS确认、自动
//                if (rgvProtocol.getStatusType1() == RgvStatusType.WAITING
//                        && rgvProtocol.getModeType() == RgvModeType.AUTO
//                ){
//
//                    log.info("{}号小车等待wcs确认,状态{},参数{}",rgvProtocol.getRgvNo(),rgvProtocol.getStatusType1(),rgvProtocol);
//                    if(rgvProtocol.getTaskNo1() == 9999){ // 预调度任务确认
//                        BasRgvMap basRgvMap = basRgvMapMapper.selectById(rgvProtocol.getRgvNo());
//                        Integer staNo = basRgvMap.getNowRoute();
//                        switch (staNo){
//                            case 1004: staNo = 1042; break;
//                            case 1007: staNo = 1105; break;
//                        }
//
//                        SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
//                        StaProtocol staProtocol = devpThread.getStation().get(staNo);
//                        boolean rgvComplete = false;
//                        long now = System.currentTimeMillis();
//                        if (staProtocol.isLoading()) {
//                            rgvProtocol.setLoadingStartTime(null); // 已到位,清空时间戳
//                        } else {
//                            if (rgvProtocol.getLoadingStartTime() == null) {
//                                rgvProtocol.setLoadingStartTime(now);
//                            }
//                        }
//
//                        if (staProtocol.isLoading()) {
//                            rgvComplete = rgvComplete((int) rgvProtocol.getRgvNo(), 3);
//                            if (!rgvComplete){
//                                log.error("小车复位失败,小车号{}!等待入库取货", rgvProtocol.getRgvNo());
//                            }
//                        }
//                    }
//                    if ( rgvProtocol.getTaskNo1()!=9999 && rgvProtocol.getTaskNo1() != 0){
//                        WrkMastSta wrkMastSta = wrkMastStaMapper.selectByWrkNo(rgvProtocol.getTaskNo1());
//                        if(null == wrkMastSta){
//                            log.error("小车无任务");
//                            continue;
//                        }
//                        if(wrkMastSta.getWrkSts() == 1){//取货确认
////                            if(!Objects.equals(rgvProtocol.getRgvPosI2(), wrkMastSta.getStaEnd())){
////                                continue;
////                            }
//                            boolean rgvComplete = false;
//                            rgvComplete = rgvComplete3((int) rgvProtocol.getRgvNo(),7,wrkMastSta.getWrkNo(),(short)2);
//                            if (!rgvComplete){
//                                log.error("小车复位失败,小车号{}!",rgvProtocol.getRgvNo());
//                                break;
//                            }
//                            wrkMastSta.setUpdateTime(new Date());
//                            wrkMastSta.setWrkSts(2);
//                            try{
//                                wrkMastStaMapper.updateById(wrkMastSta);
//                                log.error("更新小车任务成功");
//                            }catch (Exception e){
//                                log.error("更新小车任务失败");
//                            }
//                            break;
//                        }
//                    }
//
//                    else {
//                        log.error("小车复位失败,小车号{},等待wcs确认但是没有工作号!",rgvProtocol.getRgvNo());
//                    }
//                }
//                // 只有当RGV工位2等待WCS确认、自动
//                if (rgvProtocol.getStatusType2() == RgvStatusType.WAITING
//                        && rgvProtocol.getModeType() == RgvModeType.AUTO
//                ){
//                    log.info("{}号小车等待wcs确认,状态{},参数{}",rgvProtocol.getRgvNo(),rgvProtocol.getStatusType2(),rgvProtocol);
//                    if (rgvProtocol.getTaskNo2() !=0 ){
//                        WrkMastSta wrkMastSta = wrkMastStaMapper.selectByWrkNo(rgvProtocol.getTaskNo2());
//                        if(wrkMastSta.getWrkSts() == 1){//取货确认
//                            boolean rgvComplete = false;
//                            rgvComplete = rgvComplete3((int) rgvProtocol.getRgvNo(),8,wrkMastSta.getWrkNo(),(short)1);
//                            if (!rgvComplete){
//                                log.error("小车复位失败,小车号{}!",rgvProtocol.getRgvNo());
//                                break;
//                            }
//                            wrkMastSta.setWrkSts(2);
//                            try{
//                                wrkMastStaMapper.updateById(wrkMastSta);
//                                log.error("更新小车任务成功");
//                            }catch (Exception e){
//                                log.error("更新小车任务失败");
//                            }
//                            break;
//                        }
//                        if(wrkMastSta.getWrkSts() == 4){//行走后确认
//                            wrkMastSta.setWrkSts(2);
//                            try{
//                                wrkMastStaMapper.updateById(wrkMastSta);
//                                log.error("更新小车任务成功");
//                            }catch (Exception e){
//                                log.error("更新小车任务失败");
//                            }
//                            boolean rgvComplete = false;
//
//                            rgvComplete = rgvComplete((int) rgvProtocol.getRgvNo(),7);
//                            if (!rgvComplete){
//                                log.error("小车复位失败,小车号{}!",rgvProtocol.getRgvNo());
//                                break;
//                            }
//                            break;
//                        }
//                        if (Cools.isEmpty(wrkMastSta) || wrkMastSta.getWrkSts()!=1){
//                            log.error("未查到小车执行任务或者执行任务状态不符合!"+wrkMastSta);
//                            continue;
//                        }
//                        SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
//                        StaProtocol staProtocol = devpThread.getStation().get(wrkMastSta.getStaEnd());
//                        if (staProtocol == null) {
//                            continue;
//                        } else {
//                            staProtocol = staProtocol.clone();
//                        }
//                        if (!staProtocol.isAutoing() || !staProtocol.isLoading()){
//                            continue;
//                        }
//                        WrkMast wrkMast = wrkMastMapper.selectPakInStep3(wrkMastSta.getWrkNo().intValue());
//
//                        int sourceSta = wrkMast.getSourceStaNo();
//                        boolean rgvComplete = false;
//
//                        //双工位出入库不同工位复位
//                        rgvComplete = rgvComplete((int) rgvProtocol.getRgvNo(),6);
//                        if (!rgvComplete){
//                            log.error("小车复位失败,小车号{}!",rgvProtocol.getRgvNo());
//                            break;
//                        }
//                        WrkMast wrkMast1 = wrkMastService.selectByWrkNo(rgvProtocol.getTaskNo1());
//                        wrkMast1.setPdcType("Y");
//
//                        wrkMastService.updateById(wrkMast1);
//
//                        wrkMastSta.setWrkSts(3);
//                        wrkMastStaMapper.updateById(wrkMastSta);
//                        BasRgvMap basRgvMap = basRgvMapMapper.selectById(rgvProtocol.getRgvNo());
//                        basRgvMap.setNowRoute(rgvProtocol.getRgvPosI());
//                        rgvMapUpdate(basRgvMap,basRgvMap.getStartRoute(),basRgvMap.getStartRoute(),"2471");
//                    }
//                    else {
//                        log.error("小车复位失败,小车号{},等待wcs确认!",rgvProtocol.getRgvNo());
//                    }
//                }
//                //当小车无任务时取消锁定
//                if(rgvProtocol.getTaskNo1() == 0 && rgvProtocol.getTaskNo2() == 0){
//                    rgvThread.setPakMk(true);
//                    rgvThread.setPakIn(true);
//                    rgvThread.setPakOut(true);
//                }
//            }
//            }
//        }catch (Exception e){
//            log.error("小车复位线程报错!"+e);
//        }
//    }
    /**
     * rgv放货任务下发
     */
    public synchronized void rgvOutExecute() {
        for (RgvSlave rgv : slaveProperties.getRgv()) {
            // 获取RGV信息
            RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, rgv.getId());
            RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
            if (rgvProtocol.getStatusType1() != RgvStatusType.IDLE && rgvProtocol.getModeType() != RgvModeType.AUTO) {
                continue;
            }
            BasRgv basRgv = basRgvService.selectById(rgv.getId());
            if (basRgv == null) {
                log.error("{}号RGV尚未在数据库进行维护!4", rgv.getId());
                continue;
            }
            if(rgvProtocol.getStatusType1() == RgvStatusType.WORKING){
                rgvThread.setPaking(true);
                continue;
            }
            //小车无任务时跳过
            if(rgvProtocol.getTaskNo1() ==0 && rgvProtocol.getTaskNo2() == 0 ){
                continue;
            }
            if(!rgvThread.isPaking()){
                continue;
            }
            if(!basRgv.getPakAll().equals("1")){
                continue;
            }
            if(basRgv.getPakIn().equals("1")){
                for(RgvSlave.RgvStn rgvStn : rgv.getRgvInPStn()){//入库放货站点
                    boolean flag = false;
                    DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, rgvStn.getDevpPlcId());
                    StaProtocol staProtocol = devpThread.getStation().get(rgvStn.getStaNo());
                    if (staProtocol == null) {
                        News.infoNoLog( " - 1" + " - 1" + " - Rgv入库放货站信息(staProtocol!=null继续执行):staProtocol=" + staProtocol);
                        continue;
                    } else {
                        staProtocol = staProtocol.clone();
                    }
                    // 查询站点详细信息
                    BasDevp staDetl = basDevpService.selectById(rgvStn.getStaNo());
                    if (staDetl == null) {
                        News.error( " - 1" + " - 2" + " - 入库 ===>>Rgv放货站点在数据库不存在, 站点编号={}", rgvStn.getStaNo());
                        continue;
                    }
                    if (staProtocol.isAutoing() && !staProtocol.isLoading() && staDetl.getCanining() != null && staDetl.getCanining().equals("Y")) {
                        flag = true;
                    }
                    if (!flag) {
                        News.errorNoLog(  " - 1" + " - 3" + " - Rgv入库放货站信息(以下需要全true):"
                                + "自动信号" + staProtocol.isAutoing() + "有物信号" + staProtocol.isLoading()
                                + "工作号>0" + staProtocol.getWorkNo() + "可入信号" + staProtocol.isInEnable()
                                + "能入信号(wms设置).equals(\"Y\")" + staDetl.getCanining());
                        continue;
                    }
                    BasRgvMap basRgvMap = basRgvMapMapper.selectById(rgvProtocol.getRgvNo());
                    basRgvMap.setNowRoute(rgvProtocol.getRgvNo() == 1?rgvProtocol.getRgvPosI1():rgvProtocol.getRgvPosI2()); //更新小车当前位置站点号
                    basRgvMapService.updateById(basRgvMap);
                    Integer workNo = 0;
                    if(rgvProtocol.getTaskNo2() > 9999|| rgvProtocol.getTaskNo1() > 9999){
                        workNo = rgvProtocol.getTaskNo1() !=0 ? rgvProtocol.getTaskNo1() : rgvProtocol.getTaskNo2();
                    }else{
                        workNo = rgvProtocol.getTaskNo2() !=0 ? rgvProtocol.getTaskNo2() : rgvProtocol.getTaskNo1();
                    }
                    WrkMastSta wrkMastSta = wrkMastStaMapper.selectByWrkNoPut(workNo);
                    WrkMast wrkMast = wrkMastMapper.selectByWrkNo(workNo);
                    if( null == wrkMastSta ) {
                        News.infoNoLog( " - 1" + " - 4" + " - 查询无待入库数据--wrk_sts0, 工作号={}", staProtocol.getWorkNo());
                        continue;
                    }
                    boolean sign = rgvTakeFullAll(basRgvMap.getRgvNo(), wrkMastSta); //命令下发
                    if (sign){
                        try{
                            rgvThread.setPaking(false);
                            if(wrkMast != null){
                                wrkMast.setSheetNo("2");
                                wrkMastMapper.updateById(wrkMast);
                            }
                            wrkMastSta.setWrkSts(2);
                            wrkMastStaMapper.updateById(wrkMastSta);
                            log.error("更新小车任务成功");
                        }catch (Exception e){
                            log.error("更新小车任务失败"+ e);
                        }
                    } else {
                        log.error("工作号{}所属任务下发失败",wrkMastSta.getWrkNo());
                    }
                }
                basRgv.setPakRgv("1");
                basRgvService.updateById(basRgv);
            }
            //出库放货
            if( basRgv.getPakOut().equals("1")){
                for(RgvSlave.RgvStn rgvStn : rgv.getRgvOutPStn()){//入库放货站点
                    boolean flag = false;
                    DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, rgvStn.getDevpPlcId());
                    StaProtocol staProtocol = devpThread.getStation().get(rgvStn.getStaNo());
                    if (staProtocol == null) {
                        News.infoNoLog( " - 1" + " - 1" + " - Rgv出库放货站信息(staProtocol!=null继续执行):staProtocol=" + staProtocol);
                        continue;
                    } else {
                        staProtocol = staProtocol.clone();
                    }
                    // 查询站点详细信息
                    BasDevp staDetl = basDevpService.selectById(rgvStn.getStaNo());
                    if (staDetl == null) {
                        News.error( " - 1" + " - 2" + " - 出库 ===>>Rgv放货站点在数据库不存在, 站点编号={}", rgvStn.getStaNo());
                        continue;
                    }
                    if (staProtocol.isAutoing()  && staDetl.getCanouting() != null && staDetl.getCanouting().equals("Y")) {
                        flag = true;
                    }
                    if (!flag) {
                        News.errorNoLog( " - 1" + " - 3" + " - Rgv出库放货站信息(以下需要全true):"
                                + "自动信号" + staProtocol.isAutoing() + "有物信号" + staProtocol.isLoading()
                                + "工作号>0" + staProtocol.getWorkNo() + "可入信号" + staProtocol.isOutEnable()
                                + "能入信号(wms设置).equals(\"Y\")" + staDetl.getCanouting());
                        continue;
                    }
                    BasRgvMap basRgvMap = basRgvMapMapper.selectById(rgvProtocol.getRgvNo());
                    basRgvMap.setNowRoute(rgvProtocol.getRgvNo() == 1?rgvProtocol.getRgvPosI1():rgvProtocol.getRgvPosI2()); //更新小车当前位置站点号
                    basRgvMapService.updateById(basRgvMap);
                    Integer workNo = 0;
                    if(basRgv.getPakToCrn().equals("1")){
                        workNo = rgvProtocol.getTaskNo1() !=0 ? rgvProtocol.getTaskNo1():rgvProtocol.getTaskNo2();  //正常情况出库放货优先工位1放
                    }else{
                        workNo = rgvProtocol.getTaskNo2() !=0 ? rgvProtocol.getTaskNo2():rgvProtocol.getTaskNo1();  //接驳情况优先工位2放
                    }
                    WrkMastSta wrkMastSta = wrkMastStaMapper.selectByWrkNoPut(workNo);//根据站点工作号和小车工作范围检索任务档
                    WrkMast wrkMast = wrkMastMapper.selectByWrkNo(workNo);
                    if( null == wrkMastSta ) {
                        News.infoNoLog( " - 1" + " - 4" + " - 查询无待出库数据--wrk_sts0, 工作号={}", staProtocol.getWorkNo());
                        continue;
                    }
                    boolean sign = rgvTakeFullAll(basRgvMap.getRgvNo(), wrkMastSta); //命令下发
                    if (sign){
                        try{
                            rgvThread.setPaking(false);
                            if(wrkMast != null){
                                wrkMast.setSheetNo("2");
                                wrkMastMapper.updateById(wrkMast);
                            }
                            wrkMastSta.setWrkSts(2);
                            wrkMastStaMapper.updateById(wrkMastSta);
                            log.error("更新小车任务成功");
                        }catch (Exception e){
                            log.error("更新小车任务失败");
                        }
                    } else {
                        log.error("工作号{}所属任务下发失败",wrkMastSta.getWrkNo());
                    }
                }
                basRgv.setPakRgv("1");
                basRgvService.updateById(basRgv);
            }
        }
    }
    /**
     * rgv任务完成
     */
    public synchronized void rgvTaskComplete(){
        for (RgvSlave rgv : slaveProperties.getRgv()) {
            // 获取堆垛机信息
            RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, rgv.getId());
            RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
            if (rgvProtocol == null) {
                continue;
            }
            BasRgv basRgv = basRgvService.selectById(rgv.getId());
            if (basRgv == null) {
                log.error("{}号RGV尚未在数据库进行维护!4", rgv.getId());
                continue;
            }
            Long taskNo1 = Long.valueOf(rgvProtocol.getTaskNo1());
            Long taskNo2 = Long.valueOf(rgvProtocol.getTaskNo2());
            List<WrkMastSta> wrkMastStaList = wrkMastStaService.selectList(
                    new EntityWrapper<WrkMastSta>()
                            .eq("wrk_sts" ,2)
                    .eq("rgv_no", rgvProtocol.getRgvNo())
            );
            for(WrkMastSta wrkMastSta : wrkMastStaList){
                if(!Objects.equals(wrkMastSta.getWrkNo(), taskNo1) && !Objects.equals(wrkMastSta.getWrkNo(), taskNo2)){
                    try{
                        wrkMastSta.setWrkSts(3);
                        wrkMastStaMapper.updateById(wrkMastSta);
                        log.info("更新小车工作档至完成成功");
                    }catch (Exception e){
                        log.error("更新小车工作档至完成失败");
                    }
                }
            }
            if(rgvProtocol.getStatusType1() == RgvStatusType.IDLE
                    && rgvProtocol.getModeType() == RgvModeType.AUTO
                    && rgvProtocol.getTaskNo1() == 0 && rgvProtocol.getTaskNo2() == 0
                    && !rgvProtocol.isLoaded1ing()
                    && !rgvProtocol.isLoaded2ing()){
                List<WrkMastSta> wrkMastStaLock = wrkMastStaService.selectLockWrk();
                List<WrkMastSta> wrkMastStaLockT = wrkMastStaService.selectLockWrkT();
                if(wrkMastStaLock.size() > 0 && rgvProtocol.getRgvNo() == 1){
                    continue ;
                }
                if(wrkMastStaLockT.size() > 0 && rgvProtocol.getRgvNo() == 2){
                    continue ;
                }
                basRgv.setPakRgv("1");
                basRgv.setPakToCrn("1");
                basRgv.setPakIn("1");
                basRgv.setPakOut("1");
                basRgv.setPakAll("1");
                basRgvService.updateById(basRgv);
                rgvThread.setPakMk(true);
            }
//            List<WrkMastSta> wrkMastStaPakingNum = wrkMastStaService.selectPakingWrkNum(basRgv.getRgvNo());
//            if(wrkMastStaPakingNum.size() <1){
//                basRgv.setPakAll("1"); //防止无其他任务时,连续取货无法恢复
//                basRgvService.updateById(basRgv);
//            }
        }
    }
        /**
         * rgv出入库任务下发
         */
    public synchronized void rgvIoExecute(Integer mark) {
        for (RgvSlave rgv : slaveProperties.getRgv()) {
            // 获取堆垛机信息
            RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, rgv.getId());
            RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
            if (rgvProtocol == null) {
                continue;
            }
            BasRgv basRgv = basRgvService.selectById(rgv.getId());
            if (basRgv == null) {
                log.error("{}号RGV尚未在数据库进行维护!4", rgv.getId());
                continue;
            }
            if(rgvProtocol.getStatusType1() == RgvStatusType.WORKING){
                rgvThread.setPaking(true);
            }
            if(rgvProtocol.isLoaded1ing() && rgvProtocol.isLoaded2ing()){
                basRgv.setPakAll("1");
                basRgvService.updateById(basRgv);
            }
            // 只有当RGV空闲 并且 无任务时才继续执行
            if (rgvProtocol.getStatusType1() == RgvStatusType.IDLE &&
                    rgvProtocol.getModeType() == RgvModeType.AUTO && rgvThread.isPakMk()
                     && rgvThread.isPaking()) {
                News.warnNoLog(""+mark+" - 0"+" - 开始执行RGV入出库作业下发");
                // 如果最近一次是入库模式
//                rgvRunWrkMastInTest();
                if (rgvProtocol.getLastIo().equals("I")) {
                    if (basRgv.getInEnable().equals("1") && basRgv.getPakIn().equals("1")) {
                        //mark - 1 - ....
                        if (rgvProtocol.getTaskNo1()==0){
                            this.rgvRunWrkMastIn(rgv, rgvProtocol,mark); //  入库
                        }
                        rgvProtocol.setLastIo("O");
                    } else if (basRgv.getOutEnable().equals("1") && basRgv.getPakOut().equals("1")) {
                        //mark - 2 - ....
                        if (rgvProtocol.getTaskNo2()==0){
                            this.rgvRunWrkMastOut(rgv, rgvProtocol,mark); //  出库
                        }
                        rgvProtocol.setLastIo("I");
                    }
                }
                // 如果最近一次是出库模式
                else if (rgvProtocol.getLastIo().equals("O")) {
                    if (basRgv.getOutEnable().equals("1")  && basRgv.getPakOut().equals("1")) {
                        if (rgvProtocol.getTaskNo2()==0){
                            this.rgvRunWrkMastOut(rgv, rgvProtocol,mark); //  出库
                        }
                        rgvProtocol.setLastIo("I");
                    } else if (basRgv.getInEnable().equals("1") && basRgv.getPakIn().equals("1")) {
                        if (rgvProtocol.getTaskNo1()==0){
                            this.rgvRunWrkMastIn(rgv, rgvProtocol,mark); //  入库
                        }
                        rgvProtocol.setLastIo("O");
                    }
                }
            }
            WrkMastSta wrkMastSta2 = wrkMastStaMapper.selectByWorkSta(2, (int) rgvProtocol.getRgvNo());
            WrkMastSta wrkMastSta1 = wrkMastStaMapper.selectByWorkSta(1, (int) rgvProtocol.getRgvNo());
            if(wrkMastSta1 != null && wrkMastSta2 != null){
                rgvThread.setPakMk(false);  //小车双工位锁定
            }
//            if(rgvProtocol.getStatusType1() == RgvStatusType.IDLE && rgvProtocol.getTaskNo1() == 0 && rgvThread.isPakIn() && rgvThread.isPakRgv()){
//                rgvPreScheduling();//若暂无下发任务预调度提前到取货点
//            }
        }
    }
    /**
     * 小车入库任务取货下发
     */
    public synchronized void rgvRunWrkMastIn(RgvSlave slave, RgvProtocol rgvProtocol,Integer mark) {
        for (RgvSlave.RgvStn rgvStn : slave.getRgvInTStn()) {//rgv入库取货站点
            boolean flag = false;
            BasRgv basRgv = basRgvService.selectById(slave.getId());
            if (basRgv == null) {
                log.error("{}号RGV尚未在数据库进行维护!4", slave.getId());
                continue;
            }
            //遍历rgv入库取货站点
            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, rgvStn.getDevpPlcId());
            StaProtocol staProtocol = devpThread.getStation().get(rgvStn.getStaNo());
            StaProtocol staProtocol2 = null;  //连续取货任务站点
            RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, (int) rgvProtocol.getRgvNo());
            WrkMastSta wrkMastSta3 = null;//连取两个
            if(rgvStn.getStaNo2()!= null ){
                staProtocol2 = devpThread.getStation().get(rgvStn.getStaNo2());
                if (staProtocol2 == null) {
                    News.infoNoLog("" + mark + " - 1" + " - 1" + " - Rgv入库站信息(staProtocol!=null继续执行):staProtocol=" + staProtocol);
                    continue;
                } else {
                    staProtocol2 = staProtocol2.clone();
                }
                BasDevp staDetl2 = basDevpService.selectById(rgvStn.getStaNo2());
                if (staDetl2 == null) {
                    News.error("" + mark + " - 1" + " - 2" + " - 入库 ===>>Rgv站点在数据库不存在, 站点编号={}", rgvStn.getStaNo());
                    continue;
                }
                if((staProtocol.getWorkNo()>9999 && staProtocol2.getWorkNo()>9999) || (staProtocol.getWorkNo()<10000 && staProtocol2.getWorkNo()<10000)){
                    //当连续取货站点为相同类型时才能连续取
                    wrkMastSta3 = wrkMastStaMapper.selectByWrkNo(staProtocol2.getWorkNo());
                }
            }
            if(rgvProtocol.getTaskNo2() > 9999 && staProtocol.getWorkNo() < 10000){
                continue;
            }
            if (staProtocol == null) {
                News.infoNoLog("" + mark + " - 1" + " - 1" + " - Rgv入库站信息(staProtocol!=null继续执行):staProtocol=" + staProtocol);
                continue;
            } else {
                staProtocol = staProtocol.clone();
            }
            // 查询站点详细信息
            BasDevp staDetl = basDevpService.selectById(rgvStn.getStaNo());
            if (staDetl == null) {
                News.error("" + mark + " - 1" + " - 2" + " - 入库 ===>>Rgv站点在数据库不存在, 站点编号={}", rgvStn.getStaNo());
                continue;
            }
            if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.getWorkNo() != 0
                    && staDetl.getCanining() != null && staDetl.getCanining().equals("Y")) {
                flag = true;
            }
            if (!flag) {
                News.errorNoLog("" + mark + " - 1" + " - 3" + " - Rgv入库取货站信息(以下需要全true):"
                        + "自动信号" + staProtocol.isAutoing() + "有物信号" + staProtocol.isLoading()
                        + "工作号>0" + staProtocol.getWorkNo() + "能入信号(wms设置).equals(\"Y\")" + staDetl.getCanining());
                continue;
            }
            BasRgvMap basRgvMap = basRgvMapMapper.selectById(rgvProtocol.getRgvNo());
            List<Integer> route = new ArrayList<>();
            switch (rgvProtocol.getRgvNo()){
                case 1: route = RouteUtils.getRouteOne();break;
                case 2: route = RouteUtils.getRouteTwo();break;
            }
            basRgvMap.setNowRoute(rgvProtocol.getRgvNo() == 1?rgvProtocol.getRgvPosI1():rgvProtocol.getRgvPosI2()); //更新小车当前位置站点号
            basRgvMapService.updateById(basRgvMap);
            WrkMastSta wrkMastSta = wrkMastStaMapper.selectNoInterfere(route, route, Long.valueOf(staProtocol.getWorkNo()));//根据站点工作号和小车工作范围检索任务档
            if( null == wrkMastSta ) {
                News.infoNoLog("" + mark + " - 1" + " - 4" + " - 查询无待入库数据--wrk_sts0, 工作号={}", staProtocol.getWorkNo());
                continue;
            }
            WrkMastSta wrkMastSta2 = null;
            if(rgvProtocol.getTaskNo2() != null){
                wrkMastSta2 = wrkMastStaMapper.selectByWrkNo(rgvProtocol.getTaskNo2());
            }
            boolean result = false;
            if(wrkMastSta2 != null && rgvProtocol.getRgvNo() == 1){ //距离计算   2楼单入库口不需要计算
                 result = rgvCalcDistance((int) rgvProtocol.getRgvNo(),wrkMastSta2.getStaEnd(),wrkMastSta.getStaStart());//工位2放货站点,工位1取货站点
            }
            if(result){//若小车距离放货点距离近于取货点则跳过取货 true跳过取货/false优先取货
                basRgv.setPakRgv("0");
                basRgvService.updateById(basRgv);
//                rgvThread.setPakRgv(false);
                continue;
            }
            wrkMastSta.setWorkSta(wrkMastSta2 !=null ? 1 : 2);
            wrkMastSta.setRgvNo((int) rgvProtocol.getRgvNo());
            boolean sign = false;
            sign = rgvTakeFullAll(basRgvMap.getRgvNo(), wrkMastSta); //命令下发
            if (sign){
                if(wrkMastSta3 != null ){
                    List<WrkMastSta> wrkMastStaPaking = wrkMastStaService.selectPakingWrk(wrkMastSta3.getStaStart());
                    if(wrkMastStaPaking.size() < 1 ){//已有标记不再标记
                        wrkMastSta3.setMk(1);
                        basRgv.setPakAll("0");
                        basRgvService.updateById(basRgv);
                        try{
                            wrkMastStaMapper.updateById(wrkMastSta3);
                            log.error("锁定相隔站点任务");
                        }catch (Exception e){
                            log.error("锁定相隔站点任务失败");
                        }
                    }
                }
                basRgv.setPakOut("0");//出库不允许
                basRgvService.updateById(basRgv);
                rgvThread.setPaking(false);//任务下发锁定
                try{
                    wrkMastSta.setWrkSts(1);
                    wrkMastStaMapper.updateById(wrkMastSta);
                    log.error("更新小车任务成功");
                }catch (Exception e){
                    log.error("更新小车任务失败");
                }
            } else {
                log.error("工作号{}所属任务下发失败",wrkMastSta.getWrkNo());
            }
        }
    }
    /**
     * 小车出库任务取货下发
     */
    public synchronized void rgvRunWrkMastOut(RgvSlave slave, RgvProtocol rgvProtocol,Integer mark){
        for (RgvSlave.RgvStn rgvStn : slave.getRgvOutTStn()) {//rgv出库取货站点
            boolean flag = false;
            //遍历rgv入库取货站点
            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, rgvStn.getDevpPlcId());
            StaProtocol staProtocol = devpThread.getStation().get(rgvStn.getStaNo());
            RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, (int) rgvProtocol.getRgvNo());
            BasRgv basRgv = basRgvService.selectById(slave.getId());
            if (basRgv == null) {
                log.error("{}号RGV尚未在数据库进行维护!4", slave.getId());
                continue;
            }
            StaProtocol staProtocol2 = null;
            WrkMastSta wrkMastSta3 = null;
            if(rgvStn.getStaNo2()!= null ){
                staProtocol2 = devpThread.getStation().get(rgvStn.getStaNo2());
                if (staProtocol2 == null) {
                    News.infoNoLog("" + mark + " - 1" + " - 1" + " - Rgv入库站信息(staProtocol!=null继续执行):staProtocol=" + staProtocol);
                    continue;
                } else {
                    staProtocol2 = staProtocol2.clone();
                }
                BasDevp staDetl2 = basDevpService.selectById(rgvStn.getStaNo2());
                if (staDetl2 == null) {
                    News.error("" + mark + " - 1" + " - 2" + " - 入库 ===>>Rgv站点在数据库不存在, 站点编号={}", rgvStn.getStaNo());
                    continue;
                }
                wrkMastSta3 = wrkMastStaMapper.selectByWrkNo(staProtocol2.getWorkNo());
            }
            if (staProtocol == null) {
                News.infoNoLog("" + mark + " - 1" + " - 1" + " - Rgv出库站信息(staProtocol!=null继续执行):staProtocol=" + staProtocol);
                continue;
            } else {
                staProtocol = staProtocol.clone();
            }
            // 查询站点详细信息
            BasDevp staDetl = basDevpService.selectById(rgvStn.getStaNo());
            if (staDetl == null) {
                News.error("" + mark + " - 1" + " - 2" + " - 出库 ===>>Rgv站点在数据库不存在, 站点编号={}", rgvStn.getStaNo());
                continue;
            }
            if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.getWorkNo() > 0
                    && staDetl.getCanouting() != null && staDetl.getCanouting().equals("Y")) {
                flag = true;
            }
            if (!flag) {
                News.errorNoLog("" + mark + " - 1" + " - 3" + " - Rgv出库取货站信息(以下需要全true):"
                        + "自动信号" + staProtocol.isAutoing() + "有物信号" + staProtocol.isLoading()
                        + "工作号>0" + staProtocol.getWorkNo() + "可入信号" + staProtocol.isOutEnable()
                        + "能入信号(wms设置).equals(\"Y\")" + staDetl.getCanouting());
                continue;
            }
            BasRgvMap basRgvMap = basRgvMapMapper.selectById(rgvProtocol.getRgvNo());
            List<Integer> route = new ArrayList<>();
            switch (rgvProtocol.getRgvNo()){
                case 1: route = RouteUtils.getRouteOne();break;
                case 2: route = RouteUtils.getRouteTwo();break;
            }
            basRgvMap.setNowRoute(rgvProtocol.getRgvNo() == 1?rgvProtocol.getRgvPosI1():rgvProtocol.getRgvPosI2()); //更新小车当前位置站点号
            basRgvMapService.updateById(basRgvMap);
            WrkMastSta wrkMastSta = wrkMastStaMapper.selectNoInterfere(route, route, Long.valueOf(staProtocol.getWorkNo()));//根据站点工作号和小车工作范围检索任务档
            WrkMastSta wrkMastSta1 = wrkMastStaMapper.selectByWrkNo( rgvProtocol.getTaskNo1());
            if(basRgv.getPakToCrn().equals("0")){
                wrkMastSta = wrkMastStaMapper.selectNoInterfereCrn(route, route, Long.valueOf(staProtocol.getWorkNo()));//处理接驳任务时,连续只取接驳任务
            }
            if( null == wrkMastSta ) {
                News.infoNoLog("" + mark + " - 1" + " - 4" + " - 查询无待入库数据--wrk_sts0, 工作号={}", staProtocol.getWorkNo());
                continue;
            }
            boolean result = false;
            if(wrkMastSta1!= null && rgvProtocol.getRgvNo() == 1){ //距离计算   2楼单入库口不需要计算
                result = rgvCalcDistance((int) rgvProtocol.getRgvNo(),wrkMastSta1.getStaEnd(),wrkMastSta.getStaStart());//工位2放货站点,工位1取货站点
            }
            if(result){//若小车距离放货点距离近于取货点则跳过取货 true跳过取货/false优先取货
                basRgv.setPakRgv("0");
                basRgvService.updateById(basRgv);
                continue;
            }
            if(wrkMastSta != null &&LEFT_POSITION.contains(wrkMastSta.getStaEnd())){
                StaProtocol staProtocolSta = devpThread.getStation().get(wrkMastSta.getStaEnd());
                if (staProtocolSta == null) {
                    News.infoNoLog("" + mark + " - 1" + " - 1" + " - Rgv入库站信息(staProtocol!=null继续执行):staProtocol=" + staProtocol);
                    continue;
                } else {
                    staProtocolSta = staProtocolSta.clone();
                }
                if(staProtocolSta.isLoading()){
                    continue;
                }
            }
            wrkMastSta.setWorkSta(wrkMastSta1 !=null ? 2 : 1);//若1号工位有任务给2号工位
            wrkMastSta.setRgvNo((int) rgvProtocol.getRgvNo());
            boolean sign = false;
            sign = rgvTakeFullAll(basRgvMap.getRgvNo(), wrkMastSta); //命令下发
            if (sign){
                if(LEFT_POSITION.contains(wrkMastSta.getStaEnd())){
                    basRgv.setPakToCrn("0");
                    basRgvService.updateById(basRgv);
                    if(wrkMastSta3 != null){
                        if(!LEFT_POSITION.contains(wrkMastSta3.getStaEnd())){
                            wrkMastSta3 = null;//若接驳第二位不接驳时取消连续取货
                        }
                    }
                }
                if(wrkMastSta3 != null ){
                    List<WrkMastSta> wrkMastStaPaking = wrkMastStaService.selectPakingWrk(wrkMastSta3.getStaStart());
                    if(wrkMastStaPaking.size() < 1){
                        wrkMastSta3.setMk(1);
                        basRgv.setPakAll("0");
                        basRgvService.updateById(basRgv);
                        try{
                            wrkMastStaMapper.updateById(wrkMastSta3);
                            log.error("锁定相隔站点任务");
                        }catch (Exception e){
                            log.error("锁定相隔站点任务失败");
                        }
                    }
                }
                basRgv.setPakIn("0");
                basRgvService.updateById(basRgv);
                rgvThread.setPaking(false);
                try{
                    wrkMastSta.setWrkSts(1);
                    wrkMastStaMapper.updateById(wrkMastSta);
                    log.error("更新小车任务成功");
                }catch (Exception e){
                    log.error("更新小车任务失败");
                }
            } else {
                log.error("工作号{}所属任务下发失败",wrkMastSta.getWrkNo());
            }
        }
    }
    /**
     * 小车出库接驳任务取货下发
     */
    public synchronized void rgvRunWrkToCrn(RgvSlave slave, RgvProtocol rgvProtocol,Integer mark){
        for (RgvSlave.RgvStn rgvStn : slave.getRgvOutTStn()) {//rgv出库取货站点
            boolean flag = false;
            //遍历rgv入库取货站点
            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, rgvStn.getDevpPlcId());
            StaProtocol staProtocol = devpThread.getStation().get(rgvStn.getStaNo());
            RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, (int) rgvProtocol.getRgvNo());
            BasRgv basRgv = basRgvService.selectById(slave.getId());
            if (basRgv == null) {
                log.error("{}号RGV尚未在数据库进行维护!4", slave.getId());
                continue;
            }
            StaProtocol staProtocol2 = null;
            WrkMastSta wrkMastSta3 = null;
            if(rgvStn.getStaNo2()!= null ){
                staProtocol2 = devpThread.getStation().get(rgvStn.getStaNo2());
                if (staProtocol2 == null) {
                    News.infoNoLog("" + mark + " - 1" + " - 1" + " - Rgv入库站信息(staProtocol!=null继续执行):staProtocol=" + staProtocol);
                    continue;
                } else {
                    staProtocol2 = staProtocol2.clone();
                }
                BasDevp staDetl2 = basDevpService.selectById(rgvStn.getStaNo2());
                if (staDetl2 == null) {
                    News.error("" + mark + " - 1" + " - 2" + " - 入库 ===>>Rgv站点在数据库不存在, 站点编号={}", rgvStn.getStaNo());
                    continue;
                }
                wrkMastSta3 = wrkMastStaMapper.selectByWrkNo(staProtocol2.getWorkNo());
            }
            if (staProtocol == null) {
                News.infoNoLog("" + mark + " - 1" + " - 1" + " - Rgv出库站信息(staProtocol!=null继续执行):staProtocol=" + staProtocol);
                continue;
            } else {
                staProtocol = staProtocol.clone();
            }
            // 查询站点详细信息
            BasDevp staDetl = basDevpService.selectById(rgvStn.getStaNo());
            if (staDetl == null) {
                News.error("" + mark + " - 1" + " - 2" + " - 出库 ===>>Rgv站点在数据库不存在, 站点编号={}", rgvStn.getStaNo());
                continue;
            }
            if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.getWorkNo() > 0
                    && staDetl.getCanouting() != null && staDetl.getCanouting().equals("Y")) {
                flag = true;
            }
            if (!flag) {
                News.errorNoLog("" + mark + " - 1" + " - 3" + " - Rgv出库取货站信息(以下需要全true):"
                        + "自动信号" + staProtocol.isAutoing() + "有物信号" + staProtocol.isLoading()
                        + "工作号>0" + staProtocol.getWorkNo() + "可入信号" + staProtocol.isOutEnable()
                        + "能入信号(wms设置).equals(\"Y\")" + staDetl.getCanouting());
                continue;
            }
            BasRgvMap basRgvMap = basRgvMapMapper.selectById(rgvProtocol.getRgvNo());
            List<Integer> route = new ArrayList<>();
            switch (rgvProtocol.getRgvNo()){
                case 1: route = RouteUtils.getRouteOne();break;
                case 2: route = RouteUtils.getRouteTwo();break;
            }
            basRgvMap.setNowRoute(rgvProtocol.getRgvNo() == 1?rgvProtocol.getRgvPosI1():rgvProtocol.getRgvPosI2()); //更新小车当前位置站点号
            basRgvMapService.updateById(basRgvMap);
            WrkMastSta wrkMastSta = wrkMastStaMapper.selectNoInterfere(route, route, Long.valueOf(staProtocol.getWorkNo()));//根据站点工作号和小车工作范围检索任务档
            if( null == wrkMastSta ) {
                News.infoNoLog("" + mark + " - 1" + " - 4" + " - 查询无待入库数据--wrk_sts0, 工作号={}", staProtocol.getWorkNo());
                continue;
            }
            WrkMastSta wrkMastSta1 = wrkMastStaMapper.selectByWrkNo( rgvProtocol.getTaskNo1());
            if(basRgv.getPakToCrn().equals("0")){
                wrkMastSta = wrkMastStaMapper.selectNoInterfereCrn(route, route, Long.valueOf(staProtocol.getWorkNo()));
            }
            boolean result = false;
            if(wrkMastSta1!= null && rgvProtocol.getRgvNo() == 1){ //距离计算   2楼单入库口不需要计算
                result = rgvCalcDistance((int) rgvProtocol.getRgvNo(),wrkMastSta1.getStaEnd(),wrkMastSta.getStaStart());//工位2放货站点,工位1取货站点
            }
            if(result){//若小车距离放货点距离近于取货点则跳过取货 true跳过取货/false优先取货
                basRgv.setPakRgv("0");
                basRgvService.updateById(basRgv);
                continue;
            }
            wrkMastSta.setWorkSta(wrkMastSta1 !=null ? 2 : 1);//若1号工位有任务给2号工位
            wrkMastSta.setRgvNo((int) rgvProtocol.getRgvNo());
            boolean sign = false;
            sign = rgvTakeFullAll(basRgvMap.getRgvNo(), wrkMastSta); //命令下发
            if (sign){
                if(LEFT_POSITION.contains(wrkMastSta.getStaEnd())){
                    basRgv.setPakToCrn("0");
                    basRgvService.updateById(basRgv);
                    if(wrkMastSta3 != null){
                        if(!LEFT_POSITION.contains(wrkMastSta3.getStaEnd())){
                            wrkMastSta3 = null;//若接驳第二位不接驳时取消连续取货
                        }
                    }
                }
                if(wrkMastSta3 != null ){
                    List<WrkMastSta> wrkMastStaPaking = wrkMastStaService.selectPakingWrk(wrkMastSta3.getStaStart());
                    if(wrkMastStaPaking.size() < 1){
                        wrkMastSta3.setMk(1);
                        basRgv.setPakAll("0");
                        basRgvService.updateById(basRgv);
                        try{
                            wrkMastStaMapper.updateById(wrkMastSta3);
                            log.error("锁定相隔站点任务");
                        }catch (Exception e){
                            log.error("锁定相隔站点任务失败");
                        }
                    }
                }
                basRgv.setPakIn("0");
                basRgvService.updateById(basRgv);
                rgvThread.setPaking(false);
//                rgvThread.setPakIn(false);//入库不允许
                try{
                    wrkMastSta.setWrkSts(1);
                    wrkMastStaMapper.updateById(wrkMastSta);
                    log.error("更新小车任务成功");
                }catch (Exception e){
                    log.error("更新小车任务失败");
                }
            } else {
                log.error("工作号{}所属任务下发失败",wrkMastSta.getWrkNo());
            }
        }
    }
    /**
     * 执行小车搬运任务
     *
     * @return
     */
//    public synchronized boolean rgvRunWrkMastFullSta() {
//        boolean wrkEnable = false;
//        try{
//            List<BasRgvMap> basRgvMaps = basRgvMapService.selectList(new EntityWrapper<>());
//            for (BasRgvMap rgvSlave:basRgvMaps) {
//                RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, rgvSlave.getRgvNo());
//                RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
//                if (rgvProtocol == null) {
//                    continue;
//                }else {
//                    rgvProtocol = rgvProtocol.clone();
//                }
//                BasRgv basRgv = basRgvService.selectById(rgvSlave.getRgvNo());
//                if (basRgv == null) {
//                    log.error("{}号RGV尚未在数据库进行维护!4", rgvSlave.getRgvNo());
//                    continue;
//                }
//
//                // 只有当RGV空闲、自动,工位一无物//rgv可用  入库取货
//                if (rgvProtocol.getStatusType() == RgvStatusType.IDLE
//                        && rgvProtocol.getModeType() == RgvModeType.AUTO
//                        && !rgvProtocol.isLoaded1ing()
//                        && rgvProtocol.getTaskNo1() == 0
//                        && rgvThread.isPakMk()
//                        && rgvThread.isPakIn()
//                ) {
//                    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){
//                        List<Integer> staNos = Arrays.asList(1042, 1105, 1038, 1036, 2037);//入库口
//                        if (!staNos.contains(wrkMastSta.getStaStart())) {
//                            continue;
//                        }
//                        boolean sign = rgvTakeFullAll(basRgvMap.getRgvNo(), wrkMastSta); //命令下发
//                        wrkEnable = true;
//                        if (sign){
//                            wrkMastSta.setWrkSts(1);
//                            try{
//                                wrkMastStaMapper.updateById(wrkMastSta);
//                                log.error("更新小车任务成功");
//                            }catch (Exception e){
//                                log.error("更新小车任务失败");
//                            }
//                            rgvThread.setPakMk(false);
//                            rgvThread.setPakOut(false);
//                            boolean signMap = rgvMapUpdate(basRgvMap, wrkMastSta.getStaStart(), wrkMastSta.getStaEnd(),"2526");
//                            if (signMap){
//                                return wrkEnable;
////                                break;
//                            }else {
//                                log.error("货物搬运任务:工作号{}所属任务下发后地图同步失败",wrkMastSta.getWrkNo());
//                                Thread.sleep(500);
//                            }
//                        } else {
//                            log.error("工作号{}所属任务下发失败",wrkMastSta.getWrkNo());
//                            Thread.sleep(500);
//                        }
//                        break;
//                    }
//                }
//
//                // 只有当RGV空闲、自动,工位一无物//rgv可用  出库取货
//                if (rgvProtocol.getStatusType() == RgvStatusType.IDLE
//                        && rgvProtocol.getModeType() == RgvModeType.AUTO
//                        && !rgvProtocol.isLoaded2ing()
//                        && rgvProtocol.getTaskNo2() == 0
//                        && rgvThread.isPakMk()
//                        && rgvThread.isPakOut()
//                ){
//                    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){
//                        List<Integer> staNos = Arrays.asList(1042, 1105, 1038, 1036, 2037);//入库口
//                        if (staNos.contains(wrkMastSta.getStaStart())) {//非入库口(出库口)限制
//                            continue;
//                        }
//                        boolean sign = rgvTakeFullAll(basRgvMap.getRgvNo(), wrkMastSta,null); //命令下发
//                        wrkEnable = true;
//                        if (sign){
//                            wrkMastSta.setWrkSts(1);
//                            try{
//                                wrkMastStaMapper.updateById(wrkMastSta);
//                                log.error("更新小车任务成功");
//                            }catch (Exception e){
//                                log.error("更新小车任务失败");
//                            }
//                            rgvThread.setPakMk(false);
//                            rgvThread.setPakOut(false);
//                            boolean signMap = rgvMapUpdate(basRgvMap, wrkMastSta.getStaStart(), wrkMastSta.getStaEnd(),"2526");
//                            if (signMap){
//                                return wrkEnable;
////                                break;
//                            }else {
//                                log.error("货物搬运任务:工作号{}所属任务下发后地图同步失败",wrkMastSta.getWrkNo());
//                                Thread.sleep(500);
//                            }
//                        } else {
//                            log.error("工作号{}所属任务下发失败",wrkMastSta.getWrkNo());
//                            Thread.sleep(500);
//                        }
//                        break;
//                    }
//
//                }
//
//            }
//        }catch (Exception e){
//            log.error("执行小车搬运任务下发失败");
//        }
//        return wrkEnable;
//    }
    /**
     * 小车预调度
     */
//    public synchronized  void rgvPreScheduling(){
//        try{
//            List<BasRgvMap> basRgvMaps = basRgvMapService.selectList(new EntityWrapper<>());
//            for (BasRgvMap rgvSlave:basRgvMaps) {
//                RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, rgvSlave.getRgvNo());
//                RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
//                if (rgvProtocol == null) {
//                    continue;
//                }else {
//                    rgvProtocol = rgvProtocol.clone();
//                }
//                BasRgv basRgv = basRgvService.selectById(rgvSlave.getRgvNo());
//                if (basRgv == null) {
//                    log.error("{}号RGV尚未在数据库进行维护!4", rgvSlave.getRgvNo());
//                    continue;
//                }
//
//                // 只有当RGV空闲、自动,工位一无物//rgv可用  才进行预调度
//                if (rgvProtocol.getStatusType() == RgvStatusType.IDLE
//                        && rgvProtocol.getModeType() == RgvModeType.AUTO
//                        && !rgvProtocol.isLoaded1ing()
//                        && rgvProtocol.getTaskNo1() == 0
//                        && !rgvProtocol.isLoaded2ing()
//                        && rgvProtocol.getTaskNo2() == 0
//                        && rgvThread.isPakMk()
//                ) {
//                    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()); //更新小车当前位置站点号
//                    // 根据输送线plc遍历
//                    for (DevpSlave devp : slaveProperties.getDevp()) {
//                        // 遍历入库口  入库预调度
//                        List<Integer> staNos = Arrays.asList( 1043, 1104, 1029, 1022, 1019, 1008, 1005);
//                        for (Integer staNo : staNos) {
//                            SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
//                            StaProtocol staProtocol = devpThread.getStation().get(staNo);
//                            if(staProtocol.isLoading()){
//                                RgvCommand rgvCommand = new RgvCommand();
//                                rgvCommand.setRgvNo((int) rgvProtocol.getRgvNo()); // RGV编号
//                                rgvCommand.setAckFinish1(false);  // 工位1任务完成确认位
//                                rgvCommand.setTaskNo(9999); // 工位1工作号
//                                rgvCommand.setTaskMode1(RgvTaskModeType.X_MOVE); // 工位1任务模式:  移动
//                                switch (staNo){
//                                    case 1043: rgvCommand.setTargetPosition1(1042);break;  //工位1目标站点
//                                    case 1104: rgvCommand.setTargetPosition1(1105);break;
//                                    case 1037: rgvCommand.setTargetPosition1(1036);break;
//
//                                }
//                                if(Objects.equals(basRgvMap.getNowRoute(), staNo)){
//                                    continue;
//                                }
//                                rgvCommand.setCommand(true);   //工位1任务确认
//                                if (!MessageQueue.offer(SlaveType.Rgv, (int) rgvProtocol.getRgvNo(), new Task(4, rgvCommand))) {
//                                    //step=2,工位1、2写任务;   step=4,工位1写任务;     step=5,工位2写任务
//                                    log.error("RGV命令下发失败,RGV号={},任务数据={}", (int) rgvProtocol.getRgvNo(), JSON.toJSON(rgvCommand));
//                                }
//                            }
//                        }
//
//                    }
//
//                }
//            }
//        }catch (Exception e){
//            log.error("执行小车移动下发失败");
//        }
//    }
    /*
     * 小车取货至工位任务
     * */
    public synchronized boolean rgvTakeFullAll(Integer rgvId,WrkMastSta wrkMastSta){
        try{
            //  命令下发区 --------------------------------------------------------------------------
            RgvCommand rgvCommand = new RgvCommand();
            rgvCommand.setRgvNo(rgvId); // RGV编号
            RgvTaskStatusType type;
            Integer targetPosition = 0;
            if(wrkMastSta.getWrkSts() == 0){
                type = RgvTaskStatusType.FETCH; //取货
                targetPosition = wrkMastSta.getStaStart();
            }else{
                type = RgvTaskStatusType.PUT; //放货
                targetPosition = wrkMastSta.getStaEnd();
            }
            rgvCommand.setTaskNo(Math.toIntExact(wrkMastSta.getWrkNo())); // 工位工作号
            rgvCommand.setTaskStatus(type); // 工位任务模式:  取货
            rgvCommand.setTargetPosition(targetPosition);   //工位目标站点
            rgvCommand.setWrkTaskPri(wrkMastSta.getWorkSta());
            if (!MessageQueue.offer(SlaveType.Rgv, rgvId, new Task(2, 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 rgvCalcDistance(Integer rgvNo, Integer outStn, Integer inStn){
        try {
            // 小车当前位置
            BasRgvMap basRgvMap = basRgvMapMapper.selectById(rgvNo);
            Integer currPos = basRgvMap.getNowRoute(); // 或者用 rgvProtocol.getRgvPosI()
            if(currPos == null || outStn == null || inStn == null){
                return false; // 无效数据直接放弃
            }
            // 计算两段距离
            List<Integer> routeToOut = RouteUtils.getRouteDis(currPos, outStn);
            List<Integer> routeToIn  = RouteUtils.getRouteDis(currPos, inStn);
            int distOut = (routeToOut != null) ? routeToOut.size() : Integer.MAX_VALUE;
            int distIn  = (routeToIn  != null) ? routeToIn.size()  : Integer.MAX_VALUE;
            // 调试日志
            log.info("RGV距离计算: currPos={}, outStn={}, distOut={}, inStn={}, distIn={}",
                    currPos, outStn, distOut, inStn, distIn);
            return distOut < distIn; // 放货点更近 → true
        } catch (Exception e) {
            log.error("RGV路径距离计算异常", e);
            return false;
        }
    }
    /*
     * 小车复位
     * */
    public synchronized boolean rgvComplete(Integer rgvId,Integer step){
        try{
            //  命令下发区 --------------------------------------------------------------------------
            if (!MessageQueue.offer(SlaveType.Rgv, rgvId, new Task(step, 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;
        }
    }
    /*
     * arm任务完成自动组托
     * */
    public synchronized void  armMissionAccomplished() {
        try{
            for (DevpSlave devp : slaveProperties.getDevp()) {
                // 遍历拣料入库口
                for (DevpSlave.Sta armSta : devp.getArmSta()) {
                    // 获取站点信息
                    SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                    StaProtocol staProtocol = devpThread.getStation().get(armSta.getStaNo());
                    if (staProtocol == null) {
                        continue;
                    } else {
                        staProtocol = staProtocol.clone();
                    }
//                    String barcode = staProtocol.getBarcode();
//                    if(!Cools.isEmpty(barcode)) {
//                        if("NG".endsWith(barcode) || "NoRead".equals(barcode)) {
//                            armTaskAssignmentCallApiLogSave(staProtocol, "托盘条码为空", staProtocol.getSiteId()+"码垛位置,===》托盘条码为空", false);
//                            continue;
//                        }
//                    } else {
//                        armTaskAssignmentCallApiLogSave(staProtocol, "托盘条码为空", staProtocol.getSiteId()+"码垛位置,===》托盘条码为空", false);
//                        continue;
//                    }
                    List<BasArm> basArmList = basArmService.selectList(new EntityWrapper<BasArm>()
                            .eq("arm_no", armSta.getArmNo())
                            .eq("sta_no_sou", armSta.getStaNo())
                            .eq("status", 1));
                    for (BasArm basArm : basArmList) {
                        if (basArm.getStatus()!=1){
                            continue;
                        }
                        try{
                            List<BasArmMast> basArmMastList = basArmMastService.selectList(
                                    new EntityWrapper<BasArmMast>()
                                            .eq("arm_no", basArm.getArmNo())
                                            .eq("sorting_line", basArm.getSortingLineSou())
                                            .eq("status", 3)
                            );
                            if (basArmMastList.isEmpty()){
                                continue;
                            }
                            CombParam combParam = new CombParam(basArmMastList);
                            //arm任务完成自动组托
                            ReturnT<String> result = new PostMesDataUtils().postMesData("arm任务完成自动组托",wmsUrl, wmsComb, combParam);
                            if (result.getCode()==200){
                                basArmMastService.updateArmMastStatus(basArm.getArmNo(),basArm.getSortingLineSou(),3,4);
                            } else {
                                armTaskAssignmentCallApiLogSave(staProtocol, "自动组托失败", staProtocol.getSiteId()+"码垛位置,===》自动组托失败,等待重试", false);
//                                log.error("机械臂抓取任务完成:"+JSON.toJSON(basArmMastList)+"===》自动组托失败,等待重试");
                            }
                        }  catch (Exception e){
                            armTaskAssignmentCallApiLogSave(staProtocol, "机械臂抓取任务完成异常", staProtocol.getSiteId()+"码垛位置,===》自动组托失败,等待重试", false);
//                            log.error("arm编号:"+basArm.getArmNo()+"====》机械臂抓取任务完成"+e.getMessage());
                        }
                        break;
                    }
                }
            }
        } catch (Exception e){
            log.error("机械臂抓取任务完成组托失败"+e.getMessage());
        }
    }
    public synchronized void armMissionAccomplishedScanToCheckIn() {
        try{
            for (DevpSlave devp : slaveProperties.getDevp()) {
                // 遍历拣料入库口
                for (DevpSlave.Sta armSta : devp.getArmSta()) {
                    List<BasArmMast> basArmMastList = basArmMastService.selectList(
                            new EntityWrapper<BasArmMast>()
                                    .eq("arm_no", armSta.getArmNo())
                                    .eq("sta_no", armSta.getStaNo())
                                    .eq("status", 4)
                    );
                    if (basArmMastList.isEmpty()){
                        continue;
                    }
                    // 获取站点信息
                    SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                    StaProtocol staProtocol = devpThread.getStation().get(armSta.getStaNo());
                    if (staProtocol == null) {
                        continue;
                    } else {
                        staProtocol = staProtocol.clone();
                    }
//                    if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.isInEnable() && staProtocol.isPakMk()) {
//                        int workNo = commonService.getWorkNo(6);//待完善
//                        // 更新站点信息 且 下发plc命令
//                        staProtocol.setWorkNo(workNo);
//                        staProtocol.setStaNo(armSta.getStaNoEnd().shortValue());
//                        devpThread.setPakMk(staProtocol.getSiteId(), false);
//                        boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                        log.error("输送线下发5:"+workNo+","+armSta.getStaNoEnd());
//                        if (!result) {
//                            News.error(""+" - 3"+" - 发布命令至输送线队列失败!!! [plc编号:{}]", devp.getId());
//                        }
                        basArmMastService.updateArmMastStatus(basArmMastList.get(0).getArmNo(),basArmMastList.get(0).getSortingLine(),4,5);
//                    }
                }
            }
        } catch (Exception e){
            log.error("组托完成驱动托盘扫码入库失败"+e.getMessage());
        }
    }
    /*
     * arm任务下发
     * */
    public synchronized void armTaskAssignment() {
        try{
            List<BasArm> basArmList = basArmService.selectList(new EntityWrapper<>());
            for (BasArm basArm : basArmList) {
                if (basArm.getStatus()!=1){
                    continue;
                }
                try{
                    // 获取站点信息
                    SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, basArm.getDevpId());
                    StaProtocol staProtocol = devpThread.getStation().get(basArm.getStaNoSou());
                    if (staProtocol == null || !staProtocol.isLoading()) {
                        continue;
                    } else {
                        staProtocol = staProtocol.clone();
                    }
                    String barcode = staProtocol.getBarcode();
                    if(!Cools.isEmpty(barcode)) {
                        if("NG".endsWith(barcode) || "NoRead".equals(barcode)) {
                            armTaskAssignmentCallApiLogSave(staProtocol, "托盘条码为空", staProtocol.getSiteId()+"码垛位置,===》托盘条码为空", false);
//                            log.error(staProtocol.getSiteId()+"码垛位置,===》托盘条码为空");
                            continue;
                        }
                    } else {
                        armTaskAssignmentCallApiLogSave(staProtocol, "托盘条码为空", staProtocol.getSiteId()+"码垛位置,===》托盘条码为空", false);
//                        log.error(staProtocol.getSiteId()+"码垛位置,===》托盘条码为空");
                        continue;
                    }
                    if(barcode.length()!=6){
                        armTaskAssignmentCallApiLogSave(staProtocol, "条码长度不是6位", staProtocol.getSiteId()+"码垛位置,条码长度不是6位===>>" + barcode, false);
//                        log.error(staProtocol.getSiteId()+"码垛位置,条码长度不是6位===>>" + barcode);
                        continue;
//                        throw new CoolException(staProtocol.getSiteId()+"码垛位置,条码长度不是6位===>>" + barcode);
                    }
                    int countLoc = locDetlService.selectCount(new EntityWrapper<LocDetl>().eq("zpallet",barcode));
                    int countWrk = wrkDetlService.selectCount(new EntityWrapper<WrkDetl>().eq("zpallet",barcode));
                    int countwait = waitPakinMapper.selectCount(new EntityWrapper<WaitPakin>().eq("zpallet",barcode));
                    if (countLoc > 0 || countWrk > 0 || countwait > 0) {
//                        throw new CoolException("组托档/工作档/库存条码数据已存在===>>" + barcode);
                        armTaskAssignmentCallApiLogSave(staProtocol, "条码数据已存在", staProtocol.getSiteId()+"码垛位置,组托档/工作档/库存条码数据已存在===>>" + barcode, false);
//                        log.error(staProtocol.getSiteId()+"码垛位置,组托档/工作档/库存条码数据已存在===>>" + barcode);
                        continue;
                    }
                    List<BasArmMast> basArmMastListRuningBarCode = basArmMastService.selectList(
                            new EntityWrapper<BasArmMast>()
                                    .eq("barcode", barcode)
                                    .eq("status", 3)
                    );
                    if (!basArmMastListRuningBarCode.isEmpty()){
                        armTaskAssignmentCallApiLogSave(staProtocol, "条码数据已存在,正在自动组托!!!", staProtocol.getSiteId()+"码垛位置,条码数据正在自动组托===>>" + barcode, false);
                        continue;
                    }
                    List<BasArmMast> basArmMastListError = basArmMastService.selectList(
                            new EntityWrapper<BasArmMast>()
                                    .eq("arm_no", basArm.getArmNo())
                                    .eq("sorting_line", basArm.getSortingLineSou())
                                    .eq("status", 9)
                    );
                    if (!basArmMastListError.isEmpty()){
                        armTaskAssignmentCallApiLogSave(staProtocol, "存在异常机械臂任务", basArm.getArmNo()+"号机械臂存在异常数据需要维护!!!", false);
//                        log.error(basArm.getArmNo()+"号机械臂存在异常数据需要维护!!!");
                        continue;
                    }
                    List<BasArmMast> basArmMastListRuning = basArmMastService.selectList(
                            new EntityWrapper<BasArmMast>()
                                    .eq("arm_no", basArm.getArmNo())
                                    .eq("sorting_line", basArm.getSortingLineSou())
                                    .eq("status", 1)
                    );
                    List<BasArmMast> basArmMastListRuning3 = basArmMastService.selectList(
                            new EntityWrapper<BasArmMast>()
                                    .eq("arm_no", basArm.getArmNo())
                                    .eq(
                                            "sorting_line", basArm.getSortingLineSou())
                                    .eq("status", 3)
                    );
                    if (basArmMastListRuning.isEmpty() && basArmMastListRuning3.isEmpty()){
                        List<BasArmMast> basArmMastList = basArmMastService.selectList(
                                new EntityWrapper<BasArmMast>()
                                        .eq("arm_no", basArm.getArmNo())
                                        .eq("sorting_line", basArm.getSortingLineSou())
                                        .eq("status", 0)
                        );
                        if (basArmMastList.isEmpty()){
                            continue;
                        }
                        if (basArmMastList.size()>1){
                            armTaskAssignmentCallApiLogSave(staProtocol, "任务待执行数量大于1,无法分辨待执行任务", "arm编号:"+basArm.getArmNo()+"====》拆码垛任务异常禁止下发!!!任务待执行数量大于1!!!", false);
//                            log.error("arm编号:"+basArm.getArmNo()+"====》拆码垛任务异常禁止下发!!!任务待执行数量大于1!!!");
                            continue;
                        }
                        BasArmMast basArmMast = basArmMastList.get(0);
                        List<BasArmMast> basArmMastListOrder = basArmMastService.selectList(
                                new EntityWrapper<BasArmMast>()
                                        .eq("arm_no", basArm.getArmNo())
                                        .eq("sorting_line", basArm.getSortingLineSou())
                                        .eq("sku", basArmMast.getSku())
                                        .eq("order_no", basArmMast.getOrderNo())
                                        .eq("binding_tags", basArmMast.getBindingTags())
                        );
                        if (basArmMastListOrder.size()==1){
                            Thread.sleep(100);
                            List<BasArmMast> basArmMastListRuningBarCode2 = basArmMastService.selectList(
                                    new EntityWrapper<BasArmMast>()
                                            .eq("barcode", barcode)
                            );
                            if (!basArmMastListRuningBarCode2.isEmpty()){
                                int binding_tags = basArmMastService.selectCount(
                                        new EntityWrapper<BasArmMast>()
                                                .eq("status", 2)
                                                .eq("binding_tags", basArmMast.getBindingTags())
                                );
                                if (binding_tags<2){
                                    BasArmMast basArmMastOne = basArmMastService.selectOne(
                                            new EntityWrapper<BasArmMast>()
                                                    .eq("status", 2)
                                                    .eq("binding_tags", basArmMast.getBindingTags())
                                    );
                                    Double anfmeSignOne = basArmMastService.selectBasArmMastSignValue(basArmMastOne.getOrderNo(), basArmMastOne.getSku(),basArmMastOne.getBindingTags());
                                    if (anfmeSignOne>1D){
                                        armTaskAssignmentCallApiLogSave(staProtocol, "条码数据已存在!!!", staProtocol.getSiteId()+"码垛位置,条码数据正在自动组托===>>" + barcode, false);
                                        continue;
                                    }
                                }
                            }
                            OrderDetlValueResultUtil orderDetlValueResultUtil = basArmMastService.selectOrderDetlValue(basArmMast.getOrderNo(), basArmMast.getSku());
                            if (Cools.isEmpty(orderDetlValueResultUtil)){
                                continue;
                            }
                            Double anfmeSign = basArmMastService.selectBasArmMastSignValue(basArmMast.getOrderNo(), basArmMast.getSku(),basArmMast.getBindingTags());
                            orderDetlValueResultUtil.setAnfme(anfmeSign);
                            //订单下发
                            try{
                                ArmOrderAssignmentParam armOrderAssignmentParam = new ArmOrderAssignmentParam(basArmMast,orderDetlValueResultUtil);
//                                订单下发(SKU+订单)
                                ReturnT<String> result = new PostMesDataUtils().postMesData("机械臂抓取订单(SKU)下发:",ArmConstant.getArmUrl(basArmMast.getArmNo()), ArmConstant.ARM_ADAPTOR, armOrderAssignmentParam);
                                if (result.getCode()==200){
//                                    basArmMast.setStatus(1);
//                                    basArmMast.setBarcode(barcode);
//                                    basArmMastService.updateById(basArmMast);
                                } else {
                                    armTaskAssignmentCallApiLogSave(staProtocol, "机械臂抓取订单(SKU)下发", "arm编号:"+basArm.getArmNo()+"订单下发订单信息下发失败!!!", false);
//                                    log.error("arm编号:"+basArm.getArmNo()+"机械臂抓取订单(SKU)下发:"+JSON.toJSON(basArmMast)+"===》订单信息下发失败");
                                }
                            } catch (Exception e){
                                armTaskAssignmentCallApiLogSave(staProtocol, "机械臂抓取订单(SKU)下发", "arm编号:"+basArm.getArmNo()+"订单下发订单信息下发失败!!!", false);
//                                log.error("arm编号:"+basArm.getArmNo()+"机械臂抓取订单(SKU)下发:"+JSON.toJSON(basArmMast)+"===》订单下发订单信息下发失败");
                                continue;
                            }
                        }
                        ArmTaskAssignmentParam armTaskAssignmentParam = new ArmTaskAssignmentParam(basArm.getSortingLine());
                        //设置工作空间就绪
                        ReturnT<String> result = new PostMesDataUtils().postMesData("机械臂抓取任务下发:通知工作空间已就绪",ArmConstant.getArmUrl(basArmMast.getArmNo()), ArmConstant.ARM_WORKSPACE, armTaskAssignmentParam);
                        if (result.getCode()==200){
                            basArmMast.setStatus(1);
                            basArmMast.setBarcode(barcode);
                            basArmMastService.updateById(basArmMast);
                        } else {
                            armTaskAssignmentCallApiLogSave(staProtocol, "机械臂抓取任务信息下发失败", "arm编号:"+basArm.getArmNo()+"任务信息下发失败!!!", false);
//                            log.error("机械臂抓取任务:"+JSON.toJSON(basArmMast)+"===》任务信息下发失败");
                        }
                    }
                }  catch (Exception e){
                    log.error("arm编号:"+basArm.getArmNo()+"====》拆码垛任务下发失败"+e.getMessage());
                }
            }
        }catch (Exception e){
            log.error("arm任务下发失败"+e.getMessage());
        }
    }
    public void armTaskAssignmentCallApiLogSave(StaProtocol staProtocol, String tableName, String response, Boolean bool) {
        // 查询符合条件的所有 ApiLog
        List<ApiLog> apiLogs = apiLogService.selectList(new EntityWrapper<ApiLog>()
                .eq("namespace", "机械臂任务相关")
                .eq("request", "站点号:" + staProtocol.getSiteId())
                .eq("response", response)
                .eq("url", tableName)
                .eq("client_ip", staProtocol.getBarcode())
                .eq("result", 0)
                .orderBy("create_time", false)
        );
        // 遍历结果集,检查时间戳差值是否小于 5 分钟
        for (ApiLog apiLog : apiLogs) {
            long parseLong = Long.parseLong(apiLog.getTimestamp());
            if (new Date().getTime() - parseLong < 5 * 1000 * 60) {
                // 如果找到符合条件的记录且时间差小于 5 分钟,则不保存新记录,直接返回
                return;
            }
        }
        // 如果没有符合条件的记录,或者所有记录时间差大于 5 分钟,保存新的日志
        apiLogService.save("机械臂任务相关", tableName, "null", staProtocol.getBarcode(),
                "站点号:" + staProtocol.getSiteId(),
                response, bool);
    }
    /*
     * agv任务生成  Full
     * */
    public synchronized void agvTaskCreateFull() {
        // 根据输送线plc遍历
        for (DevpSlave devp : slaveProperties.getDevp()) {
            // 遍历出库口
            for (DevpSlave.Sta outStaAgv : devp.getOutStaAgvFull())  {
                // 获取入库站信息
                SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                StaProtocol staProtocol = devpThread.getStation().get(outStaAgv.getStaNo());
                if (staProtocol == null) {
                    continue;
                } else {
                    staProtocol = staProtocol.clone();
                }
                // 判断是否满足入库条件
                if (!staProtocol.isLoading()){
                    continue;
                }
                if (staProtocol.isAutoing() ) {
                    WrkMast wrkMast = wrkMastService.selectByWrkNo(staProtocol.getWorkNo());
                    if (Cools.isEmpty(wrkMast) || Cools.isEmpty(wrkMast.getTakeNone()) || !wrkMast.getTakeNone().equals("1")){
                        continue;
                    }
                    // 判断重复工作档
                    List<BasAgvMast> basAgvMastList = basAgvMastService.selectList(new EntityWrapper<BasAgvMast>().eq("task_no", staProtocol.getWorkNo()));
                    if (!basAgvMastList.isEmpty()) {
                        wrkMast.setTakeNone("2");
                        wrkMastMapper.updateById(wrkMast);
                        continue;
                    }
                    // 任务生成区 --------------------------------------------------------------------------
                    BasAgvMast basAgvMast = new BasAgvMast();
                    try {
                        LocTypeDto locTypeDto = new LocTypeDto(staProtocol);
                        SearchLocParam param = new SearchLocParam();
                        param.setBarcode(wrkMast.getBarcode());
                        param.setIoType(1);
                        param.setSourceStaNo(outStaAgv.getStaNo());
                        param.setLocType1(locTypeDto.getLocType1());
                        String response = new HttpHandler.Builder()
                                .setUri(wmsUrl)
                                .setPath("/rpc/pakin/agv/loc/v1")
                                .setJson(JSON.toJSONString(param))
                                .build()
                                .doPost();
                        JSONObject jsonObject = JSON.parseObject(response);
                        if (jsonObject.getInteger("code").equals(200)) {
                            StartupDto dto = jsonObject.getObject("data", StartupDto.class);
                            basAgvMast.setTaskNo(wrkMast.getWrkNo());
                            basAgvMast.setSourceStaNo(outStaAgv.getStaNo());
                            basAgvMast.setLocNo(dto.getLocNo());
                            basAgvMast.setSourceLocNo(wrkMast.getSourceLocNo());
                            basAgvMast.setDevpId(devp.getId());
                            basAgvMast.setIoType(2);
                            basAgvMastService.insert(basAgvMast);
                            wrkMast.setTakeNone("2");
                            wrkMastMapper.updateById(wrkMast);
                        } else {
                            News.error(JSON.toJSONString(staProtocol));
                        }
                    } catch (Exception e) {
                        News.error(JSON.toJSONString(e.getMessage()));
                    }
                }
            }
        }
    }
    /*
     * agv任务生成  Empty
     * */
    public synchronized void agvTaskCreateEmpty() {
        // 根据输送线plc遍历
        for (DevpSlave devp : slaveProperties.getDevp()) {
            // 遍历出库口
            for (DevpSlave.Sta outStaAgv : devp.getOutStaAgvEmpty())  {
                // 获取入库站信息
                SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                StaProtocol staProtocol = devpThread.getStation().get(outStaAgv.getStaNo());
                if (staProtocol == null) {
                    continue;
                } else {
                    staProtocol = staProtocol.clone();
                }
                // 判断是否满足入库条件
                if (!staProtocol.isLoading()){
                    continue;
                }
                String barcode = staProtocol.getBarcode();
                if(!Cools.isEmpty(barcode)) {
                    if("NG".endsWith(barcode) || "NoRead".equals(barcode)) {
                        News.info("{}号站点扫描器检测条码信息:{}", outStaAgv.getStaNo(), barcode);
                        continue;
                    }
                } else {
                    News.info("{}号站点扫描器检测条码信息:{}", outStaAgv.getStaNo(), barcode);
                    continue;
                }
                if (staProtocol.isAutoing()) {
                    // 判断重复工作档
                    List<BasAgvMast> basAgvMastList = basAgvMastService.selectList(new EntityWrapper<BasAgvMast>().eq("source_sta_no", outStaAgv.getStaNo()));
                    if (!basAgvMastList.isEmpty()) {
//                        News.info("{}号站点存在任务执行中,请等待任务执行完毕:{}", outStaAgv.getStaNo(), barcode);
                        continue;
                    }
                    List<LocMast> locMastList = locMastService.selectList(new EntityWrapper<LocMast>().eq("barcode", barcode));
                    if (!locMastList.isEmpty()) {
                        News.info("{}号站点条码信息重复:{}", outStaAgv.getStaNo(), barcode);
                        continue;
                    }
                    // 任务生成区 --------------------------------------------------------------------------
                    BasAgvMast basAgvMast = new BasAgvMast();
                    try {
                        LocTypeDto locTypeDto = new LocTypeDto(staProtocol);
                        SearchLocParam param = new SearchLocParam();
                        param.setBarcode(barcode);
                        param.setIoType(1);
                        param.setSourceStaNo(outStaAgv.getStaNo());
                        param.setLocType1(locTypeDto.getLocType1());
                        String response = new HttpHandler.Builder()
                                .setUri(wmsUrl)
                                .setPath("/rpc/pakin/agv/loc/v1")
                                .setJson(JSON.toJSONString(param))
                                .build()
                                .doPost();
                        JSONObject jsonObject = JSON.parseObject(response);
                        if (jsonObject.getInteger("code").equals(200)) {
                            StartupDto dto = jsonObject.getObject("data", StartupDto.class);
                            basAgvMast.setTaskNo(outStaAgv.getStaNo());
                            basAgvMast.setSourceStaNo(outStaAgv.getStaNo());
                            basAgvMast.setLocNo(dto.getLocNo());
                            basAgvMast.setDevpId(devp.getId());
                            basAgvMast.setIoType(2);
                            basAgvMastService.insert(basAgvMast);
                        } else {
                            News.error(JSON.toJSONString(staProtocol));
                        }
                    } catch (Exception e) {
                        News.error(JSON.toJSONString(e.getMessage()));
                    }
                }
            }
        }
    }
    /*
     * agv任务生成  Empty
     * */
    public synchronized void agvTaskCreateR() {
        // 根据输送线plc遍历
        for (DevpSlave devp : slaveProperties.getDevp()) {
            // 遍历出库口
            for (DevpSlave.Sta inStaAgv : devp.getInStaAgv())  {
                // 获取入库站信息
                SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                StaProtocol staProtocol = devpThread.getStation().get(inStaAgv.getStaNo());
                if (staProtocol == null) {
                    continue;
                } else {
                    staProtocol = staProtocol.clone();
                }
                // 判断是否满足入库条件
                if (staProtocol.isLoading()){
                    continue;
                }
                if (staProtocol.isAutoing()) {
                    // 判断重复工作档
                    List<BasAgvMast> basAgvMastList = basAgvMastService.selectList(new EntityWrapper<BasAgvMast>().eq("sta_no", inStaAgv.getStaNo()));
                    if (!basAgvMastList.isEmpty()) {
                        News.info("{}号站点存在任务执行中,等待任务执行完毕!!!", inStaAgv.getStaNo());
                        continue;
                    }
                    // 任务生成区 --------------------------------------------------------------------------
                    BasAgvMast basAgvMast = new BasAgvMast();
                    try {
                        List<LocMast> locMastList = locMastService.selectList(new EntityWrapper<LocMast>()
                                .eq("loc_sts", "R")
                                .ge("row1", 23)
                                .le("row1", 32)
                                .orderBy("io_time",true)
                        );
                        for (LocMast locMast : locMastList){
                            basAgvMast.setTaskNo(inStaAgv.getStaNo());
                            basAgvMast.setSourceLocNo(locMast.getLocNo());
                            basAgvMast.setStaNo(inStaAgv.getStaNo());
                            basAgvMast.setDevpId(devp.getId());
                            basAgvMast.setIoType(0);//AGV库位==》输送线站点  0
                            basAgvMastService.insert(basAgvMast);
                            break;
                        }
                    } catch (Exception e) {
                        News.error(JSON.toJSONString(e.getMessage()));
                    }
                }
            }
        }
    }
    /*
     * agv任务下发:AGV库位==》输送线站点
     * */
    public synchronized void agvTaskAssignment0() {
        try{
            List<BasAgvMast> basAgvMastList = basAgvMastService.selectList(new EntityWrapper<BasAgvMast>().eq("status", 0));
            for (BasAgvMast basAgvMast : basAgvMastList) {
                if (basAgvMast.getStatus()!=0 || basAgvMast.getIoType()!=0){//0==》AGV库位==》输送线站点
                    continue;
                }
                try{
                    // 获取站点信息
                    SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, basAgvMast.getDevpId());
                    StaProtocol staProtocol = devpThread.getStation().get(basAgvMast.getStaNo());
                    if (staProtocol == null) {
                        continue;
                    } else {
                        staProtocol = staProtocol.clone();
                    }
                    if (staProtocol.isAutoing()){
                        AgvTaskAssignmentParam agvTaskAssignmentParam = new AgvTaskAssignmentParam(basAgvMast);
                        //任务下发
                        ReturnT<String> result = new PostMesDataUtils().postMesDataAgv("AGV任务下发", AgvConstant.AGV_URL, AgvConstant.AGV_ADAPTOR, agvTaskAssignmentParam);
                        if (result.getCode()==200){
                            basAgvMast.setStatus(1);
                            basAgvMastService.updateById(basAgvMast);
                        } else {
                            agvTaskAssignmentCallApiLogSave(basAgvMast, "AGV任务下发失败", "任务号:"+basAgvMast.getTaskNo()+"任务信息下发失败!!!", false);
                        }
                    }
                }  catch (Exception e){
                    log.error("任务号:"+basAgvMast.getTaskNo()+"====》AGV任务下发失败"+e.getMessage());
                }
            }
        }catch (Exception e){
            log.error("AGV任务下发失败"+e.getMessage());
        }
    }
    /*
     * agv任务下发:AGV库位==》AGV库位
     * */
    public synchronized void agvTaskAssignment1() {
        try{
            List<BasAgvMast> basAgvMastList = basAgvMastService.selectList(new EntityWrapper<BasAgvMast>().eq("status", 0));
            for (BasAgvMast basAgvMast : basAgvMastList) {
                if (basAgvMast.getStatus()!=0 || basAgvMast.getIoType()!=1){//1==》AGV库位==》AGV库位
                    continue;
                }
                try{
                    AgvTaskAssignmentParam agvTaskAssignmentParam = new AgvTaskAssignmentParam(basAgvMast);
                    //任务下发
                    ReturnT<String> result = new PostMesDataUtils().postMesDataAgv("AGV任务下发", AgvConstant.AGV_URL, AgvConstant.AGV_ADAPTOR, agvTaskAssignmentParam);
                    if (result.getCode()==200){
                        basAgvMast.setStatus(1);
                        basAgvMastService.updateById(basAgvMast);
                    } else {
                        agvTaskAssignmentCallApiLogSave(basAgvMast, "AGV任务下发失败", "任务号:"+basAgvMast.getTaskNo()+"任务信息下发失败!!!", false);
                    }
                }  catch (Exception e){
                    log.error("任务号:"+basAgvMast.getTaskNo()+"====》AGV任务下发失败"+e.getMessage());
                }
            }
        }catch (Exception e){
            log.error("AGV任务下发失败"+e.getMessage());
        }
    }
    /*
     * agv任务下发:输送线站点==》AGV库位
     * */
    public synchronized void agvTaskAssignment2() {
        try{
            List<BasAgvMast> basAgvMastList = basAgvMastService.selectList(new EntityWrapper<BasAgvMast>().eq("status", 0));
            for (BasAgvMast basAgvMast : basAgvMastList) {
                if (basAgvMast.getStatus()!=0 || basAgvMast.getIoType()!=2){//2==》输送线站点==》AGV库位
                    continue;
                }
                try{
                    // 获取站点信息
                    SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, basAgvMast.getDevpId());
                    StaProtocol staProtocol = devpThread.getStation().get(basAgvMast.getSourceStaNo());
                    if (staProtocol == null || !staProtocol.isLoading()) {
                        continue;
                    } else {
                        staProtocol = staProtocol.clone();
                    }
                    if ((!Cools.isEmpty(staProtocol.getWorkNo()) && staProtocol.getWorkNo().equals(basAgvMast.getTaskNo()))
                            ||
                            (basAgvMast.getSourceStaNo().equals(2033))){
                        AgvTaskAssignmentParam agvTaskAssignmentParam = new AgvTaskAssignmentParam(basAgvMast);
                        //任务下发
                        ReturnT<String> result = new PostMesDataUtils().postMesDataAgv("AGV任务下发", AgvConstant.AGV_URL, AgvConstant.AGV_ADAPTOR, agvTaskAssignmentParam);
                        if (result.getCode()==200){
                            basAgvMast.setStatus(1);
                            basAgvMastService.updateById(basAgvMast);
                        } else {
                            agvTaskAssignmentCallApiLogSave(basAgvMast, "AGV任务下发失败", "任务号:"+basAgvMast.getTaskNo()+"任务信息下发失败!!!", false);
                        }
                    }
                }  catch (Exception e){
                    log.error("任务号:"+basAgvMast.getTaskNo()+"====》AGV任务下发失败"+e.getMessage());
                }
            }
        }catch (Exception e){
            log.error("AGV任务下发失败"+e.getMessage());
        }
    }
    /*
     * agv任务下发:输送线站点==》输送线站点
     * */
    public synchronized void agvTaskAssignment3() {
        try{
            List<BasAgvMast> basAgvMastList = basAgvMastService.selectList(new EntityWrapper<BasAgvMast>().eq("status", 0));
            for (BasAgvMast basAgvMast : basAgvMastList) {
                if (basAgvMast.getStatus()!=0 || basAgvMast.getIoType()!=3){//3==》输送线站点==》输送线站点
                    continue;
                }
                try{
                    // 获取站点信息
                    SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, basAgvMast.getDevpId());
                    StaProtocol staProtocol = devpThread.getStation().get(basAgvMast.getSourceStaNo());
                    if (staProtocol == null || !staProtocol.isLoading()) {
                        continue;
                    } else {
                        staProtocol = staProtocol.clone();
                    }
                    // 获取站点信息
                    StaProtocol staProtocolEnd = devpThread.getStation().get(basAgvMast.getStaNo());
                    if (staProtocolEnd == null || !staProtocolEnd.isAutoing()) {
                        continue;
                    } else {
                        staProtocolEnd = staProtocolEnd.clone();
                    }
                    if (!Cools.isEmpty(staProtocol.getWorkNo()) && staProtocol.getWorkNo().equals(basAgvMast.getTaskNo())){
                        AgvTaskAssignmentParam agvTaskAssignmentParam = new AgvTaskAssignmentParam(basAgvMast);
                        //任务下发
                        ReturnT<String> result = new PostMesDataUtils().postMesDataAgv("AGV任务下发", AgvConstant.AGV_URL, AgvConstant.AGV_ADAPTOR, agvTaskAssignmentParam);
                        if (result.getCode()==200){
                            basAgvMast.setStatus(1);
                            basAgvMastService.updateById(basAgvMast);
                        } else {
                            agvTaskAssignmentCallApiLogSave(basAgvMast, "AGV任务下发失败", "任务号:"+basAgvMast.getTaskNo()+"任务信息下发失败!!!", false);
                        }
                    }
                }  catch (Exception e){
                    log.error("任务号:"+basAgvMast.getTaskNo()+"====》AGV任务下发失败"+e.getMessage());
                }
            }
        }catch (Exception e){
            log.error("AGV任务下发失败"+e.getMessage());
        }
    }
    public void agvTaskAssignmentCallApiLogSave(BasAgvMast basAgvMast ,String tableName, String response, Boolean bool) {
        ApiLog apiLog = apiLogService.selectOne(new EntityWrapper<ApiLog>()
                .eq("namespace", "Agv任务下发")
                .eq("request", "任务号:" + basAgvMast.getTaskNo())
                .eq("response", response)
                .eq("url", tableName)
                .eq("result", 0)
                .orderBy("create_time", false)
        );
        if (!Cools.isEmpty(apiLog)){
            long parseLong = Long.parseLong(apiLog.getTimestamp());
            if (new Date().getTime()-parseLong<5*1000*60){
                return;
            }
        }
        apiLogService.save("Agv任务下发", tableName, "null", "127.0.0.1",
                "任务号:" + basAgvMast.getTaskNo() ,
                response, bool);
    }
}
src/main/java/com/zy/core/MainProcess.java
@@ -24,8 +24,7 @@
    private MainServiceImpl mainService;
    // 所属线程
    private Thread thread;
    private Thread armThread;
    private Thread agvThread;
    private Thread licenseThread;
    // 频率
    private int i = 0;
    private int k = 0;
@@ -37,12 +36,8 @@
    public void start(){
        thread = new Thread(this::crnAndDevRun);
        thread.start();
        armThread = new Thread(this::roboticArmDispatch);
        armThread.start();
        agvThread = new Thread(this::agvDispatch);
        agvThread.start();
        licenseThread = new Thread(this::licenseThreadRun);
        licenseThread.start();
    }
    private void crnAndDevRun() {
        while (!Thread.currentThread().isInterrupted()) {
@@ -55,11 +50,6 @@
                if (!SystemProperties.WCS_RUNNING_STATUS.get()) {
                    continue;
                }
                // 演示
//                    mainService.crnDemoOfLocMove1();
                //刷新RGV地图
                mainService.refreshRgvMap();
                // 入出库模式切换函数
//                    mainService.ioConvert();
@@ -92,99 +82,45 @@
                //堆垛机衔接任务生成
                mainService.connectWrk(10);
//                    mainService.outOfDevp(11);
                if (i>10){
                    //空托盘自动出库
                    mainService.autoEmptyOut();
                    //空托盘自动入库
                    mainService.autoEmptyIn();
                    i=0;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    private void licenseThreadRun(){
        int i = 0;
        while (true) {
            try{
                Thread.sleep(60*60*1000L);
                // 系统运行状态判断
                if (!SystemProperties.WCS_RUNNING_STATUS.get()) {
                    continue;
                }
                i++;
                /////////////////////////////////////RGV调度/////////////////////////////////////
                k++;
                // RGV  ===>>  小车任务作业下发
                try{
                    //RGV小车出入库取货下发
                    mainService.rgvIoExecute(11);
                    if(k > 2){
                        mainService.rgvOutExecute();
                        k = 0;
                log.info("++++++++ 开始验证许可证 ++++++++");
                if (!mainService.licenseVerify()){
                    if (i>6){
                        SystemProperties.WCS_RUNNING_STATUS.set(Boolean.FALSE);
                        log.info("++++++++ 验证许可证失败 ++++++++");
                        i = 0;
                    } else {
                        i++;
                    }
                }catch (Exception e){
                    e.printStackTrace();
                    log.error("RGV  ===>>  小车任务作业下发异常"+e);
                } else {
//                    SystemProperties.WCS_RUNNING_STATUS.set(Boolean.TRUE);
                    log.info("++++++++ 验证许可证成功 ++++++++");
                }
//                //完成小车任务
                mainService.rgvTaskComplete();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    private void roboticArmDispatch() {
        while (!Thread.currentThread().isInterrupted()) {
            try {
                // 间隔
                Thread.sleep(400);
                // 系统运行状态判断
                if (!SystemProperties.WCS_RUNNING_STATUS.get()) {
                    continue;
                }
                //arm任务完成
                mainService.armMissionAccomplished();//4==>5
                mainService.armMissionAccomplishedScanToCheckIn();//3===》4
                //arm任务下发
                mainService.armTaskAssignment();//0===》1
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    private void agvDispatch() {
        while (!Thread.currentThread().isInterrupted()) {
            try {
                // 间隔
                Thread.sleep(400);
                // 系统运行状态判断
                if (!SystemProperties.WCS_RUNNING_STATUS.get()) {
                    continue;
                }
                //agv任务下发
//                mainService.agvTaskAssignment0();//0===》1  AGV库位==》输送线站点  0
//                mainService.agvTaskAssignment1();//0===》1  AGV库位==》AGV库位  1
//                mainService.agvTaskAssignment2();//0===》1  输送线站点==》AGV库位  2
//                mainService.agvTaskAssignment3();//0===》1  输送线站点==》输送线站点  3
//
//
//                mainService.agvTaskCreateFull();//任务生成  出库口==》AGV库位
//                mainService.agvTaskCreateEmpty();//任务生成  出库口==》AGV库位
//                mainService.agvTaskCreateR();//任务生成  AGV库位==》入库口
            } catch (Exception e) {
                e.printStackTrace();
            }
            } catch (Exception e) {}
        }
    }
    @PreDestroy
    public void shutDown(){
        if (thread != null) thread.interrupt();
        if (armThread != null) armThread.interrupt();
        if (licenseThread != null) licenseThread.interrupt();
    }
}
src/main/java/com/zy/system/entity/license/AbstractServerInfos.java
New file
@@ -0,0 +1,111 @@
package com.zy.system.entity.license;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
/**
 * 用于获取客户服务器的基本信息,如:IP、Mac地址、CPU序列号、主板序列号等
 */
public abstract class AbstractServerInfos {
    private static Logger logger = LogManager.getLogger(AbstractServerInfos.class);
    /**
     * 组装需要额外校验的License参数
     */
    public LicenseCheck getServerInfos(){
        LicenseCheck result = new LicenseCheck();
        try {
            result.setIpAddress(this.getIpAddress());
            result.setMacAddress(this.getMacAddress());
            result.setCpuSerial(this.getCPUSerial());
            result.setMainBoardSerial(this.getMainBoardSerial());
        }catch (Exception e){
            logger.error("获取服务器硬件信息失败",e);
        }
        return result;
    }
    /**
     * 获取IP地址
     */
    protected abstract List<String> getIpAddress() throws Exception;
    /**
     * 获取Mac地址
     */
    protected abstract List<String> getMacAddress() throws Exception;
    /**
     * 获取CPU序列号
     */
    protected abstract String getCPUSerial() throws Exception;
    /**
     * 获取主板序列号
     */
    protected abstract String getMainBoardSerial() throws Exception;
    /**
     * 获取当前服务器所有符合条件的InetAddress
     */
    protected List<InetAddress> getLocalAllInetAddress() throws Exception {
        List<InetAddress> result = new ArrayList<>(4);
        // 遍历所有的网络接口
        for (Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces(); networkInterfaces.hasMoreElements(); ) {
            NetworkInterface iface = (NetworkInterface) networkInterfaces.nextElement();
            // 在所有的接口下再遍历IP
            for (Enumeration inetAddresses = iface.getInetAddresses(); inetAddresses.hasMoreElements(); ) {
                InetAddress inetAddr = (InetAddress) inetAddresses.nextElement();
                //排除LoopbackAddress、SiteLocalAddress、LinkLocalAddress、MulticastAddress类型的IP地址
                if(!inetAddr.isLoopbackAddress() /*&& !inetAddr.isSiteLocalAddress()*/
                        && !inetAddr.isLinkLocalAddress() && !inetAddr.isMulticastAddress()){
                    result.add(inetAddr);
                }
            }
        }
        return result;
    }
    /**
     * 获取某个网络接口的Mac地址
     */
    protected String getMacByInetAddress(InetAddress inetAddr){
        try {
            byte[] mac = NetworkInterface.getByInetAddress(inetAddr).getHardwareAddress();
            StringBuffer stringBuffer = new StringBuffer();
            for(int i=0;i<mac.length;i++){
                if(i != 0) {
                    stringBuffer.append("-");
                }
                //将十六进制byte转化为字符串
                String temp = Integer.toHexString(mac[i] & 0xff);
                if(temp.length() == 1){
                    stringBuffer.append("0" + temp);
                }else{
                    stringBuffer.append(temp);
                }
            }
            return stringBuffer.toString().toUpperCase();
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return null;
    }
}
src/main/java/com/zy/system/entity/license/CustomKeyStoreParam.java
New file
@@ -0,0 +1,57 @@
package com.zy.system.entity.license;
import de.schlichtherle.license.AbstractKeyStoreParam;
import java.io.*;
/**
 * 自定义KeyStoreParam,用于将公私钥存储文件存放到其他磁盘位置而不是项目中
 */
public class CustomKeyStoreParam extends AbstractKeyStoreParam {
    /**
     * 公钥/私钥在磁盘上的存储路径
     */
    private String storePath;
    private String alias;
    private String storePwd;
    private String keyPwd;
    public CustomKeyStoreParam(Class clazz, String resource, String alias, String storePwd, String keyPwd) {
        super(clazz, resource);
        this.storePath = resource;
        this.alias = alias;
        this.storePwd = storePwd;
        this.keyPwd = keyPwd;
    }
    @Override
    public String getAlias() {
        return alias;
    }
    @Override
    public String getStorePwd() {
        return storePwd;
    }
    @Override
    public String getKeyPwd() {
        return keyPwd;
    }
    /**
     * 复写de.schlichtherle.license.AbstractKeyStoreParam的getStream()方法<br/>
     * 用于将公私钥存储文件存放到其他磁盘位置而不是项目中
     */
    @Override
    public InputStream getStream() throws IOException {
        final InputStream in = new FileInputStream(new File(storePath));
        if (null == in) {
            throw new FileNotFoundException(storePath);
        }
        return in;
    }
}
src/main/java/com/zy/system/entity/license/CustomLicenseManager.java
New file
@@ -0,0 +1,241 @@
package com.zy.system.entity.license;
import com.core.common.Cools;
import de.schlichtherle.license.*;
import de.schlichtherle.xml.GenericCertificate;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.beans.XMLDecoder;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.List;
/**
 * 自定义LicenseManager,用于增加额外的服务器硬件信息校验
 */
public class CustomLicenseManager extends LicenseManager{
    private static Logger logger = LogManager.getLogger(CustomLicenseManager.class);
    //XML编码
    private static final String XML_CHARSET = "UTF-8";
    //默认BUFSIZE
    private static final int DEFAULT_BUFSIZE = 8 * 1024;
    public CustomLicenseManager() {
    }
    public CustomLicenseManager(LicenseParam param) {
        super(param);
    }
    /**
     * 复写create方法
     */
    @Override
    protected synchronized byte[] create(
            LicenseContent content,
            LicenseNotary notary)
            throws Exception {
        initialize(content);
        this.validateCreate(content);
        final GenericCertificate certificate = notary.sign(content);
        return getPrivacyGuard().cert2key(certificate);
    }
    /**
     * 复写install方法,其中validate方法调用本类中的validate方法,校验IP地址、Mac地址等其他信息
     */
    @Override
    protected synchronized LicenseContent install(
            final byte[] key,
            final LicenseNotary notary)
            throws Exception {
        final GenericCertificate certificate = getPrivacyGuard().key2cert(key);
        notary.verify(certificate);
        final LicenseContent content = (LicenseContent)this.load(certificate.getEncoded());
        this.validate(content);
        setLicenseKey(key);
        setCertificate(certificate);
        return content;
    }
    /**
     * 复写verify方法,调用本类中的validate方法,校验IP地址、Mac地址等其他信息
     */
    @Override
    protected synchronized LicenseContent verify(final LicenseNotary notary)
            throws Exception {
        GenericCertificate certificate = getCertificate();
        // Load license key from preferences,
        final byte[] key = getLicenseKey();
        if (null == key){
            throw new NoLicenseInstalledException(getLicenseParam().getSubject());
        }
        certificate = getPrivacyGuard().key2cert(key);
        notary.verify(certificate);
        final LicenseContent content = (LicenseContent)this.load(certificate.getEncoded());
        this.validate(content);
        setCertificate(certificate);
        return content;
    }
    /**
     * 校验生成证书的参数信息
     */
    protected synchronized void validateCreate(final LicenseContent content)
            throws LicenseContentException {
        final LicenseParam param = getLicenseParam();
        final Date now = new Date();
        final Date notBefore = content.getNotBefore();
        final Date notAfter = content.getNotAfter();
        if (null != notAfter && now.after(notAfter)){
            throw new LicenseContentException("证书失效时间不能早于当前时间");
        }
        if (null != notBefore && null != notAfter && notAfter.before(notBefore)){
            throw new LicenseContentException("证书生效时间不能晚于证书失效时间");
        }
        final String consumerType = content.getConsumerType();
        if (null == consumerType){
            throw new LicenseContentException("用户类型不能为空");
        }
    }
    /**
     * 复写validate方法,增加IP地址、Mac地址等其他信息校验
     */
    @Override
    protected synchronized void validate(final LicenseContent content)
            throws LicenseContentException {
//        1. 首先调用父类的validate方法
        super.validate(content);
        //2. 然后校验自定义的License参数
        //License中可被允许的参数信息
        LicenseCheck expectedCheckModel = (LicenseCheck) content.getExtra();
        //当前服务器真实的参数信息
        LicenseCheck serverCheckModel = getServerInfos();
        if(expectedCheckModel != null && serverCheckModel != null){
            //校验IP地址
            if(!checkIpAddress(expectedCheckModel.getIpAddress(),serverCheckModel.getIpAddress())){
                throw new LicenseContentException("当前服务器的IP没在授权范围内");
            }
            //校验Mac地址
            if(!checkIpAddress(expectedCheckModel.getMacAddress(),serverCheckModel.getMacAddress())){
                throw new LicenseContentException("当前服务器的Mac地址没在授权范围内");
            }
            //校验主板序列号
            if(!checkSerial(expectedCheckModel.getMainBoardSerial(),serverCheckModel.getMainBoardSerial())){
                throw new LicenseContentException("当前服务器的主板序列号没在授权范围内");
            }
            //校验CPU序列号
            if(!checkSerial(expectedCheckModel.getCpuSerial(),serverCheckModel.getCpuSerial())){
                throw new LicenseContentException("当前服务器的CPU序列号没在授权范围内");
            }
        }else{
            throw new LicenseContentException("不能获取服务器硬件信息");
        }
    }
    /**
     * 重写XMLDecoder解析XML
     */
    private Object load(String encoded){
        BufferedInputStream inputStream = null;
        XMLDecoder decoder = null;
        try {
            inputStream = new BufferedInputStream(new ByteArrayInputStream(encoded.getBytes(XML_CHARSET)));
            decoder = new XMLDecoder(new BufferedInputStream(inputStream, DEFAULT_BUFSIZE),null,null);
            return decoder.readObject();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } finally {
            try {
                if(decoder != null){
                    decoder.close();
                }
                if(inputStream != null){
                    inputStream.close();
                }
            } catch (Exception e) {
                logger.error("XMLDecoder解析XML失败",e);
            }
        }
        return null;
    }
    /**
     * 获取当前服务器需要额外校验的License参数
     */
    private LicenseCheck getServerInfos(){
        //操作系统类型
        String osName = System.getProperty("os.name").toLowerCase();
        AbstractServerInfos abstractServerInfos = null;
        //根据不同操作系统类型选择不同的数据获取方法
        if (osName.startsWith("windows")) {
            abstractServerInfos = new WindowsServerInfos();
        } else if (osName.startsWith("linux")) {
//            abstractServerInfos = new LinuxServerInfos();
        }else{//其他服务器类型
            abstractServerInfos = new WindowsServerInfos();
        }
        return abstractServerInfos.getServerInfos();
    }
    /**
     * 校验当前服务器的IP/Mac地址是否在可被允许的IP范围内<br/>
     * 如果存在IP在可被允许的IP/Mac地址范围内,则返回true
     */
    private boolean checkIpAddress(List<String> expectedList,List<String> serverList){
        if(expectedList != null && expectedList.size() > 0){
            if(serverList != null && serverList.size() > 0){
                for(String expected : expectedList){
                    if(serverList.contains(expected.trim())){
                        return true;
                    }
                }
            }
            return false;
        }else {
            return true;
        }
    }
    /**
     * 校验当前服务器硬件(主板、CPU等)序列号是否在可允许范围内
     */
    private boolean checkSerial(String expectedSerial,String serverSerial){
        if(!Cools.isEmpty(expectedSerial)){
            if(!Cools.isEmpty(serverSerial)){
                if(expectedSerial.equals(serverSerial)){
                    return true;
                }
            }
            return false;
        }else{
            return true;
        }
    }
}
src/main/java/com/zy/system/entity/license/LicenseCheck.java
New file
@@ -0,0 +1,45 @@
package com.zy.system.entity.license;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
 * 自定义需要校验的License参数
 */
@Data
public class LicenseCheck implements Serializable {
    private static final long serialVersionUID = 8600137500316662317L;
    /**
     * 可被允许的IP地址
     */
    private List<String> ipAddress;
    /**
     * 可被允许的MAC地址
     */
    private List<String> macAddress;
    /**
     * 可被允许的CPU序列号
     */
    private String cpuSerial;
    /**
     * 可被允许的主板序列号
     */
    private String mainBoardSerial;
    @Override
    public String toString() {
        return "LicenseCheckModel{" +
                "ipAddress=" + ipAddress +
                ", macAddress=" + macAddress +
                ", cpuSerial='" + cpuSerial + '\'' +
                ", mainBoardSerial='" + mainBoardSerial + '\'' +
                '}';
    }
}
src/main/java/com/zy/system/entity/license/LicenseCheckListener.java
New file
@@ -0,0 +1,94 @@
package com.zy.system.entity.license;
import com.core.common.Cools;
import de.schlichtherle.license.LicenseContent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import java.io.File;
/**
 * 在项目启动时安装证书
 */
@Component
public class LicenseCheckListener implements ApplicationListener<ContextRefreshedEvent> {
    private static Logger logger = LogManager.getLogger(LicenseCheckListener.class);
    /**
     * 证书subject
     */
    @Value("${license.subject}")
    private String subject;
    /**
     * 公钥别称
     */
    @Value("${license.publicAlias}")
    private String publicAlias;
    /**
     * 访问公钥库的密码
     */
    @Value("${license.storePass}")
    private String storePass;
    /**
     * 证书生成路径
     */
    @Value("${license.licensePath}")
    private String licensePath;
    /**
     * 密钥库存储路径
     */
    @Value("${license.publicKeysStorePath}")
    private String publicKeysStorePath;
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        //root application context 没有parent
        ApplicationContext context = event.getApplicationContext().getParent();
        if(context == null){
            loadLicense();
        }
    }
    //加载证书
    public boolean loadLicense() {
        if(!Cools.isEmpty(licensePath)){
            logger.info("++++++++ 开始加载许可证 ++++++++");
            try {
                String publicKeysStoreFileName = this.getClass().getClassLoader().getResource(publicKeysStorePath).getPath();
                File publicKeysStoreFile = new File(publicKeysStoreFileName);
                String licensePathFileName = this.getClass().getClassLoader().getResource(licensePath).getPath();
                File licensePathFile = new File(licensePathFileName);
                LicenseVerifyParam param = new LicenseVerifyParam();
                param.setSubject(subject);
                param.setPublicAlias(publicAlias);
                param.setStorePass(storePass);
                param.setLicensePath(licensePathFile.getPath());
                param.setPublicKeysStorePath(publicKeysStoreFile.getPath());
                LicenseVerify licenseVerify = new LicenseVerify();
                //安装证书
                LicenseContent install = licenseVerify.install(param);
                logger.info("++++++++ 许可证加载结束 ++++++++");
                return install != null;
            } catch (Exception e) {
                return false;
            }
        }
        return false;
    }
}
src/main/java/com/zy/system/entity/license/LicenseCreator.java
New file
@@ -0,0 +1,86 @@
package com.zy.system.entity.license;
import de.schlichtherle.license.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.security.auth.x500.X500Principal;
import java.io.File;
import java.text.MessageFormat;
import java.util.prefs.Preferences;
/**
 * License生成类
 */
public class LicenseCreator {
    private static Logger logger = LogManager.getLogger(LicenseCreator.class);
    private final static X500Principal DEFAULT_HOLDER_AND_ISSUER = new X500Principal("CN=localhost, OU=localhost, O=localhost, L=SH, ST=SH, C=CN");
    private LicenseCreatorParam param;
    public LicenseCreator(LicenseCreatorParam param) {
        this.param = param;
    }
    /**
     * 生成License证书
     */
    public boolean generateLicense(){
        try {
            LicenseManager licenseManager = new CustomLicenseManager(initLicenseParam());
            LicenseContent licenseContent = initLicenseContent();
            licenseManager.store(licenseContent,new File(param.getLicensePath()));
            return true;
        }catch (Exception e){
            logger.error(MessageFormat.format("证书生成失败:{0}",param),e);
            return false;
        }
    }
    /**
     * 初始化证书生成参数
     */
    private LicenseParam initLicenseParam(){
        Preferences preferences = Preferences.userNodeForPackage(LicenseCreator.class);
        //设置对证书内容加密的秘钥
        CipherParam cipherParam = new DefaultCipherParam(param.getStorePass());
        KeyStoreParam privateStoreParam = new CustomKeyStoreParam(LicenseCreator.class
                ,param.getPrivateKeysStorePath()
                ,param.getPrivateAlias()
                ,param.getStorePass()
                ,param.getKeyPass());
        LicenseParam licenseParam = new DefaultLicenseParam(param.getSubject()
                ,preferences
                ,privateStoreParam
                ,cipherParam);
        return licenseParam;
    }
    /**
     * 设置证书生成正文信息
     */
    private LicenseContent initLicenseContent(){
        LicenseContent licenseContent = new LicenseContent();
        licenseContent.setHolder(DEFAULT_HOLDER_AND_ISSUER);
        licenseContent.setIssuer(DEFAULT_HOLDER_AND_ISSUER);
        licenseContent.setSubject(param.getSubject());
        licenseContent.setIssued(param.getIssuedTime());
        licenseContent.setNotBefore(param.getIssuedTime());
        licenseContent.setNotAfter(param.getExpiryTime());
        licenseContent.setConsumerType(param.getConsumerType());
        licenseContent.setConsumerAmount(param.getConsumerAmount());
        licenseContent.setInfo(param.getDescription());
        //扩展校验服务器硬件信息
        licenseContent.setExtra(param.getLicenseCheck());
        return licenseContent;
    }
}
src/main/java/com/zy/system/entity/license/LicenseCreatorParam.java
New file
@@ -0,0 +1,96 @@
package com.zy.system.entity.license;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
 * License生成类需要的参数
 */
@Data
public class LicenseCreatorParam implements Serializable {
    private static final long serialVersionUID = -7793154252684580872L;
    /**
     * 证书subject
     */
    private String subject;
    /**
     * 密钥别称
     */
    private String privateAlias;
    /**
     * 密钥密码(需要妥善保管,不能让使用者知道)
     */
    private String keyPass;
    /**
     * 访问秘钥库的密码
     */
    private String storePass;
    /**
     * 证书生成路径
     */
    private String licensePath;
    /**
     * 密钥库存储路径
     */
    private String privateKeysStorePath;
    /**
     * 证书生效时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date issuedTime = new Date();
    /**
     * 证书失效时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date expiryTime;
    /**
     * 用户类型
     */
    private String consumerType = "user";
    /**
     * 用户数量
     */
    private Integer consumerAmount = 1;
    /**
     * 描述信息
     */
    private String description = "";
    /**
     * 额外的服务器硬件校验信息
     */
    private LicenseCheck licenseCheck;
    @Override
    public String toString() {
        return "LicenseCreatorParam{" +
                "subject='" + subject + '\'' +
                ", privateAlias='" + privateAlias + '\'' +
                ", keyPass='" + keyPass + '\'' +
                ", storePass='" + storePass + '\'' +
                ", licensePath='" + licensePath + '\'' +
                ", privateKeysStorePath='" + privateKeysStorePath + '\'' +
                ", issuedTime=" + issuedTime +
                ", expiryTime=" + expiryTime +
                ", consumerType='" + consumerType + '\'' +
                ", consumerAmount=" + consumerAmount +
                ", description='" + description + '\'' +
                ", licenseCheck=" + licenseCheck +
                '}';
    }
}
src/main/java/com/zy/system/entity/license/LicenseManagerHolder.java
New file
@@ -0,0 +1,22 @@
package com.zy.system.entity.license;
import de.schlichtherle.license.LicenseManager;
import de.schlichtherle.license.LicenseParam;
public class LicenseManagerHolder {
    private static volatile LicenseManager LICENSE_MANAGER;
    public static LicenseManager getInstance(LicenseParam param) {
        if (LICENSE_MANAGER == null) {
            synchronized (LicenseManagerHolder.class) {
                if (LICENSE_MANAGER == null) {
                    LICENSE_MANAGER = new CustomLicenseManager(param);
                }
            }
        }
        return LICENSE_MANAGER;
    }
}
src/main/java/com/zy/system/entity/license/LicenseVerify.java
New file
@@ -0,0 +1,133 @@
package com.zy.system.entity.license;
import de.schlichtherle.license.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.File;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.prefs.Preferences;
/**
 * License校验类
 */
public class LicenseVerify {
    private static Logger logger = LogManager.getLogger(LicenseVerify.class);
    /**
     * 安装License证书
     */
    public synchronized LicenseContent install(LicenseVerifyParam param){
        LicenseContent result = null;
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //1. 安装证书
        try{
            LicenseManager licenseManager = LicenseManagerHolder.getInstance(initLicenseParam(param));
            licenseManager.uninstall();
            result = licenseManager.install(new File(param.getLicensePath()));
            logger.info(MessageFormat.format("许可证加载成功,许可证有效期:{0} - {1}",format.format(result.getNotBefore()),format.format(result.getNotAfter())));
        }catch (Exception e){
            logger.error("许可证加载失败!{}",e.getMessage());
        }
        return result;
    }
    /**
     * 校验License证书
     */
    public boolean verify(){
        try {
            LicenseManager licenseManager = LicenseManagerHolder.getInstance(null);
            DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            if (!updateSystemTime()) {
                //时间更新失败,系统时间被更改
                return false;
            }
            LicenseContent licenseContent = licenseManager.verify();
            logger.info(MessageFormat.format("许可证校验通过,许可证有效期:{0} - {1}",format.format(licenseContent.getNotBefore()),format.format(licenseContent.getNotAfter())));
            return true;
        }catch (Exception e){
            logger.error("许可证校验失败!{}",e.getMessage());
            return false;
        }
    }
    /**
     * 校验License证书并获取证书信息
     */
    public LicenseContent getVerifyInfo(){
        LicenseManager licenseManager = LicenseManagerHolder.getInstance(null);
        if (!updateSystemTime()) {
            //时间更新失败,系统时间被更改
            return null;
        }
        //校验证书
        try {
            LicenseContent licenseContent = licenseManager.verify();
            return licenseContent;
        }catch (Exception e){
            logger.error("许可证校验失败!",e);
            return null;
        }
    }
    /**
     * 初始化证书生成参数
     * @param param License校验类需要的参数
     * @return de.schlichtherle.license.LicenseParam
     */
    private LicenseParam initLicenseParam(LicenseVerifyParam param){
        Preferences preferences = Preferences.userNodeForPackage(LicenseVerify.class);
        CipherParam cipherParam = new DefaultCipherParam(param.getStorePass());
        KeyStoreParam publicStoreParam = new CustomKeyStoreParam(LicenseVerify.class
                ,param.getPublicKeysStorePath()
                ,param.getPublicAlias()
                ,param.getStorePass()
                ,null);
        return new DefaultLicenseParam(param.getSubject()
                ,preferences
                ,publicStoreParam
                ,cipherParam);
    }
    /**
     * 更新时间到注册表中
     */
    private boolean updateSystemTime() {
        // 获取用户根节点
        Preferences userRoot = Preferences.userRoot();
        // 获取指定路径下的节点
        Preferences node = userRoot.node("/zhongyang");
        String key = "time";
        // 读取注册表
        String value = node.get(key, null);
        if (value != null) {
            long originTime = Long.parseLong(value);
            long now = System.currentTimeMillis();
            long diff = now - originTime;//现在时间 - 源时间 = 时间差
            if (diff > 0) {
                //时间差大于0才允许更新注册表时间
                node.put(key, String.valueOf(System.currentTimeMillis()));
                return true;
            }
        }else {
            // 写入注册表
            node.put(key, String.valueOf(System.currentTimeMillis()));
            return true;
        }
        return false;
    }
}
src/main/java/com/zy/system/entity/license/LicenseVerifyParam.java
New file
@@ -0,0 +1,48 @@
package com.zy.system.entity.license;
import lombok.Data;
/**
 * 校验签名文件
 */
@Data
public class LicenseVerifyParam {
    /**
     * 证书subject
     */
    private String subject;
    /**
     * 公钥别称
     */
    private String publicAlias;
    /**
     * 访问公钥库的密码
     */
    private String storePass;
    /**
     * 证书生成路径
     */
    private String licensePath;
    /**
     * 密钥库存储路径
     */
    private String publicKeysStorePath;
    public LicenseVerifyParam() {
    }
    public LicenseVerifyParam(String subject, String publicAlias, String storePass, String licensePath, String publicKeysStorePath) {
        this.subject = subject;
        this.publicAlias = publicAlias;
        this.storePass = storePass;
        this.licensePath = licensePath;
        this.publicKeysStorePath = publicKeysStorePath;
    }
}
src/main/java/com/zy/system/entity/license/WindowsServerInfos.java
New file
@@ -0,0 +1,85 @@
package com.zy.system.entity.license;
import java.net.InetAddress;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;
/**
 * 用于获取客户Windows服务器的基本信息
 */
public class WindowsServerInfos extends AbstractServerInfos {
    @Override
    protected List<String> getIpAddress() throws Exception {
        List<String> result = null;
        //获取所有网络接口
        List<InetAddress> inetAddresses = getLocalAllInetAddress();
        if(inetAddresses != null && inetAddresses.size() > 0){
            result = inetAddresses.stream().map(InetAddress::getHostAddress).distinct().map(String::toLowerCase).collect(Collectors.toList());
        }
        return result;
    }
    @Override
    protected List<String> getMacAddress() throws Exception {
        List<String> result = null;
        //1. 获取所有网络接口
        List<InetAddress> inetAddresses = getLocalAllInetAddress();
        if(inetAddresses != null && inetAddresses.size() > 0){
            //2. 获取所有网络接口的Mac地址
            result = inetAddresses.stream().map(this::getMacByInetAddress).distinct().collect(Collectors.toList());
        }
        return result;
    }
    @Override
    protected String getCPUSerial() throws Exception {
        //序列号
        String serialNumber = "";
        //使用WMIC获取CPU序列号
        Process process = Runtime.getRuntime().exec("wmic cpu get processorid");
        process.getOutputStream().close();
        Scanner scanner = new Scanner(process.getInputStream());
        if(scanner.hasNext()){
            scanner.next();
        }
        if(scanner.hasNext()){
            serialNumber = scanner.next().trim();
        }
        scanner.close();
        return serialNumber;
    }
    @Override
    protected String getMainBoardSerial() throws Exception {
        //序列号
        String serialNumber = "";
        //使用WMIC获取主板序列号
        Process process = Runtime.getRuntime().exec("wmic baseboard get serialnumber");
        process.getOutputStream().close();
        Scanner scanner = new Scanner(process.getInputStream());
        if(scanner.hasNext()){
            scanner.next();
        }
        if(scanner.hasNext()){
            serialNumber = scanner.next().trim();
        }
        scanner.close();
        return serialNumber;
    }
}
src/main/resources/application.yml
@@ -8,13 +8,13 @@
    name: @pom.build.finalName@
  datasource:
    driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
#    url: jdbc:sqlserver://localhost:1433;databasename=jshdasrs
    url: jdbc:sqlserver://127.0.0.1:1433;databasename=jshdasrs
    username: sa
    password: sa@123
#    url: jdbc:sqlserver://192.168.4.191:50948;databasename=jshdasrs
#    url: jdbc:sqlserver://localhost:1433;databasename=zzgtasrs
#    url: jdbc:sqlserver://127.0.0.1:1433;databasename=zzgtasrs
#    username: sa
#    password: sa@123
    url: jdbc:sqlserver://192.168.4.191:50948;databasename=zzgtasrs
    username: sa
    password: sa@123
  mvc:
    static-path-pattern: /**
  redis:
@@ -38,8 +38,17 @@
  enable: false
wms:
  url: 127.0.0.1:8081/jshdasrs
  url: 127.0.0.1:8081/zzgtasrs
  comb: mobile/combAuto/wcs/auth
#License相关配置
license:
  subject: zzgtasrs
  publicAlias: publicCert
  storePass: public_zhongyang_123456789
  licensePath: license.lic
  publicKeysStorePath: publicCerts.keystore
inventory:
  number: 7
src/main/webapp/static/js/common.js
@@ -1,4 +1,4 @@
var baseUrl = "/jshdwcs";
var baseUrl = "/zzgtwcs";
// 赋值
function setVal(el, val) {
src/main/webapp/static/js/console.map.js
@@ -1,5 +1,5 @@
mapInfo = {
    "mapName": "JSHDWCS",
    "mapName": "zzgtwcs",
    "rackCount": 4,
    "crnCount": 3,
    "stbCount": 13,