package cn.cecep.talroad.service.impl.analysis;

import cn.cecep.talroad.common.core.domain.R;
import cn.cecep.talroad.common.core.utils.DateUtils;
import cn.cecep.talroad.common.core.utils.StringUtils;
import cn.cecep.talroad.domain.AmProblemFi;
import cn.cecep.talroad.domain.BasDeviceParam;
import cn.cecep.talroad.domain.BasThresholdConfig;
import cn.cecep.talroad.enums.ProblemTypeEnum;
import cn.cecep.talroad.enums.ThresHoldConfigEnum;
import cn.cecep.talroad.service.IAmProblemFiService;
import cn.cecep.talroad.service.IBasDeviceParamService;
import cn.cecep.talroad.service.IBasDeviceService;
import cn.cecep.talroad.service.IBasThresholdConfigService;
import cn.cecep.talroad.service.IMonDevBlRealService;
import cn.cecep.talroad.service.IMonDevDlRealService;
import cn.cecep.talroad.service.IMonDevFsRealService;
import cn.cecep.talroad.service.IMonDevJhRealService;
import cn.cecep.talroad.service.IMonDevRealService;
import cn.cecep.talroad.service.IMonDevSnRealService;
import cn.cecep.talroad.service.analysis.IFacilityAnalysisService;
import cn.cecep.talroad.vo.BasDeviceParamVo;
import cn.cecep.talroad.vo.FactoryDeviceVo;
import cn.cecep.talroad.vo.analysis.AvgValueVo;
import cn.cecep.talroad.vo.analysis.PumpStateVo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @Auther: cjh
 * @Date: 2023-06-02 10:04
 * @Class: IFacilityAnalysisServiceImpl
 * @Deseription: 治理设施分析服务
 * @Version V1.0
 */
@Service
public class IFacilityAnalysisServiceImpl implements IFacilityAnalysisService {

    @Autowired
    private IMonDevFsRealService monDevFsRealService;
    @Autowired
    private IMonDevDlRealService monDevDlRealService;
    @Autowired
    private IMonDevBlRealService monDevBlRealService;
    @Autowired
    private IMonDevRealService monDevRealService;
    @Autowired
    private IMonDevJhRealService monDevJhRealService;
    @Autowired
    private IMonDevSnRealService monDevSnRealService;
    @Autowired
    private IBasDeviceService basDeviceService;
    @Autowired
    private IBasThresholdConfigService basThresholdConfigService;
    @Autowired
    private IAmProblemFiService amProblemFiService;
    @Autowired
    private IBasDeviceParamService basDeviceParamService;

    @Override
    public void analysisPhData() {
        List<AmProblemFi> alarmList = new ArrayList<>();
        Date curr = new Date();
        Date lastDay = DateUtils.addDateDays(curr,-1);
        Date lastDayBegin = DateUtils.parseFormatDate("yyyy-MM-dd 00:00:00",lastDay);
        Date lastDayEnd = DateUtils.parseFormatDate("yyyy-MM-dd 23:59:59",lastDay);
        BasThresholdConfig minConfig = basThresholdConfigService.selectByParamCode(ThresHoldConfigEnum.PH01.getCode());
        BasThresholdConfig maxConfig = basThresholdConfigService.selectByParamCode(ThresHoldConfigEnum.PH01.getCode());
        BigDecimal minValue = minConfig.getThresholdValue();
        BigDecimal maxValue = maxConfig.getThresholdValue();

        List<AvgValueVo> blList = monDevBlRealService.selectAvgPhByParams(lastDayBegin,lastDayEnd);
        doProcessAlarmData(blList,alarmList,curr,minValue,maxValue,"脱硫洗涤塔pH值","bz103");
        List<AvgValueVo> dlList = monDevDlRealService.selectAvgPhByParams(lastDayBegin,lastDayEnd);
        doProcessAlarmData(dlList,alarmList,curr,minValue,maxValue,"脱硫吸收剂pH值","hz103");
        List<AvgValueVo> fsList = monDevFsRealService.selectAvgPhByParams(lastDayBegin,lastDayEnd);
        doProcessAlarmData(fsList,alarmList,curr,minValue,maxValue,"脱硫吸收塔内浆液pH值","fz104");

        // 批量保存报警
        this.doSaveBatchAlarm(alarmList);
    }

