package com.shkj.wms.scheduled;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.shkj.common.constant.RedisConstant;
import com.shkj.common.core.domain.Result;
import com.shkj.common.enums.HttpStatus;
import com.shkj.common.utils.DateUtils;
import com.shkj.common.utils.StringUtils;
import com.shkj.plc.sdk.device.PLCReadAndWrite;
import com.shkj.plc.sdk.device.PlcOperate;
import com.shkj.system.service.ISysParameterService;
import com.shkj.wms.bo.BasePunchRecordAddBo;
import com.shkj.wms.domain.BasePoint;
import com.shkj.wms.domain.BasePunch;
import com.shkj.wms.domain.BasePunchRecord;
import com.shkj.wms.domain.WcsPlcProperty;
import com.shkj.wms.enums.SkipOverWareEnum;
import com.shkj.wms.enums.StartStopOutboundEnum;
import com.shkj.wms.mapper.*;
import com.shkj.wms.plc.PlcInit;
import com.shkj.wms.service.IBasePointService;
import com.shkj.wms.service.IBasePunchRecordService;
import com.shkj.wms.service.IBasePunchService;
import com.shkj.wms.service.IWcsPlcPropertyService;
import com.shkj.wms.third.rcs.RCSUtil;
import com.shkj.wms.third.rcs.enums.RCSTaskTypeEnum;
import com.shkj.wms.utils.TunnelTaskUtil;
import com.shkj.wms.vo.BasePunchRecordVo;
import com.shkj.wms.bo.*;
import com.shkj.wms.constants.ParameterConstants;
import com.shkj.wms.domain.*;
import com.shkj.wms.enums.TaskStatusEnum;
import com.shkj.wms.enums.TaskTypeEnum;
import com.shkj.wms.service.*;
import com.shkj.wms.service.impl.BaseLocationServiceImpl;
import com.shkj.wms.utils.JsonUtil;
import com.shkj.wms.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Component
public class ScheduledTasks {

    @Resource
    IBusinDataTaskService iBusinDataTaskService;

    @Resource
    IBusinDataTaskGoodsService iBusinDataTaskGoodsService;

    @Resource
    IBaseDeriveService iBaseDeriveService;

    @Resource
    IBaseLocationService iBaseLocationService;

    @Resource
    IPutInOutStorageService iPutInOutStorageService;

    @Resource
    ISysParameterService sysParameterService;

    @Resource
    RCSUtil rcsUtil;

    @Autowired
    ISysStockDetailService iSysStockDetailService;
    @Resource
    IBasePunchService iBasePunchService;
    @Autowired
    BaseLocationServiceImpl baseLocationService;
    @Resource
    IBasePointService iBasePointService;

    @Resource
    BaseLocationPlcMapper baseLocationPlcMapper;

    @Resource
    BaseLocationMapper baseLocationMapper;

    @Autowired
    IBasePunchRecordService iBasePunchRecordService;

    @Autowired
    IWcsPlcPropertyService iWcsPlcPropertyService;

    @Autowired
    ISysParameterService isysParameterService;

    @Resource
    BusinDpsContainerRecordMapper businDpsContainerRecordMapper;

    @Resource
    RedisTemplate redisTemplate;

    @Resource
    BasePointDeviceMapper basePointDeviceMapper;

    @Autowired
    private IBaseStorageService iBaseStorageService;

    @Resource
    SysStockDetailMapper sysStockDetailMapper;

    @Autowired
    AllocationTasksUtils allocationTasksUtils;

    @Autowired
    IWcsPlcConnectService iWcsPlcConnectService;

    @Resource
    private TunnelTaskUtil tunnelTaskUtil;

    @Resource
    IBusinEnptyContainerService iBusinEnptyContainerService;
    @Resource
    IBaseGoodsDataService iBaseGoodsDataService;

    @Resource
    IBaseBarcodesInService iBaseBarcodesInService;
    @Resource
    IBaseBarcodesOutService iBaseBarcodesOutService;

    @Resource
    BusinDataTaskMapper businDataTaskMapper;


    @Resource
    PlcInit plcInit;

    //根据派生获取
    private Long getLocationByDervie(String vehicheModel, String color) {
        // 根据条码信息获取派生信息
        BaseDeriveQueryBo deriveQueryBo = new BaseDeriveQueryBo();
        deriveQueryBo.setVehicheModel(vehicheModel);
        deriveQueryBo.setColor(color);
        BaseDerive derive = iBaseDeriveService.getBaseDeriveBybarcodes(deriveQueryBo);
        Long deriveId = derive.getId();
        return deriveId;
    }

    //呼叫AGC
    public Result<Boolean> callAGV(Long taskId, int taskType, List<String> points) {


        AGVMoveBo moveBo = new AGVMoveBo();
        moveBo.setTaskId(taskId);
        moveBo.setTaskType(taskType);
        moveBo.setPoints(points);
        Result<Boolean> booleanResult = rcsUtil.moveByAGV(moveBo);
        return booleanResult;
    }

    public Result<Boolean> callAGV(Long taskId, int taskType, List<String> points, String agvno) {


        AGVMoveBo moveBo = new AGVMoveBo();
        moveBo.setTaskId(taskId);
        moveBo.setTaskType(taskType);
        moveBo.setPoints(points);
        moveBo.setRobotId(agvno);
        Result<Boolean> booleanResult = rcsUtil.moveByAGV(moveBo);
        return booleanResult;
    }


    @Scheduled(fixedRate = 200)
    public void task() {

        //  log.info("开始获取需要执行的任务");
        //获取下发车型
        String inVehicheModel = "";
        Object objVehicheModel = redisTemplate.opsForValue().get(RedisConstant.redisInVehicheModel);
        if (objVehicheModel == null) {
            inVehicheModel = "";
        }


        //获取待下发任务数据
        BusinTaskQueryBo taskQueryBo = new BusinTaskQueryBo();
        List<BusinDataTaskVo> businDataTaskVos = new ArrayList<>();
       /* taskQueryBo.setTaskType("0");
        List<BusinDataTaskVo> businDataTaskVo0 = iBusinDataTaskService.selectBusinDataTask1(taskQueryBo);
        businDataTaskVos.addAll(businDataTaskVo0);*/
        taskQueryBo.setTaskType("21");
        List<BusinDataTaskVo> businDataTaskVo21 = iBusinDataTaskService.selectBusinDataTask1(taskQueryBo);
        businDataTaskVos.addAll(businDataTaskVo21);

        taskQueryBo.setTaskType("1");
        List<BusinDataTaskVo> businDataTaskVo1 = iBusinDataTaskService.selectBusinDataTask1(taskQueryBo);
        businDataTaskVos.addAll(businDataTaskVo1);


        //越库模式下或暂停出库，需要设置暂停出库
        String startStopOutbound= StartStopOutboundEnum.STOP.getValue();
        Object redisStartStopOutbound = redisTemplate.opsForValue().get(RedisConstant.redisStartStopOutbound);
        if (redisStartStopOutbound != null){
            startStopOutbound=redisStartStopOutbound.toString();
        }
        if (startStopOutbound.equals(StartStopOutboundEnum.START.getValue())){
            taskQueryBo.setTaskType("4");
            List<BusinDataTaskVo> businDataTaskVo4 = iBusinDataTaskService.selectOutBusinDataTask(taskQueryBo);
            businDataTaskVos.addAll(businDataTaskVo4);
        }

        taskQueryBo.setTaskType("5");
        List<BusinDataTaskVo> businDataTaskVo5 = iBusinDataTaskService.selectOutBusinDataTask(taskQueryBo);
        businDataTaskVos.addAll(businDataTaskVo5);
        taskQueryBo.setTaskType("7");
        List<BusinDataTaskVo> businDataTaskVo7 = iBusinDataTaskService.selectBusinDataTask1(taskQueryBo);
        businDataTaskVos.addAll(businDataTaskVo7);
        taskQueryBo.setTaskType("10");
        List<BusinDataTaskVo> businDataTaskVo10 = iBusinDataTaskService.selectBusinDataTask1(taskQueryBo);
        businDataTaskVos.addAll(businDataTaskVo10);
        taskQueryBo.setTaskType("11");
        List<BusinDataTaskVo> businDataTaskVo11 = iBusinDataTaskService.selectBusinDataTask1(taskQueryBo);
        businDataTaskVos.addAll(businDataTaskVo11);
        taskQueryBo.setTaskType("12");
        List<BusinDataTaskVo> businDataTaskVo12 = iBusinDataTaskService.selectBusinDataTask1(taskQueryBo);
        businDataTaskVos.addAll(businDataTaskVo12);

        if (!inVehicheModel.equals("3LN") && !inVehicheModel.equals("3UE")) {//如果车型非3LN车型，空托任务正常执行，否则根据出库任务交替执行
            taskQueryBo.setTaskType("15");
            List<BusinDataTaskVo> businDataTaskVo15 = iBusinDataTaskService.selectOutBusinDataTask(taskQueryBo);
            businDataTaskVos.addAll(businDataTaskVo15);
        }
        taskQueryBo.setTaskType("17");
        List<BusinDataTaskVo> businDataTaskVo17 = iBusinDataTaskService.selectBusinDataTask1(taskQueryBo);
        businDataTaskVos.addAll(businDataTaskVo17);
//        taskQueryBo.setTaskType("18");
//        List<BusinDataTaskVo> businDataTaskVo18 = iBusinDataTaskService.selectBusinDataTask1(taskQueryBo);
//        businDataTaskVos.addAll(businDataTaskVo18);
        taskQueryBo.setTaskType("19");
        List<BusinDataTaskVo> businDataTaskVo19 = iBusinDataTaskService.selectBusinDataTask1(taskQueryBo);
        businDataTaskVos.addAll(businDataTaskVo19);

        taskQueryBo.setTaskType("16");
        List<BusinDataTaskVo> businDataTaskVo16 = iBusinDataTaskService.selectBusinDataTask1(taskQueryBo);
        businDataTaskVos.addAll(businDataTaskVo16);


        //指定货位出库
        taskQueryBo.setTaskType("25");
        List<BusinDataTaskVo> businDataTaskVo25 = iBusinDataTaskService.selectBusinDataTask1(taskQueryBo);
        businDataTaskVos.addAll(businDataTaskVo25);
        //跨巷道移出
        taskQueryBo.setTaskType(TaskTypeEnum.relocation_out.getValue());
        List<BusinDataTaskVo> businDataTaskVo23 = iBusinDataTaskService.selectBusinDataTask1(taskQueryBo);
        businDataTaskVos.addAll(businDataTaskVo23);

        Integer[] waitIssueEmpTaskNum = {0};

        //按照优先级降序排序，优先级高的优先执行
        businDataTaskVos = businDataTaskVos.stream().sorted(Comparator.comparing(BusinDataTaskVo::getIsTop, Comparator.reverseOrder()).thenComparing(BusinDataTaskVo::getCreateTime)).collect(Collectors.toList());
        for (BusinDataTaskVo businDataTaskVo : businDataTaskVos) {
            doTask(inVehicheModel, waitIssueEmpTaskNum, businDataTaskVo,businDataTaskVos);
        }

        //查询下挂任务目前的车型：入库：3LN（20秒） 出库：3UG（40秒） 空托和保险杠交替进行 4和15
        //从redis中写入
        if (inVehicheModel.equals("3LN") || inVehicheModel.equals("3UE")) {//下挂车型为3LN的时候，根据出库任务数量执行空托任务
            //获取出库任务下发成功数
            if (redisTemplate.hasKey(RedisConstant.redisSurplusWaitIssueEmpFixTaskNum)) {
                Integer lastSurpTaskNum = (Integer) redisTemplate.opsForValue().get(RedisConstant.redisSurplusWaitIssueEmpFixTaskNum);
                log.info("上次剩余待下发空治具任务数：" + lastSurpTaskNum);
                waitIssueEmpTaskNum[0] = waitIssueEmpTaskNum[0] + lastSurpTaskNum;
            }
            log.info("总待下发空治具任务数：" + waitIssueEmpTaskNum[0]);
            if (waitIssueEmpTaskNum[0] > 0) {//上次空治具未下发成功的是否计入本次任务，如果计入，本次任务+上次未下发成功任务是否会超出查询限制条数
                taskQueryBo.setTaskType("15");
                taskQueryBo.setLimit(waitIssueEmpTaskNum[0]);
                List<BusinDataTaskVo> businDataTaskVo15 = iBusinDataTaskService.selectOutBusinDataTask(taskQueryBo);
                for (BusinDataTaskVo businDataTaskVo : businDataTaskVo15) {
                    doTask(inVehicheModel, waitIssueEmpTaskNum, businDataTaskVo,businDataTaskVos);
                }
                if (waitIssueEmpTaskNum[0] > 0) {
                    log.info("本次剩余待下发空治具任务数：" + waitIssueEmpTaskNum[0]);
                    redisTemplate.opsForValue().set(RedisConstant.redisSurplusWaitIssueEmpFixTaskNum, waitIssueEmpTaskNum[0]);
                }
            }
        }

    }


