#
taisheng
2025-05-24 53ae8e478f6034579303c51bdf881ffa526c942c
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java
@@ -1,27 +1,24 @@
package com.zy.asrs.service.impl;
import com.alibaba.fastjson.JSON;
import com.core.common.Cools;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.exception.CoolException;
import com.zy.asrs.domain.enums.TaskStatusType;
import com.zy.asrs.domain.enums.WorkNoType;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.param.WMSAndAGVInterfaceParam;
import com.zy.asrs.mapper.BasCrnErrorMapper;
import com.zy.asrs.mapper.TaskWrkMapper;
import com.zy.asrs.mapper.WaitPakinMapper;
import com.zy.asrs.mapper.WrkMastMapper;
import com.zy.asrs.entity.param.GenerateAgvTaskParam;
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.common.service.CommonService;
import com.zy.core.CrnThread;
import com.zy.common.utils.HttpHandler;
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.Task;
import com.zy.core.model.command.CrnCommand;
import com.zy.core.model.protocol.CrnProtocol;
import com.zy.core.model.protocol.StaProtocol;
import com.zy.core.properties.SlaveProperties;
import com.zy.core.thread.SiemensDevpThread;
@@ -30,16 +27,14 @@
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 java.util.Date;
import java.util.List;
import java.io.IOException;
import java.util.*;
/**
 * 立体仓库WCS系统主流程业务
 * Created by vincent on 2020/8/6
 */