    @Override
    public void analysisPumpStateData() {
        List<AmProblemFi> alarmList = new ArrayList<>();
        Date curr = new Date();
        Date lastHour = DateUtils.addDateHours(curr,-1);
        Date lastHourBegin = DateUtils.parseFormatDate("yyyy-MM-dd HH:00:00",lastHour);
        Date lastHourEnd = DateUtils.parseFormatDate("yyyy-MM-dd HH:59:59",lastHour);

        List<PumpStateVo> blList = monDevBlRealService.selectPumpStateByParams(lastHourBegin,lastHourEnd);
        doProcessAlarmData(blList,alarmList,curr,"脱硫浆液循环泵运行状态","bz106");
        List<PumpStateVo> dlList = monDevDlRealService.selectPumpStateByParams(lastHourBegin,lastHourEnd);
        doProcessAlarmData(dlList,alarmList,curr,"脱硫浆液循环泵运行状态","hz107");
        List<PumpStateVo> snList = monDevSnRealService.selectPumpStateByParams(lastHourBegin,lastHourEnd);
        doProcessAlarmData(snList,alarmList,curr,"脱硫浆液循环泵运行状态","sz110");
        List<PumpStateVo> fsList = monDevFsRealService.selectPumpStateByParams(lastHourBegin,lastHourEnd);
        doProcessAlarmData(fsList,alarmList,curr,"脱硫浆液循环泵运行状态","fz106");

        // 批量保存报警
        this.doSaveBatchAlarm(alarmList);
    }

    @Override
    public void analysisOxFanStateData() {
        List<AmProblemFi> alarmList = new ArrayList<>();
        Date curr = new Date();
        Date lastHour = DateUtils.addDateHours(curr,-1);
        Date lastHourBegin = DateUtils.parseFormatDate("yyyy-MM-dd HH:00:00",lastHour);
        Date lastHourEnd = DateUtils.parseFormatDate("yyyy-MM-dd HH:59:59",lastHour);

        List<PumpStateVo> dlList = monDevDlRealService.selectOxFanStateByParams(lastHourBegin,lastHourEnd);
        doProcessAlarmOxFanData(dlList,alarmList,curr,"氧化风机状态","g138");
        List<PumpStateVo> snList = monDevSnRealService.selectOxFanStateByParams(lastHourBegin,lastHourEnd);
        doProcessAlarmElecData(snList,alarmList,curr,"脱硫湿法氧化风机电流","sz111");
        List<PumpStateVo> fsList = monDevFsRealService.selectOxFanStateByParams(lastHourBegin,lastHourEnd);
        doProcessAlarmElecData(fsList,alarmList,curr,"脱硫湿法氧化风机电流","fz105");

        // 批量保存报警
        this.doSaveBatchAlarm(alarmList);
    }

    @Override
    public void analysisScrTemp() {
        List<AmProblemFi> alarmList = new ArrayList<>();
        Date curr = new Date();
        Date lastHour = DateUtils.addDateHours(curr,-1);
        Date lastHourBegin = DateUtils.parseFormatDate("yyyy-MM-dd HH:00:00",lastHour);
        Date lastHourEnd = DateUtils.parseFormatDate("yyyy-MM-dd HH:59:59",lastHour);

        List<AvgValueVo> blList = monDevBlRealService.selectAvgTempByParams(lastHourBegin,lastHourEnd);
        doProcessAlarmTempData(blList,alarmList,lastHour, "反应器入口烟气温度（SCR 艺）","g329");
        List<AvgValueVo> fsList = monDevFsRealService.selectAvgTempByParams(lastHourBegin,lastHourEnd);
        doProcessAlarmTempData(fsList,alarmList,lastHour, "反应器入口烟气温度（SCR 艺）","g335");
        List<AvgValueVo> jhList = monDevJhRealService.selectAvgTempByParams(lastHourBegin,lastHourEnd);
        doProcessAlarmTempData(jhList,alarmList,lastHour, "反应器入口烟气温度（SCR 艺）","jz109");
        List<AvgValueVo> gtList = monDevRealService.selectAvgTempByParams(lastHourBegin,lastHourEnd);
        doProcessAlarmTempData(gtList,alarmList,lastHour, "反应器入口烟气温度（SCR 艺）","g329");

        // 批量保存报警
        this.doSaveBatchAlarm(alarmList);
    }