    @Transactional(rollbackFor = Exception.class)
    void doTask(String inVehicheModel, Integer[] waitIssueEmpTaskNum,BusinDataTaskVo businDataTaskVo,List<BusinDataTaskVo> businDataTaskVos) {


        //如果当前任务是非紧急任务，则查询是否有紧急任务待执行，如果有，优先处理紧急的
        if (businDataTaskVo.getIsTop().equals("0")){
            BusinDataTaskVo businDataTaskVoIstop= businDataTaskVos.stream().filter(item -> item.getIsTop().equals("1")).sorted(Comparator.comparing(BusinDataTaskVo::getCreateTime)).findFirst().orElse(null);
            if(businDataTaskVoIstop !=null){
                businDataTaskVo=businDataTaskVoIstop;
            }
        }

        String taskType = businDataTaskVo.getTaskType();
        Long taskId = businDataTaskVo.getId();
        Long containerId = businDataTaskVo.getContainerId();

        BasePointDeviceQueryBo pointQueryBo = new BasePointDeviceQueryBo();

        //任务类型 0 正常入库 1维修异常 2扫码异常  3入库冲孔 4 正常出库 5紧急出库 6越库出库 7手工入库 8呼叫空治具
        if (taskType.equals("0") || taskType.equals("7"))
        {
            //获取要出入库的条码信息
            List<BusinDataTaskGoodsVo> businDataTaskGoodsVos = iBusinDataTaskGoodsService.selectBusinTaskGoodsByTaskCode(businDataTaskVo.getId());
//            if (ObjectUtils.isEmpty(businDataTaskGoodsVos)) {
//                continue;
//            }
            BusinDataTaskGoodsVo goodsVo = businDataTaskGoodsVos.get(0);
            String vehicheModel = goodsVo.getVehicheModel();
            String color = goodsVo.getColor();
            String startPoint = businDataTaskVo.getTaskPath();
            String goodsNo = goodsVo.getGoodsNo();

            BasePointDeviceVo pointDevice = new BasePointDeviceVo();
            BasePointDeviceVo basePointDeviceVo = new BasePointDeviceVo();
            //立库输送线接驳点-入
            String toLocation = "";
            int agvTaskType = 0;
            BusinTaskExeBo exeBo = new BusinTaskExeBo();
            Long plcId = null;
            Long stkPlcId = null;

            String agvno = null;

            String randome = "P01";
            if (businDataTaskVo.getWarehouseType().equals("1")) {
                randome = "P01";
            } else if (businDataTaskVo.getWarehouseType().equals("2")) {
                randome = "P02";
            }
            //从Redis中获取randome，如果没有设置为P01
            //randome = ObjectUtils.isEmpty(redisTemplate.opsForValue().get("randome").toString()) ? "P01" : redisTemplate.opsForValue().get("randome").toString();
            //randome = "P02";
            if ("P01".equals(randome)) {
                //根据车型分配库位  先判断该任务是否已经分配了货位
                Result<BaseLocationVo> locationVoResult = null;
                if (ObjectUtils.isEmpty(businDataTaskVo.getToRow())){
                    // 2024/07/18 zjx 分配货位统一方法
                    AssingEmptyLocBo emptyLocBo = new AssingEmptyLocBo();
                    emptyLocBo.setBatch(DateUtils.getDate());
                    emptyLocBo.setVehicheModel(vehicheModel);
                    emptyLocBo.setGoodsNo(goodsNo);
                    emptyLocBo.setBusinDataTaskGoodsVos(businDataTaskGoodsVos);
                    locationVoResult = iBaseLocationService.assignEmptyLocationAll(emptyLocBo,null);
                }

                if (ObjectUtils.isNotEmpty(locationVoResult) && locationVoResult.getCode() == HttpStatus.SUCCESS.getCode()) {
                    //如果是P01则设置randome为P02
                    redisTemplate.opsForValue().set("randome", "P02");
                    BaseLocationVo locationVo = locationVoResult.getData();
                    String tunnel = locationVo.getTunnel();
                    Long locationId = locationVo.getId();
                    for (BusinDataTaskGoodsVo businDataTaskGoodsVo : businDataTaskGoodsVos) {
                        businDataTaskGoodsVo.setLocationId(locationId);
                    }
                    //回填任务的入行高列
                    businDataTaskVo.setBatch(DateUtils.getDate());
                    businDataTaskVo.setToColumn(locationVo.getLocationColumn());
                    businDataTaskVo.setToLayer(locationVo.getLayer());
                    businDataTaskVo.setToRow(locationVo.getLocationRow());
                    businDataTaskVo.setTunnel(tunnel);
                    businDataTaskVo.setLocationId(locationId);
                    //获取货位对应的巷道及巷道对应的设备信息
                    pointQueryBo.setTunnel(tunnel);
                    pointQueryBo.setDirection("0");
                    basePointDeviceVo = baseLocationPlcMapper.selectBasePointByGroupno(pointQueryBo).get(0);

                    if (basePointDeviceVo != null) {
                        toLocation = basePointDeviceVo.getPointNo();
                        //输送线PLCID
                        plcId = Long.valueOf(isysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.LK_plc_id));
                    }

                    //获取巷道对应的堆垛机信息
                    pointQueryBo.setDevType("1");
                    BaseDevicePlcVo baseDevicePlcVo = baseLocationPlcMapper.selectBaseDevicePlc(pointQueryBo);
                    stkPlcId = baseDevicePlcVo.getPlcId();

                    exeBo.setTaskCode(taskId);
                    exeBo.setBusinDataTaskGoodsVo(businDataTaskGoodsVos);
                    exeBo.setContainerId(containerId);
                    exeBo.setBaseLocationVo(locationVo);
                    exeBo.setTransNo("1");
                    exeBo.setTransQual("1");

                    //根据取货时的的点位拿到对应的交互点用作取货完成点
                    agvTaskType = Integer.valueOf(basePointDeviceVo.getIsDown());
                    if (businDataTaskVo.getTaskType().equals("7")) {
                        if (businDataTaskVo.getTaskPath().contains("manMade")) {
                            agvTaskType = RCSTaskTypeEnum.TO_B_AND_PUT.getValue();
                            List agvtaskType = new ArrayList();
                            agvtaskType.add("15");
                            agvtaskType.add("12");
                            BusinDataTask manMade01 = iBusinDataTaskService.getOne(new LambdaQueryWrapper<BusinDataTask>()
                                    .in(BusinDataTask::getTaskType, agvtaskType)
                                    .eq(BusinDataTask::getContainerId, businDataTaskVo.getContainerId())
                                    .eq(BusinDataTask::getTaskStatus, "2")
                                    .orderByDesc(BusinDataTask::getId)
                                    .last("limit 1"));
                            if (ObjectUtils.isNotEmpty(manMade01)) {
                                agvno = manMade01.getAgvNo();
                            }
                        } else if (businDataTaskVo.getTaskPath().contains("Artificial")) {
                            agvTaskType = RCSTaskTypeEnum.TO_B_AND_PUT.getValue();
                            String idArr = redisTemplate.opsForValue().get(RedisConstant.Replenishment).toString();
                            String[] idArrs = idArr.split("_");
                            agvno = idArrs[1];
                        }
                    }
                }
                if (ObjectUtils.isNotEmpty(locationVoResult) && locationVoResult.getCode() == HttpStatus.ERROR.getCode()) {
                    //如果是P02则设置randome为P01
                    redisTemplate.opsForValue().set("randome", "P01");
                    String tepairGroup = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.P_in01);
                    pointQueryBo.setGroupNo(tepairGroup);
                    BasePointDeviceVo pointDeviceout = basePointDeviceMapper.selectBasePointByGroupno(pointQueryBo);
                    toLocation = pointDeviceout.getPointNo();
                    agvTaskType = Integer.valueOf(pointDeviceout.getIsDown());
                    exeBo.setTaskCode(taskId);
                    exeBo.setBusinDataTaskGoodsVo(businDataTaskGoodsVos);
                    exeBo.setContainerId(containerId);
                    exeBo.setTransNo("1");
                    exeBo.setTransQual("1");
                }else{
                    //如果已经分配了货位，取目标货位
                    if (businDataTaskVo.getToRow() !=null){
                        //获取货位对应的巷道及巷道对应的设备信息
                        pointQueryBo.setTunnel(businDataTaskVo.getTunnel());
                        pointQueryBo.setDirection("0");
                        basePointDeviceVo = baseLocationPlcMapper.selectBasePointByGroupno(pointQueryBo).get(0);
                        if (basePointDeviceVo != null) {
                            toLocation = basePointDeviceVo.getPointNo();
                            //输送线PLCID
                            plcId = Long.valueOf(isysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.LK_plc_id));
                        }
                    }
                }

            }
            if ("P02".equals(randome)) {
                //如果是P02则设置randome为P01
                redisTemplate.opsForValue().set("randome", "P01");
                String tepairGroup = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.P_in01);
                pointQueryBo.setGroupNo(tepairGroup);
                BasePointDeviceVo pointDeviceout = basePointDeviceMapper.selectBasePointByGroupno(pointQueryBo);
                toLocation = pointDeviceout.getPointNo();
                agvTaskType = Integer.valueOf(pointDeviceout.getIsDown());
                exeBo.setTaskCode(taskId);
                exeBo.setBusinDataTaskGoodsVo(businDataTaskGoodsVos);
                exeBo.setContainerId(containerId);
                exeBo.setTransNo("1");
                exeBo.setTransQual("1");
            }


            List<String> points = new ArrayList<>();
            points.add(startPoint);

            String tepairGroup = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.putout_point);
            BasePointDeviceQueryBo pointQueryBoup = new BasePointDeviceQueryBo();
            pointQueryBoup.setGroupNo(tepairGroup);

            pointDevice = basePointDeviceMapper.selectBasePointByGroupno(pointQueryBoup);

            points.add(pointDevice.getHandshakePoint());


            points.add(toLocation);
            Map<String, String> snPointMap = new HashMap<>(3);
            snPointMap.put("1", startPoint);

            snPointMap.put("2", pointDevice.getHandshakePoint());
            snPointMap.put("3", toLocation);

            businDataTaskVo.setPoints(JsonUtil.toJSONString(snPointMap));
            businDataTaskVo.setIsDown(String.valueOf(agvTaskType));
            //呼叫AGV
            Result<Boolean> booleanResult = new Result<>();
            if (businDataTaskVo.getTaskType().equals("7")) {
                booleanResult = rcsUtil.callAGV(taskId, agvTaskType, points, businDataTaskVo.getToRow(), agvno);
            } else {
                booleanResult = rcsUtil.callAGV(taskId, agvTaskType, points, businDataTaskVo.getToRow());
                log.error("入库呼叫AGV任务号:" + taskId + "   结果:" + booleanResult.getCode() + "返回信息:" + booleanResult.getMsg());
            }
            if (booleanResult.getCode() == HttpStatus.ERROR.getCode()) {
                BusinDataTask businDataTask = new BusinDataTask();
                businDataTask.setId(businDataTaskVo.getId());
                businDataTask.setTaskStatus(TaskStatusEnum.err.getValue());
                iBusinDataTaskService.updateById(businDataTask);
                return;
            }

            //呼叫AGV成功
            if (booleanResult.getCode() == HttpStatus.SUCCESS.getCode()) {
                businDataTaskVo.setTaskPath(toLocation);
                businDataTaskVo.setTaskStatus(TaskStatusEnum.wait_callback.getValue());

            }
            //立库输送线PLCID
            businDataTaskVo.setDpsNoOne(plcId);
            //巷道堆垛机PLCID
            businDataTaskVo.setDpsNoTwo(stkPlcId);
            iBusinDataTaskService.updateById(BeanUtil.toBean(businDataTaskVo, BusinDataTask.class));

        }
        else if (taskType.equals("2")) {
            //异常杠下挂区域直接调度
        }
        else if (taskType.equals("1")) {
            Long plcId = 0L;
            Long stkPlcId = 0L;
            Boolean NUMBER = true;
            //维修异常 呼叫AGV
            //获取起始点位
            String startPoint = businDataTaskVo.getTaskPath();
            //查询维修地点是否有空闲
            String tepairGroup = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.tepair_group);
            String tmpPoint = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.putout_point_tmp);

            pointQueryBo.setGroupNo(tepairGroup);
            BasePointDeviceVo basePointDeviceVo = null;
            List<BasePointDeviceVo> basePointDeviceVos = baseLocationPlcMapper.selectBasePointByGroupno(pointQueryBo);
            List<String> points = new ArrayList<>();
            points.add(startPoint);
            Map<String, String> snPointMap = new HashMap<>(3);
            snPointMap.put("1", startPoint);
            //获取机械手上报点
            String tepairGroupin = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.putout_point);
            BasePointDeviceQueryBo pointQueryBoup = new BasePointDeviceQueryBo();
            pointQueryBoup.setGroupNo(tepairGroupin);
            BasePointDeviceVo pointDevice = new BasePointDeviceVo();
            pointDevice = basePointDeviceMapper.selectBasePointByGroupno(pointQueryBoup);
            points.add(pointDevice.getHandshakePoint());
            snPointMap.put("2", pointDevice.getHandshakePoint());
            BaseLocationVo locationVo = null;
            BusinTaskExeBo exeBo = new BusinTaskExeBo();
            // TODO 中科  测试 需要还原         已还原
//                System.out.println("中科  测试 需要还原         已还原");
//                //无空闲区 分配异常区库位
//                if (basePointDeviceVos.size() ==0) {
//                    NUMBER=false;
//
//                    if (businDataTaskVo.getWarehouseType().equals("2")) {
//                        String tepairGroup1 = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.P_in01);
//                        pointQueryBo.setGroupNo(tepairGroup1);
//                        BasePointDeviceVo pointDeviceout = basePointDeviceMapper.selectBasePointByGroupno(pointQueryBo);
//                        basePointDeviceVo = pointDeviceout;
//                    } else {
//                        //异常区ID
//                        Long abnormalArea = Long.valueOf(sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.abnormal_area));
//                        List<BaseLocationVo> baseLocationVos = baseLocationMapper.getLocationByAreaId(abnormalArea);
//                        if (baseLocationVos.size() > 0) {
//                            locationVo = baseLocationVos.get(0);
//                        }
//                        businDataTaskVo.setToColumn(locationVo.getLocationColumn());
//                        businDataTaskVo.setToLayer(locationVo.getLayer());
//                        businDataTaskVo.setToRow(locationVo.getLocationRow());
//                        //获取货位及巷道；
//                        String tunnel = locationVo.getTunnel();
//                        businDataTaskVo.setTunnel(tunnel);
//                        pointQueryBo = new BasePointDeviceQueryBo();
//                        pointQueryBo.setTunnel(tunnel);
//                        pointQueryBo.setDirection("0");
//                        basePointDeviceVos = baseLocationPlcMapper.selectBasePointByGroupno(pointQueryBo);
//                        if (basePointDeviceVos.size() > 0) {
//                            basePointDeviceVo = basePointDeviceVos.get(0);
//                            basePointDeviceVo.setPlcId(Long.valueOf(isysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.LK_plc_id)));
//
//                        }
//                        //获取巷道对应的堆垛机信息
//                        pointQueryBo.setDevType("1");
//                        BaseDevicePlcVo baseDevicePlcVo = baseLocationPlcMapper.selectBaseDevicePlc(pointQueryBo);
//                        stkPlcId = baseDevicePlcVo.getPlcId();
//                        List<BusinDataTaskGoodsVo> businDataTaskGoodsVos = iBusinDataTaskGoodsService.selectBusinTaskGoodsByTaskCode(businDataTaskVo.getId());
//                        exeBo.setTaskCode(taskId);
//                        exeBo.setBusinDataTaskGoodsVo(businDataTaskGoodsVos);
//                        exeBo.setContainerId(containerId);
//                        exeBo.setBaseLocationVo(locationVo);
//                        exeBo.setTransNo("1");
//                        exeBo.setTransQual("1");
//                    }
//                }
//                else {
//                    basePointDeviceVo = basePointDeviceVos.get(0);
//                }
//                plcId =basePointDeviceVo.getPlcId();
//                String toPointNo = basePointDeviceVo.getPointNo();
//                snPointMap.put("3",toPointNo);
//                int  agvTaskType = Integer.valueOf(basePointDeviceVo.getIsDown());
//                if(toPointNo.contains("P_Lane")){
//                    // TODO 人车分流相关  需要修改对应的任务类型为 33   需要添加在RCS地图上添加对应的点位 abnormal_wait_point
//                    String abnormalWaitPintGroup = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.abnormalWaitPint);
//                    BasePointDeviceQueryBo abnormalWaitPintBo = new BasePointDeviceQueryBo();
//                    abnormalWaitPintBo.setGroupNo(abnormalWaitPintGroup);
//                    BasePointDeviceVo abnormalWaitPintDeviceVo = basePointDeviceMapper.selectBasePointByGroupno(abnormalWaitPintBo);
//                    points.add(abnormalWaitPintDeviceVo.getPointNo());
//                    points.add(abnormalWaitPintDeviceVo.getPointNo());
//                    snPointMap.put("3",abnormalWaitPintDeviceVo.getPointNo());
//                    snPointMap.put("4",abnormalWaitPintDeviceVo.getPointNo());
//                    snPointMap.put("5",toPointNo);
//                    agvTaskType = Integer.valueOf(abnormalWaitPintDeviceVo.getIsDown());
//                }else{
//                    snPointMap.put("3",toPointNo);
//                }
            // TODO 中科  测试 需要还原
            System.out.println("中科  测试 需要删除");
            // TODO 中科  测试 需要删除
            String toPointNo = "KW18";
            int agvTaskType = 24;
            snPointMap.put("3", toPointNo);
            points.add(toPointNo);
            // TODO 中科  测试 需要删除

            businDataTaskVo.setPoints(JsonUtil.toJSONString(snPointMap));
            businDataTaskVo.setIsDown(String.valueOf(agvTaskType));
            Result<Boolean> booleanResult = new Result<>();
            //呼叫AGV
            if (StringUtils.isNotEmpty(businDataTaskVo.getAgvNo())) {
                booleanResult = callAGV(taskId, agvTaskType, points, businDataTaskVo.getAgvNo());
            } else {
                booleanResult = callAGV(taskId, agvTaskType, points);
            }
            if (booleanResult.getCode() == HttpStatus.ERROR.getCode()) {
                BusinDataTask businDataTask = new BusinDataTask();
                businDataTask.setId(businDataTaskVo.getId());
                businDataTask.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
                businDataTask.setTaskPath(toPointNo);
                iBusinDataTaskService.updateById(businDataTask);
                return;
            }
            //呼叫AGV成功
            if (booleanResult.getCode() == HttpStatus.SUCCESS.getCode()) {
                businDataTaskVo.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
                businDataTaskVo.setTaskPath(toPointNo);
                // TODO 中科  测试 需要还原
//                    System.out.println("中科  测试 需要还原");
////                    把占用的点位改为已占用
//                    if (NUMBER) {
//                        BasePoint basePoint = iBasePointService.getById(basePointDeviceVo.getPointId());
//                        basePoint.setIsOccupy("1");
//                        iBasePointService.updateById(basePoint);
//                    }
//                    //更改货位状态为4已分配
//                    if (ObjectUtils.isNotEmpty(locationVo)){
//                        BaseLocation baseLocation = iBaseLocationService.getById(locationVo.getId());
//                        baseLocation.setLocationStatus("4");
//                        iBaseLocationService.updateById(baseLocation);
//                        //生成入库单成功
//                    }
//                    if(!NUMBER) {
//                        Result<String> stringResult = iPutInOutStorageService.exeTaskPutinStorage(exeBo);
//
//                        if (stringResult.getCode() == HttpStatus.SUCCESS.getCode()) {
//                            businDataTaskVo.setTransId(stringResult.getData());
//                        } else {
//                            businDataTaskVo.setTaskStatus(TaskStatusEnum.err.getValue());
//                            businDataTaskVo.setExceptionMsg("生成入库单失败");
//                        }
//                    }
//                     TODO 中科  测试 需要还原
            }
