zjj
2024-04-20 52b397b5901c0ec428d0dc6589cbf4c9c2729c24
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java
@@ -3,43 +3,49 @@
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.core.common.Cools;
import com.core.common.DateUtils;
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.param.WMSAndAGVInterfaceParam;
import com.zy.asrs.mapper.*;
import com.zy.asrs.service.*;
import com.zy.asrs.utils.CommandUtils;
import com.zy.asrs.utils.PostMesDataUtils;
import com.zy.asrs.utils.Utils;
import com.zy.asrs.utils.VersionUtils;
import com.zy.common.model.LocTypeDto;
import com.zy.common.model.MatDto;
import com.zy.common.model.SearchLocParam;
import com.zy.common.model.StartupDto;
import com.zy.common.service.CommonService;
import com.zy.common.utils.CollectionUtils;
import com.zy.common.utils.HttpHandler;
import com.zy.core.CrnThread;
import com.zy.core.DevpThread;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.*;
import com.zy.core.model.CrnSlave;
import com.zy.core.model.DevpSlave;
import com.zy.core.model.Task;
import com.zy.core.model.*;
import com.zy.core.model.command.CrnCommand;
import com.zy.core.model.command.LedCommand;
import com.zy.core.model.command.RgvCommand;
import com.zy.core.model.protocol.CrnProtocol;
import com.zy.core.model.protocol.RgvProtocol;
import com.zy.core.model.protocol.StaProtocol;
import com.zy.core.properties.SlaveProperties;
import com.zy.core.thread.BarcodeThread;
import com.zy.core.thread.LedThread;
import com.zy.core.thread.SiemensDevpThread;
import com.zy.system.entity.Config;
import com.zy.system.service.ConfigService;
import com.zy.core.thread.SiemensRgvThread;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import java.util.Date;
import java.util.List;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
 * 立体仓库WCS系统主流程业务