    @Override
    public void analysisPressOverStand() {
        List<AmProblemFi> alarmList = new ArrayList<>();
        Date curr = new Date();
        Date lastHour = DateUtils.addDateHours(curr,-1);
        Date lastHourBegin = DateUtils.parseFormatDate("yyyy-MM-dd HH:00:00",lastHour);
        Date lastHourEnd = DateUtils.parseFormatDate("yyyy-MM-dd HH:59:59",lastHour);

        List<AvgValueVo> jhList = monDevJhRealService.selectAvgPressByParams(lastHourBegin,lastHourEnd);
        doProcessAlarmPressData(jhList,alarmList,curr);
        List<AvgValueVo> gtList = monDevRealService.selectAvgPressByParams(lastHourBegin,lastHourEnd);
        doProcessAlarmPressData(gtList,alarmList,curr);

        // 批量保存报警
        this.doSaveBatchAlarm(alarmList);
    }

    /**
     * 压差过高报警
     * @param jhList
     * @param alarmList
     * @param curr
     */
    private void doProcessAlarmPressData(List<AvgValueVo> jhList, List<AmProblemFi> alarmList, Date curr) {
        if(jhList!=null&&jhList.size()>0){
            String lastHourStr = DateUtils.parseDateToStr("yyyy-MM-dd HH",curr);
            // 压差比例
            BasThresholdConfig config = basThresholdConfigService.selectByParamCode(ThresHoldConfigEnum.P03.getCode());
            jhList.forEach(real->{
                List<BasDeviceParamVo> paramsList = basDeviceParamService.selectBasDeviceParamByCondition(real.getDeviceId(),Arrays.asList("g318", "g325"));
                if(paramsList!=null&&paramsList.size()>0){
                    //标准压差
                    BigDecimal pressStandDiff = new BigDecimal(0);
                    AtomicReference<BigDecimal> ent = new AtomicReference<>(new BigDecimal(0));
                    AtomicReference<BigDecimal> exit = new AtomicReference<>(new BigDecimal(0));
                    // 获取入口、出口标准压力
                    paramsList.forEach(p->{
                        if("g318".equals(p.getParamCodeSvc())&&p.getNormalValue()!=null){
                            ent.set(p.getNormalValue());
                        }
                        if("g325".equals(p.getParamCodeSvc())&&p.getNormalValue()!=null){
                            exit.set(p.getNormalValue());
                        }
                    });
                    // 入口、出口标准压力不为空
                    if(ent.get().compareTo(new BigDecimal(0))!=0&&exit.get().compareTo(new BigDecimal(0))!=0){
                        pressStandDiff = ent.get().subtract(exit.get()).setScale(2, RoundingMode.HALF_UP).abs();
                    }
                    //标准压差不为0
                    if(pressStandDiff.compareTo(new BigDecimal(0))!=0){
                        // 实际入口、出口压差
                        BigDecimal realPressDiff = real.getAvgValue().subtract(real.getAvgValue2()).setScale(2,RoundingMode.HALF_UP).abs();
                        //求百分比
                        BigDecimal rate = new BigDecimal(1).add(config.getThresholdValue().divide(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP));
                        BigDecimal maxPress = pressStandDiff.multiply(rate);
                        //实际压差大于标准压差25%以上,则生成报警记录
                        if(realPressDiff.compareTo(maxPress)>0){
                            FactoryDeviceVo vo = basDeviceService.selectFactoryDeviceVoByDeviceId(real.getDeviceId());
                            StringBuffer sb = new StringBuffer();
                            sb.append(vo.getDeviceName()).append(lastHourStr).append("脱硝系统进出口压差过高，反应区积灰过多，出口NOX有超标风险，请及时排查。");
                            AmProblemFi problemFi = doProcessAlaram(vo, curr, new Date(), ProblemTypeEnum.SCR_TEMP_ERROR, sb.toString(), "脱硝入口压力,脱硝出口压力", "g318,g325");
                            alarmList.add(problemFi);
                        }
                    }
                }
            });
        }
    }

