package com.shkj.wcs.plc;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
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.BusinessType;
import com.shkj.common.utils.DateUtils;
import com.shkj.plc.sdk.device.PlcOperate;
import com.shkj.system.service.ISysParameterService;
import com.shkj.wcs.bo.WcsPlcConnectQueryBo;
import com.shkj.wcs.domain.BusinDataTask;
import com.shkj.wcs.domain.WcsPlcConnect;
import com.shkj.wcs.domain.WcsPlcProperty;
import com.shkj.wcs.mapper.WcsPlcConnectMapper;
import com.shkj.wcs.service.IBusinDataTaskService;
import com.shkj.wcs.service.IWcsPlcConnectService;
import com.shkj.wcs.service.IWcsPlcPropertyService;
import com.shkj.wcs.third.rcs.CounterService;
import com.shkj.wcs.third.rcs.RCSUtil;
import com.shkj.wcs.third.rcs.dto.CarrierInfoList;
import com.shkj.wcs.third.rcs.dto.RcsCreateTaskDto;
import com.shkj.wcs.third.rcs.dto.RcsIdList;
import com.shkj.wcs.third.rcs.enums.RCSOperation;
import com.shkj.wcs.third.rcs.vo.RcsResponseVo;
import com.shkj.wcs.third.workbinWcs.WCSUtil;
import com.shkj.wcs.third.workbinWcs.dto.*;
import com.shkj.wcs.vo.TaskStatusBody;
import com.shkj.wcs.vo.WcsPlcConnectVo;
import com.shkj.wcs.vo.WcsResponseVo;
import com.shkj.wms.enums.BusinTaskTypeEnum;
import com.shkj.wms.enums.MapEnum;
import com.shkj.wms.enums.TaskStatusEnum;
import com.shkj.wms.enums.TaskTypeEnum;
import com.shkj.wms.utils.IntIdUtil;
import com.shkj.wms.utils.JsonUtil;
import com.shkj.wms.vo.PlanOrderLocationVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.exceptions.TooManyResultsException;
import org.mvel2.util.Make;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.*;

import com.shkj.plc.sdk.device.PLCReadAndWrite;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;


@Slf4j
@Service("PlcEventTask")
@EnableScheduling
public class PlcEventTask {

    @Autowired
    IWcsPlcConnectService iWcsPlcConnectService;

    @Resource
    RedisTemplate redisTemplate;

    @Autowired
    RCSUtil rcsUtil;

    @Autowired
    IWcsPlcPropertyService iWcsPlcPropertyService;

    @Autowired
    IBusinDataTaskService iBusinDataTaskService;


    @Autowired
    PlcInit plcInit;

    @Autowired
    WCSUtil wcsUtil;

    @Scheduled(fixedDelay = 5000)
    public void init() {
        //查询需要连接的PLC,初始化连接对象
        List<WcsPlcConnectVo> plcList = (List<WcsPlcConnectVo>) redisTemplate.opsForValue().get(RedisConstant.redisPlcListConnect);
        if (plcList == null || plcList.size() == 0) {
            plcList = iWcsPlcConnectService.selectWcsPlcConnectList(new WcsPlcConnect().setIsActive("1"));
            redisTemplate.opsForValue().set(RedisConstant.redisPlcListConnect, plcList);
        }

        for (WcsPlcConnectVo conn : plcList) {
            if (conn.getPlcIp().contains("99.151")) {
                plcTask(plcInit.getPlcOperate_dps(), conn, conn.getPointTables());
            }

            if (conn.getPlcIp().contains("99.172")) {
                plcTask(plcInit.getPlcOperate_dpj(), conn, conn.getPointTables());
            }
        }
    }


    //输送线心跳
    @Scheduled(fixedDelay = 2000)
    public void writePlcheartbeatDps() {
        PlcOperate plcOperate = plcInit.getPlcOperate_dps();
        if (plcOperate != null) {
            //根据连接的plcId获取属性
            PLCReadAndWrite plcReadAndWrite = new PLCReadAndWrite();
            Map<String, Object> readPointMap = new HashMap<>();
            String heartbeat = "DB5100.0.0";
            readPointMap.put(heartbeat, "Boolean");
            Map<String, Object> pointMap = plcReadAndWrite.readPlcData(plcOperate, JsonUtil.toJSONString(readPointMap));

            //读取心跳，并判断是写入true还是false;
            Boolean heartbeatV = false;

            if (pointMap.containsKey(heartbeat)) {
                heartbeatV = Boolean.valueOf(pointMap.get(heartbeat).toString());
            }
            //heartbeatV = (heartbeatV == true) ? false : true;
            Map<String, Object> writeHbMap = new HashMap<>(1);
            writeHbMap.put("Boolean", heartbeatV);
            Map<String, Object> allHbMap = new HashMap<>(1);
            allHbMap.put("DB5110.0.0", writeHbMap);
            Boolean heartType = plcReadAndWrite.execWrite(plcOperate, JsonUtil.toJSONString(allHbMap));
            if (!heartType) {
                log.info("dps心跳写入失败，重连服务器");
                plcInit.connect();
            }
        }
    }

    //叠盘机心跳
    @Scheduled(fixedDelay = 2000)
    public void writePlcheartbeatStk() {
        //根据连接的plcId获取属性
        PlcOperate plcOperate = plcInit.getPlcOperate_dpj();
        if (plcOperate != null) {
            PLCReadAndWrite plcReadAndWrite = new PLCReadAndWrite();
            Map<String, Object> readPointMap = new HashMap<>();
            String heartbeat = "DB5100.0.0";
            readPointMap.put(heartbeat, "Boolean");
            Map<String, Object> pointMap = plcReadAndWrite.readPlcData(plcOperate, JsonUtil.toJSONString(readPointMap));

            //读取心跳，并判断是写入true还是false;
            Boolean heartbeatV = false;

            if (pointMap.containsKey(heartbeat)) {
                heartbeatV = Boolean.valueOf(pointMap.get(heartbeat).toString());
            }
            heartbeatV = (heartbeatV == true) ? false : true;
            Map<String, Object> writeHbMap = new HashMap<>(1);
            writeHbMap.put("Boolean", heartbeatV);
            Map<String, Object> allHbMap = new HashMap<>(1);
            allHbMap.put("DB5110.0.0", writeHbMap);
            Boolean heartType = plcReadAndWrite.execWrite(plcOperate, JsonUtil.toJSONString(allHbMap));
            if (!heartType) {
                log.info("stk心跳写入失败，重连服务器");
                plcInit.connect();
            }
        }
    }