//                else{
//                    if (redisTemplate.opsForValue().get(RedisConstant.redisAgvTaskerror+taskId)==null){
//                        redisTemplate.opsForValue().set(RedisConstant.redisAgvTaskerror+taskId,0);
//                    }
//                    Long a=Long.valueOf((String)redisTemplate.opsForValue().get(RedisConstant.redisAgvTaskerror+taskId));
//                    businDataTaskVo.setTaskStatus(TaskStatusEnum.err.getValue());
//                    businDataTaskVo.setExceptionMsg(booleanResult.getMsg());
//                    if (a<3L){
//                        long l = a + 1;
//                        redisTemplate.opsForValue().set(RedisConstant.redisAgvTaskerror+taskId,l);
//                    }else {
//                        businDataTaskVo.setTaskStatus("-2");
//                    }
//                }
            // TODO 测试注释  要打开
//                //更新入库条码表状态为异常
            List<BaseBarcodesIn> barcodesIns = new ArrayList<>();
            List<BusinDataTaskGoodsVo> goodsVos = iBusinDataTaskGoodsService.selectBusinTaskGoodsByTaskCode(taskId);
            for (BusinDataTaskGoodsVo goodsVo : goodsVos) {
                BaseBarcodesIn baseBarcodesIn = iBaseBarcodesInService.getOne(new LambdaQueryWrapper<BaseBarcodesIn>()
                        .eq(BaseBarcodesIn::getQrCode, goodsVo.getQrCode())
                );
                baseBarcodesIn.setInStatus("4");
                baseBarcodesIn.setInDate(DateUtils.getDate());
                barcodesIns.add(baseBarcodesIn);
            }
            iBaseBarcodesInService.saveOrUpdateBatch(barcodesIns);

            businDataTaskVo.setDpsNoOne(plcId);
            businDataTaskVo.setDpsNoTwo(stkPlcId);
        }
        else if (taskType.equals("4") || taskType.equals("5")) {
            //出库任务（正常出库、紧急出库）
            //获取要出库的物料信息
            List<BusinDataTaskGoodsVo> businDataTaskGoodsVos = iBusinDataTaskGoodsService.getTaskGoodsByTaskCodeForOut(businDataTaskVo.getId());

            if (businDataTaskVo.getDistinction().equals("2")) {
                List<String> goodsno = businDataTaskGoodsVos.stream().map(e -> e.getGoodsNo()).collect(Collectors.toList());
                //根据GoodsNo查看立库是否有库存
                List<SysStockDetail> list = iSysStockDetailService.list(new LambdaQueryWrapper<SysStockDetail>()
                        .in(SysStockDetail::getGoodsNo, goodsno)
                        .eq(SysStockDetail::getQty, "1")
                        .isNull(SysStockDetail::getOutQty)
                        .isNull(SysStockDetail::getLocationId));
                if (ObjectUtils.isEmpty(list)) {
                    businDataTaskVo.setDistinction("1");
                } else {
                    String frompoint = null;
                    String tepairGroup = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.P_out01);
                    pointQueryBo.setGroupNo(tepairGroup);
                    BasePointDeviceVo pointDeviceout = basePointDeviceMapper.selectBasePointByGroupno(pointQueryBo);
                    frompoint = pointDeviceout.getPointNo();
                    //查询平库出库任务使用状态
                    businDataTaskVo.setTaskStatus(TaskStatusEnum.four_out.getValue());
                    businDataTaskVo.setTaskType(TaskTypeEnum.thirteen_out.getValue());
                    businDataTaskVo.setTaskPath(frompoint);
                }
            }


            if (!businDataTaskVo.getDistinction().equals("2")) {
                Long taskVoid = businDataTaskVo.getId();
                //查询库存并返回库位信息
                BusinTaskExeBo businTaskExeBo = iBusinDataTaskService.outboundInfo(businDataTaskGoodsVos, String.valueOf(taskVoid));
                BusinDataTask businDataTask = iBusinDataTaskService.getById(taskVoid);
                if (ObjectUtils.isNotEmpty(businDataTask) && ObjectUtils.isNotEmpty(businDataTask.getFromLayer())) {
                    //添加货位预占和库存预占
                    //获取货位信息
                    BaseLocation location = iBaseLocationService.getById(businDataTask.getLocationId());
                    //根据货位查询是否有单深位的货位，如果有货，则查询单深位是否有任务，如果有则切换任务
                    String isDeep = location.getIsDeep();
                    if (isDeep.equals("2")){
                        //查询单深位
                        String locationRow = location.getLocationRow();
                        String locationColumn = location.getLocationColumn();
                        String layer = location.getLayer();
                        if (locationRow.equals("1")) {
                            locationRow = "2";
                        } else if (locationRow.equals("4")) {
                            locationRow = "3";
                        } else if (locationRow.equals("15")) {
                            locationRow = "14";
                        }
                        BaseLocation one = iBaseLocationService.getOne(new LambdaQueryWrapper<BaseLocation>()
                                .eq(BaseLocation::getLocationRow, locationRow)
                                .eq(BaseLocation::getLocationColumn, locationColumn)
                                .eq(BaseLocation::getLayer, layer));
                        if(one !=null){
                            // BusinDataTaskVo businDataTaskIsnotDeep = businDataTaskVos.stream().filter(item -> item.getLocationId().equals(one.getId())).findFirst().orElse(null);
                            BusinDataTask businDataTaskIsnotDeep = iBusinDataTaskService.getOne(
                                    new LambdaQueryWrapper<BusinDataTask>()
                                            .eq(BusinDataTask::getLocationId, one.getId())
                                            .in(BusinDataTask::getTaskStatus, Arrays.asList("0", "-1"))
                                            .last("limit 1")
                            );
                            if (businDataTaskIsnotDeep != null){
                                //单深位有任务，优先下发单深位任务
                                log.info("查询到单深位的任务："+taskVoid);
                                businDataTask=businDataTaskIsnotDeep;
                                location=one;
                            }else{
                                //单深位无任务，再查询外面深位是否有库存，如果有，更新此任务的取货路径
                                if ("1".equals(one.getLocationStatus()) || "2".equals(one.getLocationStatus())){
                                    //先把深位的货位状态改为有货或空托状态
                                    if(businDataTaskGoodsVos !=null && businDataTaskGoodsVos.size()>0){
                                        location.setLocationStatus("1");
                                    }else {
                                        location.setLocationStatus("2");
                                    }
                                    iBaseLocationService.updateById(location);
                                    businDataTask.setFromColumn(one.getLocationColumn());
                                    businDataTask.setFromRow(one.getLocationRow());
                                    businDataTask.setFromLayer(one.getLayer());
                                    businDataTask.setLocationId(one.getId());

                                    location=one;
                                }
                            }
                        }
                    }

                    location.setLocationStatus("4");
                    iBaseLocationService.updateById(location);

                    //根据货位拿到库存信息
                    List<SysStockDetail> sysStockDetailList = sysStockDetailMapper.getStockDetailByLocationId(String.valueOf(location.getId()));
                    sysStockDetailList.stream().forEach(e -> {
                        e.setOutQty(1);
                    });

                    //给库存添加出货预占
                    iSysStockDetailService.updateBatchById(sysStockDetailList);
                    //给堆垛机下发任务
                    Result<Boolean> taskResult = outTask(businDataTask);
                    if (taskResult.getCode() == HttpStatus.SUCCESS.getCode()) {

                        //成功后计算出库成功数量并写入redis
                        if (inVehicheModel.equals("3LN") || inVehicheModel.equals("3UE")) {
                            waitIssueEmpTaskNum[0]++;
                            log.info("3LN出库成功任务数：" + waitIssueEmpTaskNum[0]);

                        }

                        businDataTask.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
                        businDataTask.setExceptionMsg("");
                        businDataTask.setUpdateTime(DateUtils.getNowDate());
                        if (ObjectUtils.isEmpty(redisTemplate.opsForValue().get("outbound:" + businDataTask.getId()))) {
                            redisTemplate.opsForValue().set("outbound:" + businDataTask.getId(), businDataTask.toString());
                        }
                        //拿到库存里的治具编号(不分体的每个保险杠在一个货位一个任务,分体的只有一个任务一个货位所以只随机拿到一个库存信息的治具号就可以)
                        businDataTask.setContainerId(sysStockDetailList.get(0).getContainerCode());
                        if (!"5".equals(businDataTask.getTaskType())) {
                            //根据过点时间更改out表里的状态信息
                            List<BusinDataTaskGoods> businDataTaskGoods = iBusinDataTaskGoodsService.list(new LambdaQueryWrapper<BusinDataTaskGoods>()
                                    .eq(BusinDataTaskGoods::getTaskCode, businDataTask.getId()));
                            BaseBarcodesOut baseBarcodesOutServiceOne = iBaseBarcodesOutService.getOne(new LambdaQueryWrapper<BaseBarcodesOut>()
                                    .eq(BaseBarcodesOut::getTraverseDate, businDataTaskGoods.get(0).getTraverseDate()).isNull(BaseBarcodesOut::getIs_cancel).last("limit 1"));
                            baseBarcodesOutServiceOne.setOutStatus("2");
                            iBaseBarcodesOutService.updateById(baseBarcodesOutServiceOne);
                        }
                    } else {
                        if (ObjectUtils.isEmpty(redisTemplate.opsForValue().get("outbound:" + businDataTask.getId()))) {
                            businDataTask.setExceptionMsg("下发堆垛机失败");
                            businDataTask.setTaskStatus(TaskStatusEnum.err.getValue());
                        } else {
                            businDataTask.setExceptionMsg("已经下发堆垛机");
                            businDataTask.setTaskStatus("-3");
                        }
                    }
                    businDataTask.setDistinction(businDataTaskVo.getDistinction());
                    iBusinDataTaskService.saveOrUpdate(businDataTask);

                    businDataTaskVo = BeanUtil.toBean(businDataTask, BusinDataTaskVo.class);
                } else {
                    businDataTaskVo.setExceptionMsg("当前开放的货位已无当前库存");
                    businDataTaskVo.setTaskStatus("-3");
                }
            }
        }
        else if (taskType.equals("11") || taskType.equals("12")) {
            String agvno = "";
            int AgvType = 0;
            //空治具流向呼叫agv失败后再次呼叫agv
            if (StringUtils.isNotEmpty(businDataTaskVo.getAgvNo())) {
                agvno = businDataTaskVo.getAgvNo();
            }
            Map<String, String> agvMap = JsonUtil.JsonStrToMap(businDataTaskVo.getPoints());
            List<String> AgvPoints = agvMap.entrySet().stream().sorted(Map.Entry.comparingByKey()).map(e -> e.getValue()).collect(Collectors.toList());
            AgvType = Integer.valueOf(businDataTaskVo.getIsDown());
            //呼叫AGV
            AGVMoveBo bo = new AGVMoveBo();
            bo.setPoints(AgvPoints);
            bo.setTaskId(businDataTaskVo.getId());
            bo.setRobotId(agvno);
            bo.setTaskType(AgvType);
            Result<Boolean> result = rcsUtil.moveByAGV(bo);
            if (result.getCode() == HttpStatus.SUCCESS.getCode()) {
                businDataTaskVo.setTaskStatus("1");
                if (businDataTaskVo.getTaskType().equals(TaskTypeEnum.mechainical.getValue())) {
                    //更改空治具流向任务状态为进行中
                    BusinDpscontainerRecord businDpscontainerRecord = businDpsContainerRecordMapper.selectByTaskid(String.valueOf(businDataTaskVo.getId()));
                    businDpscontainerRecord.setIsState("0");
                    businDpsContainerRecordMapper.updateById(businDpscontainerRecord);
                }
                if (StringUtils.isNotEmpty(String.valueOf(businDataTaskVo.getLocationId())) && 0 != businDataTaskVo.getLocationId()) {
                    BaseLocation baseLocation = baseLocationService.getById(businDataTaskVo.getLocationId());
                    baseLocation.setLocationStatus("4");
                    baseLocationService.updateById(baseLocation);
                }
                if (StringUtils.isNotEmpty(businDataTaskVo.getRemark())) {
                    Long oldTaskId = Long.valueOf(businDataTaskVo.getRemark());
                    BusinDataTask oldDataTask = iBusinDataTaskService.getById(oldTaskId);
                    oldDataTask.setTaskStatus("3");
                    oldDataTask.setRemark("已取消，已被任务ID为：" + taskId + " 替代！");
                    iBusinDataTaskService.updateById(oldDataTask);
                    businDataTaskVo.setRemark(String.valueOf(oldDataTask.getId()));

                }
            } else {
                businDataTaskVo.setTaskStatus("5");
                businDataTaskVo.setExceptionMsg(result.getMsg());
            }


        }
        //空治具出库
        else if (taskType.equals("15")) {
            //给堆垛机下命令
            BusinDataTask businDataTask = iBusinDataTaskService.getById(taskId);
            if (ObjectUtils.isNotEmpty(businDataTask)) {
                Result<Boolean> taskResult = outTask(businDataTask);
                if (Result.isOk(taskResult)) {
                    if (inVehicheModel.equals("3LN") || inVehicheModel.equals("3UE")) {
                        waitIssueEmpTaskNum[0]--;
                        log.info("3LN待出库空治具任务数：" + waitIssueEmpTaskNum);
                    }

                    //完成后更新库位状态为空闲
                    BaseLocation location = iBaseLocationService.getById(businDataTask.getLocationId());
                    location.setLocationStatus("0");
                    iBaseLocationService.updateById(location);
                    businDataTaskVo.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
                    /**空治具出库库存信息处理*/
                    iSysStockDetailService.deleteBySysStockByLocationId(businDataTask.getLocationId());
                    //根据货位拿到库存信息
//                        List<SysStockDetail> listT = iSysStockDetailService.list(new LambdaQueryWrapper<SysStockDetail>()
//                                .eq(SysStockDetail::getLocationId,businDataTask.getLocationId()));
//                        if (listT.size()>0&&ObjectUtils.isNotEmpty(listT)){
//                            SysStockDetail sysStockDetail = listT.get(0);
//                            sysStockDetail.setOutQty(1);
//                            sysStockDetail.setQty(sysStockDetail.getQty().subtract(new BigDecimal("1")));
//                            iSysStockDetailService.updateById(sysStockDetail);
//                        }
                }
            }
        }
        else if (taskType.equals("10")) {
            //先判断补货入库是否是一套，如果是入存货区，否则入异常区
            List<BusinDataTaskGoodsVo> businDataTaskGoodsVos = iBusinDataTaskGoodsService.getTaskGoodsByTaskCodeForOut(businDataTaskVo.getId());
            Result<BaseLocationVo> baseLocationVoResult = iBaseLocationService.queryById(businDataTaskVo.getLocationId());
            Result<Boolean> taskResult = outTask(businDataTaskVo);
            if (taskResult.getCode() == HttpStatus.SUCCESS.getCode()) {
                businDataTaskVo.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
                //生成出库明细
                BusinTaskExeBo exeBo = new BusinTaskExeBo();
                exeBo.setTaskCode(businDataTaskVo.getId());
                exeBo.setBusinDataTaskGoodsVo(businDataTaskGoodsVos);
                exeBo.setBaseLocationVo(baseLocationVoResult.getData());
                exeBo.setTransNo("2");
                exeBo.setTransQual("2");
                ////生成出库单
                //  Result<String> billResult = iPutInOutStorageService.exeTaskPutinStorage(exeBo);
                //  businDataTaskVo.setTransId(billResult.getData());
            } else {
                businDataTaskVo.setExceptionMsg("下发堆垛机指令失败");
                businDataTaskVo.setTaskStatus(TaskStatusEnum.err.getValue());
            }
        }
        else if (taskType.equals(TaskTypeEnum.abnormal_delivery.getValue())) {
            //异常出库
            //异常区货位
            Long abnormalArea = Long.valueOf(sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.abnormal_area));
            List<BaseLocationVo> baseLocationVos = baseLocationMapper.getOutLocationByAreaId(abnormalArea);

            List<String> tunnelall = baseLocationVos.stream().map(e -> e.getTunnel()).collect(Collectors.toList());
            //拿到任务数最少的巷道
            String tunnelone = this.quickSort(tunnelall);
            List<BaseLocationVo> tunnelLocation = baseLocationVos.stream().filter(e -> e.getTunnel().equals(tunnelone)).collect(Collectors.toList());
            List<Long> listlocationId = new ArrayList<>();
            //如果是双深位 查看外侧的货位是否有托盘
            for (BaseLocationVo baseLovationVO : tunnelLocation) {
                if (baseLovationVO.getIsDeep().equals("2")) {
                    BaseLocation one = baseLocationService.getOne(new LambdaQueryWrapper<BaseLocation>()
                            .eq(BaseLocation::getRoute, baseLovationVO.getRoute())
                            .eq(BaseLocation::getIsDeep, "1")
                            .eq(BaseLocation::getTunnel, baseLovationVO.getTunnel())
                            .eq(BaseLocation::getAreaId, baseLovationVO.getAreaId()));
                    if (one != null && (one.getLocationStatus().equals("4") || one.getLocationStatus().equals("1"))) {
                        listlocationId.add(baseLovationVO.getId());
                    }
                }
            }
            if (listlocationId.size() > 0) {
                for (int i = 0; i < tunnelLocation.size(); i++) {
                    int number = i;
                    listlocationId.stream().forEach(e -> {
                        if (e.equals(tunnelLocation.get(number).getId())) {
                            tunnelLocation.remove(number);
                        }
                    });
                }
            }

            //根据巷道分配货位
            BaseLocationVo baseLocationVo = tunnelLocation.get(0);

            businDataTaskVo.setFromColumn(baseLocationVo.getLocationColumn());
            businDataTaskVo.setFromLayer(baseLocationVo.getLayer());
            businDataTaskVo.setFromRow(baseLocationVo.getLocationRow());
            //获取货位及巷道；
            String tunnel = baseLocationVo.getTunnel();
            // 获取goods信息并和当前任务关联
            List<BusinDataTaskGoods> goods = new ArrayList<>();
            List<BusinDataTaskGoodsVo> goodsVo = new ArrayList<>();
            List<SysStockDetail> sysStockDetailList = iSysStockDetailService.list(new LambdaQueryWrapper<SysStockDetail>()
                    .eq(SysStockDetail::getLocationId, baseLocationVo.getId())
                    .eq(SysStockDetail::getQty, 1)
                    .isNull(SysStockDetail::getOutQty));
            for (SysStockDetail sysStockDetail : sysStockDetailList) {
                BusinDataTaskGoods taskGoods = new BusinDataTaskGoods();
                BusinDataTaskGoodsVo taskGoodsVo = new BusinDataTaskGoodsVo();
                taskGoods.setQrCode(sysStockDetail.getQrCode());
                taskGoods.setBranchId(sysStockDetail.getBranchId());
                taskGoods.setTaskCode(taskId);
                taskGoods.setCreateTime(DateUtils.getNowDate());
                taskGoods.setGoodsNo(sysStockDetail.getGoodsNo());
                BaseGoodsData baseGoodsData = iBaseGoodsDataService.getBaseGoodsByBarcodes(sysStockDetail.getGoodsNo());
                taskGoods.setIsPunching(baseGoodsData.getIsPunching());
                taskGoods.setIsRepair("1");
                goods.add(taskGoods);

                taskGoodsVo.setQrCode(sysStockDetail.getQrCode());
                taskGoodsVo.setTaskCode(String.valueOf(taskId));
                taskGoodsVo.setGoodsNo(sysStockDetail.getGoodsNo());
                taskGoodsVo.setIsPunching(baseGoodsData.getIsPunching());
                taskGoodsVo.setIsRepair("1");
                goodsVo.add(taskGoodsVo);
            }

            BasePointDeviceQueryBo pointQueryBo1 = new BasePointDeviceQueryBo();
            pointQueryBo1.setTunnel(tunnel);
            pointQueryBo1.setDirection("0");
            //获取巷道对应的堆垛机信息
            pointQueryBo1.setDevType("1");
            BaseDevicePlcVo baseDevicePlcVo = baseLocationPlcMapper.selectBaseDevicePlc(pointQueryBo1);
            Long stkPlcId = baseDevicePlcVo.getPlcId();
            Long plcId = Long.valueOf(isysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.LK_plc_id));

            businDataTaskVo.setDevId(baseLocationVo.getDevId());
            businDataTaskVo.setTunnel(baseLocationVo.getTunnel());
            businDataTaskVo.setDpsNoOne(plcId);
            businDataTaskVo.setDpsNoTwo(stkPlcId);
            //测试使用货位id
            businDataTaskVo.setLocationId(baseLocationVo.getId());
            //拿到库存里的治具编号(不分体的每个保险杠在一个货位一个任务,分体的只有一个任务一个货位所以只随机拿到一个库存信息的治具号就可以)
            businDataTaskVo.setContainerId(sysStockDetailList.get(0).getContainerCode());

            Result<Boolean> taskResult1 = outTask(businDataTaskVo);
            if (taskResult1.getCode() == HttpStatus.SUCCESS.getCode()) {
                businDataTaskVo.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
                //生成出库单
                BusinTaskExeBo exeBo = new BusinTaskExeBo();
                exeBo.setTaskCode(taskId);
                exeBo.setBusinDataTaskGoodsVo(goodsVo);
                exeBo.setBaseLocationVo(baseLocationVo);
                exeBo.setTransNo("2");
                exeBo.setTransQual("2");

                //  Result<String> billResult = iPutInOutStorageService.exeTaskPutinStorage(exeBo);
                //  businDataTaskVo.setTransId(billResult.getData());
                //添加货位预占和库存预占
                //获取货位信息
                baseLocationVo.setLocationStatus("4");
                iBaseLocationService.updateById(baseLocationVo);
                //根据货位拿到库存信息
                sysStockDetailList.stream().forEach(e -> {
                    e.setOutQty(1);
                });
                //给库存添加出货预占
                iSysStockDetailService.updateBatchById(sysStockDetailList);
                //添加巷道任务数和总任务数
                tunnelTaskUtil.addOutboundTaskNum(businDataTaskVo.getTunnel());
            } else {
                businDataTaskVo.setExceptionMsg("下发堆垛机指令失败");
                businDataTaskVo.setTaskStatus(TaskStatusEnum.err.getValue());
            }
            //新增物料明细
            boolean b = iBusinDataTaskGoodsService.saveOrUpdateBatch(goods);


        }
        else if (taskType.equals(TaskTypeEnum.replenished_in.getValue())) {
            String agvno = null;
            if (businDataTaskVo.getTaskPath().contains("manMade")) {
                List agvtaskType = new ArrayList();
                agvtaskType.add("15");
                agvtaskType.add("12");
                BusinDataTask manMade01 = iBusinDataTaskService.getOne(new LambdaQueryWrapper<BusinDataTask>()
                        .in(BusinDataTask::getTaskType, agvtaskType)
                        .eq(BusinDataTask::getContainerId, businDataTaskVo.getContainerId())
                        .eq(BusinDataTask::getTaskStatus, "2")
                        .orderByDesc(BusinDataTask::getId)
                        .last("limit 1"));
                if (ObjectUtils.isNotEmpty(manMade01)) {
                    agvno = manMade01.getAgvNo();
                }
            } else if (businDataTaskVo.getTaskPath().contains("Artificial")) {
                String idArr = redisTemplate.opsForValue().get(RedisConstant.Replenishment).toString();
                String[] idArrs = idArr.split("_");
                agvno = idArrs[1];
            }

            List<BusinDataTaskGoodsVo> goodsVos = iBusinDataTaskGoodsService.selectBusinTaskGoodsByTaskCode(taskId);
            List<String> goodsNoStr = goodsVos.stream().map(e -> e.getGoodsNo()).collect(Collectors.toList());

            iBusinDataTaskService.runReplenishIn(businDataTaskVo, agvno);
            Result<Boolean> booleanResult = iPutInOutStorageService.reduceInventory(taskId, goodsNoStr);
        }
        else if (taskType.equals("21")) {
            if (ObjectUtils.isEmpty(businDataTaskVo.getFromRow())){
                // 冲孔出库
                //待冲孔区货位
                Long abnormalArea = Long.valueOf(sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.punching_area));
                List<BaseLocationVo> baseLocationVos = baseLocationMapper.getOutLocationByAreaId(abnormalArea);

                List<String> tunnelall = baseLocationVos.stream().map(e -> e.getTunnel()).collect(Collectors.toList());
                //拿到任务数最少的巷道
                String tunnelone = this.quickSort(tunnelall);
                List<BaseLocationVo> tunnelLocation = baseLocationVos.stream().filter(e -> e.getTunnel().equals(tunnelone)).collect(Collectors.toList());
                List<Long> listlocationId = new ArrayList<>();
                //如果是双深位 查看外侧的货位是否有托盘
                for (BaseLocationVo baseLovationVO : tunnelLocation) {
                    if (baseLovationVO.getIsDeep().equals("2")) {
                        BaseLocation one = baseLocationService.getOne(new LambdaQueryWrapper<BaseLocation>()
                                .eq(BaseLocation::getRoute, baseLovationVO.getRoute())
                                .eq(BaseLocation::getIsDeep, "1")
                                .eq(BaseLocation::getTunnel, baseLovationVO.getTunnel())
                                .eq(BaseLocation::getAreaId, baseLovationVO.getAreaId()));
                        if (one != null && (one.getLocationStatus().equals("4") || one.getLocationStatus().equals("1"))) {
                            listlocationId.add(baseLovationVO.getId());
                        }
                    }
                }
                if (listlocationId.size() > 0) {
                    for (int i = 0; i < tunnelLocation.size(); i++) {
                        int number = i;
                        listlocationId.stream().forEach(e -> {
                            if (e.equals(tunnelLocation.get(number).getId())) {
                                tunnelLocation.remove(number);
                            }
                        });
                    }
                }
                if (tunnelLocation.size() > 0) {
                    //根据巷道分配货位
                    BaseLocationVo baseLocationVo = tunnelLocation.get(0);
                    businDataTaskVo.setFromColumn(baseLocationVo.getLocationColumn());
                    businDataTaskVo.setFromLayer(baseLocationVo.getLayer());
                    businDataTaskVo.setFromRow(baseLocationVo.getLocationRow());
                    businDataTaskVo.setTunnel(baseLocationVo.getTunnel());
                    //更改货位状态为4已分配
                    BaseLocation baseLocation = iBaseLocationService.getById(baseLocationVo.getId());
                    baseLocation.setLocationStatus("4");
                    iBaseLocationService.updateById(baseLocation);
                    //获取货位及巷道；
                    String tunnel = baseLocationVo.getTunnel();
                    // 获取goods信息并和当前任务关联
                    List<BusinDataTaskGoods> goods = new ArrayList<>();
                    List<BusinDataTaskGoodsVo> goodsVo = new ArrayList<>();
                    List<SysStockDetail> sysStockDetailList = iSysStockDetailService.list(new LambdaQueryWrapper<SysStockDetail>()
                            .eq(SysStockDetail::getLocationId, ObjectUtils.isNotEmpty(businDataTaskVo.getLocationId())? businDataTaskVo.getLocationId(): baseLocationVo.getId() )
                            .eq(SysStockDetail::getQty, 1)
                            .isNull(SysStockDetail::getOutQty));
                    for (SysStockDetail sysStockDetail : sysStockDetailList) {
                        BusinDataTaskGoods taskGoods = new BusinDataTaskGoods();
                        BusinDataTaskGoodsVo taskGoodsVo = new BusinDataTaskGoodsVo();
                        taskGoods.setQrCode(sysStockDetail.getQrCode());
                        taskGoods.setBranchId(sysStockDetail.getBranchId());
                        taskGoods.setTaskCode(taskId);
                        taskGoods.setCreateTime(DateUtils.getNowDate());
                        taskGoods.setGoodsNo(sysStockDetail.getGoodsNo());
                        BaseGoodsData baseGoodsData = iBaseGoodsDataService.getBaseGoodsByBarcodes(sysStockDetail.getGoodsNo());
                        taskGoods.setIsPunching(baseGoodsData.getIsPunching());
                        taskGoods.setIsRepair("1");
                        goods.add(taskGoods);

                        taskGoodsVo.setQrCode(sysStockDetail.getQrCode());
                        taskGoodsVo.setTaskCode(String.valueOf(taskId));
                        taskGoodsVo.setGoodsNo(sysStockDetail.getGoodsNo());
                        taskGoodsVo.setIsPunching(baseGoodsData.getIsPunching());
                        taskGoodsVo.setIsRepair("1");
                        goodsVo.add(taskGoodsVo);
                    }

                    BasePointDeviceQueryBo pointQueryBo1 = new BasePointDeviceQueryBo();
                    pointQueryBo1.setTunnel(tunnel);
                    pointQueryBo1.setDirection("0");
                    //获取巷道对应的堆垛机信息
                    pointQueryBo1.setDevType("1");
                    BaseDevicePlcVo baseDevicePlcVo = baseLocationPlcMapper.selectBaseDevicePlc(pointQueryBo1);
                    Long stkPlcId = baseDevicePlcVo.getPlcId();
                    Long plcId = Long.valueOf(isysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.LK_plc_id));

                    businDataTaskVo.setDevId(baseLocationVo.getDevId());

                    businDataTaskVo.setDpsNoOne(plcId);
                    businDataTaskVo.setDpsNoTwo(stkPlcId);
                    //测试使用货位id
                    businDataTaskVo.setLocationId(baseLocationVo.getId());
                    //拿到库存里的治具编号(不分体的每个保险杠在一个货位一个任务,分体的只有一个任务一个货位所以只随机拿到一个库存信息的治具号就可以)
                    businDataTaskVo.setContainerId(sysStockDetailList.get(0).getContainerCode());

                    Result<Boolean> taskResult1 = outTask(businDataTaskVo);
                    if (taskResult1.getCode() == HttpStatus.SUCCESS.getCode()) {
                        businDataTaskVo.setTaskStatus(TaskStatusEnum.wait_callback.getValue());

                        // Result<String> billResult = iPutInOutStorageService.exeTaskPutinStorage(exeBo);
                        //  businDataTaskVo.setTransId(billResult.getData());
                        //添加货位预占和库存预占
                        //获取货位信息
                        baseLocationVo.setLocationStatus("4");
                        iBaseLocationService.updateById(baseLocationVo);
                        //根据货位拿到库存信息
                        sysStockDetailList.stream().forEach(e -> {
                            e.setOutQty(1);
                        });
                        //给库存添加出货预占
                        iSysStockDetailService.updateBatchById(sysStockDetailList);

                        //记录冲孔机排队数量
                        BasePunchRecordAddBo recordAddBo = new BasePunchRecordAddBo();
                        recordAddBo.setTaskCode(businDataTaskVo.getId());
                        recordAddBo.setPunchNo(2L);
                        recordAddBo.setIsState("0");
                        iBasePunchRecordService.insertBasePunchRecord(BeanUtil.toBean(recordAddBo, BasePunchRecord.class));
                        //添加巷道任务数和总任务数
                        tunnelTaskUtil.addOutboundTaskNum(businDataTaskVo.getTunnel());
                    } else {
                        businDataTaskVo.setExceptionMsg("下发堆垛机指令失败");
                        businDataTaskVo.setTaskStatus(TaskStatusEnum.err.getValue());
                    }
                    //新增物料明细
                    boolean b = iBusinDataTaskGoodsService.saveOrUpdateBatch(goods);
                } else {
                    businDataTaskVo.setTaskStatus("-3");
                }
            }else {
                Result<Boolean> taskResult1 = outTask(businDataTaskVo);
                if (taskResult1.getCode() == HttpStatus.SUCCESS.getCode()) {
                    businDataTaskVo.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
                    // 获取goods信息并和当前任务关联
                    List<BusinDataTaskGoods> goods = new ArrayList<>();
                    List<BusinDataTaskGoodsVo> goodsVo = new ArrayList<>();
                    List<SysStockDetail> sysStockDetailList = iSysStockDetailService.list(new LambdaQueryWrapper<SysStockDetail>()
                            .eq(SysStockDetail::getLocationId,businDataTaskVo.getLocationId())
                            .eq(SysStockDetail::getQty, 1)
                            .isNull(SysStockDetail::getOutQty));
                    for (SysStockDetail sysStockDetail : sysStockDetailList) {
                        BusinDataTaskGoods taskGoods = new BusinDataTaskGoods();
                        BusinDataTaskGoodsVo taskGoodsVo = new BusinDataTaskGoodsVo();
                        taskGoods.setQrCode(sysStockDetail.getQrCode());
                        taskGoods.setBranchId(sysStockDetail.getBranchId());
                        taskGoods.setTaskCode(taskId);
                        taskGoods.setCreateTime(DateUtils.getNowDate());
                        taskGoods.setGoodsNo(sysStockDetail.getGoodsNo());
                        BaseGoodsData baseGoodsData = iBaseGoodsDataService.getBaseGoodsByBarcodes(sysStockDetail.getGoodsNo());
                        taskGoods.setIsPunching(baseGoodsData.getIsPunching());
                        taskGoods.setIsRepair("1");
                        goods.add(taskGoods);

                        taskGoodsVo.setQrCode(sysStockDetail.getQrCode());
                        taskGoodsVo.setTaskCode(String.valueOf(taskId));
                        taskGoodsVo.setGoodsNo(sysStockDetail.getGoodsNo());
                        taskGoodsVo.setIsPunching(baseGoodsData.getIsPunching());
                        taskGoodsVo.setIsRepair("1");
                        goodsVo.add(taskGoodsVo);
                    }
                    BaseLocation baseLocationVo = baseLocationService.getOne(new LambdaQueryWrapper<BaseLocation>()
                            .eq(BaseLocation::getId, businDataTaskVo.getLocationId()));
                    // Result<String> billResult = iPutInOutStorageService.exeTaskPutinStorage(exeBo);
                    //  businDataTaskVo.setTransId(billResult.getData());
                    //添加货位预占和库存预占
                    //获取货位信息
//                    baseLocationVo.setLocationStatus("4");
//                    iBaseLocationService.updateById(baseLocationVo);
                    //根据货位拿到库存信息
                    sysStockDetailList.stream().forEach(e -> {
                        e.setOutQty(1);
                    });
                    //给库存添加出货预占
                    iSysStockDetailService.updateBatchById(sysStockDetailList);

                    //记录冲孔机排队数量
                    BasePunchRecordAddBo recordAddBo = new BasePunchRecordAddBo();
                    recordAddBo.setTaskCode(businDataTaskVo.getId());
                    recordAddBo.setPunchNo(2L);
                    recordAddBo.setIsState("0");
                    iBasePunchRecordService.insertBasePunchRecord(BeanUtil.toBean(recordAddBo, BasePunchRecord.class));
                    //添加巷道任务数和总任务数
                    tunnelTaskUtil.addOutboundTaskNum(businDataTaskVo.getTunnel());
                } else {
                    businDataTaskVo.setExceptionMsg("下发堆垛机指令失败");
                    businDataTaskVo.setTaskStatus(TaskStatusEnum.err.getValue());
                }
            }
        }
        else if (taskType.equals("22")) {
            BusinDataTask businDataTask = iBusinDataTaskService.getById(businDataTaskVo.getId());
            Result<Boolean> taskResult = outTask(businDataTask);
            if (Result.isOk(taskResult)) {
                businDataTask.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
                if (ObjectUtils.isEmpty(redisTemplate.opsForValue().get("outbound:" + businDataTask.getId()))) {
                    redisTemplate.opsForValue().set("outbound:" + businDataTask.getId(), businDataTask.toString());
                }
            } else {
                if (ObjectUtils.isEmpty(redisTemplate.opsForValue().get("outbound:" + businDataTask.getId()))) {
                    businDataTask.setExceptionMsg("下发堆垛机失败");
                    businDataTask.setTaskStatus(TaskStatusEnum.err.getValue());
                } else {
                    businDataTask.setExceptionMsg("已经下发堆垛机");
                    businDataTask.setTaskStatus("-3");
                }
            }

        }
        else if (taskType.equals(TaskTypeEnum.seat_adjustment.getValue())) {
            BusinDataTask businDataTask = iBusinDataTaskService.getById(businDataTaskVo.getId());
            Result<Boolean> booleanResult = moveTask(businDataTask);
            if (Result.isOk(booleanResult)) {
                businDataTaskVo.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
            } else {
                businDataTaskVo.setExceptionMsg("下发堆垛机失败");
                businDataTask.setTaskStatus(TaskStatusEnum.err.getValue());
            }
        }
        else if (taskType.equals(TaskTypeEnum.relocation_out.getValue())) {
            BusinDataTask businDataTask = iBusinDataTaskService.getById(businDataTaskVo.getId());
            Result<Boolean> taskResult = outTask(businDataTask);
            if (Result.isOk(taskResult)) {
                businDataTaskVo.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
            } else {
                businDataTaskVo.setExceptionMsg("下发堆垛机失败");
                businDataTask.setTaskStatus(TaskStatusEnum.err.getValue());
            }
        }
        else if ("25".equals(taskType)) {
            BusinDataTask businDataTask = iBusinDataTaskService.getById(businDataTaskVo.getId());
            //获取货位对应的巷道及巷道对应的设备信息
            pointQueryBo.setTunnel(businDataTask.getTunnel());
            pointQueryBo.setDirection("0");
            BasePointDeviceVo basePointDeviceVo = baseLocationPlcMapper.selectBasePointByGroupno(pointQueryBo).get(0);

            Long plcId = 0L;
            if (basePointDeviceVo != null) {
                plcId = Long.valueOf(isysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.LK_plc_id));
            }
            businDataTask.setDpsNoOne(plcId);
            businDataTaskVo.setDpsNoOne(plcId);
            Result<Boolean> taskResult = outTask(businDataTask);
            businDataTaskVo.setUpdateTime(DateUtils.getNowDate());
            if (Result.isOk(taskResult)) {
                businDataTaskVo.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
            } else {
                businDataTaskVo.setExceptionMsg("下发堆垛机失败");
                businDataTask.setTaskStatus(TaskStatusEnum.err.getValue());
            }
        }
        log.info("任务号" + businDataTaskVo.getId() + "任务状态" + businDataTaskVo.getTaskStatus() + "点位信息" + businDataTaskVo.getPoints());
        //统一提交任务数据
        iBusinDataTaskService.saveOrUpdate(BeanUtil.toBean(businDataTaskVo, BusinDataTask.class));

    }

    //查看堆垛机是否拥堵
    public Result<Boolean> PLCout(BusinDataTask businDataTask) {
        Long plcId = businDataTask.getDpsNoOne();
        WcsPlcConnect wcsPlcConnect = iWcsPlcConnectService.getById(plcId);
        PlcOperate stkOperate = plcInit.getPlcOperateByIp(wcsPlcConnect.getPlcIp());
        List<WcsPlcProperty> propertyList = iWcsPlcPropertyService.getWcsPlcPropertyByPlcId(plcId);
        String outAddress = "";
        //根据连接的plcId获取属性
        PLCReadAndWrite plcReadAndWriteD = new PLCReadAndWrite();
        Map<String, Object> pointMap = plcReadAndWriteD.readPlcData(stkOperate, wcsPlcConnect.getPointTables());
        for (WcsPlcProperty wcsPlcProperty : propertyList) {
            if (wcsPlcProperty.getPointType().equals("3") && wcsPlcProperty.getTunnel().equals(businDataTask.getTunnel())) {
                outAddress = wcsPlcProperty.getAddress();
            }
        }
        if (pointMap.containsKey(outAddress) && Boolean.valueOf(pointMap.get(outAddress).toString())) {
            return Result.ok();
        }
        return Result.err();
    }

    /**
     * 给堆垛机下发出库任务
     *
     * @param businDataTask
     * @return
     */
    public Result<Boolean> outTask(BusinDataTask businDataTask) {
        //查看输送线是否拥堵
        Result<Boolean> booleanResult = this.PLCout(businDataTask);
        if (HttpStatus.ERROR.getCode() == booleanResult.getCode()) {
            return Result.err();
        }
        String fromLayer = businDataTask.getFromLayer();
        String fromColumn = businDataTask.getFromColumn();
        String fromRow = businDataTask.getFromRow();
        //获取堆垛机
        BasePointDeviceQueryBo pointQueryBo = new BasePointDeviceQueryBo();
        pointQueryBo.setDevType("1");
        pointQueryBo.setTunnel(businDataTask.getTunnel());
        BaseDevicePlcVo basePointVo = baseLocationPlcMapper.selectBaseDevicePlc(pointQueryBo);
        Long plcId = basePointVo.getPlcId();

        PlcOperate stkOperate = plcInit.getPlcOperateByIp(basePointVo.getPlcIp());

        List<WcsPlcProperty> propertyList = iWcsPlcPropertyService.getWcsPlcPropertyByPlcId(plcId);
        String plcTaskId = "";
        String plcToRow = "";
        String plcToColumn = "";
        String plcToLayer = "";
        String plcHs = "";
        String plcCommand = "";
        String plcNulladdress = "";
        String Overonaddress = "";
        for (WcsPlcProperty stkProperty : propertyList) {
            //获取要堆垛机要写入的点位
            if (stkProperty.getPointType().equals("101")) {
                plcTaskId = stkProperty.getAddress();
            } else if (stkProperty.getPointType().equals("104")) {
                plcToRow = stkProperty.getAddress();
            } else if (stkProperty.getPointType().equals("105")) {
                plcToColumn = stkProperty.getAddress();
            } else if (stkProperty.getPointType().equals("106")) {
                plcToLayer = stkProperty.getAddress();
            } else if (stkProperty.getPointType().equals("107")) {
                plcHs = stkProperty.getAddress();
            } else if (stkProperty.getPointType().equals("102")) {
                plcCommand = stkProperty.getAddress();
            } else if (stkProperty.getPointType().equals("12")) {
                plcNulladdress = stkProperty.getAddress();
            } else if (stkProperty.getPointType().equals("4")) {
                Overonaddress = stkProperty.getAddress();
            }
        }
        WcsPlcConnect plcConnect = iWcsPlcConnectService.getById(plcId);
        //根据连接的plcId获取属性
        PLCReadAndWrite plcReadAndWriteD = new PLCReadAndWrite();
        Map<String, Object> pointDMap = plcReadAndWriteD.readPlcData(stkOperate, plcConnect.getPointTables());

        if (pointDMap.containsKey(plcNulladdress) && Boolean.valueOf(pointDMap.get(plcNulladdress).toString()) && (pointDMap.get(Overonaddress).equals("0"))) {
            //请求出库 给堆垛机下命令判断是否 加锁 加锁则返回
            if (ObjectUtils.isNotEmpty(redisTemplate.opsForValue().get("stackerLock:" + businDataTask.getTunnel()))
                    && redisTemplate.opsForValue().get("stackerLock:" + businDataTask.getTunnel()).toString().equals("true")) {
                log.info("出库时下发时，堆垛机加锁中" + businDataTask.getId());
                return Result.err();
            } else {
                redisTemplate.opsForValue().set("stackerLock:" + businDataTask.getTunnel(), "true");
            }
            //给堆垛机写命令
            Map<String, Object> allMap = new HashMap<>(1);
            Map<String, Object> plcTaskIdMap = new HashMap<>(1);
            plcTaskIdMap.put("INTEGER", businDataTask.getId());
            allMap.put(plcTaskId, plcTaskIdMap);
            Map<String, Object> plcToRowMap = new HashMap<>(1);
            plcToRowMap.put("SHORT", fromRow);
            allMap.put(plcToRow, plcToRowMap);
            Map<String, Object> plcToColumnMap = new HashMap<>(1);
            plcToColumnMap.put("SHORT", fromColumn);
            allMap.put(plcToColumn, plcToColumnMap);
            Map<String, Object> plcToLayerMap = new HashMap<>(1);
            plcToLayerMap.put("SHORT", fromLayer);
            allMap.put(plcToLayer, plcToLayerMap);
            Map<String, Object> plcHsMap = new HashMap<>(1);
            plcHsMap.put("SHORT", 2);
            allMap.put(plcHs, plcHsMap);

            Map<String, Object> plcCommandMap = new HashMap<>(1);
            plcCommandMap.put("SHORT", 2);
            allMap.put(plcCommand, plcCommandMap);

            PLCReadAndWrite plcReadAndWrite = new PLCReadAndWrite();
            if (plcReadAndWrite.execWrite(stkOperate, JsonUtil.toJSONString(allMap))) {
                return Result.ok();
            } else {
                return Result.err();
            }
        } else {
            return Result.err();
        }
    }

    /**
     * 巷道内移库任务，给堆垛机下发指令
     *
     * @param businDataTask
     * @return
     */
    public Result<Boolean> moveTask(BusinDataTask businDataTask) {

        List<WcsPlcProperty> propertyList = iWcsPlcPropertyService.getWcsPlcPropertyByPlcId(businDataTask.getPlcId());

        WcsPlcConnect plcConnect = iWcsPlcConnectService.getById(businDataTask.getPlcId());
        PlcOperate stkOperate = plcInit.getPlcOperateByIp(plcConnect.getPlcIp());
        //堆垛机是否空闲
        String readNullPoint = "";
        String plcTaskId = "";
        String plcToRow = "";
        String plcToColumn = "";
        String plcToLayer = "";
        String plcFromRow = "";
        String plcFromColumn = "";
        String plcFromLayer = "";
        //堆垛机工作状态
        String overonaddress = "";
        String plcml = "";
        for (WcsPlcProperty stkProperty : propertyList) {
            //获取要堆垛机要写入的点位
            if (stkProperty.getPointType().equals("101")) {
                plcTaskId = stkProperty.getAddress();
            } else if (stkProperty.getPointType().equals("108")) {
                plcToRow = stkProperty.getAddress();
            } else if (stkProperty.getPointType().equals("109")) {
                plcToColumn = stkProperty.getAddress();
            } else if (stkProperty.getPointType().equals("110")) {
                plcToLayer = stkProperty.getAddress();
            } else if (stkProperty.getPointType().equals("104")) {
                plcFromRow = stkProperty.getAddress();
            } else if (stkProperty.getPointType().equals("105")) {
                plcFromColumn = stkProperty.getAddress();
            } else if (stkProperty.getPointType().equals("106")) {
                plcFromLayer = stkProperty.getAddress();
            } else if (stkProperty.getPointType().equals("102")) {
                plcml = stkProperty.getAddress();
            } else if (stkProperty.getPointType().equals("12")) {
                readNullPoint = stkProperty.getAddress();
            } else if (stkProperty.getPointType().equals("4")) {
                overonaddress = stkProperty.getAddress();
            }
        }

        //根据连接的plcId获取属性
        PLCReadAndWrite plcReadAndWriteD = new PLCReadAndWrite();
        Map<String, Object> pointDMap = plcReadAndWriteD.readPlcData(stkOperate, plcConnect.getPointTables());
        if (pointDMap.containsKey(readNullPoint) && Boolean.valueOf(pointDMap.get(readNullPoint).toString()) && pointDMap.get(overonaddress).equals("0")) {
            //请求出库 给堆垛机下命令判断是否 加锁 加锁则返回
            if (ObjectUtils.isNotEmpty(redisTemplate.opsForValue().get("stackerLock:" + businDataTask.getTunnel()))
                    && redisTemplate.opsForValue().get("stackerLock:" + businDataTask.getTunnel()).toString().equals("true")) {
                log.info("移库任务下发时，堆垛机加锁中" + businDataTask.getId());
                return Result.err();
            } else {
                redisTemplate.opsForValue().set("stackerLock:" + businDataTask.getTunnel(), "true");
            }

            //给堆垛机写命令
            Map<String, Object> allMap = new HashMap<>(1);
            Map<String, Object> plcTaskIdMap = new HashMap<>(1);
            plcTaskIdMap.put("INTEGER", businDataTask.getId());
            allMap.put(plcTaskId, plcTaskIdMap);
            Map<String, Object> plcFromRowMap = new HashMap<>(1);
            plcFromRowMap.put("SHORT", businDataTask.getFromRow());
            allMap.put(plcFromRow, plcFromRowMap);
            Map<String, Object> plcFromColumnMap = new HashMap<>(1);
            plcFromColumnMap.put("SHORT", businDataTask.getFromColumn());
            allMap.put(plcFromColumn, plcFromColumnMap);
            Map<String, Object> plcFromLayerMap = new HashMap<>(1);
            plcFromLayerMap.put("SHORT", businDataTask.getFromLayer());
            allMap.put(plcFromLayer, plcFromLayerMap);
            Map<String, Object> plcToRowMap = new HashMap<>(1);
            plcToRowMap.put("SHORT", businDataTask.getToRow());
            allMap.put(plcToRow, plcToRowMap);
            Map<String, Object> plcToColumnMap = new HashMap<>(1);
            plcToColumnMap.put("SHORT", businDataTask.getToColumn());
            allMap.put(plcToColumn, plcToColumnMap);
            Map<String, Object> plcToLayerMap = new HashMap<>(1);
            plcToLayerMap.put("SHORT", businDataTask.getToLayer());
            allMap.put(plcToLayer, plcToLayerMap);
            Map<String, Object> plcMLMap = new HashMap<>(1);
            plcMLMap.put("Short", 4);
            allMap.put(plcml, plcMLMap);

            PLCReadAndWrite plcReadAndWrite = new PLCReadAndWrite();
            if (plcReadAndWrite.execWrite(stkOperate, JsonUtil.toJSONString(allMap))) {
                log.info("巷道内移库任务给堆垛机下发成功！" + businDataTask.getId());
                businDataTask.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
                iBusinDataTaskService.updateById(businDataTask);
                return Result.ok();
            } else {
                businDataTask.setTaskStatus(TaskStatusEnum.err.getValue());
                businDataTask.setExceptionMsg("下发堆垛机命令失败");
                businDataTask.setUpdateTime(DateUtils.getNowDate());
                iBusinDataTaskService.updateById(businDataTask);
                log.info("巷道内移库任务给堆垛机下发失败！" + businDataTask.getId());
                return Result.err().msg("巷道内移库任务给堆垛机下发失败");
            }
        } else {
            return Result.err();
        }
    }


    //检查当前物料号是否有出库任务（正常出库，紧急出库）
    public BusinDataTaskOutVo checkOutTaskData(String goods) {
        BusinDataTaskOutVo businDataTaskOutVo = null;
        BusinTaskQueryBo queryBo = new BusinTaskQueryBo();
//        queryBo.setTaskType("'4','5'");
        queryBo.setGoodsNo(goods);
        List<BusinDataTaskOutVo> businDataTaskOutVos = iBusinDataTaskService.selectOutBoundDataTask(goods);
        if (businDataTaskOutVos.size() > 0) {
            businDataTaskOutVo = businDataTaskOutVos.get(0);
        }
        return businDataTaskOutVo;
    }

    /**
     * 入库时有对应出库任务,将入库任务改为出库任务,直接将物料运往出库点位
     *
     * @param businDataTaskOutVo
     * @param businDataTaskVo
     */
    public void updateOutTask(BusinDataTaskOutVo businDataTaskOutVo, BusinDataTaskVo businDataTaskVo, String pointout) {
        Long taskId = businDataTaskVo.getId();
        BasePointDeviceQueryBo pointQueryBo = new BasePointDeviceQueryBo();
        String outPoint = "";

        pointQueryBo.setGroupNo(pointout);
        BasePointDeviceVo pointDeviceout = basePointDeviceMapper.selectBasePointByGroupno(pointQueryBo);
        if (pointDeviceout == null) {
            log.error("请维护紧急出库接驳点");
        }
        outPoint = pointDeviceout.getPointNo();
        int outtaskType = Integer.valueOf(pointDeviceout.getIsDown());


        //拿到机械手下料口上报取货完成点位
        String tepairGroupout = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.putout_point);
        BasePointDeviceQueryBo pointQueryBoup = new BasePointDeviceQueryBo();
        pointQueryBoup.setGroupNo(tepairGroupout);

        BasePointDeviceVo pointDevice = basePointDeviceMapper.selectBasePointByGroupno(pointQueryBoup);

        //更改紧急出库任务状态
        BusinDataTask businDataTaskout = iBusinDataTaskService.getById(businDataTaskOutVo.getTaskId());
        businDataTaskout.setTaskStatus("3");
        //更新入库任务对应信息
        String startPoint = businDataTaskVo.getTaskPath();
        Map<String, String> snPointMap = new HashMap<>(3);
        snPointMap.put("1", startPoint);
        snPointMap.put("2", pointDevice.getHandshakePoint());
        snPointMap.put("3", outPoint);
        List<String> points = new ArrayList<>();
        points.add(startPoint);
        points.add(pointDevice.getHandshakePoint());
        points.add(outPoint);
        businDataTaskVo.setPoints(JsonUtil.toJSONString(snPointMap));
        businDataTaskVo.setIsDown(String.valueOf(outtaskType));

        Result<Boolean> booleanResult = rcsUtil.callAGV(taskId, outtaskType, points);
        if (booleanResult.getCode() == HttpStatus.SUCCESS.getCode()) {
            businDataTaskVo.setTaskPath(outPoint);
            businDataTaskVo.setTaskType("5");
            businDataTaskVo.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
            iBusinDataTaskService.updateById(businDataTaskout);
            iBusinDataTaskService.updateById(BeanUtil.toBean(businDataTaskVo, BusinDataTask.class));
        }
    }
    //查询缓存区是否存在产品


    /**
     * 空治具出库流程
     */
    @Scheduled(cron = "0/5 * * * * ? ")
    public void exeEmptyContainerFromWare() {
        if (ObjectUtils.isEmpty(redisTemplate.opsForValue().get(RedisConstant.out_empty_type))) {
            log.info("暂未设置空治具出库");
            return;
        }
        // 将redis 中的值转成字符串
        String outEmptyType = redisTemplate.opsForValue().get(RedisConstant.out_empty_type).toString();
        if ("开启".equals(outEmptyType)) {
            iBusinEnptyContainerService.emptyContainerFromWare();
        } else {
            log.info("暂未设置空治具 “开始” 出库");
        }
    }

    /**
     * 异常出库
     *
     * @author Comair
     * @date 2023/8/12 19:32
     */