    /**
     * SCR反应器入口温度过低报警
     * @param blList
     * @param alarmList
     */
    private void doProcessAlarmTempData(List<AvgValueVo> blList,List<AmProblemFi> alarmList,Date curr,String param,String paramProperty) {
        if (blList != null && blList.size() > 0) {
            String lastHourStr = DateUtils.parseDateToStr("yyyy-MM-dd HH",curr);
            blList.forEach(real -> {
                QueryWrapper<BasDeviceParam> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("device_id",real.getDeviceId());
                queryWrapper.eq("param_id",paramProperty);
                queryWrapper.last("limit 1");
                BasDeviceParam params = basDeviceParamService.getOne(queryWrapper);
                if(StringUtils.isNotEmpty(params.getMinValue())&&StringUtils.isNotEmpty(params.getMaxValue())) {
                    BigDecimal minValue = new BigDecimal(params.getMinValue());
                    BigDecimal maxValue = new BigDecimal(params.getMaxValue());
                    // 小时温度均值，小于最小值则生成报警数据
                    if (real.getAvgValue().compareTo(minValue) < 0 ) {
                        FactoryDeviceVo vo = basDeviceService.selectFactoryDeviceVoByDeviceId(real.getDeviceId());
                        StringBuffer sb = new StringBuffer();
                        sb.append(vo.getDeviceName()).append(lastHourStr).append("脱硝系统反应区温度为").append(real.getAvgValue()).append("℃,");
                        sb.append("标准温度为").append(minValue).append("-").append(maxValue).append("℃,当前脱硝系统反应区温度过低，出口NOX有超标风险，请注意排查。");
                        AmProblemFi problemFi = doProcessAlaram(vo, curr, new Date(), ProblemTypeEnum.SCR_TEMP_ERROR, sb.toString(), param, paramProperty);
                        alarmList.add(problemFi);
                    }
                }
            });
        }
    }

