package com.mvc.service.taizhang;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.mvc.constant.BaseConstant;
import com.mvc.constant.DeviceReportInfo;
import com.mvc.constant.DeviceType;
import com.mvc.constant.TaskStatus;
import com.mvc.dao.TaskRemoteCfgMapper;
import com.mvc.entity.TaskRemoteCfg;
import com.mvc.entity.TaskRemoteCfgExample;
import com.mvc.iot.IotStoreBlockingQueue;
import com.mvc.iot.IotTaskStatus;
import com.mvc.model.*;
import com.mvc.netty.dealconstant.TaskRemoteIdentifier;
import com.mvc.service.TServerCfgService;
import com.mvc.service.temp.TempServerIdenCfgService;
import com.mvc.utils.DateUtil;
import com.mvc.utils.NumberUtil;
import com.mvc.utils.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Service
@Transactional
public class TaskRemoteCfgService {
    @Resource
    private TaskRemoteCfgMapper taskRemoteCfgMapper;

    @Resource
    private TTaskDownService tTaskDownService;

    @Resource
    private StationAccService stationAccService;

    @Resource
    private DeviceAccService deviceAccService;

    @Resource
    private TAicbqCfgService tAicbqCfgService;

    @Resource
    private TempServerIdenCfgService tempServerIdenCfgService;

    @Resource
    private TServerCfgService serverCfgService;

    //忽略的校验项(在验证前台有没有配置时使用,防止没有配置任何一项就提交了)
    private final String IGNORED_FIELDS = "id,taskId,deviceSn,createMan,createTime,finishedFlag,finishedTime,page,rows,createTimeStart,createTimeEnd,stationName,deviceType,batchFlag";

    public Map<String, Object> findAllTaskRemoteCfg(TaskRemoteCfgModel queryModel) {
        Map<String, Object> resMap = new HashMap<>();
        Page<Object> pageObject = PageHelper.startPage(queryModel.getPage(), queryModel.getRows());

        TaskRemoteCfgExample example = new TaskRemoteCfgExample();
        TaskRemoteCfgExample.Criteria criteria = example.createCriteria();
        if (!io.netty.util.internal.StringUtil.isNullOrEmpty(queryModel.getDeviceSn())) {
            if (queryModel.getDeviceSn().length() == BaseConstant.LENGTH_DEVICE_SN) {
                criteria.andDeviceSnEqualTo(queryModel.getDeviceSn());
            } else {
                criteria.andDeviceSnLike(StringUtil.getLikeFormat(queryModel.getDeviceSn()));
            }
        }
        if (!io.netty.util.internal.StringUtil.isNullOrEmpty(queryModel.getStationCode())) {
            if (queryModel.getStationCode().length() == BaseConstant.LENGTH_STATION_CODE) {
                criteria.andStationCodeEqualTo(queryModel.getStationCode());
            } else {
                criteria.andStationCodeLike(StringUtil.getLikeFormat(queryModel.getStationCode()));
            }
        }
        if (!io.netty.util.internal.StringUtil.isNullOrEmpty(queryModel.getFinishedFlag()) &&
                !queryModel.getFinishedFlag().equals("9")) {
            criteria.andFinishedFlagEqualTo(queryModel.getFinishedFlag());
        }

        if (queryModel.getCreateTimeStart() != null) {
            criteria.andCreateTimeGreaterThan(queryModel.getCreateTimeStart());
        }

        if (queryModel.getCreateTimeEnd() != null) {
            criteria.andCreateTimeLessThan(queryModel.getCreateTimeEnd());
        }

        //APP按创建人查询 2022-07-18 guozhao
        if (!io.netty.util.internal.StringUtil.isNullOrEmpty(queryModel.getCreateMan())) {
            criteria.andCreateManLike(StringUtil.getLikeFormat(queryModel.getCreateMan()));
        }

        if (StringUtils.isNotEmpty(queryModel.getDeviceType())) {
            criteria.andDeviceTypeEqualTo(queryModel.getDeviceType());
        }

        criteria.andBatchFlagNotEqualTo("1");//过滤掉批量任务的暂存记录 2022-10-13 guozhao
        example.setOrderByClause("CREATE_TIME desc");

        List<TaskRemoteCfg> TaskRemoteCfgs = taskRemoteCfgMapper.selectByExample(example);
        List<TaskRemoteCfgModel> resList = new ArrayList<>();
        for (TaskRemoteCfg TaskRemoteCfg : TaskRemoteCfgs) {
            TaskRemoteCfgModel model = new TaskRemoteCfgModel();
            BeanUtils.copyProperties(TaskRemoteCfg, model);
            //遥测站台账中不再记录 deviceSN,因此注释掉了 2024-03-14 guozhao
            /*StationAccModel accModel = stationAccService.findStationAccByDeviceSn(model.getDeviceSn());
            if (accModel != null) {
                model.setStationName(accModel.getStationName());
            }*/
            model = getOecByPgManualConfig(model);
            getWITaskSpecdate(model);
            getLogUploadRules(model);
            getImageConfig(model);
            resList.add(model);
        }
        resMap.put("total", pageObject.getTotal());
        resMap.put("list", resList);
        return resMap;
    }

    public TaskRemoteCfgModel saveTaskRemoteCfg(TaskRemoteCfgModel model) {
        DeviceAccModel accModel = deviceAccService.findDeviceAccBysn(model.getDeviceSn());

        if (accModel != null) {
            //服务侧识别设备,单独处理 2025-07-23
            if (model.getCfgType() != null && model.getCfgType() == 2 && accModel.getDeviceType().equals(DeviceType.SERVER_SIDE.getCode())) {
                return saveServerCfgByModel(model);
            }

            model.setDeviceType(accModel.getDeviceType());
            //IOT平台注册的设备
            if (StringUtils.isNotEmpty(accModel.getIotType()) && StringUtils.isNotEmpty(accModel.getIotDeviceId())) {
                model.setIotType(accModel.getIotType());
                model.setIotDeviceId(accModel.getIotDeviceId());
            } else {
                model.setIotType("0");
            }

        }
        handleDataByDialType(model);
        model.setUpInterval(model.getSampleInterval());
        model.setTaskId(StringUtil.getUuid());
        model.setCreateTime(new Date());
        model.setFinishedFlag(TaskStatus.NOT_EXECUTED.getCode());
        model.setBatchFlag("0");
        setUnitType0718(model);//版本过度,特殊处理
        String pgManualConfig = getPgManualConfigByOec(model);
        if (StringUtils.isNotEmpty(pgManualConfig)) {
            model.setPgManualConfig(pgManualConfig);
        }

        setWITaskSpecdate(model);
        setLogUploadRules(model);
        setImageConfig(model);
        TaskRemoteCfg TaskRemoteCfg = new TaskRemoteCfg();
        BeanUtils.copyProperties(model, TaskRemoteCfg);
        int insert = taskRemoteCfgMapper.insert(TaskRemoteCfg);
        model.setId(TaskRemoteCfg.getId());
        addTTaskDown(model);

        tempServerIdenCfgService.saveTempServerIdenCfg(model);
        //加入IOT命令处理队列 2024-10-16 guozhao
        if (insert > 0 && accModel != null && model.getIotType() != null && model.getIotType().equals("1")) {
            try {
                model.setIotCommandType(1);
                model.setDeviceAccModel(accModel);
                IotStoreBlockingQueue.iotCommandQueue.put(model);
            } catch (Exception e) {

            }
        }
        return model;
    }

    private TaskRemoteCfgModel saveServerCfgByModel(TaskRemoteCfgModel model) {
        TServerCfgModel serverCfgModel = new TServerCfgModel();
        BeanUtils.copyProperties(model, serverCfgModel);
        serverCfgModel = serverCfgService.saveTServerCfg(serverCfgModel);
        BeanUtils.copyProperties(serverCfgModel, model);
        return model;
    }

    /**
     * 特殊处理:由于MCU侧程序数据类型的变化,导致升级新版本后,如果只配置初值,不配置尾数单位,配置的存储区会乱
     * 处理方法:只改了初值,没有改尾数单位,系统自动添加上尾数单位
     * 2023-07-18 guozhao
     */
    private void setUnitType0718(TaskRemoteCfgModel model) {
        if (model.getLastVal() != null && model.getUnitType() == null) {
            TAicbqCfgModel cfgModel = tAicbqCfgService.findTAicbqCfgModel(model.getDeviceSn(), "", "1");
            if (cfgModel != null) {
                model.setUnitType(cfgModel.getUnitType());
            }
        }
    }