    public void plcTask(PlcOperate plcOperate, WcsPlcConnectVo conn, String pointTables) {

        Long plcId = conn.getId();
        //根据连接的plcId获取属性
        PLCReadAndWrite plcReadAndWrite = new PLCReadAndWrite();
        Map<String, Object> pointMap = plcReadAndWrite.readPlcData(plcOperate, pointTables);
        log.info("连接的IP:" + conn.getPlcIp() + ":设备：" + conn.getConnectName() + "   读取的点位内容：" + pointMap);

        List<WcsPlcProperty> propertyList = (List<WcsPlcProperty>) redisTemplate.opsForValue().get(RedisConstant.redisPlcProperty + plcId);
        if (propertyList == null || propertyList.size() == 0) {
            propertyList = iWcsPlcPropertyService.getWcsPlcPropertyByPlcId(plcId);
        }

        // 设备类型：2输送线  1 堆垛机
        switch (conn.getDevType()) {
            //输送线
            case "1":
                dpsRealTimeTask(propertyList, pointMap, plcReadAndWrite, plcOperate);
                break;
            case "2":
                dpjRealTimeTask(propertyList, pointMap, plcReadAndWrite, plcOperate);
                break;
            default:
                log.info("无匹配的设备类型");
                break;
        }

    }

    public void dpsRealTimeTask(List<WcsPlcProperty> propertyList, Map<String, Object> pointMap, PLCReadAndWrite plcReadAndWrite, PlcOperate plcOperate) {
        try {
            /**
             * 请求入库
             */
            //BCR01请求序列号
            String reqInSeria = "";

            //BCR01条码
            String reqInBarcod = "";
            //BCR01条码数据类型

            //BCR01外形检测
            String reqInLength = "";

            //请求入库返回序列号
            String reqInCfmSeria = "";
            String reqInCfmSeriaVt = "";

            //请求入库返回条码
            String reqInCfmBarcod = "";
            String reqInCfmBarcodVt = "";

            //返回去向
            String reqInDest = "";
            String reqInDestVt = "";

            /**
             * 空托
             */
            //空托申请
            String reqEmpty = "";

            //空托确认
            String reqCfm = "";
            String reqCfmVt = "";

            /**
             * 出口上报
             */
            //出口上报请求序列号
            String rptOutSeria = "";

            //出口上报条码
            String rptOutBarcod = "";

            //出口上报确认序列号
            String rptOutCfmSeria = "";
            String rptOutCfmSeriaVt = "";

            //出口上报条码确认
            String rptOutCfmBarcod = "";
            String rptOutCfmBarcodVt = "";

            //出口上报返回信息
            String retOut = "";
            String retOutVt = "";

            /**
             * 出口上报
             */
            //出口上报请求序列号
            String rptOutSeria1 = "";

            //出口上报条码
            String rptOutBarcod1 = "";

            //出口上报确认序列号
            String rptOutCfmSeria1 = "";
            String rptOutCfmSeriaVt1 = "";

            //出口上报条码确认
            String rptOutCfmBarcod1 = "";
            String rptOutCfmBarcodVt1 = "";

            //出口上报返回信息
            String retOut1 = "";
            String retOutVt1 = "";

            /**
             * 出入库切换
             */
            //出入库切换
            String inOutSwit = "";

            //出入库切换返回
            String retInOutSwit = "";
            String retInOutSwitVt = "";


            //空托上报请求序列号
            String rptEySeria = "";

            //空托上报条码
            String rptEyBarcod = "";

            //空托上报确认序列号
            String retEyCfmSeria = "";
            String retEyCfmSeriaVt = "";

            //空托上报条码确认
            String retEyCfmBarcod = "";
            String retEyCfmBarcodVt = "";

            //空托上报返回信息
            String retEy = "";
            String retEyVt = "";


            for (WcsPlcProperty plcProperty : propertyList) {
                String pointType = plcProperty.getPointType();
                //请求分配
                if (pointType.equals("reqInSeria")) {
                    reqInSeria = plcProperty.getAddress();
                } else if (pointType.equals("reqInBarcod")) {
                    reqInBarcod = plcProperty.getAddress();
                } else if (pointType.equals("reqInLength")) {
                    //外形检测
                    reqInLength = plcProperty.getAddress();
                    reqInLength = plcProperty.getValueType();
                } else if (pointType.equals("reqInCfmSeria")) {
                    reqInCfmSeria = plcProperty.getAddress();
                    reqInCfmSeriaVt = plcProperty.getValueType();
                } else if (pointType.equals("reqInCfmBarcod")) {
                    reqInCfmBarcod = plcProperty.getAddress();
                    reqInCfmBarcodVt = plcProperty.getValueType();
                } else if (pointType.equals("reqInDest")) {
                    reqInDest = plcProperty.getAddress();
                    reqInDestVt = plcProperty.getValueType();

                } else if (pointType.equals("reqEmpty")) {
                    reqEmpty = plcProperty.getAddress();
                } else if (pointType.equals("reqCfm")) {
                    reqCfm = plcProperty.getAddress();
                    reqCfmVt = plcProperty.getValueType();
                } else if (pointType.equals("rptOutSeria")) {
                    rptOutSeria = plcProperty.getAddress();
                } else if (pointType.equals("rptOutBarcod")) {
                    rptOutBarcod = plcProperty.getAddress();
                } else if (pointType.equals("rptOutCfmSeria")) {
                    rptOutCfmSeria = plcProperty.getAddress();
                    rptOutCfmSeriaVt = plcProperty.getValueType();
                } else if (pointType.equals("rptOutCfmBarcod")) {
                    rptOutCfmBarcod = plcProperty.getAddress();
                    rptOutCfmBarcodVt = plcProperty.getValueType();
                } else if (pointType.equals("retOut")) {
                    retOut = plcProperty.getAddress();
                    retOutVt = plcProperty.getValueType();
                } else if (pointType.equals("inOutSwit")) {
                    inOutSwit = plcProperty.getAddress();
                } else if (pointType.equals("retInOutSwit")) {
                    retInOutSwit = plcProperty.getAddress();
                    retInOutSwitVt = plcProperty.getValueType();
                } else if (pointType.equals("rptOutSeria1")) {
                    rptOutSeria1 = plcProperty.getAddress();
                } else if (pointType.equals("rptOutBarcod1")) {
                    rptOutBarcod1 = plcProperty.getAddress();
                } else if (pointType.equals("rptOutCfmSeria1")) {
                    rptOutCfmSeria1 = plcProperty.getAddress();
                    rptOutCfmSeriaVt1 = plcProperty.getValueType();
                } else if (pointType.equals("rptOutCfmBarcod1")) {
                    rptOutCfmBarcod1 = plcProperty.getAddress();
                    rptOutCfmBarcodVt1 = plcProperty.getValueType();
                } else if (pointType.equals("retOut1")) {
                    retOut1 = plcProperty.getAddress();
                    retOutVt1 = plcProperty.getValueType();
                } else if (pointType.equals("rptEySeria")) {
                    rptEySeria = plcProperty.getAddress();
                } else if (pointType.equals("rptEyBarcod")) {
                    rptEyBarcod = plcProperty.getAddress();
                } else if (pointType.equals("retEyCfmSeria")) {
                    retEyCfmSeria = plcProperty.getAddress();
                    retEyCfmSeriaVt = plcProperty.getValueType();
                } else if (pointType.equals("retEyCfmBarcod")) {
                    retEyCfmBarcod = plcProperty.getAddress();
                    retEyCfmBarcodVt = plcProperty.getValueType();
                } else if (pointType.equals("retEy")) {
                    retEy = plcProperty.getAddress();
                    retEyVt = plcProperty.getValueType();
                }

            }
            //生产区扫码处入库申请
            //&& Boolean.valueOf(pointMap.get(reqInSeria).toString())
            if (pointMap.containsKey(reqInSeria) && !pointMap.get(reqInSeria).equals("0")) {
                //读取请求序列号内容
                String bCR01SeriaV1 = Objects.toString(pointMap.get(reqInSeria), "");
                Integer bCR01SeriaV = 0;
                if (!bCR01SeriaV1.isEmpty()) {
                    bCR01SeriaV = Integer.parseInt(bCR01SeriaV1.toString());
                }
                //读取托盘条码内容
                String barcodeValueOne = Objects.toString(pointMap.get(reqInBarcod), "");
                String s = barcodeValueOne.replaceAll("[^A-Za-z0-9]", "");
                log.info("扫码处入库申请时，读取的条码内容：" + s);
                //根据托盘条码返回正在执行的任务号
                WcsIncomingTrayCheckBody body = new WcsIncomingTrayCheckBody();
                body.setStation(MapEnum.oneIn.getValue());
                body.setTaskType(TaskTypeEnum.In.getValue());
                body.setBussinessType(BusinTaskTypeEnum.trayCheck.getValue());
                body.setTrayCode(s);
                body.setCreateDt(getNowDate());
                WcsResponseVo vo = wcsUtil.wcsIncomingTrayCheck(body);
                log.info("扫码处入库申请wz-wcs返回：" + vo.getHeader());
                Map<String, Object> allMap = new HashMap<>(1);
                Map<String, Integer> seriaMap = new HashMap<>(1);
                seriaMap.put(reqInCfmSeriaVt, bCR01SeriaV);
                allMap.put(reqInCfmSeria, seriaMap);

//                Map<String, String> barcodMap = new HashMap<>(1);
//                barcodMap.put(reqInCfmBarcod00000Vt, s1);
//                allMap.put(reqInCfmBarcod, barcodMap);
                //成功直行 失败回退
                if (Result.isOk(vo.getHeader().getMsgCode())) {
                    Map<String, Integer> destMap = new HashMap<>(1);
                    destMap.put(reqInDestVt, 1);
                    allMap.put(reqInDest, destMap);
                } else {
                    Map<String, Integer> destMap = new HashMap<>(1);
                    destMap.put(reqInDestVt, 2);
                    allMap.put(reqInDest, destMap);
                }
                String allMapJson = JsonUtil.toJSONString(allMap);
                log.info("扫码处入库申请时，给输送线写命令数据：{}", allMapJson);
                Boolean reqInBoolean = plcReadAndWrite.execWrite(plcOperate, allMapJson);
                log.info("扫码处入库申请时，写入的命令返回结果：" + reqInBoolean.toString());
            }
            //空托盘申请
            if (pointMap.containsKey(reqEmpty) && !pointMap.get(reqEmpty).equals("0")) {
                WcsIncomingTaskRequestBody body = new WcsIncomingTaskRequestBody();
                body.setStation(MapEnum.oneOut.getValue());
                body.setTaskType(TaskTypeEnum.Out.getValue());
                body.setBussinessType(BusinTaskTypeEnum.stockOut.getValue());
                body.setCreateDt(getNowDate());
                //调用agv接口查询库区状态
                Map<String, Object> map1 = new HashMap<>();
                map1.put("areaInLocation", "SC-A2");
                map1.put("status", 0);

                Map<String, Object> map2 = new HashMap<>();
                map2.put("areaInLocation", "SC-B2");
                map2.put("status", 1);

                Map<String, Object> map3 = new HashMap<>();
                map3.put("areaInLocation", "SC-C2");
                map3.put("status", 1);

                Map<String, Object> map4 = new HashMap<>();
                map4.put("areaInLocation", "SC-D2");
                map4.put("status", 1);

                Object[] areaStatus = new Object[]{map1, map2, map3, map4};
                log.info("每个库区的状态:" + Arrays.toString(areaStatus));
                body.setAreaStatus(areaStatus);
                WcsResponseVo vo = wcsUtil.wcsIncomingTaskRequest(body);
                log.info("空托申请wz-wcs返回：" + vo.getHeader());
                Map<String, Object> allMap = new HashMap<>(1);
                Map<String, Integer> reqMap = new HashMap<>(1);

                if (Result.isOk(vo.getHeader().getMsgCode())) {
                    reqMap.put(reqCfmVt, 1);
                } else {
                    reqMap.put(reqCfmVt, 2);
                }
                allMap.put(reqCfm, reqMap);
                String allMapJson = JsonUtil.toJSONString(allMap);
                log.info("空托申请时，给输送线写命令数据：{}", allMapJson);
                Boolean bCR01Boolean = plcReadAndWrite.execWrite(plcOperate, allMapJson);
                log.info("空托申请时，写入的命令返回结果：" + bCR01Boolean.toString());
            }

            //实盘出口上报
            if (pointMap.containsKey(rptOutSeria) && !pointMap.get(rptOutSeria).equals("0")) {
                //读取序列号
                String IntegeroutSeria = Objects.toString(pointMap.get(rptOutSeria), "");
                Integer outSeria = 0;
                if (!IntegeroutSeria.isEmpty()) {
                    outSeria = Integer.parseInt(IntegeroutSeria.toString());
                }
                //读取托盘条码内容
                String barcodeValueOne = Objects.toString(pointMap.get(rptOutBarcod), "");
                String s = barcodeValueOne.replaceAll("[^A-Za-z0-9]", "");
                log.info("实盘出口上报时，读取的条码内容：" + s);
                //调用wz-wcs接口
                WcsIncomingTaskRequestBody body = new WcsIncomingTaskRequestBody();
                body.setStation(MapEnum.twoDownIn.getValue());
                body.setTaskType(TaskTypeEnum.In.getValue());
                body.setBussinessType(BusinTaskTypeEnum.stockIn.getValue());
                body.setTrayCode(s);
                body.setCreateDt(getNowDate());
                //调用agv接口查询库区状态
                Map<String, Object> map1 = new HashMap<>();
                map1.put("areaInLocation", "SC-A2");
                map1.put("status", 0);

                Map<String, Object> map2 = new HashMap<>();
                map2.put("areaInLocation", "SC-B2");
                map2.put("status", 1);

                Map<String, Object> map3 = new HashMap<>();
                map3.put("areaInLocation", "SC-C2");
                map3.put("status", 1);

                Map<String, Object> map4 = new HashMap<>();
                map4.put("areaInLocation", "SC-D2");
                map4.put("status", 1);

                Object[] areaStatus = new Object[]{map1, map2, map3, map4};
                log.info("每个库区的状态:" + Arrays.toString(areaStatus));
                body.setAreaStatus(areaStatus);
                WcsResponseVo vo = wcsUtil.wcsIncomingTaskRequest(body);
                log.info("实盘出口上报wz-wcs返回：" + vo.getHeader());
                Map<String, Object> allMap = new HashMap<>(1);
                Map<String, Integer> seriaMap = new HashMap<>(1);
                seriaMap.put(rptOutCfmSeriaVt, outSeria);
                allMap.put(rptOutCfmSeria, seriaMap);

//                Map<String, String> barcodMap = new HashMap<>(1);
//                barcodMap.put(rptOutCfmBarcodVt, barcodeValueOne);
//                allMap.put(rptOutCfmBarcod, barcodMap);
                Map<String, Integer> reqMap = new HashMap<>(1);

                if (Result.isOk(vo.getHeader().getMsgCode())) {
                    reqMap.put(retOutVt, 1);
                } else {
                    reqMap.put(retOutVt, 1);
                }
                allMap.put(retOut, reqMap);
                String allMapJson = JsonUtil.toJSONString(allMap);
                log.info("出口上报时，给输送线写命令数据：{}", allMapJson);
                Boolean rptOutBoolean = plcReadAndWrite.execWrite(plcOperate, allMapJson);
                log.info("出口上报时，写入的命令返回结果：" + rptOutBoolean.toString());
            }

            //实盘出口上报
            if (pointMap.containsKey(rptOutSeria1) && !pointMap.get(rptOutSeria1).equals("0")) {
                //读取序列号
                String IntegeroutSeria = Objects.toString(pointMap.get(rptOutSeria1), "");
                Integer outSeria = 0;
                if (!IntegeroutSeria.isEmpty()) {
                    outSeria = Integer.parseInt(IntegeroutSeria);
                }
                //读取托盘条码内容
                String barcodeValueOne = Objects.toString(pointMap.get(rptOutBarcod1), "");
                String s = barcodeValueOne.replaceAll("[^A-Za-z0-9]", "");

                log.info("实盘出口上报时，读取的条码内容：" + s);
                //调用wz-wcs接口
                WcsIncomingTaskRequestBody body = new WcsIncomingTaskRequestBody();
                body.setStation(MapEnum.twoUpIn.getValue());
                body.setTaskType(TaskTypeEnum.In.getValue());
                body.setBussinessType(BusinTaskTypeEnum.stockIn.getValue());
                body.setTrayCode(s);
                body.setCreateDt(getNowDate());
                //调用agv接口查询库区状态
                Map<String, Object> map1 = new HashMap<>();
                map1.put("areaInLocation", "SC-A2");
                map1.put("status", 0);

                Map<String, Object> map2 = new HashMap<>();
                map2.put("areaInLocation", "SC-B2");
                map2.put("status", 1);

                Map<String, Object> map3 = new HashMap<>();
                map3.put("areaInLocation", "SC-C2");
                map3.put("status", 1);

                Map<String, Object> map4 = new HashMap<>();
                map4.put("areaInLocation", "SC-D2");
                map4.put("status", 1);

                Object[] areaStatus = new Object[]{map1, map2, map3, map4};
                log.info("每个库区的状态:" + Arrays.toString(areaStatus));
                body.setAreaStatus(areaStatus);
                WcsResponseVo vo = wcsUtil.wcsIncomingTaskRequest(body);
                log.info("agv扫码处申请wz-wcs返回：" + vo.getHeader());
                Map<String, Object> allMap = new HashMap<>(1);
                Map<String, Integer> seriaMap = new HashMap<>(1);
                seriaMap.put(rptOutCfmSeriaVt1, outSeria);
                allMap.put(rptOutCfmSeria1, seriaMap);
                Map<String, Integer> reqMap = new HashMap<>(1);

                if (Result.isOk(vo.getHeader().getMsgCode())) {
                    reqMap.put(retOutVt1, 1);
                } else {
                    reqMap.put(retOutVt1, 2);
                }
                allMap.put(retOut1, reqMap);
                String allMapJson = JsonUtil.toJSONString(allMap);
                log.info("出口上报时，给输送线写命令数据：{}", allMapJson);
                Boolean rptOutBoolean = plcReadAndWrite.execWrite(plcOperate, allMapJson);
                log.info("出口上报时，写入的命令返回结果：" + rptOutBoolean.toString());
            }


            //出入库切换
            if (pointMap.containsKey(inOutSwit) && !pointMap.get(inOutSwit).equals("0")) {
                WCSQueryTaskStatusBody body = new WCSQueryTaskStatusBody();
                body.setDestination(MapEnum.oneOut.getValue());
                body.setTaskType("1");
                body.setTrayType("2");
                WcsResponseVo<TaskStatusBody> vo = JSON.parseObject(
                        JSON.toJSONString(wcsUtil.queryTaskStatus(body)),
                        new TypeReference<WcsResponseVo<TaskStatusBody>>() {
                        }
                );
                Integer taskCount = vo.getBody().get(0).getTaskCount();

                Map<String, Object> allMap = new HashMap<>(1);
                Map<String, Integer> reqMap = new HashMap<>(1);
                if (Result.isOk(vo.getHeader().getMsgCode())) {
                    if (taskCount == 0) {
                        reqMap.put(retInOutSwitVt, 2);
                    } else {
                        reqMap.put(retInOutSwitVt, 1);
                    }
                } else {
                    reqMap.put(retInOutSwitVt, 1);
                }
                allMap.put(retInOutSwit, reqMap);
                String allMapJson = JsonUtil.toJSONString(allMap);
                log.info("出入库切换时，给输送线写命令数据：{}", allMapJson);
                Boolean inOutSwitBoolean = plcReadAndWrite.execWrite(plcOperate, allMapJson);
                log.info("出入库切换时，写入的命令返回结果：" + inOutSwitBoolean.toString());
            }

            //空托上报完成
            if (pointMap.containsKey(rptEySeria) && !pointMap.get(rptEySeria).equals("0")) {
                //读取序列号
                String IntegeroutSeria = Objects.toString(pointMap.get(rptEySeria), "");
                Integer outSeria = 0;
                if (!IntegeroutSeria.isEmpty()) {
                    outSeria = Integer.parseInt(IntegeroutSeria);
                }
                //读取托盘条码内容
                String barcodeValueOne = Objects.toString(pointMap.get(rptEyBarcod), "");
                String s = barcodeValueOne.replaceAll("[^A-Za-z0-9]", "");

                Map<String, Object> allMap = new HashMap<>(1);
                Map<String, Integer> seriaMap = new HashMap<>(1);
                Map<String, Integer> reqMap = new HashMap<>(1);

                log.info("空托上报完成时，读取的条码内容：" + s);
                if(!s.isEmpty()){
                    LambdaQueryWrapper<BusinDataTask> lqw = new LambdaQueryWrapper<BusinDataTask>().eq(BusinDataTask::getContainerCode,s)
                            .eq(BusinDataTask::getTaskStatus,TaskStatusEnum.wait_callback.getValue());
                    BusinDataTask businDataTask = iBusinDataTaskService.getOne(lqw);
                    if(businDataTask != null){
                        log.info("空托报完成任务号："+ businDataTask.getTaskCode());
                        businDataTask.setTaskStatus(TaskStatusEnum.finished.getValue());
                        businDataTask.setDestination(MapEnum.oneOut.getValue());
                        businDataTask.setTaskEntime(new Date());
                        iBusinDataTaskService.updateById(businDataTask);
                        UploadWCSTaskStatusDto uploadWCSTaskStatusDto = new UploadWCSTaskStatusDto();
                        WcsCreateTaskHeader header = new WcsCreateTaskHeader();
                        header.setBusinessType("stockOutReturn");

                        uploadWCSTaskStatusDto.setHeader(header);
                        UploadWCSTaskStatusBody body = new UploadWCSTaskStatusBody();
                        List<UploadWCSTaskStatusBody> bodyList = new ArrayList<>();
                        body.setTaskId(businDataTask.getTaskCode());
                        body.setTrayCode(businDataTask.getContainerCode());
                        body.setTaskType(businDataTask.getTaskType());
                        body.setStatus(businDataTask.getTaskStatus());
                        body.setDestination(MapEnum.oneOut.getValue());
                        body.setMsgCode("200");
                        bodyList.add(body);
                        uploadWCSTaskStatusDto.setBody(bodyList);
                        log.info("空托任务状态上报请求zk-wcs参数{}", JSONObject.toJSONString(uploadWCSTaskStatusDto));
                        WcsResponseVo vo = wcsUtil.uploadWCSTaskStatus(uploadWCSTaskStatusDto);
                        log.info("空托任务状态上报反馈："+ JSONObject.toJSONString(vo));
                        if (Result.isOk(vo.getHeader().getMsgCode())) {
                            reqMap.put(retEyVt, 1);
                        } else {
                            reqMap.put(retEyVt, 2);
                        }
                    }else{
                        log.info("未查询到条码为："+s+"未完成的任务");
                        reqMap.put(retEyVt, 2);
                    }
                }else{
                    reqMap.put(retEyVt, 2);
                }
                seriaMap.put(retEyCfmSeriaVt, outSeria);
                allMap.put(retEy, reqMap);
                allMap.put(retEyCfmSeria,seriaMap);
                String allMapJson = JsonUtil.toJSONString(allMap);
                log.info("空托上报完成时，给输送线写命令数据：{}", allMapJson);
                Boolean rptOutBoolean = plcReadAndWrite.execWrite(plcOperate, allMapJson);
                log.info("空托上报完成时，写入的命令返回结果：" + rptOutBoolean.toString());
            }

        } catch (Exception e) {
            log.error("dpsRealTimeTask:" + e.getMessage());
        }


    }