    /**
     * 根据氧化风机电流分析-氧化风机运行异常
     * @param snList
     * @param alarmList
     * @param curr
     * @param param
     * @param paramProperty
     */
    private void doProcessAlarmElecData(List<PumpStateVo> snList, List<AmProblemFi> alarmList, Date curr, String param, String paramProperty) {
        if(snList!=null&&snList.size()>0) {
            Date lastHour = DateUtils.addDateHours(curr,-1);
            String lastHourStr = DateUtils.parseDateToStr("yyyy-MM-dd HH",lastHour);
            BasThresholdConfig config = basThresholdConfigService.selectByParamCode(ThresHoldConfigEnum.P02.getCode());
            snList.forEach(real->{
                QueryWrapper<BasDeviceParam> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("device_id",real.getDeviceId());
                queryWrapper.eq("param_id",paramProperty);
                queryWrapper.last("limit 1");
                BasDeviceParam params = basDeviceParamService.getOne(queryWrapper);
                if(params!=null&&StringUtils.isNotEmpty(params.getMinValue())){
                    // 过滤电流大于额定电流的数据条数
                    Map<String,Long> map = snList.stream().filter(r-> r.getStateValue().compareTo(new BigDecimal(params.getMinValue()))>0).collect(Collectors.groupingBy(PumpStateVo::getDeviceId,Collectors.counting()));
                    Map<String,Integer> dCount = new HashMap<>();
                    // 过滤出addiParam不为空，存在多个风机电流信息
                    snList.stream().filter(r->StringUtils.isNotEmpty(r.getAddiParam())).forEach(p->{
                        JSONObject obj = JSONObject.parseObject(p.getAddiParam());
                        // 设备额外风机数量
                        dCount.put(p.getDeviceId(),obj.keySet().size());
                        obj.values().forEach(t->{
                            // 风机电流大于额定电流10%的，放到map集合
                            if(new BigDecimal((String)t).compareTo(new BigDecimal(params.getMinValue()))>0){
                                Long oldV = map.get(p.getDeviceId());
                                if(oldV!=null){
                                    map.put(p.getDeviceId(),oldV+1);
                                }else{
                                    map.put(p.getDeviceId(),1L);
                                }
                            }
                        });
                    });
                    // 遍历所有设备状态为1的判断是否报警
                    map.forEach((d,count)->{
                        FactoryDeviceVo vo = basDeviceService.selectFactoryDeviceVoByDeviceId(d);
                        StringBuffer sb = new StringBuffer();
                        // 额外循环泵的数量
                        Integer pCount = dCount.get(d);
                        if(pCount!=null){
                            if(count<pCount*config.getThresholdValue().intValue()){
                                sb.append(vo.getDeviceName()).append("共有").append(pCount+1).append("台脱硫湿法氧化风机,").append(lastHourStr).append("正常运行的氧化风机不足").append(pCount).append("台，").append("氧化风机停停运将导致不稳定的亚硫酸钙（或亚硫酸氢钙）无法氧化成硫酸盐，降低脱硫效率，请注意排查。");
                            }
                        }else{
                            if(count<config.getThresholdValue().intValue()) {
                                sb.append(vo.getDeviceName()).append("共有1台脱硫湿法氧化风机，").append(lastHourStr).append("正常运行的氧化风机不足1台，").append("氧化风机停停运将导致不稳定的亚硫酸钙（或亚硫酸氢钙）无法氧化成硫酸盐，降低脱硫效率，请注意排查。");
                            }
                        }
                        if(StringUtils.isNotEmpty(sb.toString())) {
                            AmProblemFi problemFi = doProcessAlaram(vo, curr, new Date(), ProblemTypeEnum.OX_ERROR, sb.toString(), param, paramProperty);
                            alarmList.add(problemFi);
                        }
                    });
                }
            });

        }
    }