//    @Scheduled(cron = "0 0/1 * * * ? ")
    public void abnormalDelivery() {
        //查询维修地点是否有空闲
        String repairGroup = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.tepair_group);
        BasePointDeviceQueryBo pointQueryBo = new BasePointDeviceQueryBo();
        pointQueryBo.setGroupNo(repairGroup);
        BasePointDeviceVo basePointDeviceVo = null;
        List<BasePointDeviceVo> basePointDeviceVos = baseLocationPlcMapper.selectBasePointByGroupno(pointQueryBo);
        // 查询是否有待出库的待维修保险杠
        Long abnormalArea = Long.valueOf(sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.abnormal_area));
        List<BaseLocationVo> baseLocationVos = baseLocationMapper.getOutLocationByAreaId(abnormalArea);
        // 判断是否符合生成任务
        if (ObjectUtils.isNotEmpty(basePointDeviceVos) && ObjectUtils.isNotEmpty(baseLocationVos.size())) {
            basePointDeviceVo = basePointDeviceVos.get(0);
            String toPointNo = basePointDeviceVo.getPointNo();

            //生成异常出库任务
            BusinDataTask task = new BusinDataTask();
            task.setTaskType(TaskTypeEnum.abnormal_delivery.getValue());
            task.setBatch(DateUtils.getDate());
            task.setPriority("2");
            task.setIsTop("0");
            task.setIsUrgent("0");
            task.setCreateTime(DateUtils.getNowDate());
            task.setTaskPath(toPointNo);
            task.setTaskStatus("0");

            iBusinDataTaskService.insertBusinDataTask(task);

            BasePoint basePoint = iBasePointService.getById(basePointDeviceVo.getPointId());
            basePoint.setIsOccupy("1");
            iBasePointService.updateById(basePoint);
        }
    }

    /**
     * 冲孔出库
     *
     * @author Comair
     * @date 2023/8/12 19:33
     */
    @Scheduled(cron = "0 0/1 * * * ? ")
    public void punchingDelivery() {
        // 查询冲孔机是否符合并可以出库冲孔
        BasePointDeviceQueryBo pointQueryBo = new BasePointDeviceQueryBo();
        BasePunchRecordVo basePunchRecordVos = iBasePunchService.selectBasePunchRecord(new BasePunch());
        // 查询是否有待出库的待冲孔保险杠
        Long punchingArea = Long.valueOf(sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.punching_area));
        List<BaseLocationVo> baseLocationVos = baseLocationMapper.getOutLocationByAreaId(punchingArea);
        // 判断是否符合生成任务
        if (ObjectUtils.isNotEmpty(basePunchRecordVos) && basePunchRecordVos.getRecordQty() < 5 && ObjectUtils.isNotEmpty(baseLocationVos)) {
            Long punchId = basePunchRecordVos.getId();
            //获取冲孔机设备对用的点位
            String punchingGroup = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.punching_group);
            pointQueryBo.setGroupNo(punchingGroup);
            pointQueryBo.setDevCode(punchId);

            List<BasePointDeviceVo> tempList = baseLocationPlcMapper.selectBasePointByGroupno(pointQueryBo);
            BasePointDeviceVo basePointDeviceVo = tempList.get(0);
            if (tempList.get(0).getPointNo().contains("KW11")) {
                basePointDeviceVo = tempList.get(1);
            }

            String toPointNo = basePointDeviceVo.getPointNo();

            //生成冲孔出库任务
            BusinDataTask task = new BusinDataTask();
            task.setTaskType("21");
            task.setBatch(DateUtils.getDate());
            task.setPriority("2");
            task.setIsTop("0");
            task.setIsUrgent("0");
            task.setCreateTime(DateUtils.getNowDate());
            task.setTaskPath(toPointNo);
            task.setTaskStatus("0");
            iBusinDataTaskService.insertBusinDataTask(task);
        }
    }

    /**
     * 返回任务数最少的巷道号
     *
     * @param tunnelAll
     * @return java.lang.String
     * @author Comair
     * @date 2023/8/12 20:57
     */
    public String quickSort(List<String> tunnelAll) {
        String tunnel = "";
        Map<String, Integer> tunnelmap = new HashMap<>();
        tunnelAll.stream().forEach(e -> {
            tunnelmap.put(e, tunnelTaskUtil.getTotalTaskNum(e, 1));
        });
        List<Integer> collect = tunnelmap.values().stream().sorted().collect(Collectors.toList());
        for (String key : tunnelmap.keySet()) {
            if (tunnelmap.get(key).equals(collect.get(0))) {
                tunnel = key;
            }
        }
        return tunnel;
    }


    public void inTask(Long taskId, Long containerId) {
        //获取待下发任务数据
        BusinDataTask businDataTaskVo = businDataTaskMapper.selectById(taskId);
        //获取要出入库的条码信息
        List<BusinDataTaskGoodsVo> businDataTaskGoodsVos = iBusinDataTaskGoodsService.selectBusinTaskGoodsByTaskCode(businDataTaskVo.getId());
        String taskType = businDataTaskVo.getTaskType();
        if (!taskType.equals("0") && !taskType.equals("3") && !taskType.equals("2"))
        { return;}


        if ("3".equals(taskType)){
            Long plcId = 0L;
            Long stkPlcId = 0L;
            Boolean NUMBER = true;
            //需要冲孔，呼叫AGV
            //获取起始点位
            String startPoint = businDataTaskVo.getTaskPath();
            String tmpPoint = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.putout_point_tmp);
            //冲孔模式是自动，并且是启用的，并且待冲孔任务小于最大冲孔任务量,，则可以到冲孔，否在到入库
            BasePunchRecordVo basePunchRecordVos = iBasePunchService.selectBasePunchRecord(new BasePunch());
            BasePointDeviceVo basePointDeviceVo = null;
            List<String> points = new ArrayList<>();
            points.add(startPoint);
            Map<String, String> snPointMap = new HashMap<>(3);
            snPointMap.put("1", startPoint);
            //获取机械手上报点
            String tepairGroupin = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.putout_point);
            BasePointDeviceQueryBo pointQueryBoup = new BasePointDeviceQueryBo();
            pointQueryBoup.setGroupNo(tepairGroupin);
            BasePointDeviceVo pointDevice = new BasePointDeviceVo();
            pointDevice = basePointDeviceMapper.selectBasePointByGroupno(pointQueryBoup);
            points.add(pointDevice.getHandshakePoint());
            snPointMap.put("2", pointDevice.getHandshakePoint());
            BaseLocationVo locationVo = null;
            BasePointDeviceQueryBo pointQueryBo = new BasePointDeviceQueryBo();
            if (businDataTaskVo.getWarehouseType().equals("2")) {
                NUMBER = false;
                String tepairGroup1 = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.P_in01);
                pointQueryBo.setGroupNo(tepairGroup1);
                BasePointDeviceVo pointDeviceout = basePointDeviceMapper.selectBasePointByGroupno(pointQueryBo);
                basePointDeviceVo = pointDeviceout;
            } else {
                if (basePunchRecordVos != null) {
                    Long punchId = basePunchRecordVos.getId();
                    //获取冲孔机设备对用的点位
                    String punchingGroup = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.punching_group);
                    pointQueryBo.setGroupNo(punchingGroup);
                    pointQueryBo.setDevCode(punchId);

                    List<BasePointDeviceVo> tempList = baseLocationPlcMapper.selectBasePointByGroupno(pointQueryBo);
                    basePointDeviceVo = baseLocationPlcMapper.selectBasePointByGroupno(pointQueryBo).get(0);
                    if (tempList.get(0).getPointNo().contains("KW11")) {
                        basePointDeviceVo = baseLocationPlcMapper.selectBasePointByGroupno(pointQueryBo).get(1);
                    }
                } else {
                    NUMBER = false;
                    //先入待冲孔区
                    Long punchingArea = Long.valueOf(sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.punching_area));

                    List<BusinDataTaskGoodsVo> businDataTaskGoodsVoList = iBusinDataTaskGoodsService.selectBusinTaskGoodsByTaskCode(businDataTaskVo.getId());
                    AssingEmptyLocBo assingEmptyLocBo = new AssingEmptyLocBo();
                    assingEmptyLocBo.setBusinDataTaskGoodsVos(businDataTaskGoodsVoList);
                    assingEmptyLocBo.setAreaId(punchingArea);
                    //冲孔杠分配货位
                    Result<BaseLocationVo> locationVoResult = iBaseLocationService.assignEmptyLocatioPunching(assingEmptyLocBo);

                    if (ObjectUtils.isNotEmpty(locationVoResult) && locationVoResult.getCode() == HttpStatus.SUCCESS.getCode()) {
                        //如果是P01则设置randome为P02
                        redisTemplate.opsForValue().set("randome", "P02");
                        locationVo = locationVoResult.getData();
                    }
                    if (locationVo == null) {
                        log.info("冲孔杠分配货位为空");
                        return;
                    }
                    businDataTaskVo.setToColumn(locationVo.getLocationColumn());
                    businDataTaskVo.setToLayer(locationVo.getLayer());
                    businDataTaskVo.setToRow(locationVo.getLocationRow());
                    //获取货位及巷道；
                    String tunnel = locationVo.getTunnel();
                    businDataTaskVo.setTunnel(tunnel);
                    businDataTaskVo.setLocationId(locationVo.getId());
                    //获取巷道对应的立库输送线接驳口
                    pointQueryBo.setTunnel(tunnel);
                    pointQueryBo.setDirection("0");
                    List<BasePointDeviceVo> basePointDeviceVos = baseLocationPlcMapper.selectBasePointByGroupno(pointQueryBo);
                    if (basePointDeviceVos.size() > 0) {
                        basePointDeviceVo = basePointDeviceVos.get(0);
                        basePointDeviceVo.setPlcId(Long.valueOf(isysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.LK_plc_id)));
                    }
                    //获取巷道对应的堆垛机信息
                    pointQueryBo.setDevType("1");
                    BaseDevicePlcVo baseDevicePlcVo = baseLocationPlcMapper.selectBaseDevicePlc(pointQueryBo);
                    stkPlcId = baseDevicePlcVo.getPlcId();
                }
            }
            String toPointNo = "";
            toPointNo = basePointDeviceVo.getPointNo();
            if (basePointDeviceVo != null) {
                plcId = basePointDeviceVo.getPlcId();
            }

            points.add(toPointNo);
            snPointMap.put("3", toPointNo);
            int agvTaskType;
            if (toPointNo.equals("KW12")) {
                agvTaskType = 24;
            } else {
                agvTaskType = 27;
            }
            businDataTaskVo.setPoints(JsonUtil.toJSONString(snPointMap));
            businDataTaskVo.setIsDown(String.valueOf(agvTaskType));
            //呼叫AGV
            Result<Boolean> callAGVResult = callAGV(taskId, agvTaskType, points);
            //下发任务成功
            if (callAGVResult.getCode() == HttpStatus.SUCCESS.getCode()) {
                businDataTaskVo.setTaskPath(toPointNo);
                businDataTaskVo.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
                log.info("任务" + businDataTaskVo.getId() + "修改目的地成功");
                if (toPointNo.equals("KW12")) {
                    //记录冲孔机排队数量
                    Long punchId = basePunchRecordVos.getId();
                    BasePunchRecordAddBo recordAddBo = new BasePunchRecordAddBo();
                    recordAddBo.setTaskCode(taskId);
                    recordAddBo.setPunchNo(punchId);
                    recordAddBo.setAgvNo(businDataTaskVo.getAgvNo());
                    recordAddBo.setIsState("0");
                    iBasePunchRecordService.insertBasePunchRecord(BeanUtil.toBean(recordAddBo, BasePunchRecord.class));
                }

                //更改货位状态为4已分配
                if (ObjectUtils.isNotEmpty(locationVo)) {
                    BaseLocation baseLocation = iBaseLocationService.getById(locationVo.getId());
                    baseLocation.setLocationStatus("4");
                    iBaseLocationService.updateById(baseLocation);
                }
            }
            businDataTaskVo.setDpsNoOne(plcId);
            businDataTaskVo.setDpsNoTwo(stkPlcId);
            iBusinDataTaskService.updateById(BeanUtil.toBean(businDataTaskVo, BusinDataTask.class));
        }
        else if ("0".equals(taskType)){
            BasePointDeviceQueryBo pointQueryBo = new BasePointDeviceQueryBo();
            BusinDataTaskGoodsVo goodsVo = businDataTaskGoodsVos.get(0);
            String vehicheModel = goodsVo.getVehicheModel();
            String goodsNo = goodsVo.getGoodsNo();
            String startPoint = businDataTaskVo.getTaskPath();

            redisTemplate.opsForValue().set(RedisConstant.redisInVehicheModel, vehicheModel);
            /**
             * 1.判断是否启动越库
             * 2.判断此入库的保险杠是否是有出库任务，如果有，送往小组装
             */
            List<BusinDataTaskVo> outTaskVos =null;
            Boolean blSkipOverWare =false;
            String skipOverWare= SkipOverWareEnum.STOP.getValue();
            Object redisSkipOverWare = redisTemplate.opsForValue().get(RedisConstant.redisSkipOverWare);
            if (redisSkipOverWare != null){
                skipOverWare=redisSkipOverWare.toString();
            }
            if (skipOverWare.equals(SkipOverWareEnum.START.getValue())){
                //获取入库任务中的保险杠编码
                List<String> goodsList = businDataTaskGoodsVos.stream().map(o -> o.getGoodsNo()).collect(Collectors.toList());
                //根据保险杠编码获取出库任务
                BusinTaskQueryBo businTaskQueryBo = new BusinTaskQueryBo();
                businTaskQueryBo.setGoodsNoList(goodsList);
                outTaskVos = iBusinDataTaskService.selectOutBusinDataTaskBySkipOver(businTaskQueryBo);
                if (outTaskVos !=null && outTaskVos.size()>0){
                    blSkipOverWare=true;
                }
            }

            BasePointDeviceVo pointDevice ;
            BasePointDeviceVo basePointDeviceVo;
            //立库输送线接驳点-入
            String toLocation = "";
            int agvTaskType = 0;
            BusinTaskExeBo exeBo = new BusinTaskExeBo();
            Long plcId = null;
            Long stkPlcId = null;

            String agvno = null;
            String randome = "P01";
            if (businDataTaskVo.getWarehouseType().equals("1")) {
                randome = "P01";
            } else if (businDataTaskVo.getWarehouseType().equals("2")) {
                randome = "P02";
            }

            //机械手下挂出口的点位信息及握手点位
            String tepairGroup = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.putout_point);
            BasePointDeviceQueryBo pointQueryBoup = new BasePointDeviceQueryBo();
            pointQueryBoup.setGroupNo(tepairGroup);
            pointDevice = basePointDeviceMapper.selectBasePointByGroupno(pointQueryBoup);

            List<String> points = new ArrayList<>();
            Map<String, String> snPointMap = new HashMap<>(3);

            Long locationId = 0L;
            //非越库任务，分配立库或平库的货位
            if (!blSkipOverWare){
                if ("P01".equals(randome)) {
                    //根据车型分配库位  先判断该任务是否已经分配了货位
                    Result<BaseLocationVo> locationVoResult = null;
                    if (ObjectUtils.isEmpty(businDataTaskVo.getToRow())) {
                        AssingEmptyLocBo emptyLocBo = new AssingEmptyLocBo();
                        emptyLocBo.setBatch(DateUtils.getDate());
                        emptyLocBo.setVehicheModel(vehicheModel);
                        emptyLocBo.setGoodsNo(goodsNo);
                        emptyLocBo.setBusinDataTaskGoodsVos(businDataTaskGoodsVos);
                        locationVoResult = iBaseLocationService.assignEmptyLocationAll(emptyLocBo,null);

                    }

                    if (ObjectUtils.isNotEmpty(locationVoResult) && locationVoResult.getCode() == HttpStatus.SUCCESS.getCode()) {
                        //如果是P01则设置randome为P02
                        redisTemplate.opsForValue().set("randome", "P02");
                        BaseLocationVo locationVo = locationVoResult.getData();
                        String tunnel = locationVo.getTunnel();
                        locationId = locationVo.getId();
                        for (BusinDataTaskGoodsVo businDataTaskGoodsVo : businDataTaskGoodsVos) {
                            businDataTaskGoodsVo.setLocationId(locationId);
                        }
                        //回填任务的入行高列
                        businDataTaskVo.setBatch(DateUtils.getDate());
                        businDataTaskVo.setToColumn(locationVo.getLocationColumn());
                        businDataTaskVo.setToLayer(locationVo.getLayer());
                        businDataTaskVo.setToRow(locationVo.getLocationRow());
                        businDataTaskVo.setTunnel(tunnel);
                        businDataTaskVo.setLocationId(locationVo.getId());
                        //获取货位对应的巷道及巷道对应的设备信息
                        pointQueryBo.setTunnel(tunnel);
                        pointQueryBo.setDirection("0");
                        basePointDeviceVo = baseLocationPlcMapper.selectBasePointByGroupno(pointQueryBo).get(0);

                        if (basePointDeviceVo != null) {
                            toLocation = basePointDeviceVo.getPointNo();
                            //输送线PLCID
                            plcId = Long.valueOf(isysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.LK_plc_id));
                        }

                        //获取巷道对应的堆垛机信息
                        pointQueryBo.setDevType("1");
                        BaseDevicePlcVo baseDevicePlcVo = baseLocationPlcMapper.selectBaseDevicePlc(pointQueryBo);
                        stkPlcId = baseDevicePlcVo.getPlcId();

                        exeBo.setTaskCode(taskId);
                        exeBo.setBusinDataTaskGoodsVo(businDataTaskGoodsVos);
                        exeBo.setContainerId(containerId);
                        exeBo.setBaseLocationVo(locationVo);
                        exeBo.setTransNo("1");
                        exeBo.setTransQual("1");

                        //根据取货时的的点位拿到对应的交互点用作取货完成点
                        agvTaskType = Integer.valueOf(basePointDeviceVo.getIsDown());
                        if (taskType.equals("7")) {
                            if (businDataTaskVo.getTaskPath().contains("manMade")) {
                                agvTaskType = RCSTaskTypeEnum.TO_B_AND_PUT.getValue();
                                List agvtaskType = new ArrayList();
                                agvtaskType.add("15");
                                agvtaskType.add("12");
                                BusinDataTask manMade01 = iBusinDataTaskService.getOne(new LambdaQueryWrapper<BusinDataTask>()
                                        .in(BusinDataTask::getTaskType, agvtaskType)
                                        .eq(BusinDataTask::getContainerId, businDataTaskVo.getContainerId())
                                        .eq(BusinDataTask::getTaskStatus, "2")
                                        .orderByDesc(BusinDataTask::getId)
                                        .last("limit 1"));
                                if (ObjectUtils.isNotEmpty(manMade01)) {
                                    agvno = manMade01.getAgvNo();
                                }
                            } else if (businDataTaskVo.getTaskPath().contains("Artificial")) {
                                agvTaskType = RCSTaskTypeEnum.TO_B_AND_PUT.getValue();
                                String idArr = redisTemplate.opsForValue().get(RedisConstant.Replenishment).toString();
                                String[] idArrs = idArr.split("_");
                                agvno = idArrs[1];
                            }
                        }
                    }
                    if (locationVoResult.getCode() == HttpStatus.ERROR.getCode()) {
                        //如果是P02则设置randome为P01
                        redisTemplate.opsForValue().set("randome", "P01");
                        String tepairGroup_p = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.P_in01);
                        pointQueryBo.setGroupNo(tepairGroup_p);
                        BasePointDeviceVo pointDeviceout = basePointDeviceMapper.selectBasePointByGroupno(pointQueryBo);
                        toLocation = pointDeviceout.getPointNo();
                        agvTaskType = Integer.valueOf(pointDeviceout.getIsDown());
                        exeBo.setTaskCode(taskId);
                        exeBo.setBusinDataTaskGoodsVo(businDataTaskGoodsVos);
                        exeBo.setContainerId(containerId);
                        exeBo.setTransNo("1");
                        exeBo.setTransQual("1");
                    }

                }
                if ("P02".equals(randome)) {
                    //如果是P02则设置randome为P01
                    redisTemplate.opsForValue().set("randome", "P01");
                    String tepairGroup_p = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.P_in01);
                    pointQueryBo.setGroupNo(tepairGroup_p);
                    BasePointDeviceVo pointDeviceout = basePointDeviceMapper.selectBasePointByGroupno(pointQueryBo);
                    toLocation = pointDeviceout.getPointNo();
                    agvTaskType = Integer.valueOf(pointDeviceout.getIsDown());
                    exeBo.setTaskCode(taskId);
                    exeBo.setBusinDataTaskGoodsVo(businDataTaskGoodsVos);
                    exeBo.setContainerId(containerId);
                    exeBo.setTransNo("1");
                    exeBo.setTransQual("1");
                }

                points.add(startPoint);

                if (!taskType.equals("7")) {
                    points.add(pointDevice.getHandshakePoint());
                }

                points.add(toLocation);

                snPointMap.put("1", startPoint);
                if (!taskType.equals("7")) {
                    snPointMap.put("2", pointDevice.getHandshakePoint());
                    snPointMap.put("3", toLocation);
                } else {
                    snPointMap.put("2", toLocation);
                }

                businDataTaskVo.setPoints(JsonUtil.toJSONString(snPointMap));
                businDataTaskVo.setIsDown(String.valueOf(agvTaskType));
            }
            else{
                // 越库时 agv搬运路径处理
                //到达组装线等待上报点进行的业务处理
                String reportPointGroup = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.report_point);
                BasePointDeviceQueryBo pointReportQueryBo = new BasePointDeviceQueryBo();
                pointReportQueryBo.setGroupNo(reportPointGroup);
                BasePointDeviceVo reportPointDeviceOut = basePointDeviceMapper.selectBasePointByGroupno(pointReportQueryBo);
                if (ObjectUtils.isEmpty(reportPointDeviceOut)) {
                    log.error("请维护组装线上报点");
                    return;
                }
                //越库到小组装的下挂点
                toLocation =outTaskVos.get(0).getTaskPath();

                points.add(businDataTaskVo.getTaskPath());

                points.add(toLocation);

                snPointMap.put("1", businDataTaskVo.getTaskPath());
                snPointMap.put("2", toLocation);
            }
            //呼叫AGV
            Result<Boolean> booleanResult = new Result<>();
            if (taskType.equals("7")) {
                booleanResult = rcsUtil.callAGV(taskId, agvTaskType, points, businDataTaskVo.getToRow(), agvno);
            } else {
                //越库时，任务ID为出库任务的ID,agv模板类型为：6
                if(blSkipOverWare){
                    taskId=outTaskVos.get(0).getId();
                    agvTaskType=6;
                }
                booleanResult = rcsUtil.callAGV(taskId, agvTaskType, points, businDataTaskVo.getToRow());

                log.info("入库呼叫AGV任务号:" + taskId + "   结果:" + booleanResult.getCode() + "返回信息:" + booleanResult.getMsg());
            }
            if (booleanResult.getCode() == HttpStatus.ERROR.getCode()) {
                BusinDataTask businDataTask = new BusinDataTask();
                businDataTask.setId(businDataTaskVo.getId());
                businDataTask.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
                businDataTask.setLocationId(locationId);
                iBusinDataTaskService.updateById(businDataTask);
                return;
            }

            //呼叫AGV成功
            if (booleanResult.getCode() == HttpStatus.SUCCESS.getCode()) {
                //越库任务更新出库任务的状态
                if (blSkipOverWare){
                    if (outTaskVos !=null && outTaskVos.size()>0){
                        BusinDataTask businDataTask = iBusinDataTaskService.getById(outTaskVos.get(0).getId());
                        businDataTask.setTaskStatus(TaskStatusEnum.finished.getValue());
                        businDataTask.setRemark("越库任务："+taskId);
                        businDataTask.setUpdateTime(DateUtils.getNowDate());
                        businDataTask.setPoints(JsonUtil.toJSONString(snPointMap));
                        businDataTask.setIsDown(String.valueOf(agvTaskType));
                        businDataTask.setTaskPath(toLocation);
                        iBusinDataTaskService.updateById(businDataTask);
                        //越库时，入库的目标点位是小组装下挂点，状态是完成状态
                        businDataTaskVo.setTaskPath(toLocation);
                        businDataTaskVo.setTaskStatus(TaskStatusEnum.finished.getValue());
                    }
                }else
                {
                    businDataTaskVo.setTaskPath(toLocation);
                    businDataTaskVo.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
                    //立库输送线PLCID
                    businDataTaskVo.setDpsNoOne(plcId);
                    //巷道堆垛机PLCID
                    businDataTaskVo.setDpsNoTwo(stkPlcId);

                }
            }
            iBusinDataTaskService.updateById(BeanUtil.toBean(businDataTaskVo, BusinDataTask.class));
        }
        else if ("2".equals(taskType)){
            Long plcId = 0L;
            Long stkPlcId = 0L;
            Boolean NUMBER = true;

            BaseLocationVo locationVo = null;
            String toPointNo="";
            int agvTaskType=33;
            //获取起始点位
            String startPoint = businDataTaskVo.getTaskPath();

            //获取机械手上报点
            List<String> points = new ArrayList<>();
            Map<String, String> snPointMap = new HashMap<>(3);
            String tepairGroupin = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.putout_point);
            BasePointDeviceQueryBo pointQueryBoup = new BasePointDeviceQueryBo();
            pointQueryBoup.setGroupNo(tepairGroupin);
            BasePointDeviceVo pointDevice = basePointDeviceMapper.selectBasePointByGroupno(pointQueryBoup);
            points.add(startPoint);
            snPointMap.put("1", startPoint);
            points.add(pointDevice.getHandshakePoint());
            snPointMap.put("2", pointDevice.getHandshakePoint());

            //查询维修地点是否有空闲
            String tepairGroup = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.scanexc_group);
            BasePointDeviceQueryBo  pointQueryBo = new BasePointDeviceQueryBo();
            pointQueryBo.setGroupNo(tepairGroup);
            BasePointDeviceVo basePointDeviceVo = null;
            List<BasePointDeviceVo> basePointDeviceVos = baseLocationPlcMapper.selectBasePointByGroupno(pointQueryBo);

            //无空闲区 分配异常区库位
            if (basePointDeviceVos.size() == 0) {
                NUMBER = false;
                agvTaskType=RCSTaskTypeEnum.A_TO_B_HAND_PUT.getValue();
                if (businDataTaskVo.getWarehouseType().equals("2")) {
                    String tepairGroup1 = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.P_in01);
                    pointQueryBo.setGroupNo(tepairGroup1);
                    basePointDeviceVo = basePointDeviceMapper.selectBasePointByGroupno(pointQueryBo);

                } else {
                    //异常区ID
                    Long abnormalArea = Long.valueOf(sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.abnormal_area));
                    //分配货位
                    List<BusinDataTaskGoodsVo> businDataTaskGoodsVoList = iBusinDataTaskGoodsService.selectBusinTaskGoodsByTaskCode(businDataTaskVo.getId());
                    AssingEmptyLocBo assingEmptyLocBo = new AssingEmptyLocBo();
                    assingEmptyLocBo.setBusinDataTaskGoodsVos(businDataTaskGoodsVoList);
                    assingEmptyLocBo.setAreaId(abnormalArea);
                    Result<BaseLocationVo> locationVoResult = iBaseLocationService.assignEmptyLocatioError(assingEmptyLocBo);
                    if (Result.isOk(locationVoResult)){
                        locationVo = locationVoResult.getData();
                    }
                    businDataTaskVo.setToColumn(locationVo.getLocationColumn());
                    businDataTaskVo.setToLayer(locationVo.getLayer());
                    businDataTaskVo.setToRow(locationVo.getLocationRow());
                    businDataTaskVo.setLocationId(locationVo.getId());
                    //获取货位及巷道；
                    String tunnel = locationVo.getTunnel();
                    businDataTaskVo.setTunnel(tunnel);
                    pointQueryBo = new BasePointDeviceQueryBo();
                    pointQueryBo.setTunnel(tunnel);
                    pointQueryBo.setDirection("0");
                    basePointDeviceVos = baseLocationPlcMapper.selectBasePointByGroupno(pointQueryBo);
                    if (basePointDeviceVos.size() > 0) {
                        basePointDeviceVo = basePointDeviceVos.get(0);
                    }
                    //获取巷道对应的堆垛机信息
                    pointQueryBo.setDevType("1");
                    BaseDevicePlcVo baseDevicePlcVo = baseLocationPlcMapper.selectBaseDevicePlc(pointQueryBo);
                    stkPlcId = baseDevicePlcVo.getPlcId();
                    plcId =Long.valueOf(isysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.LK_plc_id));
                    toPointNo = basePointDeviceVo.getPointNo();
                    snPointMap.put("3",toPointNo);
                    points.add(toPointNo);
                }
            } else {
                agvTaskType = 33;
                basePointDeviceVo = basePointDeviceVos.get(0);
                toPointNo = basePointDeviceVo.getPointNo();
                snPointMap.put("3", "XX");
                points.add("XX");
                snPointMap.put("4", "XX");
                points.add("XX");
                snPointMap.put("5", toPointNo);
                points.add(toPointNo);
            }
            businDataTaskVo.setPoints(JsonUtil.toJSONString(snPointMap));
            businDataTaskVo.setIsDown(String.valueOf(agvTaskType));

            Result<Boolean> booleanResult;
            //呼叫AGV
            if (StringUtils.isNotEmpty(businDataTaskVo.getAgvNo())) {
                booleanResult = callAGV(taskId, agvTaskType, points, businDataTaskVo.getAgvNo());
            } else {
                booleanResult = callAGV(taskId, agvTaskType, points);
            }
            if (booleanResult.getCode() == HttpStatus.ERROR.getCode()) {
                BusinDataTask businDataTask = new BusinDataTask();
                businDataTask.setId(businDataTaskVo.getId());
                businDataTask.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
                businDataTask.setTaskPath(toPointNo);
                iBusinDataTaskService.updateById(businDataTask);
                return;
            }
            //呼叫AGV成功
            if (booleanResult.getCode() == HttpStatus.SUCCESS.getCode()) {
                businDataTaskVo.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
                businDataTaskVo.setTaskPath(toPointNo);
                if (NUMBER) {
                    BasePoint basePoint = iBasePointService.getById(basePointDeviceVo.getPointId());
                    basePoint.setIsOccupy("1");
                    iBasePointService.updateById(basePoint);
                }
            }
            //更新入库条码表状态为异常
            List<BaseBarcodesIn> barcodesIns = new ArrayList<>();
            List<BusinDataTaskGoodsVo> goodsVos = iBusinDataTaskGoodsService.selectBusinTaskGoodsByTaskCode(taskId);
            for (BusinDataTaskGoodsVo goodsVo : goodsVos) {
                BaseBarcodesIn baseBarcodesIn = iBaseBarcodesInService.getOne(new LambdaQueryWrapper<BaseBarcodesIn>()
                        .eq(BaseBarcodesIn::getQrCode, goodsVo.getQrCode())
                );
                baseBarcodesIn.setInStatus("4");
                baseBarcodesIn.setInDate(DateUtils.getDate());
                barcodesIns.add(baseBarcodesIn);
            }
            iBaseBarcodesInService.saveOrUpdateBatch(barcodesIns);
            businDataTaskVo.setDpsNoOne(plcId);
            businDataTaskVo.setDpsNoTwo(stkPlcId);
            businDataTaskVo.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
            iBusinDataTaskService.updateById(BeanUtil.toBean(businDataTaskVo, BusinDataTask.class));
        }
    }
}