    public void dpjRealTimeTask(List<WcsPlcProperty> propertyList, Map<String, Object> pointMap, PLCReadAndWrite plcReadAndWrite, PlcOperate plcOperate) {
        try {

            /**
             * 叠盘机
             */


            //叠盘机请求序列号
            String dpjSeria = "";

            //叠盘机确认序列号
            String retDpjCfmSeria = "";
            String retDpjCfmSeriaVt = "";

            //叠盘机请求条码
            String dpjBarcod = "";

            //叠盘机返回条码
            String retDpjCfmBarcod = "";
            String retDpjCfmBarcodVt = "";

            //叠盘机完成
            String dpj = "";

            //叠盘机返回
            String retDpj = "";
            String retDpjVt = "";

            //叠盘机返回
            String retDpj1 = "";
            String retDpj1Vt = "";

            //请求叠盘工位1
            String dpjGw1 = "";

            //请求叠盘工位1返回
            String retDpjGw1 = "";
            String retDpjGw1Vt = "";

            //请求叠盘工位2
            String dpjGw2 = "";

            //请求叠盘工位2返回
            String retDpjGw2 = "";
            String retDpjGw2Vt = "";

            //请求叠盘工位3
            String dpjGw3 = "";

            //请求叠盘工位3返回
            String retDpjGw3 = "";
            String retDpjGw3Vt = "";


            for (WcsPlcProperty plcProperty : propertyList) {
                String pointType = plcProperty.getPointType();

                if (pointType.equals("dpj")) {
                    dpj = plcProperty.getAddress();
                } else if (pointType.equals("retDpj")) {
                    retDpj = plcProperty.getAddress();
                    retDpjVt = plcProperty.getValueType();
                } else if (pointType.equals("dpjSeria")) {
                    dpjSeria = plcProperty.getAddress();
                } else if (pointType.equals("retDpjCfmSeria")) {
                    retDpjCfmSeria = plcProperty.getAddress();
                    retDpjCfmSeriaVt = plcProperty.getValueType();
                }else if (pointType.equals("dpjBarcod")) {
                    dpjBarcod = plcProperty.getAddress();
                } else if (pointType.equals("retDpj1")) {
                    retDpj1 = plcProperty.getAddress();
                    retDpj1Vt = plcProperty.getValueType();
                }  else if (pointType.equals("dpjGw1")) {
                    dpjGw1 = plcProperty.getAddress();
                } else if (pointType.equals("retDpjGw1")) {
                    retDpjGw1 = plcProperty.getAddress();
                    retDpjGw1Vt = plcProperty.getValueType();
                } else if (pointType.equals("dpjGw2")) {
                    dpjGw2 = plcProperty.getAddress();
                } else if (pointType.equals("retDpjGw2")) {
                    retDpjGw2 = plcProperty.getAddress();
                    retDpjGw2Vt = plcProperty.getValueType();
                } else if (pointType.equals("dpjGw3")) {
                    dpjGw3 = plcProperty.getAddress();
                } else if (pointType.equals("retDpjGw3")) {
                    retDpjGw3 = plcProperty.getAddress();
                    retDpjGw3Vt = plcProperty.getValueType();
                }

            }

            //叠盘机
            if (pointMap.containsKey(dpjSeria) && !pointMap.get(dpjSeria).equals("0")) {

                //读取序列号
                String IntegeroutSeria = Objects.toString(pointMap.get(dpjSeria), "");
                Integer seria = 0;
                if (!IntegeroutSeria.isEmpty()) {
                    seria = Integer.parseInt(IntegeroutSeria);
                }
                //读取托盘条码内容
                String barcodeValueOne = Objects.toString(pointMap.get(dpjBarcod), "");
                String s = barcodeValueOne.replaceAll("[^A-Za-z0-9]", "");
                log.info("叠盘机入库请求读取的条码："+ s);
                WcsIncomingTaskRequestBody body = new WcsIncomingTaskRequestBody();
                body.setStation(MapEnum.dpj.getValue());
                body.setTaskType(TaskTypeEnum.In.getValue());
                body.setTrayCode(s);
                body.setBussinessType(BusinTaskTypeEnum.stockIn.getValue());
                body.setCreateDt(getNowDate());
                //调用agv接口查询库区状态
                Map<String, Object> map1 = new HashMap<>();
                map1.put("areaInLocation", "SC-A2");
                map1.put("status", 0);

                Map<String, Object> map2 = new HashMap<>();
                map2.put("areaInLocation", "SC-B2");
                map2.put("status", 1);

                Map<String, Object> map3 = new HashMap<>();
                map3.put("areaInLocation", "SC-C2");
                map3.put("status", 1);

                Map<String, Object> map4 = new HashMap<>();
                map4.put("areaInLocation", "SC-D2");
                map4.put("status", 1);

                Object[] areaStatus = new Object[]{map1, map2, map3, map4};
                log.info("每个库区的状态:" + Arrays.toString(areaStatus));
                body.setAreaStatus(areaStatus);
                WcsResponseVo vo = wcsUtil.wcsIncomingTaskRequest(body);
                log.info("叠盘机满入库任务申请WZ-WCS返回：" + vo.getHeader());
                Map<String, Object> allMap = new HashMap<>(1);
                Map<String, Integer> reqMap = new HashMap<>(1);
                Map<String, Integer> req1Map = new HashMap<>(1);
                Map<String, Integer> seriaMap = new HashMap<>(1);
                seriaMap.put(retDpjCfmSeriaVt,seria);
                if (Result.isOk(vo.getHeader().getMsgCode())) {
                    reqMap.put(retDpjVt, 1);
                    req1Map.put(retDpj1Vt,1);
                } else {
                    reqMap.put(retDpjVt, 2);
                    req1Map.put(retDpj1Vt,2);
                }
                allMap.put(retDpj, reqMap);
                allMap.put(retDpj1, req1Map);
                allMap.put(retDpjCfmSeria,seriaMap);
                String allMapJson = JsonUtil.toJSONString(allMap);
                log.info("叠盘机叠满上报时，给输送线写命令数据：{}", allMapJson);
                Boolean bCR01Boolean = plcReadAndWrite.execWrite(plcOperate, allMapJson);
                log.info("叠盘机叠满上报时，写入的命令返回结果：" + bCR01Boolean.toString());
            }

            //叠盘机搬运1
            if (pointMap.containsKey(dpjGw1) && !pointMap.get(dpjGw1).equals("0")) {
                BusinDataTask businDataTask;
                boolean save = true;
                Map<String, Object> allMap = new HashMap<>(1);
                Map<String, Integer> reqMap = new HashMap<>(1);
                LambdaQueryWrapper<BusinDataTask> lqwTask = new LambdaQueryWrapper<BusinDataTask>()
                        .eq(BusinDataTask::getFromSide,MapEnum.dpjGw1.getValue())
                        .eq(BusinDataTask::getTaskStatus,TaskStatusEnum.wait_put);
                businDataTask = iBusinDataTaskService.getOne(lqwTask);
                if(businDataTask != null){
                    log.info("还未下发的任务："+businDataTask.getTaskCode());
                }else{
                    String taskCode = IntIdUtil.generateIntId().toString();
                    businDataTask.setTaskCode(taskCode);
                    businDataTask.setTaskStatus(TaskStatusEnum.wait_put.getValue());
                    businDataTask.setTaskType(TaskTypeEnum.Carry.getValue());
                    businDataTask.setTaskPath(MapEnum.dpj.getValue());
                    businDataTask.setPriority("1");
                    businDataTask.setFromSide(MapEnum.dpjGw1.getValue());
                    businDataTask.setToSide(MapEnum.dpj.getValue());
                    businDataTask.setCreateTime(DateUtils.getNowDate());
                    businDataTask.setAgvType("B113");
                    save = iBusinDataTaskService.save(businDataTask);
                }
                if (!save) {
                    log.info("叠盘工位1，任务存储失败！");
                    reqMap.put(retDpjGw1Vt, 2);
                    allMap.put(retDpjGw1, reqMap);
                }else{
                    Result result = iBusinDataTaskService.rcsTaskIssued(businDataTask);
                    if (!Result.isOk(result)) {
                        log.info("叠盘工位1，给rcs下发任务失败！");
                        reqMap.put(retDpjGw1Vt, 2);
                        allMap.put(retDpjGw1, reqMap);
                    }else{
                        log.info("叠盘工位1，给rcs下发任务成功！");
                        reqMap.put(retDpjGw1Vt, 1);
                        allMap.put(retDpjGw1, reqMap);
                        businDataTask.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
                        businDataTask.setTaskStarttime(DateUtils.getNowDate());
                        businDataTask.setUpdateTime(DateUtils.getNowDate());
                        iBusinDataTaskService.updateById(businDataTask);
                    }
                }
                String allMapJson = JsonUtil.toJSONString(allMap);
                log.info("叠盘工位1叠盘请求时，给输送线写命令数据：{}", allMapJson);
                Boolean bCR01Boolean = plcReadAndWrite.execWrite(plcOperate, allMapJson);
                log.info("叠盘工位1叠盘请求时，写入的命令返回结果：" + bCR01Boolean.toString());
            }

            //叠盘机搬运2
            if (pointMap.containsKey(dpjGw2) && !pointMap.get(dpjGw2).equals("0")) {
                BusinDataTask businDataTask;
                boolean save = true;
                Map<String, Object> allMap = new HashMap<>(1);
                Map<String, Integer> reqMap = new HashMap<>(1);
                LambdaQueryWrapper<BusinDataTask> lqwTask = new LambdaQueryWrapper<BusinDataTask>()
                        .eq(BusinDataTask::getFromSide,MapEnum.dpjGw2.getValue())
                        .eq(BusinDataTask::getTaskStatus,TaskStatusEnum.wait_put);
                businDataTask = iBusinDataTaskService.getOne(lqwTask);
                if(businDataTask != null){
                    log.info("还未下发的任务："+businDataTask.getTaskCode());
                }else{
                    String taskCode = IntIdUtil.generateIntId().toString();
                    businDataTask.setTaskCode(taskCode);
                    businDataTask.setTaskStatus(TaskStatusEnum.wait_put.getValue());
                    businDataTask.setTaskType(TaskTypeEnum.Carry.getValue());
                    businDataTask.setTaskPath(MapEnum.dpj.getValue());
                    businDataTask.setPriority("1");
                    businDataTask.setFromSide(MapEnum.dpjGw2.getValue());
                    businDataTask.setToSide(MapEnum.dpj.getValue());
                    businDataTask.setCreateTime(DateUtils.getNowDate());
                    businDataTask.setAgvType("B113");
                    save = iBusinDataTaskService.save(businDataTask);
                }
                if (!save) {
                    log.info("叠盘工位2，任务存储失败！");
                    reqMap.put(retDpjGw2Vt, 2);
                    allMap.put(retDpjGw2, reqMap);
                }else{
                    Result result = iBusinDataTaskService.rcsTaskIssued(businDataTask);
                    if (!Result.isOk(result)) {
                        log.info("叠盘工位2，给rcs下发任务失败！");
                        reqMap.put(retDpjGw2Vt, 2);
                        allMap.put(retDpjGw2, reqMap);
                    }else{
                        log.info("叠盘工位2，给rcs下发任务成功！");
                        reqMap.put(retDpjGw2Vt, 1);
                        allMap.put(retDpjGw2, reqMap);
                        businDataTask.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
                        businDataTask.setTaskStarttime(DateUtils.getNowDate());
                        businDataTask.setUpdateTime(DateUtils.getNowDate());
                        iBusinDataTaskService.updateById(businDataTask);
                    }
                }
                String allMapJson = JsonUtil.toJSONString(allMap);
                log.info("叠盘工位2叠盘请求时，给输送线写命令数据：{}", allMapJson);
                Boolean bCR01Boolean = plcReadAndWrite.execWrite(plcOperate, allMapJson);
                log.info("叠盘工位2叠盘请求时，写入的命令返回结果：" + bCR01Boolean.toString());
            }

            //叠盘机搬运3
            if (pointMap.containsKey(dpjGw3) && !pointMap.get(dpjGw3).equals("0")) {
                BusinDataTask businDataTask;
                boolean save = true;
                Map<String, Object> allMap = new HashMap<>(1);
                Map<String, Integer> reqMap = new HashMap<>(1);
                LambdaQueryWrapper<BusinDataTask> lqwTask = new LambdaQueryWrapper<BusinDataTask>()
                        .eq(BusinDataTask::getFromSide,MapEnum.dpjGw3.getValue())
                        .eq(BusinDataTask::getTaskStatus,TaskStatusEnum.wait_put);
                businDataTask = iBusinDataTaskService.getOne(lqwTask);
                if(businDataTask != null){
                        log.info("还未下发的任务："+businDataTask.getTaskCode());
                }else{
                    String taskCode = IntIdUtil.generateIntId().toString();
                    businDataTask.setTaskCode(taskCode);
                    businDataTask.setTaskStatus(TaskStatusEnum.wait_put.getValue());
                    businDataTask.setTaskType(TaskTypeEnum.Carry.getValue());
                    businDataTask.setTaskPath(MapEnum.dpj.getValue());
                    businDataTask.setPriority("1");
                    businDataTask.setFromSide(MapEnum.dpjGw3.getValue());
                    businDataTask.setToSide(MapEnum.dpj.getValue());
                    businDataTask.setCreateTime(DateUtils.getNowDate());
                    businDataTask.setAgvType("B113");
                    save = iBusinDataTaskService.save(businDataTask);
                }
                if (!save) {
                    log.info("叠盘工位3，任务存储失败！");
                    reqMap.put(retDpjGw3Vt, 2);
                    allMap.put(retDpjGw3, reqMap);
                }else{
                    Result result = iBusinDataTaskService.rcsTaskIssued(businDataTask);
                    if (!Result.isOk(result)) {
                        log.info("叠盘工位3，给rcs下发任务失败！");
                        reqMap.put(retDpjGw3Vt, 2);
                        allMap.put(retDpjGw3, reqMap);
                    }else{
                        log.info("叠盘工位3，给rcs下发任务成功！");
                        reqMap.put(retDpjGw3Vt, 1);
                        allMap.put(retDpjGw3, reqMap);
                        businDataTask.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
                        businDataTask.setTaskStarttime(DateUtils.getNowDate());
                        businDataTask.setUpdateTime(DateUtils.getNowDate());
                        iBusinDataTaskService.updateById(businDataTask);
                    }
                }
                String allMapJson = JsonUtil.toJSONString(allMap);
                log.info("叠盘工位3叠盘请求时，给输送线写命令数据：{}", allMapJson);
                Boolean bCR01Boolean = plcReadAndWrite.execWrite(plcOperate, allMapJson);
                log.info("叠盘工位3叠盘请求时，写入的命令返回结果：" + bCR01Boolean.toString());
            }


        } catch (Exception e) {
            log.error("dpsRealTimeTask:" + e.getMessage());
        }


    }