@Slf4j
@Service("mainService")
@@ -51,38 +46,305 @@
    @Autowired
    private SlaveProperties slaveProperties;
    @Autowired
    private WrkMastMapper wrkMastMapper;
    @Autowired
    private LocMastService locMastService;
    @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;
    @Autowired
    private CommandInfoService commandInfoService;
    @Autowired
    private ApiLogService apiLogService;
    @Autowired
    private OpenService openService;
    @Autowired
    private CommonService commonService;
    @Value("${wcs.urlWcs}")
    private String wcsUrl;
    @Value("${wcs.inboundTaskApplyPathWcs}")
    private String wcsInboundTaskApplyPath;
    @Value("${wms.url}")
    private String wmsUrl;
    @Value("${wms.movePath}")
    private String movePath;
    public synchronized void demo() {
        boolean demoEnable = false;
        Config demoEnableConfig = configService.selectByCode("demoEnable");
        if(demoEnableConfig != null) {
            demoEnable = Boolean.parseBoolean(demoEnableConfig.getValue());
        }
        if (!demoEnable) {
            return;
        }
        //演示模式-AGV出库
        demoAgvOut();
        //演示模式-AGV入库
        demoAgvIn();
        //演示模式-四向库出库
        demoShuttleOut();
        //演示模式-四向库入库
        demoShuttleIn();
    }
    //演示模式-AGV出库
    private synchronized void demoAgvOut() {
        LocMast locMast = locMastService.selectByLocNo("0900601");
        if(locMast == null) {
            return;
        }
        if (!locMast.getLocSts().equals("O")) {
            return;
        }
        List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>()
                .eq("mk", "agv")
                .eq("loc_sts", "F")
                .notIn("loc_no", "1100601")
        );
        if (locMasts.isEmpty()) {
            return;
        }
        LocMast originLocMast = locMasts.get(0);
        //生成AGV出库任务
        GenerateAgvTaskParam param = new GenerateAgvTaskParam();
        param.setOriginPoint(originLocMast.getLocNo());
        param.setTargetPoint(locMast.getLocNo());
        openService.generateAgvTask(param);
    }
    //演示模式-AGV入库
    private synchronized void demoAgvIn() {
        LocMast locMast = locMastService.selectByLocNo("1100601");
        if(locMast == null) {
            return;
        }
        if (!locMast.getLocSts().equals("F")) {
            return;
        }
        List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>()
                .eq("mk", "agv")
                .eq("loc_sts", "O")
                .notIn("loc_no", "0900601")
        );
        if (locMasts.isEmpty()) {
            return;
        }
        LocMast targetLocMast = locMasts.get(0);
        //生成AGV出库任务
        GenerateAgvTaskParam param = new GenerateAgvTaskParam();
        param.setOriginPoint(locMast.getLocNo());
        param.setTargetPoint(targetLocMast.getLocNo());
        openService.generateAgvTask(param);
    }
    //演示模式-四向库出库
    private synchronized void demoShuttleOut() {
        LocMast locMast = locMastService.selectByLocNo("1100601");
        if(locMast == null) {
            return;
        }
        if (!locMast.getLocSts().equals("O")) {
            return;
        }
        ArrayList<Integer> disableLevList = new ArrayList<>();
        disableLevList.add(1);
        //query in task
        List<TaskWrk> taskWrks = taskWrkService.selectList(new EntityWrapper<TaskWrk>()
                .eq("io_type", 1));
        for (TaskWrk taskWrk : taskWrks) {
            int lev = Utils.getLev(taskWrk.getTargetPoint());
            if(!disableLevList.contains(lev)) {
                disableLevList.add(lev);
            }
        }
        List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>()
                .notIn("lev1", disableLevList)
                .eq("loc_sts", "F")
        );
        if(locMasts.isEmpty()) {
            return;
        }
        LocMast locMast1 = locMasts.get(0);
        Date now = new Date();
        TaskWrk taskWrk = new TaskWrk();
        int workNo1 = commonService.getWorkNo(WorkNoType.PAKOUT.type);//获取入库工作号
        taskWrk.setTaskNo(String.valueOf(workNo1));//任务号
        taskWrk.setWrkNo(workNo1);
        taskWrk.setStatus(TaskStatusType.RECEIVE.id);//任务状态:接收
        taskWrk.setWrkSts(11);
        taskWrk.setCreateTime(now);
        taskWrk.setIoType(2);//出库
        taskWrk.setIoPri(100);//优先级
        taskWrk.setStartPoint(locMast1.getLocNo());
        taskWrk.setTargetPoint("101");//终点
        boolean result = taskWrkService.insert(taskWrk);
        locMast1.setLocSts("R");
        locMast1.setModiTime(now);
        locMastService.updateById(locMast1);
        locMast.setLocSts("S");
        locMast.setModiTime(now);
        locMastService.updateById(locMast);
    }
    //演示模式-四向库入库
    private synchronized void demoShuttleIn() {
        LocMast locMast = locMastService.selectByLocNo("0900601");
        if(locMast == null) {
            return;
        }
        if (!locMast.getLocSts().equals("F")) {
            return;
        }
        ArrayList<Integer> disableLevList = new ArrayList<>();
        disableLevList.add(1);
        //query out task
        List<TaskWrk> taskWrks = taskWrkService.selectList(new EntityWrapper<TaskWrk>()
                .eq("io_type", 2));
        for (TaskWrk taskWrk : taskWrks) {
            int lev = Utils.getLev(taskWrk.getTargetPoint());
            if(!disableLevList.contains(lev)) {
                disableLevList.add(lev);
            }
        }
        List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>()
                .notIn("lev1", disableLevList)
                .eq("loc_sts", "O")
        );
        if(locMasts.isEmpty()) {
            return;
        }
        LocMast locMast1 = locMasts.get(0);
        Date now = new Date();
        TaskWrk taskWrk = new TaskWrk();
        int workNo1 = commonService.getWorkNo(WorkNoType.PAKIN.type);//获取入库工作号
        taskWrk.setTaskNo(String.valueOf(workNo1));//任务号
        taskWrk.setWrkNo(workNo1);
        taskWrk.setStatus(TaskStatusType.RECEIVE.id);//任务状态:接收
        taskWrk.setWrkSts(1);
        taskWrk.setCreateTime(now);
        taskWrk.setIoType(1);//入库
        taskWrk.setIoPri(100);//优先级
        taskWrk.setOriginStartPoint("1");
        taskWrk.setOriginTargetPoint(String.valueOf(Utils.getLev(locMast1.getLocNo())));
        taskWrk.setTargetPoint(locMast1.getLocNo());//终点
        boolean result = taskWrkService.insert(taskWrk);
        locMast1.setLocSts("S");
        locMast1.setModiTime(now);
        locMastService.updateById(locMast1);
        locMast.setLocSts("R");
        locMast.setModiTime(now);
        locMastService.updateById(locMast);
    }
    /**
     * 堆垛机站出库到出库站
     */
    @Async
    public void crnStnToOutStn() {
    public synchronized 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) {
                    try {
                        // 获取堆垛机出库站信息
                        DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, crnStn.getDevpPlcId());
                        StaProtocol staProtocol = devpThread.getStation().get(crnStn.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) {
                                continue;
                            }
                            log.info("下发输送线任务:taskWrk:" + JSON.toJSONString(taskWrk));
//                            R r = siteController.siteDetlUpdate(Integer.valueOf(taskWrk.getTargetPoint()), taskWrk.getWrkNo().shortValue(), (short) 0, "Y", false, false);
                            staProtocol.setWorkNo(taskWrk.getWrkNo().shortValue());
                            staProtocol.setStaNo(staDesc.getStnNo().shortValue());
                            boolean offer = false;
                            try {
                                offer = MessageQueue.offer(SlaveType.Devp, 1, new Task(2, staProtocol));
                            } catch (Exception e) {
                                log.error("下发输送线任务失败:异常:" + e);
                                log.error("下发输送线任务失败:异常:offer:" + offer);
                            }
//                            JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(r));
                            if (offer) {
                                log.info("下发输送线任务成功:taskWrk:" + JSON.toJSONString(taskWrk));
                                taskWrk.setStatus(5);
                                taskWrk.setWrkSts(14);
                                taskWrkService.updateById(taskWrk);
                            } else {
                                log.error("下发输送线任务失败:taskWrk:" + JSON.toJSONString(taskWrk));
//                                log.error("下发输送线任务失败:异常信息:"+JSON.toJSONString(r));
                            }
                        }
                    } catch (Exception e) {
                        log.error("出库到出库站异常:异常信息:" + e);
                    }
                }
            }
        }
    }
    /**
     * 入出库  ===>>  调用RCS进行入出库
     */
    public synchronized void crnIoExecute() throws IOException {
        for (CrnSlave crn : slaveProperties.getCrn()) {
            this.crnStnToLoc(crn); //  入库
            this.locToCrnStn(crn); //  出库
            // 库位移转
//            this.locToLoc(crn, crnProtocol);
        }
    }
    /**
     * 入库  ===>>  堆垛机站到库位
     */
    public synchronized void crnStnToLoc(CrnSlave slave) throws IOException {
        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) {
@@ -90,175 +352,66 @@
                } else {
                    staProtocol = staProtocol.clone();
                }
                if (staProtocol.isAutoing() && staProtocol.isLoading() && (staProtocol.getWorkNo() == 0 || staProtocol.getStaNo() == null)) {
                    // 查询工作档
                    TaskWrk taskWrk = taskWrkMapper.selectCrnStaWorking(crnSlave.getId(), staProtocol.getSiteId().toString());
                    if (taskWrk == null) {
                        continue;
                // 查询站点详细信息
                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;
                }
                String mbz=taskWrk.getTargetPoint().substring(5);
                HashMap<String, Object> hashMap = new HashMap<>();
                hashMap.put("taskNo",taskWrk.getTaskNo());//wms任务号
                hashMap.put("sourceStaNo",staDetl.getDevNo());//源站点
                hashMap.put("staNo",Integer.parseInt(mbz)+"");//目标站
                hashMap.put("locNo",taskWrk.getTargetPoint());//目标库位
                String response = "";
                Boolean bool = false;
                try {
                    //开始上报,出库任务开始时,WCS回调WMS
                    response = new HttpHandler.Builder()
                            .setUri(wcsUrl)
                            .setPath(wcsInboundTaskApplyPath)
                            .setJson(JSON.toJSONString(hashMap))
                            .build()
                            .doPost();
                    JSONObject jsonObject = JSON.parseObject(response);
                    if(jsonObject.get("code").equals(200)){
                        bool = true;
                        taskWrk.setStatus(TaskStatusType.DISTRIBUTE.id);//派发状态
                        taskWrk.setAssignTime(new Date());//派发时间
                        taskWrk.setWrkSts(3);//工作状态 3.成功下发入库任务给RCS
                        taskWrk.setCrnNo(staDesc.getCrnNo());//堆垛机号
                        taskWrk.setModiTime(new Date());
                        taskWrk.setModiUser(9988L);
                    }
                    // 判断工作档条件
                    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.modeType == CrnModeType.AUTO && crnProtocol.getTaskNo().equals(taskWrk.getWrkNo().shortValue())
                                && crnProtocol.getTaskFinish() == 1
                                && crnProtocol.forkPosType == CrnForkPosType.HOME) {
                            // 命令下发区 --------------------------------------------------------------------------
                            // 下发站点信息
                            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);
                            } else {
                                log.error("更新工作档的工作状态为14失败!!! [工作号:{}]", taskWrk.getWrkNo());
                            }
                        }
                    }
                } catch (Exception e) {
                }finally {
                    apiLogService.save("wcs派发入库任务给RCS"
                            , wcsUrl + wcsInboundTaskApplyPath
                            , null
                            , "127.0.0.1"
                            , JSON.toJSONString(hashMap)
                            , response
                            , bool
                    );
                }
            }
        }
    }
    /**
     * 入出库  ===>>  堆垛机入出库作业下发
     */
    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()) {
            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(), crnStn.getStaNo().toString());
            if(null == taskWrk) {
                continue;
            }
            // 获取库位信息
            String locNo = taskWrk.getTargetPoint();
            LocMast locMast = locMastService.selectById(locNo);
            if (locMast == null) {
                log.error("查询库存无数据--库位号{}", locNo);
                continue;
            }
            if (!locMast.getLocSts().equals("S") && !locMast.getLocSts().equals("Q")) {
                log.error("入库操作库位状态不符合--状态, 库位号={},库位状态={}", locNo, locMast.getLocSts());
                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.getRow().shortValue());     // 源库位排
            crnCommand.setSourcePosY(crnStn.getBay().shortValue());     // 源库位列
            crnCommand.setSourcePosZ(crnStn.getLev().shortValue());     // 源库位层
            crnCommand.setDestinationPosX(locMast.getRow1().shortValue());     // 目标库位排
            crnCommand.setDestinationPosY(locMast.getBay1().shortValue());     // 目标库位列
            crnCommand.setDestinationPosZ(locMast.getLev1().shortValue());     // 目标库位层
            if (!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;
        }
    }