    /**
     * 分析处理循环泵状态，并生成报警
     * @param blList
     * @param alarmList
     * @param curr
     * @param param
     * @param paramProperty
     */
    private void doProcessAlarmOxFanData(List<PumpStateVo> blList,List<AmProblemFi> alarmList,Date curr,String param,String paramProperty) {
        if(blList!=null && blList.size()>0){
            Date lastHour = DateUtils.addDateHours(curr,-1);
            String lastHourStr = DateUtils.parseDateToStr("yyyy-MM-dd HH",lastHour);
            BasThresholdConfig config = basThresholdConfigService.selectByParamCode(ThresHoldConfigEnum.P02.getCode());
            Map<String,Long> map = blList.stream().filter(r-> r.getStateValue().intValue()==1).collect(Collectors.groupingBy(PumpStateVo::getDeviceId,Collectors.counting()));
            Map<String,Integer> dCount = new HashMap<>();
            // 过滤出addiParam不为空，存在多个循环泵的信息
            blList.stream().filter(r->StringUtils.isNotEmpty(r.getAddiParam())).forEach(p->{
                JSONObject obj = JSONObject.parseObject(p.getAddiParam());
                // 设备循环泵额外的个数
                dCount.put(p.getDeviceId(),obj.keySet().size());
                obj.values().forEach(t->{
                    // 循环泵状态为1的放到map集合
                    if(new BigDecimal((String)t).compareTo(new BigDecimal(1))==0){
                        Long oldV = map.get(p.getDeviceId());
                        if(oldV!=null){
                            map.put(p.getDeviceId(),oldV+1);
                        }else{
                            map.put(p.getDeviceId(),1L);
                        }
                    }
                });
            });

            // 遍历所有设备状态为1的判断是否报警
            map.forEach((d,count)->{
                FactoryDeviceVo vo = basDeviceService.selectFactoryDeviceVoByDeviceId(d);
                StringBuffer sb = new StringBuffer();
                // 额外循环泵的数量
                Integer pCount = dCount.get(d);
                if(pCount!=null){
                    if(count<pCount*config.getThresholdValue().intValue()){
                        sb.append(vo.getDeviceName()).append("共有").append(pCount+1).append("台脱硫湿法氧化风机,").append(lastHourStr).append("正常运行的氧化风机不足").append(pCount).append("台，").append("氧化风机停停运将导致不稳定的亚硫酸钙（或亚硫酸氢钙）无法氧化成硫酸盐，降低脱硫效率，请注意排查。");
                    }
                }else{
                    if(count<config.getThresholdValue().intValue()) {
                        sb.append(vo.getDeviceName()).append("共有1台脱硫湿法氧化风机，").append(lastHourStr).append("正常运行的氧化风机不足1台，").append("氧化风机停停运将导致不稳定的亚硫酸钙（或亚硫酸氢钙）无法氧化成硫酸盐，降低脱硫效率，请注意排查。");
                    }
                }
                if(StringUtils.isNotEmpty(sb.toString())) {
                    AmProblemFi problemFi = doProcessAlaram(vo, curr, new Date(), ProblemTypeEnum.OX_ERROR, sb.toString(), param, paramProperty);
                    alarmList.add(problemFi);
                }
            });
        }
    }

    /**
     * 分析处理循环泵状态，并生成报警
     * @param blList
     * @param alarmList
     * @param curr
     * @param param
     * @param paramProperty
     */
    private void doProcessAlarmData(List<PumpStateVo> blList,List<AmProblemFi> alarmList,Date curr,String param,String paramProperty) {
        if(blList!=null && blList.size()>0){
            Date lastHour = DateUtils.addDateHours(curr,-1);
            String lastHourStr = DateUtils.parseDateToStr("yyyy-MM-dd HH",lastHour);
            BasThresholdConfig config = basThresholdConfigService.selectByParamCode(ThresHoldConfigEnum.P01.getCode());
            Map<String,Long> map = blList.stream().filter(r-> r.getStateValue().intValue()==1).collect(Collectors.groupingBy(PumpStateVo::getDeviceId,Collectors.counting()));
            Map<String,Integer> dCount = new HashMap<>();
            // 过滤出addiParam不为空，存在多个循环泵的信息
            blList.stream().filter(r->StringUtils.isNotEmpty(r.getAddiParam())).forEach(p->{
                JSONObject obj = JSONObject.parseObject(p.getAddiParam());
                // 设备循环泵额外的个数
                dCount.put(p.getDeviceId(),obj.keySet().size());
                obj.values().forEach(t->{
                    // 循环泵状态为1的放到map集合
                    if(new BigDecimal((String)t).compareTo(new BigDecimal(1))==0){
                        Long oldV = map.get(p.getDeviceId());
                        if(oldV!=null){
                            map.put(p.getDeviceId(),oldV+1);
                        }else{
                            map.put(p.getDeviceId(),1L);
                        }
                    }
                });
            });

            // 遍历所有设备状态为1的判断是否报警
            map.forEach((d,count)->{
                FactoryDeviceVo vo = basDeviceService.selectFactoryDeviceVoByDeviceId(d);
                StringBuffer sb = new StringBuffer();
                // 额外循环泵的数量
                Integer pCount = dCount.get(d);
                if(pCount!=null){
                    if(count<pCount*config.getThresholdValue().intValue()){
                        sb.append(vo.getDeviceName()).append("共有").append(pCount+1).append("台脱硫浆液循环泵,").append(lastHourStr).append("正常运行的循环泵不足").append(pCount).append("台，").append("循环泵异常停运将导致浆液与烟气接触面积减少，降低脱硫效率");
                    }
                }else{
                    if(count<config.getThresholdValue().intValue()) {
                        sb.append(vo.getDeviceName()).append("共有1台脱硫浆液循环泵，").append(lastHourStr).append("正常运行的循环泵不足1台，").append("循环泵异常停运将导致浆液与烟气接触面积减少，降低脱硫效率");
                    }
                }
                if(StringUtils.isNotEmpty(sb.toString())) {
                    AmProblemFi problemFi = doProcessAlaram(vo, curr, new Date(), ProblemTypeEnum.PUMP_ERROR, sb.toString(), param, paramProperty);
                    alarmList.add(problemFi);
                }
            });
        }
    }

