/*
 *  Copyright 2019-2020 Zheng Jie
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.yfd.platform.modules.patroltask.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.*;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.yfd.platform.component.WebSocketServer;
import com.yfd.platform.component.voiceserver.VoiceServerService;
import com.yfd.platform.config.HttpServerConfig;
import com.yfd.platform.constant.SystemCode;
import com.yfd.platform.modules.basedata.domain.LinkageSignal;
import com.yfd.platform.modules.basedata.domain.SubstationPatroldevice;
import com.yfd.platform.modules.basedata.mapper.SubstationPatroldeviceMapper;
import com.yfd.platform.modules.basedata.service.ILinkageSignalService;
import com.yfd.platform.modules.basedata.service.ISubstationDeviceService;
import com.yfd.platform.modules.patroltask.domain.TaskDolog;
import com.yfd.platform.modules.patroltask.domain.TaskResult;
import com.yfd.platform.modules.patroltask.domain.TaskTodo;
import com.yfd.platform.modules.patroltask.mapper.TaskResultMapper;
import com.yfd.platform.modules.patroltask.service.ITaskService;
import com.yfd.platform.modules.patroltask.service.ITaskTodoService;
import com.yfd.platform.system.domain.SysDictionaryItems;
import com.yfd.platform.system.service.ISysDictionaryItemsService;
import com.yfd.platform.utils.GroupAndProcessParallel;
import com.yfd.platform.utils.HttpRESTfulUtils;
import com.yfd.platform.utils.SpringContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.quartz.InterruptableJob;
import org.quartz.JobExecutionContext;
import org.quartz.UnableToInterruptJobException;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.io.File;
import java.net.URLEncoder;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @date 2023-04-28
 * 同步执行任务，避免资源冲突
 */
@Slf4j
public class TodoTaskJob extends QuartzJobBean implements InterruptableJob {

    private boolean _interrupted = false; // job 是否中断