    public static String getNowDate() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
        return LocalDateTime.now().format(formatter);
    }


    /**
     * 单个的plc写入
     */
    public Boolean plcExecWrite(Integer stk) {
        PLCReadAndWrite plcReadAndWrite = new PLCReadAndWrite();
        List<WcsPlcProperty> propertyList = new ArrayList<>();
        propertyList = iWcsPlcPropertyService.getWcsPlcPropertyByPlcId(51L);
        if (!propertyList.isEmpty()) {
            for (WcsPlcProperty wcsPlcProperty : propertyList) {
                if (wcsPlcProperty.getPointType().equals("retStk")) {
                    String valueType = wcsPlcProperty.getValueType();
                    String address = wcsPlcProperty.getAddress();
                    Map<String, Object> allMap = new HashMap<>(1);
                    Map<String, Integer> reqMap = new HashMap<>(1);
                    reqMap.put(valueType, stk);
                    allMap.put(address, reqMap);
                    String allMapJson = JsonUtil.toJSONString(allMap);
                    log.info("叠盘机叠满上报时，给输送线写命令数据：{}", allMapJson);
                    Boolean bCR01Boolean = plcReadAndWrite.execWrite(plcInit.getPlcOperate_dps(), allMapJson);
                    log.info("叠盘机叠满上报时，写入的命令返回结果：" + bCR01Boolean.toString());
                    return true;
                }
            }
        }
        return false;
    }
}