    /**
     * 判断PH是否超标，并生成报警
     * @param blList
     * @param alarmList
     */
    private void doProcessAlarmData(List<AvgValueVo> blList,List<AmProblemFi> alarmList,Date curr,BigDecimal minValue,BigDecimal maxValue,String param,String paramProperty) {
        if (blList != null && blList.size() > 0) {
            blList.forEach(real -> {
                // 日均PH值，小于最小值，大于最大值则生成报警数据
                if(real.getAvgValue().compareTo(minValue)<0||real.getAvgValue().compareTo(maxValue)>0){
                    FactoryDeviceVo vo = basDeviceService.selectFactoryDeviceVoByDeviceId(real.getDeviceId());
                    StringBuffer sb = new StringBuffer();
                    sb.append(vo.getDeviceName()).append("湿法脱硫浆液PH值日均值为").append(real.getAvgValue()).append(",超出合理理范围(").append(minValue).append("-").append(maxValue).append(")，");
                    sb.append("，PH过高，石灰石中碳酸钙溶出速度变慢，二氧化硫的氧化也受到抑制，两种物质的增加易发生结垢、堵塞现象。低PH会抑制SO2的吸收，低于4.0后，SO2几乎不被浆液吸收，而且会加剧设备的腐蚀。请注意排查。");
                    AmProblemFi problemFi = doProcessAlaram(vo,curr,new Date(),ProblemTypeEnum.PH_OVER,sb.toString(),param,paramProperty);
                    alarmList.add(problemFi);
                }
            });
        }
    }

    /**
     * 生成报警数据
     * @param vo
     * @param start
     * @param end
     * @param problemType
     * @param msg
     * @param param
     * @param paramProperty
     * @return
     */
    private AmProblemFi doProcessAlaram(FactoryDeviceVo vo, Date start, Date end, ProblemTypeEnum problemType, String msg,String param ,String paramProperty) {
        AmProblemFi problemFi = new AmProblemFi();
        problemFi.setProblemSources("1");
        problemFi.setFactoryId(vo.getFactoryId());
        problemFi.setProblemDetails(msg);
        problemFi.setType(1);
        problemFi.setProblemType(problemType.getCode());
        problemFi.setProblemTreatmentState("1");
        problemFi.setAnalyseTime(start);
        problemFi.setAnalyseTimeEnd(end);
        problemFi.setStationId(vo.getDeviceId());
        problemFi.setStationName(vo.getDeviceName());
        problemFi.setCreateTime(new Date());
        problemFi.setParamName(param);
        problemFi.setParamProperty(paramProperty);
        Map<String,Object> map = new HashMap<>();
        List<Map<String,Object>> list = new ArrayList<>();
        Map m = new HashMap();
        m.put("deviceId",vo.getDeviceId());
        m.put("params", Arrays.asList(paramProperty.split(",")));
        list.add(m);
        map.put("dcsDeviceList",list);
        problemFi.setExtra(JSON.toJSONString(map));
        return problemFi;
    }

    /**
     * 批量保存报警
     * @param list
     */
    private void doSaveBatchAlarm(List<AmProblemFi> list){
        if(list!=null&&list.size()>0) {
            amProblemFiService.saveBatch(list);
        }
    }

}