    @Override
    public void executeInternal(JobExecutionContext context) {

        TaskTodo quartzJob =
                (TaskTodo) context.getMergedJobDataMap().get(TaskTodo.JOB_KEY);
        // 获取spring bean
        ITaskTodoService todoTaskService =
                SpringContextHolder.getBean(ITaskTodoService.class);
        // 获取spring bean
        ITaskService taskService = SpringContextHolder.getBean(ITaskService.class);
        // 获取spring bean 中 HttpRESTfulUtils 类实例
        HttpRESTfulUtils httpUtil =
                SpringContextHolder.getBean(HttpRESTfulUtils.class);
        // 获取spring bean 中 ILinkageSignalService 类实例
        ILinkageSignalService linkageSignalService =
                SpringContextHolder.getBean(ILinkageSignalService.class);
        ISubstationDeviceService substationDeviceService = SpringContextHolder.getBean(ISubstationDeviceService.class);
        SubstationPatroldeviceMapper substationPatroldeviceMapper =
                SpringContextHolder.getBean(SubstationPatroldeviceMapper.class);
        // 获取spring bean 中 HttpServerConfig 类实例
        HttpServerConfig config =
                SpringContextHolder.getBean(HttpServerConfig.class);
        ISysDictionaryItemsService sysDictionaryItemsService =
                SpringContextHolder.getBean(ISysDictionaryItemsService.class);
        TaskResultMapper taskResultMapper = SpringContextHolder.getBean(TaskResultMapper.class);
        VoiceServerService voiceServerService = SpringContextHolder.getBean(VoiceServerService.class);

        if ("false".equals(config.getDoTask())) {
            return;
        }
        TaskTodo taskTodo = todoTaskService.getById(quartzJob.getTaskTodoId());
        if ("1".equals(quartzJob.getTaskState()) || "3".equals(quartzJob.getTaskState())) {
            return;
        }
        if (taskTodo == null) {
            return;
        }
        String dockInfo = taskTodo.getDockInfo();
        if (StrUtil.isNotBlank(dockInfo) && JSONUtil.isTypeJSONObject(dockInfo)) {
            // 发送机巢任务执行
            String api = "wayline/api/v1/myWayLine/flight-tasks-execute";
            if (StrUtil.isNotBlank(config.getDockServerApp())) {
                api = config.getDockServerApp() + "/" + api;
            }
            Map<String, Object> param = new HashMap<>();
            param.put("jobId", taskTodo.getTaskTodoId());
            JSONObject jsonObject = httpUtil.sendHttpPost("json", config.getDockServerIp(),
                    config.getDockServerPort(), "", api, param, null);
            if (!SystemCode.SUCCESS_STATUS_CODE.getCode().equals(jsonObject.getString("code"))) {
                throw new RuntimeException(jsonObject.getString("msg"));
            }
            return;
        }

        long startTime = System.currentTimeMillis();
        String jobName = quartzJob.getTaskName();
//        int waitTime = 20000;
        int waitTime = 3000;
        try {
            // 执行任务
            log.info(
                    "--------------------------------------------------------------------------------------------------------------");
            log.info(String.format("任务开始执行[%s];任务名称:%s;任务ID:%s;计划执行时间:%s", DateUtil.now(), jobName,
                    quartzJob.getTaskTodoId(), quartzJob.getPlanStartTime()));
            // 任务增加开始时间
            LambdaUpdateWrapper<TaskTodo> updateWrapper = new LambdaUpdateWrapper<>();
            if (StrUtil.isBlank(quartzJob.getStartTime())) {
                updateWrapper.eq(TaskTodo::getTaskTodoId, quartzJob.getTaskTodoId()).ne(TaskTodo::getTaskState, "1").set(TaskTodo::getTaskState, "2").set(TaskTodo::getStartTime, DateUtil.now());
                todoTaskService.update(updateWrapper);
                if (StrUtil.isBlank(quartzJob.getControlNum())) {
                    WebSocketServer.sendInfo("taskresult_" + quartzJob.getStationCode(), "msg");
                } else {
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("taskTodoId", taskTodo.getTaskTodoId());
                    jsonObject.put("taskType", taskTodo.getTaskType());
                    jsonObject.put("status", "1");
                    WebSocketServer.sendInfo("taskresult_" + taskTodo.getStationCode(), jsonObject.toString());
                    try {
                        Thread.sleep(2000);
                    } catch (Exception e) {
                        log.error(e.getMessage());;
                    }
                }
            }
            String priority = "2".equals(quartzJob.getCustom3()) ? "4" : quartzJob.getPriority();
            //0、任务开始前，先暂停当前执行中的比当前任务级别低的任务
            todoTaskService.pauseLowerTask(quartzJob.getStationCode(), quartzJob.getTaskTodoId(), priority);
            // 任务开始前，判断是否有任务等级大于等于当前任务的，有就暂停当前任务
            if (StrUtil.isBlank(quartzJob.getCustom3())) {
                todoTaskService.pauseUpperTask(quartzJob.getStationCode(), quartzJob.getTaskTodoId(),
                        quartzJob.getPriority());
            }
            // 1、 根据任务ID 查询 当前任务需要巡视的点位
            List<Map<String, Object>> devicelist = todoTaskService.queryTaskResult(quartzJob.getTaskTodoId());
            List<Map<String, Object>> deviceList = new ArrayList<>();
            String linkageType = null;
            String linkageDeviceType = null;
            if (StrUtil.isNotBlank(taskTodo.getControlNum())) {
                LinkageSignal linkageSignal =
                        linkageSignalService.getOne(new LambdaQueryWrapper<LinkageSignal>().eq(LinkageSignal::getControlNum, taskTodo.getControlNum()));
                linkageType = linkageSignal.getLinkageType();
                linkageDeviceType = linkageSignal.getLinkageDeviceType();
                if ("1".equals(linkageSignal.getLinkageType())) {
                    List<Map<String, Object>> collect = devicelist.stream().filter(d -> !d.get("deviceName").toString().contains("全景")).collect(Collectors.toList());
                    deviceList.addAll(collect);
                    //                    todoTaskService.executeTask(devicelist,quartzJob, linkageDeviceType);
                } else {
                    deviceList.addAll(devicelist);
                }
                //                deviceList.addAll(devicelist);

            } else {
                deviceList.addAll(devicelist);
            }
            // 2、 遍历巡视点位对应摄像头位置信息
            AtomicBoolean isFlag = new AtomicBoolean(false);
            Map<String, List<Map<String, Object>>> groupedByCode =
                    deviceList.stream().collect(Collectors.groupingBy(r -> r.get("patroldeviceCode").toString()));
            // 将分组结果分配到n个新的集合中
            List<List<Map<String, Object>>> collections =
                    GroupAndProcessParallel.distributeToTenCollections1(groupedByCode);
            // 创建一个固定大小的线程池
            ExecutorService executorService = Executors.newFixedThreadPool(6);
            AtomicInteger number = new AtomicInteger();
            int size = 0;
            // 提交任务到线程池
            for (final List<Map<String, Object>> maps : collections) {
                String finalLinkageType = linkageType;
                String finalLinkageDeviceType = linkageDeviceType;
                size += maps.size();
                log.info("数量" + size);
                executorService.submit(() -> {
                    // 集合内部单线程处理
                    //摄像头视频流采集图片
                    for (Map<String, Object> map : maps) {
                        try {
                            if (_interrupted) {
                                isFlag.set(true);
                                //跳出执行
                                return;
                            }
                            String flag = map.get("flag").toString();
                            if (!("0".equals(flag) || "4".equals(flag))) {
                                continue;
                            }
                            number.getAndIncrement();
                            //排除当前时刻需要检修的巡视点
                            int count = todoTaskService.queryExaminePlan(map.get("deviceId").toString(),
                                    quartzJob.getPlanStartTime());
                            if (count > 0) {
                                //更新当前记录状态，修改为  3:设备检修中
                                todoTaskService.updateTaskResultStatus(quartzJob.getTaskTodoId(),
                                        map.get("resultId").toString(), "", "3");
                                continue;//跳过设备检修区间对应的巡视点
                            }

                            //获取typelist 识别类型
                            String pictureAnalysisTypeList = map.get("pictureAnalysisTypeList").toString();
                            JSONArray typelist = new JSONArray();
                            String analysePort = config.getAnalysePort11();
                            JSONObject customParams = new JSONObject();
                            customParams.put("taskName", taskTodo.getTaskName());
                            if (StrUtil.isNotEmpty(pictureAnalysisTypeList)) {
                                JSONObject jobj = JSON.parseObject(pictureAnalysisTypeList);

                                if (ObjectUtil.isNotEmpty(jobj.getString("PictureAnalysisType"))) {
                                    if ("meter".equals(jobj.getString("PictureAnalysisType"))) {
                                        customParams.put("meterType", map.get("outsideFeature").toString());
                                    }
                                    typelist.add(jobj.getString("PictureAnalysisType"));
                                }
                                if (ObjectUtil.isNotEmpty(jobj.getString("PictureDefectAnalysisType"))) {
                                    JSONArray defectresult = new JSONArray();
                                    analysePort = config.getAnalysePort12();
                                    List<String> pictureType = StrUtil.split(jobj.getString(
                                            "PictureDefectAnalysisType"), ",");
                                    List<Map<String, Object>> pictureDefectAnalysisType =
                                            sysDictionaryItemsService.getDeviceByType("PictureDefectAnalysisType");
                                    // 获取到子项
                                    List<String> itemCodeList =
                                            pictureDefectAnalysisType.stream().filter(p -> pictureType.contains(p.get("itemcode").toString())).map(m -> m.get("custom1").toString()).collect(Collectors.toList());

                                    for (String code : itemCodeList) {
                                        JSONArray jsonArray = JSONUtil.parseArray(code);
                                        defectresult.addAll(jsonArray);
                                        List<String> keyList =
                                                jsonArray.stream().map(j -> JSONUtil.parseObj(j).getStr("key")).collect(Collectors.toList());
                                        typelist.addAll(keyList);
                                    }
                                    if (defectresult.size() > 0) {
                                        //缺陷识别结果类型
                                        customParams.put("defectresulttypes", defectresult);
                                    }
                                }
                                if (ObjectUtil.isNotEmpty(jobj.getString("PictureDiscriminateAnalysisType"))) {
                                    typelist.add(jobj.getString("PictureDiscriminateAnalysisType"));
                                    analysePort = config.getAnalysePort12();
                                }
                            }

                            if (typelist.size() == 0) {
                                throw new Exception("未设置识别方式，不能进行图形识别！");
                            }

                            //路径命名格式为：变电站编码/年/月/日/巡视任务编码/CCD
                            //其中 CCD 为可见光图片  FIR  红外图谱文件  Audio 音频文件 Video 视频文件
                            //图片类型
                            String filetype = "CCD";
                            if (ObjectUtil.isNotEmpty(map.get("fileType"))) {
                                switch (map.get("fileType").toString()) {
                                    case "1":
                                        filetype = "FIR";
                                        break;
                                    case "3":
                                        filetype = "Audio";
                                        break;
                                    case "4":
                                        filetype = "Video";
                                        break;
                                    default:
                                        filetype = "CCD";
                                        break;
                                }
                            }
                            String filepath = String.format("%s/%s/%s/%s/%s/%s/",
                                    quartzJob.getStationCode(),
                                    DateUtil.format(DateUtil.date(), "yyyy"),
                                    DateUtil.format(DateUtil.date(), "MM"),
                                    DateUtil.format(DateUtil.date(), "dd"),
                                    quartzJob.getTaskCode(),
                                    filetype
                            );

                            String filename = String.format("%s_%s_%s.jpg",
                                    map.get("deviceId").toString(),
                                    map.get("patroldeviceCode").toString(),
                                    DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss")
                            );
                            if ("1".equals(finalLinkageType)) {
                                filename = String.format("%s_%s_%s.mp4",
                                        map.get("deviceId").toString(),
                                        map.get("patroldeviceCode").toString(),
                                        DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss")
                                );
                            }
                            String fullfilename = filepath + filename;
                            String csvFilePath = config.getSnapFilePath() + filepath + filename;
                            String rtspurl = String.format("rtsp://%s:%s/rtp/%s_%s", config.getMediaIp(),
                                    config.getMonitorRtspPort(),
                                    map.get("rtspDeviceCode").toString(), map.get("rtspChannelCode").toString());

                            List<SubstationPatroldevice> devices =
                                    substationPatroldeviceMapper.selectList(new LambdaQueryWrapper<SubstationPatroldevice>().eq(SubstationPatroldevice::getInternationalId, map.get("patroldeviceCode").toString()));
                            if (devices.size() > 0) {
                                SubstationPatroldevice device = devices.get(0);
                                if (ObjUtil.isNotEmpty(device.getChannelinfo()) && JSONUtil.isTypeJSONArray(device.getChannelinfo())) {
                                    JSONArray channels = JSONUtil.parseArray(device.getChannelinfo());
                                    for (int i = 0; i < channels.size(); i++) {
                                        cn.hutool.json.JSONObject channel = channels.getJSONObject(i);
                                        //设备rstp流地址不为空，优先取摄像头地址
                                        if (map.get("patroldeviceChannelcode").toString().equals(channel.getStr(
                                                "channel_code"))) {
                                            if (StrUtil.isNotBlank(channel.getStr("channel_rtspurl"))) {
                                                rtspurl = channel.getStr("channel_rtspurl");
                                                break;
                                            }

                                        }
                                    }
                                }
                            }
                            JSONObject callresult;
                            if ("sound".equals(typelist.get(0).toString())) {
                                //声音检测
                                filename = String.format("%s_%s_%s_%s_%s.wav",
                                        DateUtil.format(DateUtil.date(), "yyyyMMdd"),
                                        DateUtil.format(DateUtil.date(), "HHmmss"),
                                        map.get("bayName").toString(),
                                        map.get("mainDeviceName").toString(),
                                        map.get("deviceName").toString()
                                );
                                fullfilename = filepath + filename;
                                String encodefilename = fullfilename;
                                int duration = 10;
                                if (ObjUtil.isNotEmpty(map.get("duration"))) {
                                    duration = NumberUtil.parseInt(map.get("duration").toString());
                                }
                                if (ObjectUtil.isNotEmpty(map.get("outsideAngle"))) {
                                    if (JSONUtil.isTypeJSONArray(map.get("outsideAngle").toString())) {
                                        JSONArray jsonArray = JSONUtil.parseArray(map.get("outsideAngle").toString());
                                        customParams.put("SoundAlarmThresholdList", jsonArray);
                                    }
                                    if (JSONUtil.isTypeJSONObject(map.get("outsideAngle").toString())) {
                                        cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(map.get(
                                                "outsideAngle").toString());
                                        customParams.put("SoundAlarmThreshold", jsonObject);
                                    }
                                }
                                try {
                                    String patroldeviceCode = map.get("patroldeviceCode").toString();
                                    voiceServerService.sendVoiceServerControl(patroldeviceCode, "ON", fullfilename);
                                    Thread.sleep(duration * 1000);
                                    voiceServerService.sendVoiceServerControl(patroldeviceCode, "OFF", fullfilename);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                                //更新当前记录状态，修改为  1：已巡视(声音已采集)
                                fullfilename = URLEncoder.encode(fullfilename, "utf-8");//转码存储
                                todoTaskService.updateTaskResultStatus(quartzJob.getTaskTodoId(),
                                        map.get("resultId").toString(),
                                        fullfilename, "2");

                                System.out.println("customParams：" + JSONUtil.toJsonStr(customParams));
                                callresult = httpUtil.callPicAnalyse(map.get("taskTodoId").toString(),
                                        map.get("resultId").toString(), JSONUtil.toJsonStr(typelist),
                                        JSONUtil.toJsonStr(customParams), encodefilename, analysePort);

                            } else {
                                if (!"3".equals(finalLinkageType)) {
                                    if ("1".equals(finalLinkageType)) {
                                        typelist.clear();
                                        typelist.add("yjsk");
                                        log.info("调用摄像机截取视频");
                                        String videoStream = map.get("rtspDeviceCode").toString() + "_" + map.get(
                                                "rtspChannelCode").toString();
                                        httpUtil.getMonitorVideo(config.getffmpegPath(), rtspurl, fullfilename,
                                                finalLinkageDeviceType, videoStream);
                                        if ("遥信".equals(finalLinkageDeviceType)) {
                                            fullfilename = null;
                                        }
                                    } else {
                                        //图像检测
                                        if ("1".equals(config.getFilefromtype())) {
                                            //锁定摄像机状态(设置摄像机为工作状态，其他地方不能调用预置位操作)
                                            todoTaskService.updatePatrolDeviceState(map.get("stationCode").toString()
                                                    , map.get(
                                                            "rtspDeviceCode").toString(), "1");

                                            log.info("开始调用摄像头预置位");
                                            JSONObject callresult1 =
                                                    httpUtil.callDevicePos(map.get("rtspDeviceCode").toString(),
                                                            map.get("rtspChannelCode").toString(), map.get(
                                                                    "rtspChannelPos").toString(), null);
                                            log.info("摄像头预置位调用成功！" + JSONUtil.toJsonStr(callresult1));
                                            //延迟时间
                                            Thread.sleep(waitTime);
                                            log.info("开始调用视频并截图");
                                            log.info("rtspurl" + rtspurl);
                                            httpUtil.getMonitorVideoSnap(config.getffmpegPath(), rtspurl, fullfilename);
                                            log.info("完成视频截图并保存到对应位置下！,文件名称：" + fullfilename);
                                            String identifyMaterialId = ObjectUtil.isNotEmpty(map.get(
                                                    "identifyMaterialId")) ? map.get(
                                                    "identifyMaterialId").toString() : "";
                                            if ("1".equals(identifyMaterialId)) {
                                                // 设置实物ID
                                                todoTaskService.setMaterialIdByImg(map.get("resultId").toString(),
                                                        config.getSnapFilePath() + fullfilename);
                                            }
                                        } else if ("3".equals(config.getFilefromtype())) {
                                            String sourceFilePath = config.getTestfilepath();
                                            String deviceName = ObjectUtil.isNotEmpty(map.get("deviceName")) ?
                                                    map.get("deviceName").toString() : "";
                                            if (StrUtil.isNotBlank(deviceName)) {
                                                String formatfilePath = String.format("%s%s.jpg", sourceFilePath,
                                                        deviceName);
                                                if (FileUtil.exist(formatfilePath)) {
                                                    FileUtil.copy(formatfilePath,
                                                            config.getSnapFilePath() + fullfilename, true);
                                                    log.info("直接获取文件夹中文件" + fullfilename);
                                                }
                                            }

                                        }
                                    }
                                }
                                //更新当前记录状态，修改为  1：已巡视(图像已采集)
                                //转码存储
                                String encodefilename = fullfilename;
                                if (fullfilename != null) {
                                    fullfilename = URLEncoder.encode(fullfilename, "utf-8");
                                }
                                //                                if (!"3".equals(config.getFilefromtype())) {
                                todoTaskService.updateTaskResultStatus(quartzJob.getTaskTodoId(),
                                        map.get("resultId").toString(), fullfilename, "1");
                                if (ObjectUtil.isNotEmpty(map.get("outsideAngle"))) {
                                    if (JSONUtil.isTypeJSONArray(map.get("outsideAngle").toString())) {
                                        JSONArray jsonArray = JSONUtil.parseArray(map.get("outsideAngle").toString());
                                        customParams.put("TempAngleList", jsonArray);
                                    }

                                    if (JSONUtil.isTypeJSONObject(map.get("outsideAngle").toString())) {
                                        cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(map.get("outsideAngle").toString());
                                        customParams.put("TempAngle", jsonObject);
                                    }

                                }

                                //基准图
                                if (ObjUtil.isNotEmpty(map.get("patroldeviceBaseimage"))) {
                                    String path = URLEncoder.encode(map.get("patroldeviceBaseimage").toString(), "utf-8");
                                    String imageurl = String.format("http://%s:%s/%s/snapNormalFile?filename=%s",
                                            config.getPatrolIp(), config.getPatrolPort(), config.getPatrolAppname(),
                                            path);
                                    customParams.put("imageNormalUrlPath", imageurl);
                                }

                                //有效识别区域
                                if (ObjectUtil.isNotEmpty(map.get("patroldeviceJson"))) {
                                    String pos = map.get("patroldevicePos").toString();
                                    String channelcode = map.get("patroldeviceChannelcode").toString();
                                    JSONArray patroldevices =
                                            JSONUtil.parseArray(map.get("patroldeviceJson").toString());
                                    for (int i = 0; i < patroldevices.size(); i++) {
                                        cn.hutool.json.JSONObject patroldevice = patroldevices.getJSONObject(i);
                                        if (pos.equals(patroldevice.getStr("patroldevice_pos")) && channelcode.equals(patroldevice.getStr("patroldevice_channelcode"))) {
                                            if (ObjUtil.isNotEmpty(patroldevice.getStr("effective_region"))) {
                                                customParams.put("effectiveregion", patroldevice.getStr(
                                                        "effective_region"));
                                            }
                                        }

                                    }
                                }
                                log.info("==============================typelist=======================" + typelist.toString());
                                if ("infrared".equals(typelist.get(0).toString()) && !"3".equals(config.getFilefromtype())) {
                                    //红外测温
                                    log.info("进入红外测温方法");
                                    String outsideAngle = "";
                                    if (ObjectUtil.isNotEmpty(map.get("outsideAngle"))) {
                                        outsideAngle = map.get("outsideAngle").toString();
                                    }
                                    String resultId = map.get("taskTodoId").toString();
                                    String objectId = map.get("resultId").toString();
                                    String patrolDeviceCode = map.get("rtspDeviceCode").toString();
                                    // 调用温度的sdk识别并给图片加上温度
                                    callresult = todoTaskService.callPicAnalyse(resultId, objectId, patrolDeviceCode,
                                            rtspurl, fullfilename, outsideAngle,
                                            csvFilePath);
                                } else {
                                        callresult = httpUtil.callPicAnalyse(map.get("taskTodoId").toString(),
                                                map.get("resultId").toString(), JSONUtil.toJsonStr(typelist),
                                                JSONUtil.toJsonStr(customParams), encodefilename);
                                }

                                // 解除摄像头的工作状态
                                todoTaskService.updatePatrolDeviceState(map.get("stationCode").toString(), map.get(
                                        "rtspDeviceCode").toString(), "0");
                            }

                            if (callresult != null) {
                                String code = callresult.get("code").toString();
                                if ("-2".equals(code) || "201".equals(code)) {
                                    // 设置请求分析主机调用失败的任务为巡视失败
                                    todoTaskService.setTaskResultAndTodo(quartzJob.getStationCode(),
                                            map.get("resultId").toString(), quartzJob.getDeviceSumnum(),
                                            quartzJob.getTaskTodoId());
                                }
                            }

                        } catch (Exception e) {
                            log.error(String.format("单条任务执行失败，任务名称:%s,时间：%s", jobName, DateUtil.now()));
                            e.printStackTrace();
                            log.error(e.getMessage());;
                            try {
                                // 解除摄像头的工作状态
                                todoTaskService.updatePatrolDeviceState(map.get("stationCode").toString(), map.get(
                                        "rtspDeviceCode").toString(), "0");
                                String flag = "4";
                                if ("获取摄像头截图失败".equals(e.getMessage())) {
                                    flag = "6";
                                }
                                todoTaskService.updateTaskResultStatus(quartzJob.getTaskTodoId(), map.get("resultId").toString(), "", flag);
                            } catch (Exception e1) {
                                log.error("====================单条任务失败================");
                                log.error(e1.getMessage());
                            }

                        }

                    }

                });
            }

            // 关闭线程池并等待所有任务完成
            executorService.shutdown();
            // 等待所有任务完成，这里不设置超时时间，也可以根据需要设置超时时间
            executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
            //9 当前巡视任务完成后，恢复暂停的任务
            if (!isFlag.get()) {
                todoTaskService.resumeLowerTask(quartzJob.getStationCode(), quartzJob.getTaskTodoId(),
                        quartzJob.getPriority(), quartzJob.getCustom3());
            }

            // 更新任务进度
            todoTaskService.update(new LambdaUpdateWrapper<TaskTodo>().eq(TaskTodo::getTaskTodoId, taskTodo.getTaskTodoId()).set(TaskTodo::getTaskProgress, "100").set(TaskTodo::getTaskState, "1").set(TaskTodo::getEndTime, DateUtil.now()));
            // 更新任务进度
            taskResultMapper.update(null, new LambdaUpdateWrapper<TaskResult>().eq(TaskResult::getTaskTodoId, taskTodo.getTaskTodoId()).eq(TaskResult::getFlag, "0").set(TaskResult::getFlag, "1"));
            log.info("=======================执行点位数量=========================" + number);
            // 任务执行完判断如果是周期任务看是否还存在没生成完的任务，接着后面生成一条
            taskService.createOnceTodoTask(taskTodo.getTaskId());
            long endTime = System.currentTimeMillis();
            long times = endTime - startTime;
            // 10-记录任务执行日志
            TaskDolog taskDolog = new TaskDolog();
            taskDolog.setId(IdUtil.fastSimpleUUID());
            taskDolog.setStationCode(quartzJob.getStationCode());
            taskDolog.setTaskCode(quartzJob.getTaskCode());
            taskDolog.setTaskName(quartzJob.getTaskName());
            taskDolog.setTaskTodoid(quartzJob.getTaskTodoId());
            if (_interrupted) {
                taskDolog.setDoType("系统中断任务");
            } else {
                taskDolog.setDoType("系统执行任务");
            }
            taskDolog.setPlanStartTime(quartzJob.getPlanStartTime());
            taskDolog.setDoStartTime(DateUtil.formatDateTime(DateUtil.date(startTime)));
            taskDolog.setDoTotalTime(String.format("%.1f", times * 1.0 / 1000));
            taskDolog.setLogger(quartzJob.getLastmodifier());
            taskDolog.setLogTime(new Timestamp(DateUtil.current()));
            taskDolog.setDescription(String.format("任务执行完毕[%s];共耗时：%s秒;任务名称:%s;任务ID:%s", DateUtil.now(),
                    String.format("%.1f", times * 1.0 / 1000), jobName, quartzJob.getTaskTodoId()));
            todoTaskService.recordTaskDoLog(taskDolog);

            log.info(String.format("任务执行完毕[%s];共耗时：%s秒;任务名称:%s;任务ID:%s", DateUtil.now(), String.format("%" +
                    ".1f", times * 1.0 / 1000), jobName, quartzJob.getTaskTodoId()));
            log.info(
                    "--------------------------------------------------------------------------------------------------------------");
        } catch (Exception e) {
            log.error(String.format("任务执行失败[%s];任务名称:%s;任务ID:%s;", DateUtil.now(), jobName,
                    quartzJob.getTaskTodoId()));
        }
    }

    @Override
    public void interrupt() throws UnableToInterruptJobException {
        _interrupted = true;
    }
}