@@ -266,394 +419,105 @@
     * 出库  ===>>  库位到堆垛机站
     * 2022-06-09 TQS修改,查询工作档LIST,遍历下发,防止第一个任务堵塞出库
     */
    public void locToCrnStn(CrnSlave slave, CrnProtocol crnProtocol){
    public synchronized void locToCrnStn(CrnSlave slave) {
        List<TaskWrk> taskWrksInitial = taskWrkMapper.selectPakOut(slave.getId(), null);
        if (taskWrksInitial.size() == 0) {
            return;
        }
        for (CrnSlave.CrnStn crnStn : slave.getCrnOutStn()) {
            // 获取工作状态为11(生成出库ID)的出库工作档
            List<TaskWrk> taskWrks = taskWrkMapper.selectPakOut(slave.getId(), crnStn.getStaNo().toString());
            for (TaskWrk taskWrk : taskWrks){
                if (taskWrk == null) {
                    continue;
                }
                // 工作档状态判断
                if (taskWrk.getIoType() != 2 || taskWrk.getTargetPoint() == null) {
                    log.error("查询工作档数据不符合条件--入出类型/站点, 工作号={},源库位={},入出类型={}", taskWrk.getWrkNo(), taskWrk.getTargetPoint(), taskWrk.getIoType());
                    continue;
                }
                // 获取源库位信息
                String locNo = taskWrk.getStartPoint();
                LocMast sourceSta = locMastService.selectById(locNo);
                if (!sourceSta.getLocSts().equals("R") &&!sourceSta.getLocSts().equals("P")) {
                    log.error("出库操作库位状态不符合--状态, 库位号={},库位状态={}", locNo, sourceSta.getLocSts());
                    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();
                }
            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;
                    }
                // 查询站点详细信息
                BasDevp staDetl = basDevpService.selectById(crnStn.getStaNo());
                if (staDetl == null) {
                    log.error("出库 ===>> 堆垛机站点在数据库不存在, 站点编号={}", crnStn.getStaNo());
                    break;
                }
                    LocMast locMast = locMastService.selectByLocNo(taskWrk.getStartPoint());
                    //判断其库位是否为深库位,如果为深库位找其浅库位是都有货
                    //预留
                // 判断堆垛机出库站状态
                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) {
                    // 获取堆垛机出库站信息
                    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 (taskWrkMapper.selectCrnWorking(slave.getId()) != null) {
                        break;
                    }
                    // 判断堆垛机出库站状态
                    if (staProtocol.isAutoing() && !staProtocol.isLoading() && staDetl.getCanouting() != null && staDetl.getCanouting().equals("Y")
                            && staProtocol.getWorkNo() == 0 && staProtocol.isOutEnable()) {
                        // 命令下发区 --------------------------------------------------------------------------
                    // 双深库位且浅库位有货,则需先对浅库位进行库位移转
                    if (Utils.isDeepLoc(slaveProperties, taskWrk.getStartPoint())) {
                        List<TaskWrk> taskWrks1 = taskWrkMapper.selectPakOutIoType(taskWrk.getCrnNo());
                        if (Cools.isEmpty(taskWrks1) && taskWrks1.size()!=0){
                        // 已经存在吊车执行任务时,则过滤
                        if (taskWrkMapper.selectCrnWorking(slave.getId()) != null) {
                            break;
                        }
                        String shallowLocNo = Utils.getShallowLoc(slaveProperties, taskWrk.getStartPoint());
                        LocMast shallowLoc = locMastService.selectById(shallowLocNo);
                        if (!shallowLoc.getLocSts().equals("O")){
                            // O.空库位、Q.拣料/盘点/并板再入库、S.入库预约、X.禁用 直接搬!
                            if (shallowLoc.getLocSts().equals("P") || shallowLoc.getLocSts().equals("R")) {
                                log.error("工作号={},库位号={},浅库位异常:浅库位号:={},库位状态={}",taskWrk.getTaskNo(),taskWrk.getStartPoint(),shallowLocNo,shallowLoc.getLocSts());
                            } else if (shallowLoc.getLocSts().equals("F") || shallowLoc.getLocSts().equals("D")) {
                                taskWrk.setTransferMark(1);
                                taskWrkMapper.updateById(taskWrk);
                                WMSAndAGVInterfaceParam param = new WMSAndAGVInterfaceParam();
                                param.setTaskNo(taskWrk.getTaskNo());
                                new PostMesDataUtils().postMesData("MES系统",wmsUrl,movePath,param);
                                log.error("工作号={},库位号={},浅库位需要移库:浅库位号:={},库位状态={}",taskWrk.getTaskNo(),taskWrk.getStartPoint(),shallowLocNo,shallowLoc.getLocSts());
                            } else if (shallowLoc.getLocSts().equals("Q") || shallowLoc.getLocSts().equals("S")) {
                                log.error("工作号={},库位号={},浅库位异常:浅库位号:={},库位状态={}",taskWrk.getTaskNo(),taskWrk.getStartPoint(),shallowLocNo,shallowLoc.getLocSts());
                            }
                            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(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 (!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) {
                        try {
                            // 修改工作档状态 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());
                            }
                        } catch (Exception e) {
                            log.error("修改工作档状态 11.生成出库ID => 12.吊车出库中 失败!!,工作号={}", taskWrk.getWrkNo());
                            log.error("修改工作档状态 11.生成出库ID => 12.吊车出库中 失败!!,异常:" + e);
                        }
                        break;
                    }
                    return;
                }
            }
        }
    }
//                            try {
//                                HashMap<String, Object> headParam = new HashMap<>();
//                                headParam.put("taskNo", taskWrk.getTaskNo());
//                                headParam.put("status", taskWrk.getStatus());
//                                headParam.put("ioType", taskWrk.getIoType());
//                                headParam.put("barcode", taskWrk.getBarcode());
//                                String response;
//                                response = new HttpHandler.Builder()
//                                        // .setHeaders(headParam)
//                                        .setUri(wmsUrl)
//                                        .setPath(taskStatusFeedbackPath)
//                                        .setJson(JSON.toJSONString(headParam))
//                                        .build()
//                                        .doPost();
//                                JSONObject jsonObject = JSON.parseObject(response);
//                                apiLogService.save("wcs派发出库任务上报wms"
//                                        , wmsUrl + taskStatusFeedbackPath
//                                        , null
//                                        , "127.0.0.1"
//                                        , JSON.toJSONString(headParam)
//                                        , response
//                                        , true
//                                );
//                            } catch (Exception e) {
//                                log.error("wcs派发出库任务上报wms失败", JSON.toJSONString(taskWrk));
////                                throw new CoolException("wcs派发入库任务上报wms失败");
//                            }
    /**
     * 库位移转
     */
    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) {
                    continue;
                }
                // 工作档状态判断
                if (taskWrk.getIoType() != 3 || taskWrk.getTargetPoint() == null) {
                    log.error("查询工作档数据不符合条件--入出类型/目标库位号, 工作号={},源库位={},入出类型={}", taskWrk.getWrkNo(), taskWrk.getTargetPoint(), taskWrk.getIoType());
                    continue;
                }
                // 获取源库位信息
                String locNo = taskWrk.getStartPoint();
                LocMast sourceSta = locMastService.selectById(locNo);
                if (!sourceSta.getLocSts().equals("R") &&!sourceSta.getLocSts().equals("P")) {
                    log.error("出库操作库位状态不符合--状态, 库位号={},库位状态={}", locNo, sourceSta.getLocSts());
                    continue;
                }
                // 获取目标库位信息
                String locNoEnd = taskWrk.getTargetPoint();
                LocMast sourceEnd = locMastService.selectById(locNoEnd);
                if (!sourceEnd.getLocSts().equals("S") && !sourceEnd.getLocSts().equals("Q")) {
                    log.error("出库操作库位状态不符合--状态, 库位号={},库位状态={}", locNo, sourceSta.getLocSts());
                    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());
                    continue;
                }
                // 命令下发区 --------------------------------------------------------------------------
                // 堆垛机控制过滤
                if (!crnProtocol.getStatusType().equals(CrnStatusType.IDLE) || crnProtocol.getTaskNo() != 0) {
                    continue;
                }
                // 已经存在吊车执行任务时,则过滤
                if (taskWrkMapper.selectCrnWorking(slave.getId()) != null) {
                    continue;
                }
                // 起始深库位浅库位不为空
                if (Utils.isDeepLoc(slaveProperties, taskWrk.getStartPoint())) {
                    // 获取浅库位信息
                    String shallowLocNo = Utils.getShallowLoc(slaveProperties, taskWrk.getStartPoint());
                    LocMast shallowLocMast = locMastService.selectById(shallowLocNo);
                    if (!shallowLocMast.getLocSts().equals("O")) {
                        log.error("移库操作起始库位浅库位状态不符合--状态, 库位号={},库位状态={}", locNo, shallowLocMast.getLocSts());
                        continue;
                    }
                }
                // 目标库位为深库位且浅库位不为空
                if (Utils.isDeepLoc(slaveProperties, taskWrk.getTargetPoint())) {
                    // 获取浅库位信息
                    String shallowLocNo = Utils.getShallowLoc(slaveProperties, taskWrk.getTargetPoint());
                    LocMast shallowLocMast = locMastService.selectById(shallowLocNo);
                    if (!shallowLocMast.getLocSts().equals("O")) {
                        log.error("移库操作目标库位浅库位状态不符合--状态, 库位号={},库位状态={}", locNo, shallowLocMast.getLocSts());
                        continue;
                    }
                }
                // 目标库位为浅库位且深库位无货
                if (Utils.isShallowLoc(slaveProperties, taskWrk.getTargetPoint())) {
                    // 获取深库位信息
                    String deepLocNo = Utils.getDeepLoc(slaveProperties, taskWrk.getTargetPoint());
                    LocMast deepLocMast = locMastService.selectById(deepLocNo);
                    if (!deepLocMast.getLocSts().equals("F") && !deepLocMast.getLocSts().equals("D") ) {
                        log.error("移库操作目标库位深库位状态不符合--状态, 库位号={},库位状态={}", locNo, deepLocMast.getLocSts());
                        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(sourceSta.getRow1().shortValue());     // 源库位排
                crnCommand.setSourcePosY(sourceSta.getBay1().shortValue());     // 源库位列
                crnCommand.setSourcePosZ(sourceSta.getLev1().shortValue());     // 源库位层
                crnCommand.setDestinationPosX(sourceEnd.getRow1().shortValue());     // 目标库位排
                crnCommand.setDestinationPosY(sourceEnd.getBay1().shortValue());     // 目标库位列
                crnCommand.setDestinationPosZ(sourceEnd.getLev1().shortValue());     // 目标库位层
                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() == 1 && crnProtocol.getTaskNo() != 0) {
                // 获取入库待确认工作档
                TaskWrk taskWrk = taskWrkMapper.selectCrnNoWorking(crn.getId(),crnProtocol.getTaskNo().intValue());
                if (taskWrk == null) {
                    log.error("堆垛机处于等待确认且任务完成状态,但未找到工作档。堆垛机号={},工作号={}", crn.getId(), crnProtocol.getTaskNo());
                    continue;
                }
                // 入库 + 库位转移  ==> 4.入库完成
                if (taskWrk.getWrkSts() == 3 || (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);
                }
            }
        }
    }
    /**
     * 堆垛机异常信息记录
     */
    @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) {
                continue;
            }
            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());
                            }
                        }
                    }
                }
            }
        }
    }
    //自动派发任务
    public void autoDistribute() {
    public synchronized void autoDistribute() {
        Config config = configService.selectByCode("autoDistribute");
        if (config == null) {
            return;
@@ -664,13 +528,121 @@
        }
        for (TaskWrk taskWrk : taskWrkService.selectReceive()) {
            try {
                taskWrkService.distribute(taskWrk.getTaskNo(), 9527L);
            } catch (CoolException e) {
                e.printStackTrace();
                log.info(e.getMessage());
            }
        }
    }
    //agv取放货任务完成
    public synchronized void autoCompleteAGV() {
        List<BasDevp> basDevps = basDevpService.selectList(new EntityWrapper<>());
        try {
            Thread.sleep(500);
        } catch (Exception e) {
        }
        for (BasDevp basDevp : basDevps) {
            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, 1);
            StaProtocol staProtocol = devpThread.getStation().get(basDevp.getDevNo());
            if (staProtocol == null) {
                continue;
            } else {
                staProtocol = staProtocol.clone();
            }
            if (basDevp.getWrkNo() != 0) {
                if (basDevp.getAgvTargetPick() != 0) {//取货
                    staProtocol.setAgvTypeSign((short) 0);
                    staProtocol.setStaNo(basDevp.getDevNo().shortValue());
                    MessageQueue.offer(SlaveType.Devp, 1, new Task(4, staProtocol));
                }
                boolean sign = true;
                if (basDevp.getAgvTargetPlace() != 0) {
                    sign = false;
                    basDevp.setAgvTargetPlace(0);
                    basDevpService.updateById(basDevp);
                    staProtocol.setAgvTypeSign((short) 3);//1
                    staProtocol.setStaNo(basDevp.getDevNo().shortValue());
                    MessageQueue.offer(SlaveType.Devp, 1, new Task(4, staProtocol));
                }
            } else {
                if (basDevp.getAgvTargetPlace() != 0) {
                    if (basDevp.getLoading().equals("Y")) {
                        staProtocol.setAgvTypeSign((short) 1);
                        staProtocol.setStaNo(basDevp.getDevNo().shortValue());
                        MessageQueue.offer(SlaveType.Devp, 1, new Task(4, staProtocol));
                    } else {
                        log.error("AGV放货完成但输送线无物,复位信号 ===>> [staNo:{}] [basDevp:{}]", basDevp.getDevNo(), basDevp);
                        basDevp.setAgvTargetPlace(0);
                        basDevpService.updateById(basDevp);
                        staProtocol.setAgvTypeSign((short) 3);//1
                        staProtocol.setStaNo(basDevp.getDevNo().shortValue());
                        MessageQueue.offer(SlaveType.Devp, 1, new Task(4, staProtocol));
                    }
                }
                if (basDevp.getAgvTargetPick() != 0) {
                    basDevp.setAgvTargetPick(0);
                    basDevpService.updateById(basDevp);
                    staProtocol.setAgvTypeSign((short) 2);//0
                    staProtocol.setStaNo(basDevp.getDevNo().shortValue());
                    MessageQueue.offer(SlaveType.Devp, 1, new Task(4, staProtocol));
                }
            }
        }
    }
    public synchronized void autoCompleteTask() {
        List<TaskWrk> taskWrks = taskWrkMapper.selectWorkingTask();
        for (TaskWrk taskWrk : taskWrks) {
            //获取命令集合
            List<CommandInfo> commandInfos = commandInfoService.selectByTaskNo(taskWrk.getTaskNo());
            if (taskWrk.getCommandStep() < commandInfos.size()) {
                continue;//当前步序没有到达最后一条命令
            }
            //判断末端命令是否执行完成
            CommandInfo commandInfo = commandInfos.get(commandInfos.size() - 1);
            if (commandInfo.getCommandStatus() != CommandStatusType.COMPLETE.id) {
                continue;//指令未完成
            }
            Date now = new Date();
            //指令已完成,更新任务
            if (taskWrk.getIoType() == 1) {
                //入库任务
                taskWrk.setWrkSts(4);//3.吊车入库中 => 4.入库完成
                //taskWrk.setStatus(TaskStatusType.COMPLETE.id);
                taskWrk.setModiTime(now);
                taskWrkService.updateById(taskWrk);
                //更新库位状态
                LocMast locMast = locMastService.selectByLocNo(taskWrk.getTargetPoint());
                locMast.setLocSts("F");//F.在库
                locMast.setBarcode(taskWrk.getBarcode());//托盘码
                locMast.setModiTime(now);
                locMast.setModiUser(9999L);
                locMastService.updateById(locMast);
            } else if (taskWrk.getIoType() == 2) {
                //出库任务
                taskWrk.setWrkSts(14);//12.吊车出库中 => 14.出库完成
//                taskWrk.setStatus(TaskStatusType.COMPLETE.id);
                taskWrk.setModiTime(now);
                taskWrkService.updateById(taskWrk);
                //更新库位状态
                LocMast locMast = locMastService.selectByLocNo(taskWrk.getStartPoint());
                locMast.setLocSts("O");//O.空库位
                locMast.setBarcode("");//托盘码
                locMast.setModiTime(now);
                locMast.setModiUser(9999L);
                locMastService.updateById(locMast);
            }
        }
    }
}