    public TaskRemoteCfgModel updateTaskRemoteCfg(TaskRemoteCfgModel model) {
        TaskRemoteCfg taskRemoteCfg = taskRemoteCfgMapper.selectByPrimaryKey(model.getId());

        if (taskRemoteCfg == null) {
            return null;
        }

        boolean isCancel = false;
        //状态改为取消了 2025-03-13 guozhao
        if (taskRemoteCfg.getFinishedFlag().equals(TaskStatus.NOT_EXECUTED.getCode()) &&
                model.getFinishedFlag().equals(TaskStatus.CANCELLED.getCode())) {
            isCancel = true;
            model.setFinishedTime(new Date());
        }

        model.setUpInterval(model.getSampleInterval());//采样与上报现在是统一的。
        model.setPgManualConfig(getPgManualConfigByOec(model));
        setWITaskSpecdate(model);
        setLogUploadRules(model);
        setImageConfig(model);
        BeanUtils.copyProperties(model, taskRemoteCfg);
        int i = taskRemoteCfgMapper.updateByPrimaryKey(taskRemoteCfg);
        if (i > 0 && isCancel) {//取消时同步一下状态
            tTaskDownService.updateFinishedFlagByTaskRemoteCfg(model);
            tempServerIdenCfgService.saveTempServerIdenCfg(model);
        }

        return model;
    }

    public int deleteTaskRemoteCfg(int id) {
        TaskRemoteCfg entity = taskRemoteCfgMapper.selectByPrimaryKey(id);

        //IOT平台只执行取消,不删除 2024-10-16 guozhao
        if (StringUtils.isNotEmpty(entity.getIotTaskId())) {
            TaskRemoteCfgModel model = new TaskRemoteCfgModel();
            BeanUtils.copyProperties(entity, model);
            model.setIotCommandType(2);

            entity.setFinishedFlag(BaseConstant.VALID_FLAG);
            entity.setFinishedTime(new Date());
            entity.setIotTaskStatus(IotTaskStatus.CANCELED.getCode());
            taskRemoteCfgMapper.updateByPrimaryKey(entity);
            try {
                IotStoreBlockingQueue.iotCommandQueue.put(model);
            } catch (Exception e) {

            }
        } else {
            //删除远程配置任务时,同时删除下行任务表中的数据
            if (entity != null) {
                tTaskDownService.deleteTTaskDownByTaskid(entity.getTaskId());
            }
            int i = taskRemoteCfgMapper.deleteByPrimaryKey(id);
            return i;
        }

        return 0;
    }

    /**
     * 根据taskId删除记录
     *
     * @param taskId
     * @return
     */
    public int deleteTaskRemoteCfgByTaskId(String taskId) {
        TaskRemoteCfgExample example = new TaskRemoteCfgExample();
        TaskRemoteCfgExample.Criteria criteria = example.createCriteria();
        criteria.andTaskIdEqualTo(taskId);
        return taskRemoteCfgMapper.deleteByExample(example);
    }