@@ -53,673 +59,308 @@
    public static final long COMMAND_TIMEOUT = 5 * 1000;
    @Autowired
    private CommonService commonService;
    @Autowired
    private SlaveProperties slaveProperties;
    @Autowired
    private WrkMastMapper wrkMastMapper;
    private WrkMastStaMapper wrkMastStaMapper;
    @Autowired
    private LocMastService locMastService;
    private FillingMastService fillingMastService;
    @Autowired
    private BasCrnpService basCrnpService;
    @Autowired
    private BasDevpService basDevpService;
    @Autowired
    private BasErrLogService basErrLogService;
    @Autowired
    private BasCrnErrorMapper basCrnErrorMapper;
    @Autowired
    private TaskWrkMapper taskWrkMapper;
    @Autowired
    private TaskWrkService taskWrkService;
    @Autowired
    private ConfigService configService;
    @Autowired
    private StaDescMapper staDescMapper;
    private VacuumMastService vacuumMastService;
    @Value("${wms.url}")
    private String wmsUrl;
    @Value("${wms.movePath}")
    private String movePath;
    public Integer wrkNo1 = 10000;
    public void generateStoreWrkFile() {
        // 根据输送线plc遍历
        for (DevpSlave devp : slaveProperties.getDevp()) {
            // 遍历入库口
            for (DevpSlave.Sta inSta : devp.getInSta()) {
                // 获取入库站信息
                DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                StaProtocol staProtocol = devpThread.getStation().get(inSta.getStaNo());
                if (staProtocol == null) {
                    continue;
                } else {
                    staProtocol = staProtocol.clone();
                }
                Short workNo = staProtocol.getWorkNo();
                // 判断是否满足入库条件
                if (staProtocol.isAutoing() && staProtocol.isLoading()
                        && !staProtocol.isInEnable()
                        && !staProtocol.isEmptyMk() && (workNo >= 0)
                        && staProtocol.isPakMk()) {
    public Integer wrkNo2 = 20000;
                    // 尺寸检测异常
                    boolean back = false;
                    String errMsg = "";
                    if (staProtocol.isFrontErr()) {
                        errMsg = "前超限";
                        back = true;
                    }
                    if (!back && staProtocol.isBackErr()) {
                        errMsg = "后超限";
                        back = true;
                    }
                    if (!back && staProtocol.isHighErr()) {
                        errMsg = "高超限";
                        back = true;
                    }
                    if (!back && staProtocol.isLeftErr()) {
                        errMsg = "左超限";
                        back = true;
                    }
                    if (!back && staProtocol.isRightErr()) {
                        errMsg = "右超限";
                        back = true;
                    }
                    if (!back && staProtocol.isWeightErr()) {
                        errMsg = "超重";
                        back = true;
                    }
                    if (!back && staProtocol.isBarcodeErr()) {
                        errMsg = "扫码失败";
                        back = true;
                    }
                    // 退回
                    if (back) {
//                        News.warn("扫码入库失败,{}入库站因{}异常,托盘已被退回", inSta.getStaNo(), errMsg);
                        staProtocol.setWorkNo(workNo);
                        staProtocol.setStaNo(inSta.getBackSta().shortValue());
                        devpThread.setPakMk(staProtocol.getSiteId(), false);
                        MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                        TaskWrk taskWrk = taskWrkMapper.selectByWrkNo(Integer.valueOf(workNo));
                        if (taskWrk != null) {
                            taskWrk.setMemo(errMsg);//将错误码存入备注字段进行展示
                            taskWrkMapper.updateById(taskWrk);
                        }
                        continue;
                    }
                    // 获取条码扫描仪信息
                    BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, inSta.getBarcode());
                    if (barcodeThread == null) {
                        continue;
                    }
                    String barcode = barcodeThread.getBarcode();
                    if(!Cools.isEmpty(barcode)) {
                    }
                }
            }
        }
    }
    /**
     * 堆垛机站出库到出库站
     * 堆垛机演示  ===>> 库位移转
     */
    @Async
    public void crnStnToOutStn() {
        for (CrnSlave crnSlave : slaveProperties.getCrn()) {
            // 遍历堆垛机出库站
            for (CrnSlave.CrnStn crnStn : crnSlave.getCrnOutStn()) {
                List<StaDesc> staDescs = staDescMapper.selectList(new EntityWrapper<StaDesc>().eq("crn_no", crnSlave.getId()).eq("crn_stn", crnStn.getStaNo()));
                for (StaDesc staDesc : staDescs){
                    // 获取堆垛机出库站信息
                    DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, crnStn.getDevpPlcId());
                    StaProtocol staProtocol = devpThread.getStation().get(crnStn.getStaNo());
    public void getRgvTask() {
        for (DevpSlave devp : slaveProperties.getDevp()) {
            for (DevpSlave.Sta inSta : devp.getInSta()) {
                for (RgvSlave rgv : slaveProperties.getRgv()) {
                    if (!rgv.getDemo()){
                        continue;
                    }
                    SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                    StaProtocol staProtocol = devpThread.getStation().get(inSta.getStaNo());
                    if (staProtocol == null) {
                        continue;
                    } else {
                        staProtocol = staProtocol.clone();
                    }
                    if (staProtocol.isAutoing() && staProtocol.isLoading() && (staProtocol.getWorkNo() == 0 || staProtocol.getStaNo() == 0)) {
                        // 查询工作档
                        TaskWrk taskWrk = taskWrkMapper.selectCrnStaWorking(crnSlave.getId(), staDesc.getStnNo().toString());
                        if (taskWrk == null) {
                    if (staProtocol.isPakMk()){
                        VacuumMast vacuumMast = vacuumMastService.selectByStatusIsN();
                        FillingMast fillingMast = fillingMastService.selectByStatusIsn();
                        Date now = new Date();
                        WrkMastSta wrkMastSta = new WrkMastSta();
                        int workNo = commonService.getWorkNo(0);
                        wrkMastSta.setWrkNo((long)workNo);
                        wrkMastSta.setWrkStart(2);
                        wrkMastSta.setWrkEnd(vacuumMast.getStaNo());
//                    wrkMastSta.setStaStart();
                        wrkMastSta.setStaEnd(fillingMast.getStaNo());
                        wrkMastSta.setCreateTime(now);
                        wrkMastSta.setUpdateTime(now);
                        wrkMastSta.setBignTime(now);
                        wrkMastSta.setType(0);      //类型 0:非空  1:空板
                        wrkMastSta.setWrkType(3);                      //工作类型  1:取(叠盘)  2:放 3:取放 4:拆盘
                        Integer insert = wrkMastStaMapper.insert(wrkMastSta);
                        if (insert>0){
                            devpThread.setPakMk(devp.getId(),false);
                        }
                    }
                }
            }
        }
    }
    public synchronized void RGVDemoShow0() {
        try {
            for (DevpSlave devp : slaveProperties.getDevp()) {
                for (DevpSlave.Sta inSta : devp.getInSta()) {
                    SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                    StaProtocol staProtocol = devpThread.getStation().get(inSta.getStaNo());
                    if (staProtocol == null) {
                        continue;
                    } else {
                        staProtocol = staProtocol.clone();
                    }
//                    if (){ //输送线状态
//
//                    }
                    for (RgvSlave rgv : slaveProperties.getRgv()) {
                        SiemensRgvThread rgvThread = (SiemensRgvThread) SlaveConnection.get(SlaveType.Rgv, rgv.getId());
                        RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
                        if (rgvProtocol == null) {
                            continue;
                        }else {
                            rgvProtocol = rgvProtocol.clone();
                        }
                        if (rgvProtocol.getStatusType() == RgvStatusType.IDLE
                                && rgvProtocol.getModeType() == RgvModeType.AUTO
                                && rgvProtocol.getLoaded1()==0
                                && rgvProtocol.getTaskNo1() == 0
                                && rgvThread.isPakMk()
                        ){
                            WrkMastSta wrkMastSta = wrkMastStaMapper.selectWrkSts0();
                            if (!Cools.isEmpty(wrkMastSta)){
                                //  命令下发区 --------------------------------------------------------------------------
                                RgvCommand rgvCommand = new RgvCommand();
                                rgvCommand.setRgvNo(rgv.getId()); // RGV编号
                                rgvCommand.setAckFinish1(false);  // 工位1任务完成确认位
                                rgvCommand.setTaskNo1(wrkNo1); // 工位1工作号
                                rgvCommand.setTaskMode1(RgvTaskModeType.FETCH_PUT); // 工位1任务模式:  取放货
                                rgvCommand.setSourceStaNo1(wrkMastSta.getWrkStart().shortValue());   //工位1起点
                                rgvCommand.setDestinationStaNo1(wrkMastSta.getWrkEnd().shortValue());   //工位1目标站点
                                rgvCommand.setCommand((short) 1);   //工位1任务确认
                                if (!MessageQueue.offer(SlaveType.Rgv, rgv.getId(), new Task(4, rgvCommand))) {
                                    //step=2,工位1、2写任务;   step=4,工位1写任务;     step=5,工位2写任务
                                    log.error("RGV命令下发失败,RGV号={},任务数据={}", rgv.getId(), JSON.toJSON(rgvCommand));
                                } else {
                                    vacuumMastStatusSetY(wrkMastSta.getWrkEnd());
                                    rgvThread.setPakMk(false);
                                    wrkMastSta.setWrkSts(1);
                                    Integer update = wrkMastStaMapper.updateById(wrkMastSta);
                                    if (update>0){
                                    }else {
                                        log.error("RGV命令下发后,更新工作任务状态失败");
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("Rgv演示  ===>> 失败", e);
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }
    public synchronized void RGVDemoShow1() {
        try {
            for (DevpSlave devp : slaveProperties.getDevp()) {
                for (DevpSlave.Sta inSta : devp.getInSta()) {
                    SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
                    StaProtocol staProtocol = devpThread.getStation().get(inSta.getStaNo());
                    if (staProtocol == null) {
                        continue;
                    } else {
                        staProtocol = staProtocol.clone();
                    }
//                    if (){ //输送线状态
//
//                    }
                    for (RgvSlave rgv : slaveProperties.getRgv()) {
                        if (!rgv.getDemo()) {
                            continue;
                        }
                        // 判断工作档条件
                        if (taskWrk.getWrkSts() == 12 && taskWrk.getIoType() == 2) {
                            // 判断吊车是否实际已完成,且电脑状态在move中,以备电脑进行更新工作档
                            CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, taskWrk.getCrnNo());
                            CrnProtocol crnProtocol = crnThread.getCrnProtocol();
                            if (crnProtocol.statusType == CrnStatusType.FETCHING || crnProtocol.statusType == CrnStatusType.PUTTING) {
                                // 移动中
                                continue;
                            }
                            //  判断堆垛机状态等待确认
                            if (crnProtocol.statusType == CrnStatusType.HANDLING_COMPLETED && crnProtocol.modeType == CrnModeType.AUTO && crnProtocol.getTaskNo().equals(taskWrk.getWrkNo().shortValue())
                                    && crnProtocol.getTaskFinish() == 0
                                    && crnProtocol.forkPosType == CrnForkPosType.HOME) {
                                // 命令下发区 --------------------------------------------------------------------------
                        SiemensRgvThread rgvThread = (SiemensRgvThread) SlaveConnection.get(SlaveType.Rgv, rgv.getId());
                        RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
                        if (rgvProtocol == null) {
                            continue;
                        }else {
                            rgvProtocol = rgvProtocol.clone();
                        }
                        if (rgvProtocol.getStatusType() == RgvStatusType.IDLE
                                && rgvProtocol.getModeType() == RgvModeType.AUTO
                                && rgvProtocol.getLoaded1()==0
                                && rgvProtocol.getTaskNo1() == 0
                                && rgvThread.isPakMk()
                        ){
                            WrkMastSta wrkMastSta = wrkMastStaMapper.selectWrkSts1();
                            if (!Cools.isEmpty(wrkMastSta)){
                                //  命令下发区 --------------------------------------------------------------------------
                                RgvCommand rgvCommand = new RgvCommand();
                                rgvCommand.setRgvNo(rgv.getId()); // RGV编号
                                rgvCommand.setAckFinish1(false);  // 工位1任务完成确认位
                                rgvCommand.setTaskNo1(wrkNo1); // 工位1工作号
                                rgvCommand.setTaskMode1(RgvTaskModeType.FETCH_PUT); // 工位1任务模式:  取放货
                                rgvCommand.setSourceStaNo1(wrkMastSta.getWrkEnd().shortValue());   //工位1起点
                                rgvCommand.setDestinationStaNo1(wrkMastSta.getStaEnd().shortValue());   //工位1目标站点
                                rgvCommand.setCommand((short) 1);   //工位1任务确认
                                if (!MessageQueue.offer(SlaveType.Rgv, rgv.getId(), new Task(4, rgvCommand))) {
                                    //step=2,工位1、2写任务;   step=4,工位1写任务;     step=5,工位2写任务
                                    log.error("RGV命令下发失败,RGV号={},任务数据={}", rgv.getId(), JSON.toJSON(rgvCommand));
                                // 下发站点信息
                                staProtocol.setWorkNo(taskWrk.getWrkNo().shortValue());
                                String targetPoint = taskWrk.getTargetPoint();
                                int i = Integer.parseInt(targetPoint);
                                staProtocol.setStaNo((short)i);
                                if (!CommandUtils.offer(SlaveType.Devp, crnStn.getDevpPlcId(), new Task(2, staProtocol))) {
                                    continue;
                                }
                                // 更新工作档状态为14
                                taskWrk.setWrkSts(14);
                                if (taskWrkMapper.updateById(taskWrk) != 0) {
                                    // 复位堆垛机
                                    crnThread.setResetFlag(true);
                                    //更新库位状态
                                    LocMast locMast = locMastService.selectByLocNo(taskWrk.getTargetPoint());
                                    locMast.setLocSts("O");//O.空库位
                                    locMast.setBarcode("");//托盘码
                                    locMast.setModiTime(new Date());
                                    locMast.setModiUser(9999L);
                                    locMastService.updateById(locMast);
                                } else {
                                    log.error("更新工作档的工作状态为14失败!!! [工作号:{}]", taskWrk.getWrkNo());
                                }
                                    rgvThread.setPakMk(false);
                                    vacuumMastStatusSetN(wrkMastSta.getWrkEnd());
                                    fillingMastStatusSetY(wrkMastSta.getStaEnd());
                            }
                        }
                    }
                }
                                    wrkMastSta.setWrkSts(2);
                                    Integer update = wrkMastStaMapper.updateById(wrkMastSta);
                                    if (update>0){
            }
        }
    }
    /**
     * 入出库  ===>>  堆垛机入出库作业下发
     */
    public synchronized void crnIoExecute(){
        for (CrnSlave crn : slaveProperties.getCrn()) {
            // 获取堆垛机信息
            CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crn.getId());
            CrnProtocol crnProtocol = crnThread.getCrnProtocol();
            if (crnProtocol == null) { continue; }
            BasCrnp basCrnp = basCrnpService.selectById(crn.getId());
            if (basCrnp == null) {
                log.error("{}号堆垛机尚未在数据库进行维护!", crn.getId());
                continue;
            }
            // 只有当堆垛机空闲 并且 无任务时才继续执行
            if (crnProtocol.getStatusType() == CrnStatusType.IDLE && crnProtocol.getTaskNo() == 0 && crnProtocol.getModeType() == CrnModeType.AUTO
                    && crnProtocol.getLoaded() == 0 && crnProtocol.getForkPos() == 0) {
                // 如果最近一次是入库模式
                if (crnProtocol.getLastIo().equals("I")) {
                    if (basCrnp.getInEnable().equals("Y")) {
                        this.crnStnToLoc(crn, crnProtocol); //  入库
                        crnProtocol.setLastIo("O");
                    } else if (basCrnp.getOutEnable().equals("Y")) {
                        this.locToCrnStn(crn, crnProtocol); //  出库
                        crnProtocol.setLastIo("I");
                    }
                }
                // 如果最近一次是出库模式
                else if (crnProtocol.getLastIo().equals("O")) {
                    if (basCrnp.getOutEnable().equals("Y")) {
                        this.locToCrnStn(crn, crnProtocol); //  出库
                        crnProtocol.setLastIo("I");
                    } else if (basCrnp.getInEnable().equals("Y")) {
                        this.crnStnToLoc(crn, crnProtocol); //  入库
                        crnProtocol.setLastIo("O");
                    }
                }
            }
            // 库位移转
            this.locToLoc(crn, crnProtocol);
        }
    }
    /**
     * 入库  ===>>  堆垛机站到库位
     */
    public void crnStnToLoc(CrnSlave slave, CrnProtocol crnProtocol){
        for (CrnSlave.CrnStn crnStn : slave.getCrnInStn()) {
            List<StaDesc> staDescs = staDescMapper.selectList(new EntityWrapper<StaDesc>().eq("crn_no", slave.getId()).eq("crn_stn", crnStn.getStaNo()));
            for (StaDesc staDesc : staDescs) {
                boolean flag = false;
                // 获取堆垛机入库站信息
                DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, crnStn.getDevpPlcId());
                StaProtocol staProtocol = devpThread.getStation().get(crnStn.getStaNo());
                if (staProtocol == null) {
                    continue;
                } else {
                    staProtocol = staProtocol.clone();
                }
                // 查询站点详细信息
                BasDevp staDetl = basDevpService.selectById(crnStn.getStaNo());
                if (staDetl == null) {
                    log.error("入库 ===>> 堆垛机站点在数据库不存在, 站点编号={}", crnStn.getStaNo());
                    continue;
                }
                if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.getWorkNo() > 0 && staProtocol.isInEnable()
                        && staDetl.getCanining()!=null && staDetl.getCanining().equals("Y")) {
                    flag = true;
                }
                if (!flag) {
                    continue;
                }
                // 获取工作状态为2(设备上走)的入库工作档
                TaskWrk taskWrk = taskWrkMapper.selectPakIn(slave.getId(), staProtocol.getWorkNo().intValue(), staDesc.getStnNo().toString());
                if(null == taskWrk) {
                    continue;
                }
                // 堆垛机控制过滤
                if (!crnProtocol.getStatusType().equals(CrnStatusType.IDLE) || crnProtocol.getTaskNo() != 0) {
                    continue;
                }
                // 已经存在吊车执行任务时,则过滤
                if (taskWrkMapper.selectCrnWorking(slave.getId()) != null) {
                    continue;
                }
                // 命令下发区 --------------------------------------------------------------------------
                CrnCommand crnCommand = new CrnCommand();
                crnCommand.setCrnNo(slave.getId()); // 堆垛机编号
                crnCommand.setTaskNo(taskWrk.getWrkNo().shortValue()); // 工作号
                crnCommand.setAckFinish((short) 0);  // 任务完成确认位
                crnCommand.setTaskMode(CrnTaskModeType.LOC_MOVE); // 任务模式:  库位移转
                crnCommand.setSourcePosX(crnStn.getBay().shortValue());     // 源库位列
                crnCommand.setSourcePosY(crnStn.getLev().shortValue());     // 源库位层
                crnCommand.setSourcePosZ(crnStn.getRow().shortValue());     // 源库位排
                crnCommand.setDestinationPosX(Utils.getBayShort(taskWrk.getTargetPoint()));     // 目标库位列
                crnCommand.setDestinationPosY(Utils.getLevShort(taskWrk.getTargetPoint()));     // 目标库位层
                crnCommand.setDestinationPosZ(Utils.getRowShort(taskWrk.getTargetPoint()));     // 目标库位排
                crnCommand.setCommand((short)1);
                if (!CommandUtils.offer(SlaveType.Crn, taskWrk.getCrnNo(), new Task(2, crnCommand))) {
                    log.error("堆垛机命令下发失败,堆垛机号={},任务数据={}", taskWrk.getCrnNo(), JSON.toJSON(crnCommand));
                } else {
                    // 修改工作档状态 2.设备上走 => 3.吊车入库中
                    Date now = new Date();
                    taskWrk.setWrkSts(3);
                    taskWrk.setModiTime(now);
                    if (taskWrkMapper.updateById(taskWrk) == 0) {
                        log.error("修改工作档状态 2.设备上走 => 3.吊车入库中 失败!!,工作号={}", taskWrk.getWrkNo());
                    }
                }
            }
            return;
        }
    }
    /**
     * 出库  ===>>  库位到堆垛机站
     * 2022-06-09 TQS修改,查询工作档LIST,遍历下发,防止第一个任务堵塞出库
     */
    public void locToCrnStn(CrnSlave slave, CrnProtocol crnProtocol){
        List<TaskWrk> taskWrksInitial = taskWrkMapper.selectPakOut(slave.getId(), null);
        if (taskWrksInitial.size()==0){
            return;
        }
        for (CrnSlave.CrnStn crnStn : slave.getCrnOutStn()) {
            List<StaDesc> staDescs = staDescMapper.selectList(new EntityWrapper<StaDesc>().eq("crn_no", slave.getId()).eq("crn_stn", crnStn.getStaNo()));
            for (StaDesc staDesc : staDescs){
                // 获取工作状态为11(生成出库ID)的出库工作档
                List<TaskWrk> taskWrks = taskWrkMapper.selectPakOut(slave.getId(),staDesc.getStnNo().toString());
                for (TaskWrk taskWrk : taskWrks){
                    if (taskWrk == null) {
                        continue;
                    }
                    // 工作档状态判断
                    if (taskWrk.getIoType() != 2 || taskWrk.getTargetPoint() == null || taskWrk.getStartPoint() == null) {
                        log.error("查询工作档数据不符合条件--入出类型/站点, 工作号={},源库位={},入出类型={}", taskWrk.getWrkNo(), taskWrk.getStartPoint(), taskWrk.getIoType());
                        continue;
                    }
                    // 获取堆垛机出库站信息
                    SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, crnStn.getDevpPlcId());
                    StaProtocol staProtocol = devpThread.getStation().get(crnStn.getStaNo());
                    if (staProtocol == null) {
                        break;
                    } else {
                        staProtocol = staProtocol.clone();
                    }
                    // 查询站点详细信息
                    BasDevp staDetl = basDevpService.selectById(crnStn.getStaNo());
                    if (staDetl == null) {
                        log.error("出库 ===>> 堆垛机站点在数据库不存在, 站点编号={}", crnStn.getStaNo());
                        break;
                    }
                    // 判断堆垛机出库站状态
                    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) {
                            break;
                        }
                        // 已经存在吊车执行任务时,则过滤
                        if (taskWrkMapper.selectCrnWorking(slave.getId()) != null) {
                            break;
                        }
                        // 双深库位且浅库位有货,则需先对浅库位进行库位移转
                        if (Utils.isDeepLoc(slaveProperties, taskWrk.getStartPoint())) {
                            taskWrkMapper.selectPakOutIoType(taskWrk.getCrnNo());
                            List<TaskWrk> taskWrks1 = taskWrkMapper.selectPakOutIoType(taskWrk.getCrnNo());
                            if (Cools.isEmpty(taskWrks1) && taskWrks1.size()!=0){
                                continue;
                            }
                            String shallowLocNo = Utils.getShallowLoc(slaveProperties, taskWrk.getStartPoint());
                            TaskWrk hallowLocNoTask = taskWrkMapper.selectByStartPoint(shallowLocNo);
                            if (!Cools.isEmpty(hallowLocNoTask)){
                                if (!Cools.isEmpty(hallowLocNoTask.getTargetPoint())){
                                    continue;
                                }
//                            new PostMesDataUtils().postMesData("移库任务分配库位",wmsUrl,movePath,hallowLocNoTask);
                                try {
                                    String response = new HttpHandler.Builder()
                                            .setUri(wmsUrl)
                                            .setPath(movePath)
                                            .setJson(JSON.toJSONString(hallowLocNoTask))
                                            .build()
                                            .doPost();
                                    System.out.println("response:"+response);
                                    JSONObject jsonObject = JSON.parseObject(response);
                                    if (jsonObject.getInteger("code").equals(200)) {
                                        //解析
                                    }else {
                                        log.error("RGV命令下发后,更新工作任务状态失败");
                                    }
                                }catch (Exception e){
                                    log.error("请求接口失败!!!url:{};request:{};response:{}", wmsUrl+"/"+movePath, JSON.toJSONString(hallowLocNoTask), "请求移库任务分配库位");
                                }
                                continue;
                            }
                        }
                        // 1.堆垛机开始移动
                        CrnCommand crnCommand = new CrnCommand();
                        crnCommand.setCrnNo(slave.getId()); // 堆垛机编号
                        crnCommand.setTaskNo(taskWrk.getWrkNo().shortValue()); // 工作号
                        crnCommand.setAckFinish((short) 0);  // 任务完成确认位
                        crnCommand.setTaskMode(CrnTaskModeType.LOC_MOVE); // 任务模式:  库位移转
                        crnCommand.setSourcePosX(Utils.getBayShort(taskWrk.getStartPoint()));     // 源库位排
                        crnCommand.setSourcePosY(Utils.getLevShort(taskWrk.getStartPoint()));     // 源库位列
                        crnCommand.setSourcePosZ(Utils.getRowShort(taskWrk.getStartPoint()));     // 源库位层
                        crnCommand.setDestinationPosX(crnStn.getBay().shortValue());     // 目标库位排
                        crnCommand.setDestinationPosY(crnStn.getLev().shortValue());     // 目标库位列
                        crnCommand.setDestinationPosZ(crnStn.getRow().shortValue());     // 目标库位层
                        crnCommand.setCommand((short)1);
                        if (!CommandUtils.offer(SlaveType.Crn, taskWrk.getCrnNo(), new Task(2, crnCommand))) {
                            log.error("堆垛机命令下发失败,堆垛机号={},任务数据={}", taskWrk.getCrnNo(), JSON.toJSON(crnCommand));
                        } else {
                            // 修改工作档状态 11.生成出库ID => 12.吊车出库中
                            Date now = new Date();
                            taskWrk.setWrkSts(12);
                            taskWrk.setModiTime(now);
                            if (taskWrkMapper.updateById(taskWrk) == 0) {
                                log.error("修改工作档状态 11.生成出库ID => 12.吊车出库中 失败!!,工作号={}", taskWrk.getWrkNo());
                            }
                        }
                        return;
                    }
                }
            }
        } catch (Exception e) {
            log.error("Rgv演示  ===>> 失败", e);
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }
    /**
     * 库位移转
     */
    public void locToLoc(CrnSlave slave, CrnProtocol crnProtocol){
        for (CrnSlave.CrnStn crnStn : slave.getCrnOutStn()) {
            // 获取工作状态为11(生成出库ID)的移库工作档
            List<TaskWrk> taskWrks = taskWrkMapper.selectPakOut3(slave.getId(), crnStn.getStaNo().toString());
            for (TaskWrk taskWrk : taskWrks){
                if (taskWrk == null || Cools.isEmpty(taskWrk.getTargetPoint()) || taskWrk.getTargetPoint().equals("")) {
                    continue;
                }
                // 工作档状态判断
                if (taskWrk.getIoType() != 3 || taskWrk.getTargetPoint() == null) {
                    log.error("查询工作档数据不符合条件--入出类型/目标库位号, 工作号={},源库位={},入出类型={}", taskWrk.getWrkNo(), taskWrk.getTargetPoint(), taskWrk.getIoType());
                    continue;
                }
                // 命令下发区 --------------------------------------------------------------------------
                // 堆垛机控制过滤
                if (!crnProtocol.getStatusType().equals(CrnStatusType.IDLE) || crnProtocol.getTaskNo() != 0) {
                    continue;
                }
                // 已经存在吊车执行任务时,则过滤
                if (taskWrkMapper.selectCrnWorking(slave.getId()) != null) {
                    continue;
                }
                // 1.堆垛机开始移动
                CrnCommand crnCommand = new CrnCommand();
                crnCommand.setCrnNo(slave.getId()); // 堆垛机编号
                crnCommand.setTaskNo(taskWrk.getWrkNo().shortValue()); // 工作号
                crnCommand.setAckFinish((short) 0);  // 任务完成确认位
                crnCommand.setTaskMode(CrnTaskModeType.LOC_MOVE); // 任务模式:  库位移转
                crnCommand.setSourcePosX(Utils.getRowShort(taskWrk.getStartPoint()));     // 源库位排
                crnCommand.setSourcePosY(Utils.getBayShort(taskWrk.getStartPoint()));     // 源库位列
                crnCommand.setSourcePosZ(Utils.getLevShort(taskWrk.getStartPoint()));     // 源库位层
                crnCommand.setDestinationPosX(Utils.getRowShort(taskWrk.getTargetPoint()));     // 目标库位排
                crnCommand.setDestinationPosY(Utils.getBayShort(taskWrk.getTargetPoint()));     // 目标库位列
                crnCommand.setDestinationPosZ(Utils.getLevShort(taskWrk.getTargetPoint()));     // 目标库位层
                if (!CommandUtils.offer(SlaveType.Crn, taskWrk.getCrnNo(), new Task(2, crnCommand))) {
                    log.error("堆垛机命令下发失败,堆垛机号={},任务数据={}", taskWrk.getCrnNo(), JSON.toJSON(crnCommand));
                } else {
                    // 修改工作档状态 11.生成出库ID => 12.吊车出库中
                    Date now = new Date();
                    taskWrk.setWrkSts(12);
                    taskWrk.setModiTime(now);
                    if (taskWrkMapper.updateById(taskWrk) == 0) {
                        log.error("修改工作档状态 11.生成出库ID => 12.吊车出库中 失败!!,工作号={}", taskWrk.getWrkNo());
                    }
                    break;
                }
                return;
            }
        }
    }
    /**
     * 执行对工作档的完成操作
     */
    @Async
    public void storeFinished() {
        for (CrnSlave crn : slaveProperties.getCrn()) {
            // 获取堆垛机信息
            CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crn.getId());
            CrnProtocol crnProtocol = crnThread.getCrnProtocol();
            if (crnProtocol == null) { continue; }
            //  状态:等待确认 并且  任务完成位 = 1
            if (crnProtocol.getTaskFinish() == 0 && crnProtocol.statusType == CrnStatusType.HANDLING_COMPLETED && crnProtocol.getTaskNo() != 0) {
                // 获取入库待确认工作档
                TaskWrk taskWrk = taskWrkMapper.selectCrnNoWorking(crn.getId(),crnProtocol.getTaskNo().intValue());
                if (Cools.isEmpty(taskWrk)) {
                    log.error("堆垛机处于等待确认且任务完成状态,但未找到工作档。堆垛机号={},工作号={}", crn.getId(), crnProtocol.getTaskNo());
                    continue;
                }
                // 入库 + 库位转移  ==> 4.入库完成
                if ((taskWrk.getWrkSts() == 3 && taskWrk.getIoType() == 1) || (taskWrk.getWrkSts() == 12 && taskWrk.getIoType() == 3)) {
                    taskWrk.setWrkSts(4);
                } else {
                    continue;
                }
                Date now = new Date();
                taskWrk.setModiTime(now);
                Integer integerTaskWrk = taskWrkMapper.updateById(taskWrk);
                // 修改成功后复位堆垛机
                if (integerTaskWrk > 0) {
                    // 堆垛机复位
                    crnThread.setResetFlag(true);
                    //更新库位状态
                    LocMast locMast = locMastService.selectByLocNo(taskWrk.getTargetPoint());
                    locMast.setLocSts("F");//F.在库
                    locMast.setBarcode(taskWrk.getBarcode());//托盘码
                    locMast.setModiTime(now);
                    locMast.setModiUser(9999L);
                    locMastService.updateById(locMast);
                }
            }
        }
    }
    /**
     * 堆垛机异常信息记录
     */
    @Async
    public void recCrnErr(){
        Date now = new Date();
        for (CrnSlave crn : slaveProperties.getCrn()) {
            // 获取堆垛机信息
            CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crn.getId());
            CrnProtocol crnProtocol = crnThread.getCrnProtocol();
            if (crnProtocol == null) {
    public synchronized void RGVDemoShow2() throws InterruptedException {
        for (RgvSlave rgv : slaveProperties.getRgv()) {
//            if (!rgv.getDemo()) {
//                continue;
//            }
            SiemensRgvThread rgvThread = (SiemensRgvThread) SlaveConnection.get(SlaveType.Rgv, rgv.getId());
            RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
            if (rgvProtocol == null) {
                continue;
            }else {
                rgvProtocol = rgvProtocol.clone();
            }
            if (true) {
//            if (crnProtocol.getModeType() != CrnModeType.STOP) {
                // 有任务
                if (crnProtocol.getTaskNo() != 0) {
                    BasErrLog latest = basErrLogService.findLatestByTaskNo(crn.getId(), crnProtocol.getTaskNo().intValue());
                    // 有异常
                    if (latest == null) {
                        if (crnProtocol.getAlarm1() != null && crnProtocol.getAlarm1() > 0) {
                            WrkMast wrkMast = wrkMastMapper.selectById(crnProtocol.getTaskNo());
                            if (wrkMast == null) {
                                continue;
                            }
                            BasCrnError crnError = basCrnErrorMapper.selectById(crnProtocol.getAlarm1());
                            String errName = crnError==null? String.valueOf(crnProtocol.getAlarm1()):crnError.getErrName();
                            BasErrLog basErrLog = new BasErrLog(
                                    null,    // 编号
                                    wrkMast.getWrkNo(),    // 工作号
                                    now,    // 发生时间
                                    null,    // 结束时间
                                    wrkMast.getWrkSts(),    // 工作状态
                                    wrkMast.getIoType(),    // 入出库类型
                                    crn.getId(),    // 堆垛机
                                    null,    // plc
                                    wrkMast.getLocNo(),    // 目标库位
                                    wrkMast.getStaNo(),    // 目标站
                                    wrkMast.getSourceStaNo(),    // 源站
                                    wrkMast.getSourceLocNo(),    // 源库位
                                    wrkMast.getBarcode(),    // 条码
                                    (int) crnProtocol.getAlarm1(),    // 异常码
                                    errName,    // 异常
                                    1,    // 异常情况
                                    now,    // 添加时间
                                    null,    // 添加人员
                                    now,    // 修改时间
                                    null,    // 修改人员
                                    "任务中异常"    // 备注
                            );
                            if (!basErrLogService.insert(basErrLog)) {
                                log.error("堆垛机plc异常记录失败 ===>> [id:{}] [error:{}]", crn.getId(), errName);
                            }
                        }
                    } else {
                        // 异常修复
                        if (crnProtocol.getAlarm1() == null || crnProtocol.getAlarm1() == 0) {
                            latest.setEndTime(now);
                            latest.setUpdateTime(now);
                            latest.setStatus(2);
                            if (!basErrLogService.updateById(latest)) {
                                log.error("堆垛机plc异常记录修复失败 ===>> [id:{}] [errLogId:{}]", crn.getId(), latest.getId());
                            }
                        }
                    }
                // 无任务
                } else {
                    BasErrLog latest = basErrLogService.findLatest(crn.getId());
                    // 有异常
                    if (crnProtocol.getAlarm1() != null && crnProtocol.getAlarm1() > 0) {
                        // 记录新异常
                        if (latest == null || (latest.getErrCode() != crnProtocol.getAlarm1().intValue())) {
                            BasCrnError crnError = basCrnErrorMapper.selectById(crnProtocol.getAlarm1());
                            String errName = crnError==null? String.valueOf(crnProtocol.getAlarm1()):crnError.getErrName();
                            BasErrLog basErrLog = new BasErrLog(
                                    null,    // 编号
                                    null,    // 工作号
                                    now,    // 发生时间
                                    null,    // 结束时间
                                    null,    // 工作状态
                                    null,    // 入出库类型
                                    crn.getId(),    // 堆垛机
                                    null,    // plc
                                    null,    // 目标库位
                                    null,    // 目标站
                                    null,    // 源站
                                    null,    // 源库位
                                    null,    // 条码
                                    (int)crnProtocol.getAlarm1(),    // 异常码
                                    errName,    // 异常
                                    1,    // 异常情况
                                    now,    // 添加时间
                                    null,    // 添加人员
                                    now,    // 修改时间
                                    null,    // 修改人员
                                    "无任务异常"    // 备注
                            );
                            if (!basErrLogService.insert(basErrLog)) {
                                log.error("堆垛机plc异常记录失败 ===>> [id:{}] [error:{}]", crn.getId(), errName);
                            }
                        }
                    // 无异常
                    } else {
                        // 异常修复
                        if (latest != null && latest.getStatus() == 1) {
                            latest.setEndTime(now);
                            latest.setUpdateTime(now);
                            latest.setStatus(2);
                            if (!basErrLogService.updateById(latest)) {
                                log.error("堆垛机plc异常记录修复失败 ===>> [id:{}] [errLogId:{}]", crn.getId(), latest.getId());
                            }
                        }
                    }
            if ((rgvProtocol.getStatusType1() == RgvStatusType.WAITING || rgvProtocol.getStatusType1()==RgvStatusType.FETCHWAITING)
                    && rgvProtocol.getModeType() == RgvModeType.AUTO
                    && rgvProtocol.getTaskNo1() >0
//                    && (rgvProtocol.getStatusType() == RgvStatusType.WORKING1)
            ){
                boolean rgvComplete = rgvComplete(rgv.getId());
                if (rgvComplete){
                    rgvThread.setPakMk(true);
                }
            }
        }
    }
    //自动派发任务
    public void autoDistribute() {
        Config config = configService.selectByCode("autoDistribute");
        if (config == null) {
            return;
        }
    public boolean vacuumMastStatusSetN(Integer staNo){
        EntityWrapper<VacuumMast> vacuumMastEntityWrapper = new EntityWrapper<>();
        vacuumMastEntityWrapper.eq("sta_no",staNo);
        VacuumMast vacuumMast = vacuumMastService.selectOne(vacuumMastEntityWrapper);
        vacuumMast.setStatus("N");
        boolean update = vacuumMastService.update(vacuumMast, vacuumMastEntityWrapper);
        return update;
    }
    public boolean vacuumMastStatusSetY(Integer staNo){
        EntityWrapper<VacuumMast> vacuumMastEntityWrapper = new EntityWrapper<>();
        vacuumMastEntityWrapper.eq("sta_no",staNo);
        VacuumMast vacuumMast = vacuumMastService.selectOne(vacuumMastEntityWrapper);
        vacuumMast.setStatus("Y");
        boolean update = vacuumMastService.update(vacuumMast, vacuumMastEntityWrapper);
        return update;
    }
    public boolean fillingMastStatusSetN(Integer staNo){
        EntityWrapper<FillingMast> fillingMastEntityWrapper = new EntityWrapper<>();
        fillingMastEntityWrapper.eq("sta_no",staNo);
        FillingMast fillingMast = fillingMastService.selectOne(fillingMastEntityWrapper);
        fillingMast.setStatus("N");
        boolean update = fillingMastService.update(fillingMast, fillingMastEntityWrapper);
        return update;
    }
        if (config.getValue().equals("false")) {//判断是否开启自动派发任务
            return;
        }
    public boolean fillingMastStatusSetY(Integer staNo){
        EntityWrapper<FillingMast> fillingMastEntityWrapper = new EntityWrapper<>();
        fillingMastEntityWrapper.eq("sta_no",staNo);
        FillingMast fillingMast = fillingMastService.selectOne(fillingMastEntityWrapper);
        fillingMast.setStatus("Y");
        boolean update = fillingMastService.update(fillingMast, fillingMastEntityWrapper);
        return update;
    }
        for (TaskWrk taskWrk : taskWrkService.selectReceive()) {
            try {
                taskWrkService.distribute(taskWrk.getTaskNo(), 9527L);
            } catch (CoolException e) {
                e.printStackTrace();
    /*
     * 小车复位
     * */
    public synchronized boolean rgvComplete(Integer rgvId){
        try{
            //  命令下发区 --------------------------------------------------------------------------
            if (!MessageQueue.offer(SlaveType.Rgv, rgvId, new Task(3, new RgvCommand()))) {
                //step=2,工位1、2写任务;   step=4,工位1写任务;     step=5,工位2写任务
                log.error("RGV命令下发失败,RGV号={}",rgvId);
                return false;
            } else {
                log.info("RGV命令下发成功,RGV号={}",rgvId);
                return true;
            }
        }catch (Exception e){
            log.error("RGV命令下发失败,RGV号={}。异常:"+e,rgvId);
            return false;
        }
    }
}