    public String getHexaskRemoteCfg(TaskRemoteCfgModel cfg) {
        String data = "";

        //后面全部使用sb拼接,开始写的时间不太规范(后面统一改为TaskRemoteIdentifier,不要写死0228..) 2024-04-12 guozhao
        StringBuilder sb = new StringBuilder();
        //遥测站地址
        if (StringUtils.isNotEmpty(cfg.getStationCode())) {
            data += "0228" + cfg.getStationCode();
        }
        //ip1-port1
        if (StringUtils.isNotEmpty(cfg.getIp1Port1())) {
            String ip1port1 = cfg.getIp1Port1();
            if (ip1port1.equals("0")) {//如果只配了一个数字0,代表不向此IP发送了,但协议还是要按IP格式
                ip1port1 = "0.0.0.0:0";
            }
            String[] split1 = ip1port1.split(":");
            String[] split2 = split1[0].split("\\.");

            String value1 = ("000" + split2[0]).substring(("000" + split2[0]).length() - 3, ("000" + split2[0]).length());
            String value2 = ("000" + split2[1]).substring(("000" + split2[1]).length() - 3, ("000" + split2[1]).length());
            String value3 = ("000" + split2[2]).substring(("000" + split2[2]).length() - 3, ("000" + split2[2]).length());
            String value4 = ("000" + split2[3]).substring(("000" + split2[3]).length() - 3, ("000" + split2[3]).length());
            String value5 = ("000000" + split1[1]).substring(("000000" + split1[1]).length() - 6, ("000000" + split1[1]).length());
            data += "045000" + value1 + value2 + value3 + value4 + value5;

            //新设备是配置是否启用智慧院平台,而APP没有这一项,在此特殊处理,如果配置了IP1,就自动加一个智慧院平台配置项,端口是0代表不启用,否则启用 2024-07-26 guozhao
            if (StringUtils.isEmpty(cfg.getEnableSendBjzhy())) {
                if (split1[1].equals(BaseConstant.INVALID_FLAG)) {
                    cfg.setEnableSendBjzhy(BaseConstant.INVALID_FLAG);
                } else {
                    cfg.setEnableSendBjzhy(BaseConstant.VALID_FLAG);
                }
            }
        }
        //ip2-port2(ip2和ip3不再需要配置了)
        if (StringUtils.isNotEmpty(cfg.getIp2Port2())) {
            String ip1port1 = cfg.getIp2Port2();
            String[] split1 = ip1port1.split(":");
            String[] split2 = split1[0].split("\\.");
            String value1 = ("000" + split2[0]).substring(("000" + split2[0]).length() - 3, ("000" + split2[0]).length());
            String value2 = ("000" + split2[1]).substring(("000" + split2[1]).length() - 3, ("000" + split2[1]).length());
            String value3 = ("000" + split2[2]).substring(("000" + split2[2]).length() - 3, ("000" + split2[2]).length());
            String value4 = ("000" + split2[3]).substring(("000" + split2[3]).length() - 3, ("000" + split2[3]).length());
            String value5 = ("000000" + split1[1]).substring(("000000" + split1[1]).length() - 6, ("000000" + split1[1]).length());
            data += "065000" + value1 + value2 + value3 + value4 + value5;
        }
        //ip3-port3(ip2和ip3不再需要配置了)
        if (StringUtils.isNotEmpty(cfg.getIp3Port3())) {
            String ip1port1 = cfg.getIp3Port3();
            String[] split1 = ip1port1.split(":");
            String[] split2 = split1[0].split("\\.");
            String value1 = ("000" + split2[0]).substring(("000" + split2[0]).length() - 3, ("000" + split2[0]).length());
            String value2 = ("000" + split2[1]).substring(("000" + split2[1]).length() - 3, ("000" + split2[1]).length());
            String value3 = ("000" + split2[2]).substring(("000" + split2[2]).length() - 3, ("000" + split2[2]).length());
            String value4 = ("000" + split2[3]).substring(("000" + split2[3]).length() - 3, ("000" + split2[3]).length());
            String value5 = ("000000" + split1[1]).substring(("000000" + split1[1]).length() - 6, ("000000" + split1[1]).length());
            data += "085000" + value1 + value2 + value3 + value4 + value5;
        }
        //ip14-port4(ip4没有使用过)
        if (StringUtils.isNotEmpty(cfg.getIp4Port4())) {
            String ip1port1 = cfg.getIp4Port4();
            String[] split1 = ip1port1.split(":");
            String[] split2 = split1[0].split("\\.");
            String value1 = ("000" + split2[0]).substring(("000" + split2[0]).length() - 3, ("000" + split2[0]).length());
            String value2 = ("000" + split2[1]).substring(("000" + split2[1]).length() - 3, ("000" + split2[1]).length());
            String value3 = ("000" + split2[2]).substring(("000" + split2[2]).length() - 3, ("000" + split2[2]).length());
            String value4 = ("000" + split2[3]).substring(("000" + split2[3]).length() - 3, ("000" + split2[3]).length());
            String value5 = ("000000" + split1[1]).substring(("000000" + split1[1]).length() - 6, ("000000" + split1[1]).length());
            data += "0A5000" + value1 + value2 + value3 + value4 + value5;
        }
        //水表类型
        if (cfg.getDnType() != null) {
            String value = "000" + cfg.getDnType().intValue();
            data += "1010" + value.substring(value.length() - 4);
        }
        //水表数字 个数和轮子个数？？？？？必须得同时修改
        //规则改变(全配置模式下允许全数字或全指针的) 2025-05-14 guozhao
        if (cfg.getDigitNum() != null || cfg.getWheelNum() != null) {
            int dignum = cfg.getDigitNum() == null ? 0 : cfg.getDigitNum().intValue();
            int wheelnum = cfg.getWheelNum() == null ? 0 : cfg.getWheelNum().intValue();
            int value = dignum << 4 | wheelnum;
            data += "1108" + NumberUtil.numToHex8(value);
        }
        //水表数字最后一位单位
        if (cfg.getUnitType() != null) {
            String value = "0" + cfg.getUnitType();
            data += "1208" + value.substring(value.length() - 2);
        }
        //水表安装方向
        if (StringUtils.isNotEmpty(cfg.getSetupDir())) {
            String value = "0" + cfg.getSetupDir();
            data += "1308" + value.substring(value.length() - 2);
        }
        //采样时间间隔  2位
        if (cfg.getSampleInterval() != null) {
            String value = "000" + cfg.getSampleInterval();
            data += "1410" + value.substring(value.length() - 4);
        }
        //上传服务器时间间隔   2位        //2位 2022-06-27 guozhao
        if (cfg.getUpInterval() != null) {
            String value = "000" + cfg.getUpInterval();
            data += "1510" + value.substring(value.length() - 4);
        }
        //低温采样时间间隔 1位
        if (cfg.getLtSampleInterval() != null) {
            String value = "0" + cfg.getLtSampleInterval();
            data += "1608" + value.substring(value.length() - 2);
        }
        //最低工作温度 高字节=1代表正数，=0代表负数，低字节代表温度数
        if (cfg.getWorkLt() != null) {
            if (cfg.getWorkLt().intValue() < 0) {
                String value = "0" + cfg.getWorkLt().intValue() * (-1);
                data += "171000" + value.substring(value.length() - 2);
            } else {
                String value = "0" + cfg.getWorkLt().intValue();
                data += "171001" + value.substring(value.length() - 2);
            }
        }
        //安装年份
        if (StringUtils.isNotEmpty(cfg.getSetupYear())) {
            data += "1810" + cfg.getSetupYear();
        }
        //入网超时时间  1位
        if (cfg.getNetworkRegTimeout() != null) {
            String value = "0" + cfg.getNetworkRegTimeout().intValue();
            data += "1908" + value.substring(value.length() - 2);
        }
        //电池报警电量
        if (cfg.getBatAlarmSoc() != null) {
            String value = "0" + cfg.getBatAlarmSoc().intValue();
            data += "1A08" + value.substring(value.length() - 2);
        }
        //强拉回值概率值
        if (cfg.getAiPullBack() != null) {
            String value = "0" + cfg.getAiPullBack().intValue();
            data += "1B08" + value.substring(value.length() - 2);
        }
        //识别概率阀值
        if (cfg.getAiPass() != null) {
            String value = "0" + cfg.getAiPass().intValue();
            data += "1C08" + value.substring(value.length() - 2);
        }
        //位概率阀值
        if (cfg.getAiSinglePass() != null) {
            String value = "0" + cfg.getAiSinglePass().intValue();
            data += "1D08" + value.substring(value.length() - 2);
        }
        //最高工作温度 高字节=1代表正数，=0代表负数，低字节代表温度数
        if (cfg.getWorkHt() != null) {
            if (cfg.getWorkHt().intValue() < 0) {
                String value = "0" + cfg.getWorkHt().intValue() * (-1);
                data += "1E1000" + value.substring(value.length() - 2);
            } else {
                String value = "0" + cfg.getWorkHt().intValue();
                data += "1E1001" + value.substring(value.length() - 2);
            }
        }
        //电压报警值
        if (cfg.getBatAlarmVt() != null) {
            int v = cfg.getBatAlarmVt().multiply(new BigDecimal(100)).intValue();
            String value = "0000" + v;
            data += "1F12" + value.substring(value.length() - 4);
        }
        //CPU版本号？？？
        if (StringUtils.isNotEmpty(cfg.getCpuVersion())) {
            String value = "000" + cfg.getCpuVersion();
            data += "B110" + value.substring(value.length() - 4);
        }
        //通讯板版本号？？、
        if (StringUtils.isNotEmpty(cfg.getTongxunVersion())) {
            String value = "000" + cfg.getTongxunVersion();
            data += "B210" + value.substring(value.length() - 4);
        }
        //天线类型
        if (StringUtils.isNotEmpty(cfg.getTianxianType())) {
            data += "B308" + "0" + cfg.getTianxianType();
        }
        //背光频率
        if (cfg.getPwmHz() != null) {
            String value = "000" + cfg.getPwmHz();
            data += "B410" + value.substring(value.length() - 4);
        }
        //占空比
        if (cfg.getPwmDuty() != null) {
            String value = "000" + cfg.getPwmDuty();
            data += "B510" + value.substring(value.length() - 4);
        }
        //灯光灯亮范围 2字节 高字节最小值，低两字节最大值
        if (cfg.getFlashBrightMax() != null && cfg.getFlashBrightMin() != null) {
            String max = "0000" + cfg.getFlashBrightMax().intValue();
            String min = "0000" + cfg.getFlashBrightMin().intValue();
            max = max.substring(max.length() - 4);
            min = min.substring(min.length() - 4);
            data += "B620" + min + max;
        }
        //通讯方式数传类型
        if (StringUtils.isNotEmpty(cfg.getTongxunWay())) {
            data += "B708" + "0" + cfg.getTongxunWay();
        }
        //水表当前读数
        if (cfg.getLastVal() != null) {
            //兼容全配置模式 2025-03-10 guozhao
            if (cfg.getLastValTime() == null) {
                String value = "0000000000" + cfg.getLastVal().intValue();
                data += "BA28" + value.substring(value.length() - 10);
            } else {
                String lastValue = StringUtils.leftPad(String.valueOf(cfg.getLastVal().intValue()), 10, "0");
                String timeValue = DateUtil.formateDate(cfg.getLastValTime(), "yyMMddHHmm");
                sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EE95, lastValue + timeValue));
            }
        }
        //整图报周规则
        if (StringUtils.isNotEmpty(cfg.getUpWholeImgWeekRule())) {
            int a = NumberUtil.binaryToDecimal(cfg.getUpWholeImgWeekRule());
            data += "BB08" + NumberUtil.numToHex8(a);
        }

        //域名地址 2022-08-03 guozhao
        if (StringUtils.isNotEmpty(cfg.getDomainNamePort())) {
            String[] arrDomain = cfg.getDomainNamePort().split(":");
            if (arrDomain.length == 2 && StringUtils.isNotEmpty(arrDomain[0]) && StringUtils.isNumeric(arrDomain[1])) {
                byte[] dz = arrDomain[0].getBytes(StandardCharsets.US_ASCII);
                byte[] dk = NumberUtil.intTo2bytes(Integer.parseInt(arrDomain[1]));
                byte[] bytes = new byte[30];
                System.arraycopy(dz, 0, bytes, 0, dz.length);
                System.arraycopy(dk, 0, bytes, 28, dk.length);
                String domain = NumberUtil.bytesToHexStr(bytes);
                data += "BCF0" + domain;
            } else {
                System.out.println("[" + cfg.getDeviceSn() + "]远程配置域名格式错误");
            }
        }

        //是否运行串口输出日志信息
        if (cfg.getIsprintcomlog() != null) {
            data += "BD08" + "0" + cfg.getIsprintcomlog();
        }

        //WDT计数清零
        if (cfg.getIsresetwdt() != null) {
            data += "BE08" + "0" + cfg.getIsresetwdt();
        }

        //手动触发发送大图开关
        if (StringUtils.isNotEmpty(cfg.getWiTaskManwakeupFlag())) {
            data += "D1080" + cfg.getWiTaskManwakeupFlag();
        }
        //月初月底发送大图开关
        if (StringUtils.isNotEmpty(cfg.getWiTaskMonthFlag())) {
            data += "D2080" + cfg.getWiTaskMonthFlag();
        }
        //指定日期发送大图
        if (StringUtils.isNotEmpty(cfg.getWiTaskSpecdateFlag())) {
            data += "D330" + cfg.getWiTaskSpecdateFlag();
        }
        //日志上传规则
        if (StringUtils.isNotEmpty(cfg.getLogUploadRules())) {
            data += "BF40" + cfg.getLogUploadRules();
        }
        //是否上传上一次MCU通讯错误的日志
        if (StringUtils.isNotEmpty(cfg.getUploadLastFailLogFlag())) {
            data += "D4080" + cfg.getUploadLastFailLogFlag();
        }
        //手动触发发送本次工作日志
        if (StringUtils.isNotEmpty(cfg.getLogTaskManwakeupFlag())) {
            data += "D5080" + cfg.getLogTaskManwakeupFlag();
        }
        data += getPgConfigString(cfg);
        sb.append(data);
        /** 2022-11-08 guozhao 添加开始 */
        //上传的图片类型
        if (cfg.getImageType() != null) {
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEDA, cfg.getImageType().toString()));
        }

        //图片像素外扩
        if (cfg.getImageMargin() != null) {
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEDB, cfg.getImageMargin().toString()));
        }
        //人工配置值启用标志、旋转角度、数字区域坐标
        if (StringUtils.isNotEmpty(cfg.getImageConfig())) {
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEDC, cfg.getImageConfig()));
        }

        //是否上传模型输出结果
        if (StringUtils.isNotEmpty(cfg.getUploadCnnFlag())) {
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEDD, cfg.getUploadCnnFlag()));
        }

        //是否上传模型输出结果
        if (cfg.getNmsThreshold() != null) {
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEDE, cfg.getNmsThreshold().toString()));
        }
        /** 2022-11-08 guozhao 添加结束 */

        /** 2022-11-15 guozhao 添加开始 */
        //是否使用检测到的大框来排除野数字
        if (StringUtils.isNotEmpty(cfg.getIsUseDetectedNum())) {
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEDF, cfg.getIsUseDetectedNum()));
        }
        /** 2022-11-15 guozhao 添加结束 */

        /** 2024-04-12 guozhao 添加开始 */
        if (cfg.getRsPortEnable() != null) {//RS485使能开关
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EE80, cfg.getRsPortEnable().toString()));
        }
        if (cfg.getRsBandRate() != null) {//RS485波特率
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EE81, cfg.getRsBandRate().toString()));
        }
        if (cfg.getRsChecksumType() != null) {//RS485校验类型
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EE84, cfg.getRsChecksumType().toString()));
        }
        if (cfg.getRsStopbitType() != null) {//RS485停止位
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EE85, cfg.getRsStopbitType().toString()));
        }
        if (cfg.getModuleId() != null) {//模块ID
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EE82, cfg.getModuleId()));
        }
        if (cfg.getModuleName() != null) {//模块名称
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EE83, cfg.getModuleName()));
        }
        if (cfg.getImageBrightness() != null) {//图像亮度(1位整数1位小数)
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEA0, cfg.getImageBrightness().toString()));
        }
        if (cfg.getImageSynthesisType() != null) {//图像合成方式
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEA1, cfg.getImageSynthesisType().toString()));
        }
        /** 2024-04-12 guozhao 添加结束*/

        /** 2024-04-24 guozhao 添加开始 */
        if (cfg.getFirsttxntimeDaily() != null) {//日首次采样时间
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEA2, cfg.getFirsttxntimeDaily().toString()));
        }
        if (cfg.getUploadImageSize() != null) {//上传图片的大小
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEA3, cfg.getUploadImageSize().toString()));
        }
        if (StringUtils.isNotEmpty(cfg.getEnableAiImageProcess())) {//AI输出测试(标注)图开关
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEA4, cfg.getEnableAiImageProcess()));
        }
        if (StringUtils.isNotEmpty(cfg.getEnableNoconfigManualConfig())) {//是否使用人工配置的参数用于AI识别过程
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEA5, cfg.getEnableNoconfigManualConfig()));
        }
        if (StringUtils.isNotEmpty(cfg.getDisableAiRecognition())) {//禁用AI识别
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEA6, cfg.getDisableAiRecognition()));
        }
        if (cfg.getMaxDiscreteDuration() != null) {//最大离散时长范围
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEA7, cfg.getMaxDiscreteDuration().toString()));
        }
        if (StringUtils.isNotEmpty(cfg.getEnableDiscrete())) {//启用离散标志
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEA8, cfg.getEnableDiscrete()));
        }
        if (StringUtils.isNotEmpty(cfg.getEnableSendBjzhy())) {//启用智慧院平台
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEA9, cfg.getEnableSendBjzhy()));
        }
        if (StringUtils.isNotEmpty(cfg.getEnableSendBjzls())) {//启用北京自来水平台
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEAA, cfg.getEnableSendBjzls()));
        }
        if (StringUtils.isNotEmpty(cfg.getBjzlsMeterAddress())) {//水表地址
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEF0, cfg.getBjzlsMeterAddress()));
        }
        if (StringUtils.isNotEmpty(cfg.getBjzlsEnableAes())) {//启用AES加密
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEF1, cfg.getBjzlsEnableAes()));
        }
        if (StringUtils.isNotEmpty(cfg.getIsResetData())) {//恢复数据
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEFA, cfg.getIsResetData()));
        }
        if (StringUtils.isNotEmpty(cfg.getIsUploadRedPointer())) {//是否上传红色指针部分
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEAB, cfg.getIsUploadRedPointer()));
        }
        if (StringUtils.isNotEmpty(cfg.getBjzlsSecretKeyType())) {//北京自来水平台密钥类型
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEF2, cfg.getBjzlsSecretKeyType()));
        }
        if (cfg.getNoconfigSetupAngle() != null) {//人工配置角度
            String value = cfg.getNoconfigSetupAngle().toString();
            String temp;
            if (cfg.getNoconfigSetupAngle() < 0) {
                temp = "00";
                value = value.substring(1);
            } else {
                temp = "01";
            }
            value = StringUtils.leftPad(value, 4, "0");//MCU要求是固定长度 2024-06-25 guozhao
            temp = temp + (value.length() % 2 == 0 ? value : StringUtils.leftPad(value, value.length() + 1, "0"));
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEAC, temp));
        }
        if (StringUtils.isNotEmpty(cfg.getDigitalPosition())) {//数字位置
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEAD, cfg.getDigitalPosition()));
        }
        if (cfg.getAiDigitalZoomFactor() != null) {//数字表放大倍率
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEAE, cfg.getAiDigitalZoomFactor().toString()));
        }
        if (cfg.getAiPointerZoomFactor() != null) {//指针表放大倍率
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EEAF, cfg.getAiPointerZoomFactor().toString()));
        }
        /** 2024-04-24 guozhao 添加结束*/
        sb.append(getServerAIConfigString(cfg));

        /** 针对全配置模式 2025-03-07 guozhao 添加开始*/
        if (StringUtils.isNotEmpty(cfg.getOperationStatus())) {//投运类型
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EE90, cfg.getOperationStatus()));
        }
        if (StringUtils.isNotEmpty(cfg.getDialType())) {//水表类型
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EE91, cfg.getDialType()));
        }
        if (StringUtils.isNotEmpty(cfg.getDialAreaCoordinates())) {//表盘区域坐标
            String value = StringUtil.convertCoordinateString(cfg.getDialAreaCoordinates());
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EE92, value));
        }
        if (StringUtils.isNotEmpty(cfg.getDigitAreaCoordinates())) {//数字区域坐标
            String value = StringUtil.convertCoordinateString(cfg.getDigitAreaCoordinates());
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EE93, value));
        }
        if (StringUtils.isNotEmpty(cfg.getStartEndPointerCoordinates())) {//首尾指针坐标
            String value = StringUtil.convertCoordinateString(cfg.getStartEndPointerCoordinates());
            sb.append(TaskRemoteIdentifier.getIdentifierMsg(TaskRemoteIdentifier.EE94, value));
        }
        /** 2025-03-07 guozhao 添加结束*/

        return sb.toString();
    }

    /**
     * 生成压力表配置项远程报文
     *
     * @param cfg
     */
    private String getPgConfigString(TaskRemoteCfgModel cfg) {
        String data = "";
        //压力表量程范围下限(可以负数)
        if (cfg.getPgRangeMin() != null) {
            String flag = cfg.getPgRangeMin().compareTo(new BigDecimal(0)) < 0 ? "00" : "01";

            BigDecimal min = cfg.getPgRangeMin().abs().multiply(new BigDecimal(100000));
            String strMin = "00000000000000" + min.stripTrailingZeros().toPlainString();
            data += "C145" + flag + strMin.substring(strMin.length() - 14);
        }

        //压力表量程范围上限(可以负数)
        if (cfg.getPgRangeMax() != null) {
            String flag = cfg.getPgRangeMax().compareTo(new BigDecimal(0)) < 0 ? "00" : "01";

            BigDecimal max = cfg.getPgRangeMax().abs().multiply(new BigDecimal(100000));
            String strMax = "00000000000000" + max.stripTrailingZeros().toPlainString();

            data += "C245" + flag + strMax.substring(strMax.length() - 14);
        }

        //压力表数据精度类型(0-4)(代表小数位数)
        if (cfg.getPgPrecisionType() != null) {
            data += "C308" + "0" + cfg.getPgPrecisionType();
        }

        //压力表系统校正参数(共8字节,首字节0为负数，1为正数)
        if (cfg.getPgCorrectvalue() != null) {
            String flag = cfg.getPgCorrectvalue().compareTo(new BigDecimal(0)) < 0 ? "00" : "01";

            BigDecimal value = cfg.getPgCorrectvalue().abs().multiply(new BigDecimal(100000));
            String strValue = "00000000000000" + value.stripTrailingZeros().toPlainString();

            data += "C445" + flag + strValue.substring(strValue.length() - 14);
        }

        //压力表坐标点赋值
        if (StringUtils.isNotEmpty(cfg.getPgManualConfig())) {
            data += "C560" + cfg.getPgManualConfig();
        }

        //压力表图片是否描点
        if (StringUtils.isNotEmpty(cfg.getPgIsDebug())) {
            data += "C608" + (cfg.getPgIsDebug().equals("1") ? "01" : "00");
        }

        //压力表目标区域历史数据初始化
        if (StringUtils.isNotEmpty(cfg.getPgInitTargetRegion())) {
            data += "C708" + (cfg.getPgInitTargetRegion().equals("1") ? "01" : "00");
        }

        //电池使用时长清零
        if (StringUtils.isNotEmpty(cfg.getIsresetbat()) && cfg.getIsresetbat().equals("1")) {
            data += "B80801";
        }

        //MCU使用次数清零
        if (StringUtils.isNotEmpty(cfg.getIsrestmcu()) && cfg.getIsrestmcu().equals("1")) {
            data += "B90801";
        }

        //压力表人工配置坐标点的优先级
        if (StringUtils.isNotEmpty(cfg.getPgManualConfigLevel())) {
            data += "C8080" + cfg.getPgManualConfigLevel();
        }

        return data;
    }

    /**
     * 获取服务器识别水表的配置报文串
     *
     * @param cfg
     * @return
     */
    private String getServerAIConfigString(TaskRemoteCfgModel cfg) {
        StringBuffer sb = new StringBuffer();
        if (StringUtils.isNotEmpty(cfg.getRegionImageType())) {
            String value = StringUtils.leftPad(cfg.getRegionImageType(), 2, '0');
            sb.append(TaskRemoteIdentifier.EE71.getKey());
            int len = (value.length() / 2) << 3;
            String lenFlag = NumberUtil.numToHex8(len);
            sb.append(lenFlag);
            sb.append(value);
        }
        if (StringUtils.isNotEmpty(cfg.getJpgCompressType())) {
            String value = StringUtils.leftPad(cfg.getJpgCompressType(), 2, '0');
            sb.append(TaskRemoteIdentifier.EE71.getKey());
            int len = (value.length() / 2) << 3;
            String lenFlag = NumberUtil.numToHex8(len);
            sb.append(lenFlag);
            sb.append(value);
        }
        return sb.toString();
    }

    /**
     * 根据taskid删除记录
     *
     * @param taskid
     * @return
     */
    public int deleteTaskRemoteCfgByTaskid(String taskid) {
        TaskRemoteCfgExample example = new TaskRemoteCfgExample();
        TaskRemoteCfgExample.Criteria criteria = example.createCriteria();
        criteria.andTaskIdEqualTo(taskid);
        return taskRemoteCfgMapper.deleteByExample(example);
    }

    /**
     * 根据专项配置ID删除记录
     *
     * @param specialCfgId
     * @return
     */
    public int deleteTaskRemoteCfgBySpecialCfgId(Integer specialCfgId) {
        TaskRemoteCfgExample example = new TaskRemoteCfgExample();
        TaskRemoteCfgExample.Criteria criteria = example.createCriteria();
        criteria.andSpecialCfgIdEqualTo(specialCfgId);
        return taskRemoteCfgMapper.deleteByExample(example);
    }

    /**
     * 根据SN查询是否已经存在未执行的远程配置任务
     *
     * @param deviceSn
     * @return
     */
    public boolean existTaskRemoteCfgSameFlag(String deviceSn) {
        TaskRemoteCfgExample example = new TaskRemoteCfgExample();
        TaskRemoteCfgExample.Criteria criteria = example.createCriteria();
        criteria.andDeviceSnEqualTo(deviceSn);
        criteria.andFinishedFlagEqualTo(TaskStatus.NOT_EXECUTED.getCode());
        List<TaskRemoteCfg> taskRemoteCfgs = taskRemoteCfgMapper.selectByExample(example);

        return taskRemoteCfgs != null && taskRemoteCfgs.size() > 0;
    }

    /**
     * 根据设备SN列表获取未执行的任务列表
     *
     * @param list
     * @return
     */
    public List<TaskRemoteCfg> getUnexecutedTasksForDevices(List<String> list) {
        TaskRemoteCfgExample example = new TaskRemoteCfgExample();
        TaskRemoteCfgExample.Criteria criteria = example.createCriteria();
        criteria.andDeviceSnIn(list);
        criteria.andFinishedFlagEqualTo(TaskStatus.NOT_EXECUTED.getCode());

        return taskRemoteCfgMapper.selectByExample(example);
    }

    /**
     * 根据主键获取对象
     *
     * @param id
     * @return
     */
    public TaskRemoteCfgModel findTaskRemoteCfgById(int id) {
        TaskRemoteCfgModel model = null;
        TaskRemoteCfg entity = taskRemoteCfgMapper.selectByPrimaryKey(id);
        if (entity != null) {
            model = new TaskRemoteCfgModel();
            BeanUtils.copyProperties(entity, model);
        }
        return model;
    }

    /**
     * 根据任务ID(子表、明细表的业务主键)查询下行任务对象
     *
     * @param taskid
     * @return
     */
    public TaskRemoteCfgModel findTaskRemoteCfgByTaskid(String taskid) {
        TaskRemoteCfgExample example = new TaskRemoteCfgExample();
        TaskRemoteCfgExample.Criteria criteria = example.createCriteria();
        criteria.andTaskIdEqualTo(taskid);
        List<TaskRemoteCfg> taskRemoteCfgs = taskRemoteCfgMapper.selectByExample(example);

        if (taskRemoteCfgs != null && taskRemoteCfgs.size() > 0) {
            TaskRemoteCfgModel model = new TaskRemoteCfgModel();
            BeanUtils.copyProperties(taskRemoteCfgs.get(0), model);
            return model;
        }
        return null;
    }

    /**
     * 新增下行数据任务(在新增远程配置任务时,自动创建下行任务记录)
     *
     * @param model
     */
    private TTaskDownModel addTTaskDown(TaskRemoteCfgModel model) {
        TTaskDownModel taskDownModel = new TTaskDownModel();
        //taskDownModel.setTaskDownId(model.getTaskId());
        taskDownModel.setTaskType("2");                             //任务类型:远程配置
        taskDownModel.setTaskId(model.getTaskId());
        taskDownModel.setDeviceSn(model.getDeviceSn());

        taskDownModel.setStationCode(model.getStationCode());
        taskDownModel.setCreateMan(model.getCreateMan());
        taskDownModel.setCreateTime(model.getCreateTime());
        taskDownModel.setTaskLevel(3);                              //任务等级(紧急,配置相对优先)

        //下行任务表的站代码,不来源于远程配置表,远程配置表不是依赖项(只在远程修改站代码时才有值)
        StationAccModel accModel = stationAccService.findStationAccByDeviceSn(model.getDeviceSn());
        if (accModel != null) {
            taskDownModel.setStationCode(accModel.getStationCode());
        } else {
            taskDownModel.setStationCode("0000000000");     //支持通过仅SN配置 2022-07-21 guozhao
        }

        return tTaskDownService.saveTTaskDown(taskDownModel);
    }

    //前台提交的压力表6个坐标点合并到一个串中
    private String getPgManualConfigByOec(TaskRemoteCfgModel model) {
        String pgManualConfig = "";

        if (model.getOriginx() == null && model.getOriginy() == null &&
                model.getEndx() == null && model.getEndy() == null &&
                model.getCenterx() == null && model.getCentery() == null) {
            return pgManualConfig;
        }

        String temp = "0000" + model.getOriginx().intValue();
        pgManualConfig += temp.substring(temp.length() - 4);

        temp = "0000" + model.getOriginy().intValue();
        pgManualConfig += temp.substring(temp.length() - 4);

        temp = "0000" + model.getEndx().intValue();
        pgManualConfig += temp.substring(temp.length() - 4);

        temp = "0000" + model.getEndy().intValue();
        pgManualConfig += temp.substring(temp.length() - 4);

        temp = "0000" + model.getCenterx().intValue();
        pgManualConfig += temp.substring(temp.length() - 4);

        temp = "0000" + model.getCentery().intValue();
        pgManualConfig += temp.substring(temp.length() - 4);

        return pgManualConfig;
    }

    //将数据库中存储的24位坐标串,转换到对象中的6个坐标点
    private TaskRemoteCfgModel getOecByPgManualConfig(TaskRemoteCfgModel model) {
        if (StringUtils.isNotEmpty(model.getPgManualConfig()) && model.getPgManualConfig().length() == 24) {
            String pgManualConfigCol = "";
            for (int i = 0; i < model.getPgManualConfig().length(); i += 4) {
                String temp = model.getPgManualConfig().substring(i, i + 4);
                if (i == 0) {
                    model.setOriginx(Integer.parseInt(temp));
                    pgManualConfigCol += (temp + ",");
                } else if (i == 4) {
                    model.setOriginy(Integer.parseInt(temp));
                    pgManualConfigCol += (temp + " | ");
                } else if (i == 8) {
                    model.setEndx(Integer.parseInt(temp));
                    pgManualConfigCol += (temp + ",");
                } else if (i == 12) {
                    model.setEndy(Integer.parseInt(temp));
                    pgManualConfigCol += (temp + " | ");
                } else if (i == 16) {
                    model.setCenterx(Integer.parseInt(temp));
                    pgManualConfigCol += (temp + ",");
                } else if (i == 20) {
                    model.setCentery(Integer.parseInt(temp));
                    pgManualConfigCol += (temp);
                }
            }
            model.setPgManualConfigCol(pgManualConfigCol);
        }
        return model;
    }

    //大图上传规则---前台分割的对象转到一个字段中
    private void setWITaskSpecdate(TaskRemoteCfgModel model) {
        if (StringUtils.isNotEmpty(model.getWiTaskSpecdateEnable())) {
            String msg = "";
            msg += StringUtil.leftPad(model.getWiTaskSpecdateEnable(), 2, '0');
            String date = "";
            if (StringUtils.isEmpty(model.getWiTaskSpecdateDate()) || model.getWiTaskSpecdateDate().length() != 8) {
                date = DateUtil.formateDate(new Date(), "yyMMdd");
            } else {
                date = model.getWiTaskSpecdateDate().substring(2);
            }
            msg += date;
            msg += StringUtil.leftPad(model.getWiTaskSpecdateDays() + "", 2, '0');
            msg += StringUtil.leftPad(model.getWiTaskSpecdateTimes() + "", 2, '0');
            model.setWiTaskSpecdateFlag(msg);
        }
    }

    //大图上传规则---一个字段分割到前台所需要的多个字段
    public void getWITaskSpecdate(TaskRemoteCfgModel model) {
        if (StringUtils.isNotEmpty(model.getWiTaskSpecdateFlag()) && model.getWiTaskSpecdateFlag().length() == 12) {
            String msg = model.getWiTaskSpecdateFlag();
            model.setWiTaskSpecdateEnable(Integer.parseInt(msg.substring(0, 2)) + "");

            Date date = DateUtil.parseTimeStr(msg.substring(2, 8), "yyMMdd");
            String wiTaskSpecdateDate = DateUtil.formateDate(date, "yyyyMMdd");
            model.setWiTaskSpecdateDate(wiTaskSpecdateDate);
            model.setWiTaskSpecdateDays(Integer.parseInt(msg.substring(8, 10)));
            model.setWiTaskSpecdateTimes(Integer.parseInt(msg.substring(10)));
        }
    }

    //日志上传规则---将前台多个属性合并到一个字段中
    private void setLogUploadRules(TaskRemoteCfgModel model) {
        if (StringUtils.isNotEmpty(model.getLogUploadEnable())) {
            if (model.getLogUploadMcuLevel() == null) {//MCU日志等级默认值
                model.setLogUploadMcuLevel(0);
            }
            if (model.getLogUploadAiLevel() == null) {//AI日志等级默认值
                model.setLogUploadAiLevel(0);
            }
            String msg = "";
            msg += StringUtil.leftPad(model.getLogUploadEnable(), 2, '0');
            if (StringUtils.isEmpty(model.getLogUploadRules()) || model.getLogUploadRules().length() != 8) {
                model.setLogUploadRules(DateUtil.formateDate(new Date(), "yyMMdd"));
            }
            String date = "";
            if (StringUtils.isEmpty(model.getLogUploadDate()) || model.getLogUploadDate().length() != 8) {
                date = DateUtil.formateDate(new Date(), "yyMMdd");
            } else {
                date = model.getLogUploadDate().substring(2);
            }
            msg += date;
            msg += StringUtil.leftPad(model.getLogUploadDays() + "", 2, '0');
            msg += StringUtil.leftPad(model.getLogUploadTimes() + "", 2, '0');
            msg += StringUtil.leftPad(model.getLogUploadMcuLevel() + "", 2, '0');
            msg += StringUtil.leftPad(model.getLogUploadAiLevel() + "", 2, '0');
            model.setLogUploadRules(msg);
        }
    }

    //日志上传规则---为前台将一个字段分割到多个属性中
    public void getLogUploadRules(TaskRemoteCfgModel model) {
        if (StringUtils.isNotEmpty(model.getLogUploadRules()) && model.getLogUploadRules().length() == 16) {
            String msg = model.getLogUploadRules();
            model.setLogUploadEnable(Integer.parseInt(msg.substring(0, 2)) + "");

            Date date = DateUtil.parseTimeStr(msg.substring(2, 8), "yyMMdd");
            String logUploadDate = DateUtil.formateDate(date, "yyyyMMdd");
            model.setLogUploadDate(logUploadDate);

            model.setLogUploadDays(Integer.parseInt(msg.substring(8, 10)));
            model.setLogUploadTimes(Integer.parseInt(msg.substring(10, 12)));
            model.setLogUploadMcuLevel(Integer.parseInt(msg.substring(12, 14)));
            model.setLogUploadAiLevel(Integer.parseInt(msg.substring(14)));
        }
    }

    //坐标人工配置值---将前台的多个值合并到一个字段中
    private void setImageConfig(TaskRemoteCfgModel model) {
        if (StringUtils.isEmpty(model.getImageConfigFlag())) return;
        StringBuilder sb = new StringBuilder();
        sb.append(StringUtil.leftPad(model.getImageConfigFlag(), 2, '0'));
        if (model.getImageConfigFlag().equals("1")) {//启用
            sb.append(model.getImageLeanAngle() < 0 ? "00" : "01");
            sb.append(StringUtil.leftPad(Math.abs(model.getImageLeanAngle()) + "", 4, '0'));
            sb.append(StringUtil.leftPad(model.getImageNumRegionXMin().toString(), 4, '0'));
            sb.append(StringUtil.leftPad(model.getImageNumRegionYMin().toString(), 4, '0'));
            sb.append(StringUtil.leftPad(model.getImageNumRegionXMax().toString(), 4, '0'));
            sb.append(StringUtil.leftPad(model.getImageNumRegionYMax().toString(), 4, '0'));
        } else {//禁用(禁用状态下,其它类型的值不再是必写项)
            sb.append(model.getImageLeanAngle() == null || model.getImageLeanAngle() < 0 ? "00" : "01");
            sb.append(model.getImageLeanAngle() == null ? "0000" : StringUtil.leftPad(model.getImageNumRegionXMin().toString(), 4, '0'));
            sb.append(model.getImageNumRegionXMin() == null ? "0000" : StringUtil.leftPad(model.getImageNumRegionXMin().toString(), 4, '0'));
            sb.append(model.getImageNumRegionYMin() == null ? "0000" : StringUtil.leftPad(model.getImageNumRegionYMin().toString(), 4, '0'));
            sb.append(model.getImageNumRegionXMax() == null ? "0000" : StringUtil.leftPad(model.getImageNumRegionXMax().toString(), 4, '0'));
            sb.append(model.getImageNumRegionYMax() == null ? "0000" : StringUtil.leftPad(model.getImageNumRegionYMax().toString(), 4, '0'));
        }

        model.setImageConfig(sb.toString());
    }

    //坐标人工配置值---为前台将一个字段分割到多个中
    private void getImageConfig(TaskRemoteCfgModel model) {
        if (StringUtils.isEmpty(model.getImageConfig()) || model.getImageConfig().length() != 24) return;
        String imageConfig = model.getImageConfig();
        model.setImageConfigFlag(Integer.valueOf(imageConfig.substring(0, 2)).toString());
        int sign = Integer.valueOf(imageConfig.substring(2, 4)) == 0 ? -1 : 1;
        model.setImageLeanAngle(sign * Integer.valueOf(imageConfig.substring(4, 8)));
        model.setImageNumRegionXMin(Integer.valueOf(imageConfig.substring(8, 12)));
        model.setImageNumRegionYMin(Integer.valueOf(imageConfig.substring(12, 16)));
        model.setImageNumRegionXMax(Integer.valueOf(imageConfig.substring(16, 20)));
        model.setImageNumRegionYMax(Integer.valueOf(imageConfig.substring(20)));
    }

    /**
     * 检查是否存在有效的配置项
     *
     * @param model
     * @return
     */
    public boolean checkConfigItem(TaskRemoteCfgModel model) {
        Class cls = model.getClass();
        Field[] fields = cls.getDeclaredFields();
        try {
            int num = 0;
            for (Field field : fields) {
                String name = field.getName();
                if (!IGNORED_FIELDS.contains(name)) {
                    field.setAccessible(true);
                    Object value = field.get(model);

                    if (value != null && StringUtils.isNotEmpty(value + "")) {
                        num++;
                    }
                }
            }
            return num > 0;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 检查数据合法性
     *
     * @param model
     * @return
     */
    public String checkDataLegitimacy(TaskRemoteCfgModel model, boolean isAdd) {
        if (isAdd) {
            if (deviceAccService.findDeviceAccBysn(model.getDeviceSn()) == null) {
                return "台账中不存在此设备[" + model.getDeviceSn() + "]";
            }

            if (existTaskRemoteCfgSameFlag(model.getDeviceSn())) {
                return "当前设备存在未执行的任务";
            }
        }

        if (StringUtils.isNotEmpty(model.getIp1Port1())) {
            if (!StringUtil.isIPAndPort(model.getIp1Port1())) {
                return "通道1地址不合法";
            }
        }

        if (!checkConfigItem(model)) {//防止不配任何项 2022.10.10 guozhao
            return "未配置任何项";
        }

        if (StringUtils.isNotEmpty(model.getWiTaskSpecdateEnable())) {
            if (StringUtils.isEmpty(model.getWiTaskSpecdateDate())) {
                return "指定日期发大图的[开始日期]不合法";
            }
            if (model.getWiTaskSpecdateDays() == null || model.getWiTaskSpecdateDays() < 1) {
                return "指定日期发大图的[持续天数]不合法";
            }
            if (model.getWiTaskSpecdateTimes() == null || model.getWiTaskSpecdateTimes() < 1) {
                return "指定日期发大图的[每天次数]不合法";
            }
        }

        if (StringUtils.isNotEmpty(model.getLogUploadEnable())) {
            if (StringUtils.isEmpty(model.getLogUploadDate())) {
                return "日志上传规则的[开始日期]不合法";
            }
            if (model.getLogUploadDays() == null || model.getLogUploadDays() < 1) {
                return "日志上传规则的[持续天数]不合法";
            }
            if (model.getLogUploadTimes() == null || model.getLogUploadTimes() < 1) {
                return "日志上传规则的[每天次数]不合法";
            }
            if (model.getLogUploadMcuLevel() == null) {
                return "日志上传规则的[MCU日志等级]不合法";
            }
            if (model.getLogUploadAiLevel() == null) {
                return "日志上传规则的[AI日志等级]不合法";
            }
            if (model.getLogUploadMcuLevel() == model.getLogUploadAiLevel() && model.getLogUploadAiLevel() == 0) {
                return "日志上传规则的[MCU日志等级]和[AI日志等级]不能同时为不上传";
            }
        }

        if (model.getImageType() != null) {
            int imageType = model.getImageType();
            if (imageType < 1 || (imageType > 1 && imageType < 1800) || imageType > 20000) {
                return "上传图片类型,值应该=1或(>=1800且<20000)";
            }
        }

        if (StringUtils.isNotEmpty(model.getImageConfigFlag())) {
            if (model.getImageConfigFlag().equals("1")) {
                Integer region = model.getImageLeanAngle();
                if (region == null || region < -360 || region > 360) {
                    return "指定数字区域的[转换角度]不合法(-360,360)";
                }
                region = model.getImageNumRegionXMin();
                if (region == null || region < 0 || (region > 319 && region != 333)) {
                    return "指定数字区域的[XMin]坐标不合法(0-319|333)";
                }
                region = model.getImageNumRegionYMin();
                if (region == null || region < 0 || (region > 239 && region != 333)) {
                    return "指定数字区域的[YMin]坐标不合法(0-239|333)";
                }
                region = model.getImageNumRegionXMax();
                if (region == null || region < 0 || (region > 319 && region != 333)) {
                    return "指定数字区域的[XMax]坐标不合法(0-319|333)";
                }
                region = model.getImageNumRegionYMax();
                if (region == null || region < 0 || (region > 239 && region != 333)) {
                    return "指定数字区域的[YMax]坐标不合法(0-239|333)";
                }
            }
        }

        //对新加的配置项进行校验  2024-04-26 guozhao
        if (model.getImageBrightness() != null && (model.getImageBrightness() < 1 || model.getImageBrightness() > 2)) {
            return "图片亮度取值范围[1.0-2.0]";
        }

        if (model.getUploadImageSize() != null && (model.getUploadImageSize() < 10 || model.getUploadImageSize() > 50)) {
            return "上传图片大小取值范围[10-50]";
        }
        if (model.getFirsttxntimeDaily() != null && (model.getFirsttxntimeDaily() < 0 || model.getFirsttxntimeDaily() > 23)) {
            return "日首次采样时间取值范围[0-23]";
        }
        if (model.getMaxDiscreteDuration() != null) {
            if (model.getMaxDiscreteDuration() < 0 || model.getMaxDiscreteDuration() > 24) {
                return "最大离散时长范围[0-24]";
            }
            if (model.getSampleInterval() != null && model.getMaxDiscreteDuration() * 60 > model.getSampleInterval()) {
                return "最大离散时长范围不可超过采样间隔";
            }
        }

        //对启用人工配置参数进行校验 2024-06-13 guozhao
        if (model.getEnableNoconfigManualConfig() != null && model.getEnableNoconfigManualConfig().equals("1")) {
            if (model.getDigitNum() == null || model.getWheelNum() == null || model.getUnitType() == null || model.getDnType() == null || model.getLastVal() == null) {
                return "启用人工配置参数后,数字个数、字轮个数、尾数单位、设备口径、当前读数均需要填写";
            }
        }
        if (model.getNoconfigSetupAngle() != null) {
            if ((model.getNoconfigSetupAngle() < -360 || model.getNoconfigSetupAngle() > 360) && model.getNoconfigSetupAngle() != 888) {
                return "安装角度范围[-360至360]或888";
            }
        }

        if (model.getAiDigitalZoomFactor() != null) {
            if (model.getAiDigitalZoomFactor() < 0 || model.getAiDigitalZoomFactor() > 9.9) {
                return "数字表放大倍率范围[0-9.9]";
            }
        }

        if (model.getAiPointerZoomFactor() != null) {
            if (model.getAiPointerZoomFactor() < 0 || model.getAiPointerZoomFactor() > 9.9) {
                return "指针表放大倍率范围[0-9.9]";
            }
        }

        return null;
    }

    /**
     * 保存远程配置记录(批量模块使用)
     *
     * @param model
     * @return
     */
    public TaskRemoteCfgModel saveTaskRemoteCfg_Batch(TaskRemoteCfgModel model) {
        //TaskId存的是TaskBatchRemote表中的taskBatchId

        if (model.getSampleInterval() != null && model.getUpInterval() == null) {//统一采样间隔和上传间隔 2022-10-25 guozhao
            model.setUpInterval(model.getSampleInterval());
        }
        if (model.getUpInterval() != null && model.getSampleInterval() == null) {
            model.setSampleInterval(model.getUpInterval());
        }

        setWITaskSpecdate(model);
        setLogUploadRules(model);
        setImageConfig(model);

        model.setCreateTime(new Date());
        model.setFinishedFlag(TaskStatus.NOT_EXECUTED.getCode());
        model.setBatchFlag("1");
        TaskRemoteCfg TaskRemoteCfg = new TaskRemoteCfg();
        BeanUtils.copyProperties(model, TaskRemoteCfg);
        int insert = taskRemoteCfgMapper.insert(TaskRemoteCfg);
        model.setId(TaskRemoteCfg.getId());
        return model;
    }

    /**
     * 获取远程配置记录(批量任务模块使用)
     *
     * @param taskId
     * @return
     */
    public TaskRemoteCfgModel findTaskRemoteCfg_Batch(String taskId) {
        TaskRemoteCfgExample example = new TaskRemoteCfgExample();
        TaskRemoteCfgExample.Criteria criteria = example.createCriteria();
        criteria.andTaskIdEqualTo(taskId);

        List<TaskRemoteCfg> taskRemoteCfgs = taskRemoteCfgMapper.selectByExample(example);
        TaskRemoteCfgModel model = new TaskRemoteCfgModel();
        for (TaskRemoteCfg TaskRemoteCfg : taskRemoteCfgs) {
            BeanUtils.copyProperties(TaskRemoteCfg, model);
            getWITaskSpecdate(model);
            getLogUploadRules(model);
            getImageConfig(model);
        }
        return model;
    }

    /**
     * 添加远程任务,并返回生成的下行任务对象
     *
     * @param model
     * @return
     */
    public TTaskDownModel addTaskRemoteCfg(TaskRemoteCfgModel model) {
        model.setTaskId(StringUtil.getUuid());
        model.setFinishedFlag(TaskStatus.NOT_EXECUTED.getCode());
        model.setBatchFlag("0");
        String pgManualConfig = getPgManualConfigByOec(model);
        if (StringUtils.isNotEmpty(pgManualConfig)) {
            model.setPgManualConfig(pgManualConfig);
        }

        setWITaskSpecdate(model);
        setLogUploadRules(model);
        setImageConfig(model);
        TaskRemoteCfg TaskRemoteCfg = new TaskRemoteCfg();
        BeanUtils.copyProperties(model, TaskRemoteCfg);
        TaskRemoteCfg.setId(null);
        int insert = taskRemoteCfgMapper.insert(TaskRemoteCfg);
        model.setId(TaskRemoteCfg.getId());
        return addTTaskDown(model);
    }

    /**
     * 根据SN获取未执行的远程任务
     *
     * @param deviceSn
     * @return
     */
    public TaskRemoteCfgModel findUnfinishedTaskByDeviceSn(String deviceSn) {
        TaskRemoteCfgExample example = new TaskRemoteCfgExample();
        TaskRemoteCfgExample.Criteria criteria = example.createCriteria();
        criteria.andDeviceSnEqualTo(deviceSn);
        criteria.andFinishedFlagEqualTo(TaskStatus.NOT_EXECUTED.getCode());
        criteria.andBatchFlagNotEqualTo("1");
        List<TaskRemoteCfg> taskRemoteCfgs = taskRemoteCfgMapper.selectByExample(example);
        if (taskRemoteCfgs != null && taskRemoteCfgs.size() > 0) {
            TaskRemoteCfgModel model = new TaskRemoteCfgModel();
            BeanUtils.copyProperties(taskRemoteCfgs.get(0), model);
            return model;
        }
        return null;
    }

    /**
     * 更新IOT任务状态
     *
     * @param iotTaskId
     * @param status
     * @return
     */
    public Integer updateIotTaskStatus(String iotTaskId, String status) {
        TaskRemoteCfgExample example = new TaskRemoteCfgExample();
        TaskRemoteCfgExample.Criteria criteria = example.createCriteria();
        criteria.andIotTaskIdEqualTo(iotTaskId);

        List<TaskRemoteCfg> taskRemoteCfgs = taskRemoteCfgMapper.selectByExample(example);
        if (taskRemoteCfgs.size() > 0) {
            TaskRemoteCfg taskRemoteCfg = taskRemoteCfgs.get(0);
            taskRemoteCfg.setIotTaskStatus(status);
            return taskRemoteCfgMapper.updateByPrimaryKey(taskRemoteCfg);
        }
        return 0;
    }

    /**
     * 根据专项配置更新远程配置任务
     *
     * @param model
     * @return
     */
    public boolean updateTaskRemoteCfgByTaskSpecialCfg(TaskSpecialCfgModel model) {
        TaskRemoteCfgExample example = new TaskRemoteCfgExample();
        TaskRemoteCfgExample.Criteria criteria = example.createCriteria();
        criteria.andSpecialCfgIdEqualTo(model.getId());
        List<TaskRemoteCfg> taskRemoteCfgs = taskRemoteCfgMapper.selectByExample(example);
        if (taskRemoteCfgs.size() > 0) {
            TaskRemoteCfg taskRemoteCfg = taskRemoteCfgs.get(0);
            if (taskRemoteCfg.getFinishedFlag().equals(BaseConstant.VALID_FLAG)) {
                return false;//已经完成了
            }
            taskRemoteCfg.setDeviceSn(model.getDeviceSn());
            taskRemoteCfg.setStationCode(model.getDeviceSn().substring(1));
            //taskRemoteCfg.setCpuVersion(model.getCpuVersion());//
            return taskRemoteCfgMapper.updateByPrimaryKey(taskRemoteCfg) > 0;
        }
        return false;
    }

    /**
     * 根据表盘类型处理数据
     * 前端在切换水表类型时,没有清空上一类型的数据(因为Null赋值问题)
     *
     * @param model
     */
    private void handleDataByDialType(TaskRemoteCfgModel model) {
        if (StringUtils.isEmpty(model.getDialType())) {
            return;
        }

        DeviceReportInfo deviceReportInfo = DeviceReportInfo.findDeviceReportInfoByCode(model.getDialType());
        if (deviceReportInfo == DeviceReportInfo.DIGITAL_AND_POINTER) {//数字+指针表
            model.setStartEndPointerCoordinates(null);
        } else if (deviceReportInfo == DeviceReportInfo.FULL_POINTER) {//全指针表
            model.setDigitNum(null);
            model.setDigitAreaCoordinates(null);
        } else if (deviceReportInfo == DeviceReportInfo.FULL_DIGITAL) {//全数字表
            model.setWheelNum(null);
            model.setStartEndPointerCoordinates(null);
        }
    }
}
