/**
 * Copyright 2019 DH
 * All right reserved.
 * 项目名称: 运维系统
 * 创建日期:2022/8/24
 */
package org.springblade.modules.business.warning.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springblade.constant.RedisBusinessConstant;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.tool.jackson.JsonUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.enums.WarnKindEnum;
import org.springblade.enums.WarningStatusEnum;

import org.springblade.modules.baseinfo.rtu.entity.RtuInfoEntity;
import org.springblade.modules.baseinfo.warn.entity.BaseWarnSettingEntity;
import org.springblade.modules.business.data.dto.RtuDataRainDTO;
import org.springblade.modules.business.data.dto.RtuDataRiverDTO;
import org.springblade.modules.business.data.dto.RtuDataRsvrDTO;
import org.springblade.modules.business.data.entity.*;
import org.springblade.modules.business.data.service.*;
import org.springblade.modules.business.warning.dto.RtuWarningInfoDTO;
import org.springblade.modules.business.warning.entity.RtuWarningInfoEntity;
import org.springblade.modules.business.warning.mapper.RtuWarningMapper;
import org.springblade.modules.business.warning.service.IRtuWarningService;
import org.springblade.modules.business.warning.vo.RtuWarningInfoVO;
import org.springblade.modules.etl.entity.EtlGroundDataEntity;
import org.springblade.modules.etl.entity.EtlRainDataEntity;
import org.springblade.modules.etl.entity.EtlRiverDataEntity;
import org.springblade.modules.etl.entity.EtlRsvrDataEntity;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.List;


/***
 * Date:2022/8/24
 * Title:预警服务接口实现模块
 * Description：对本文件的详细描述，原则上不能少于30字
 * @author dylan
 * @version 1.0
 * Remark：认为有必要的其他信息
 */
@Slf4j
@Service
public class RtuWarningServiceImpl extends BaseServiceImpl<RtuWarningMapper, RtuWarningInfoEntity> implements IRtuWarningService {

	@Resource
	private IRtuDataRainStoreService rainStoreService;

	@Resource
	private IRtuDataRiverStoreService riverStoreService;

	@Resource
	private IRtuDataRsvrStoreService rsvrStoreService;

	@Resource
	private KafkaTemplate<String, String> kafkaTemplate;

	@Resource
	private RedisTemplate<String, String> redisTemplate;

	@Value("${spring.mq-topic.ywxt-warning}")
	private String topicYwxtWarning;

	@Value("${spring.warn-config.missout}")
	private Integer missout;

	@Value("${spring.warn-config.clock-failure-duration}")
	private Integer clockFailureDuration;

	@Value("${spring.warn-config.outlier-value}")
	private Integer outlierValue;


	@Override
	public IPage<RtuWarningInfoVO> selectPage(IPage<RtuWarningInfoVO> page, RtuWarningInfoDTO rtuWarningInfoDTO) {
		return page.setRecords(baseMapper.selectPage(page, rtuWarningInfoDTO));
	}

	@Override
	public IPage<RtuWarningInfoVO> selectClockPage(IPage page, RtuWarningInfoDTO rtuWarningInfoDTO) {
		return page.setRecords(baseMapper.selectClockPage(page, rtuWarningInfoDTO));
	}

	@Override
	public IPage<RtuWarningInfoVO> selectOfflinePage(IPage<RtuWarningInfoVO> page, RtuWarningInfoDTO rtuWarningInfoDTO) {
		return page.setRecords(baseMapper.selectOfflinePage(page, rtuWarningInfoDTO));
	}

	@Override
	public IPage<RtuWarningInfoVO> selectOthersWarnPage(IPage<RtuWarningInfoVO> page, RtuWarningInfoDTO rtuWarningInfoDTO) {
		return page.setRecords(baseMapper.selectOthersWarnPage(page, rtuWarningInfoDTO));
	}

	@Override
	public IPage<RtuWarningInfoVO> selectHourMissOutPage(IPage<RtuWarningInfoVO> page, RtuWarningInfoDTO rtuWarningInfoDTO) {
		return page.setRecords(baseMapper.selectHourMissOutPage(page, rtuWarningInfoDTO));
	}

	@Override
	public IPage<RtuWarningInfoVO> selectRainHourMissOutPage(IPage page, RtuWarningInfoDTO rtuWarningInfoDTO) {
		return page.setRecords(baseMapper.selectRainHourMissOutPage(page, rtuWarningInfoDTO));
	}

	@Override
	public IPage<RtuWarningInfoVO> selectRiverHourMissOutPage(IPage page, RtuWarningInfoDTO rtuWarningInfoDTO) {
		return page.setRecords(baseMapper.selectRiverHourMissOutPage(page, rtuWarningInfoDTO));
	}

	@Override
	public IPage<RtuWarningInfoVO> selectMinUpDelayPage(IPage<RtuWarningInfoVO> page, RtuWarningInfoDTO rtuWarningInfoDTO) {
		return page.setRecords(baseMapper.selectMinUpDelayPage(page, rtuWarningInfoDTO));
	}

	@Override
	public IPage<RtuWarningInfoVO> selectHourUpDelayPage(IPage<RtuWarningInfoVO> page, RtuWarningInfoDTO rtuWarningInfoDTO) {
		return page.setRecords(baseMapper.selectHourUpDelayPage(page, rtuWarningInfoDTO));
	}

	@Override
	public IPage<RtuWarningInfoVO> selectRainHourUpDelayPage(IPage page, RtuWarningInfoDTO rtuWarningInfoDTO) {
		return page.setRecords(baseMapper.selectRainHourUpDelayPage(page, rtuWarningInfoDTO));
	}

	@Override
	public IPage<RtuWarningInfoVO> selectRiverHourUpDelayPage(IPage page, RtuWarningInfoDTO rtuWarningInfoDTO) {
		return page.setRecords(baseMapper.selectRiverHourUpDelayPage(page, rtuWarningInfoDTO));
	}

	@Override
	public IPage<RtuWarningInfoVO> selectOutlierValuePage(IPage page, RtuWarningInfoDTO rtuWarningInfoDTO) {
		return page.setRecords(baseMapper.selectOutlierValuePage(page, rtuWarningInfoDTO));
	}

	@Override
	public Long warningRtuCount(RtuWarningInfoDTO rtuWarningInfoDTO) {
		return baseMapper.warningRtuCount(rtuWarningInfoDTO);
	}

	@Override
	public Long warningOfflineRtuCount(RtuWarningInfoDTO rtuWarningInfoDTO) {
		return baseMapper.warningOfflineRtuCount(rtuWarningInfoDTO);
	}

	@Override
	public Long otherWarningRtuCount(RtuWarningInfoDTO rtuWarningInfoDTO) {
		return baseMapper.otherWarningRtuCount(rtuWarningInfoDTO);
	}

	@Override
	public Long warningClockRtuCount(RtuWarningInfoDTO rtuWarningInfoDTO) {
		return this.baseMapper.warningClockRtuCount(rtuWarningInfoDTO);
	}

	@Override
	public Long warningHourMissOutRtuCount(RtuWarningInfoDTO rtuWarningInfoDTO) {
		return baseMapper.warningHourMissOutRtuCount(rtuWarningInfoDTO);
	}

	@Override
	public Long warningRainHourMissOutRtuCount(RtuWarningInfoDTO rtuWarningInfoDTO) {
		return this.baseMapper.warningRainHourMissOutRtuCount(rtuWarningInfoDTO);
	}

	@Override
	public Long warningRiverHourMissOutRtuCount(RtuWarningInfoDTO rtuWarningInfoDTO) {
		return this.baseMapper.warningRiverHourMissOutRtuCount(rtuWarningInfoDTO);
	}

	@Override
	public Long warningMinUpDelayRtuCount(RtuWarningInfoDTO rtuWarningInfoDTO) {
		return baseMapper.warningMinUpDelayRtuCount(rtuWarningInfoDTO);
	}

	@Override
	public Long warningHourUpDelayRtuCount(RtuWarningInfoDTO rtuWarningInfoDTO) {
		return baseMapper.warningHourUpDelayRtuCount(rtuWarningInfoDTO);
	}

	@Override
	public Long warningRainHourUpDelayRtuCount(RtuWarningInfoDTO rtuWarningInfoDTO) {
		return this.baseMapper.warningRainHourUpDelayRtuCount(rtuWarningInfoDTO);
	}

	@Override
	public Long warningRiverHourUpDelayRtuCount(RtuWarningInfoDTO rtuWarningInfoDTO) {
		return this.baseMapper.warningHourUpDelayRtuCount(rtuWarningInfoDTO);
	}

	@Override
	public Long warningOutlierValueRtuCount(RtuWarningInfoDTO rtuWarningInfoDTO) {
		return this.baseMapper.warningOutlierValueRtuCount(rtuWarningInfoDTO);
	}

	/**
	 * 时钟预警
	 *
	 * @param rtuInfoEntity
	 * @param checkTm
	 * @param upTime
	 */
	private void clockWarnHappen(RtuInfoEntity rtuInfoEntity, Date checkTm, Date upTime) {
		LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
		warningWrapper.eq(RtuWarningInfoEntity::getIsDeleted, 0);
		warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, rtuInfoEntity.getRtuCode());
		warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
		warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_CLOCK.getCode());
		RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
		if (null != warningInfoEntity) {
			warningInfoEntity.setUpdateTime(checkTm);
			this.updateById(warningInfoEntity);
			kafkaTemplate.send(topicYwxtWarning, JsonUtil.toJson(warningInfoEntity));
		} else {
			RtuWarningInfoEntity entity = new RtuWarningInfoEntity();
			entity.setRtuCode(rtuInfoEntity.getRtuCode());
			entity.setWarningHappenTime(checkTm);
			entity.setWarningStatus(WarningStatusEnum.STATUS_HAPPEN.getCode());
			entity.setWarningKind(WarnKindEnum.WARN_CLOCK.getCode());
			entity.setWarningDesc("时钟异常，服务器时间：" + Func.formatDateTime(checkTm) + "," + "测站采集时间：" + Func.formatDateTime(upTime));
			this.save(entity);
			kafkaTemplate.send(topicYwxtWarning, JsonUtil.toJson(entity));
		}
	}

	/**
	 * 时钟预警恢复
	 *
	 * @param rtuInfoEntity
	 * @param checkTm
	 */
	private void clockWarnRecovery(RtuInfoEntity rtuInfoEntity, Date checkTm) {
		LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
		warningWrapper.eq(RtuWarningInfoEntity::getIsDeleted, 0);
		warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, rtuInfoEntity.getRtuCode());
		warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
		warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_CLOCK.getCode());
		RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
		if (null != warningInfoEntity) {
			//恢复
			warningInfoEntity.setWarningRecoveryTime(checkTm);
			warningInfoEntity.setWarningStatus(WarningStatusEnum.STATUS_CLOSE.getCode());
			warningInfoEntity.setUpdateTime(checkTm);
			this.updateById(warningInfoEntity);
			kafkaTemplate.send(topicYwxtWarning, JsonUtil.toJson(warningInfoEntity));
		}
	}

	/**
	 * 时钟预警检测
	 *
	 * @param checkTm
	 * @param upTime
	 * @param fromDate
	 */
	private boolean clockWarnCheck(Date checkTm, Date upTime, Date fromDate) {
		//检测时钟异常,情况1，上报时间比服务器时间晚，时钟错误
		if (upTime.after(checkTm)) {
			long tm = (upTime.getTime() - checkTm.getTime()) / 1000L;
			if (tm > clockFailureDuration * 60) {
				return true;
			}
		} else {
			//检测时钟异常,情况2，上报时间比数据库服务器（东华）时间晚，时钟错误
			if (upTime.after(fromDate)) {
				long tm = (upTime.getTime() - fromDate.getTime()) / 1000L;
				if (tm > clockFailureDuration * 60) {
					return true;
				}
			}
		}
		return false;
	}

	@Override
	public boolean checkRtuClockStatus(RtuInfoEntity rtuInfoEntity, BaseWarnSettingEntity warnSettingEntity, LocalDateTime checkTime) {
		ValueOperations<String, String> ops = redisTemplate.opsForValue();
		boolean isWarn = false;
		StringBuilder warnDesc = new StringBuilder();
		StringBuilder warnRecoveryDesc = new StringBuilder();
		if (rtuInfoEntity.getIsRain() != null && rtuInfoEntity.getIsRain() == 1) {

			String key = RedisBusinessConstant.KEY_ETL_RAIN_UP_LAST + rtuInfoEntity.getRtuCode();
			String lastRainInfo = ops.get(key);
			if (null != lastRainInfo && lastRainInfo.length() > 0) {
				EtlRainDataEntity etlRainDataEntity = JSONObject.parseObject(lastRainInfo, EtlRainDataEntity.class);
				LocalDateTime upTime = LocalDateTime.ofInstant(etlRainDataEntity.getTm().toInstant(), ZoneId.systemDefault());
				LocalDateTime fromDate = LocalDateTime.ofInstant(etlRainDataEntity.getFromDate().toInstant(), ZoneId.systemDefault());

				warnRecoveryDesc.append("雨量站，服务器时间：");
				warnRecoveryDesc.append(checkTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
				warnRecoveryDesc.append(",上报时间：");
				warnRecoveryDesc.append(upTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
				//检测时钟异常,情况1，上报时间比服务器时间晚，时钟错误
				if (upTime.isAfter(checkTime)) {
					long min = ChronoUnit.MINUTES.between(upTime, checkTime);
					if (min > clockFailureDuration) {
						isWarn = true;
						warnDesc.append("雨量站时钟异常,服务器时间：");
						warnDesc.append(checkTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
						warnDesc.append(",上报时间：");
						warnDesc.append(upTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
						warnDesc.append(",时钟快");
						warnDesc.append(Func.toStr(min));
						warnDesc.append("分钟");
					}
				} else {
					//检测时钟异常,情况2，上报时间比数据库服务器（东华）时间晚，时钟错误
					if (upTime.isAfter(fromDate)) {
						long min = ChronoUnit.MINUTES.between(upTime, fromDate);
						if (min > clockFailureDuration) {
							isWarn = true;
							warnDesc.append("雨量站时钟异常,服务器时间：");
							warnDesc.append(fromDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
							warnDesc.append(",上报时间：");
							warnDesc.append(upTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
							warnDesc.append(",时钟快");
							warnDesc.append(Func.toStr(min));
							warnDesc.append("分钟");
						}
					}
				}
			}
		}
		if (rtuInfoEntity.getIsRiver() != null && rtuInfoEntity.getIsRiver() == 1) {

			String key = RedisBusinessConstant.KEY_ETL_RIVER_UP_LAST + rtuInfoEntity.getRtuCode();
			String lastRiverInfo = ops.get(key);
			if (null != lastRiverInfo && lastRiverInfo.length() > 0) {
				EtlRiverDataEntity etlRiverDataEntity = JSONObject.parseObject(lastRiverInfo, EtlRiverDataEntity.class);
				LocalDateTime upTime = LocalDateTime.ofInstant(etlRiverDataEntity.getTm().toInstant(), ZoneId.systemDefault());
				LocalDateTime fromDate = LocalDateTime.ofInstant(etlRiverDataEntity.getFromDate().toInstant(), ZoneId.systemDefault());
				if (warnRecoveryDesc.length() > 0) {
					warnRecoveryDesc.append(",");
				}
				warnRecoveryDesc.append("水位站，服务器时间：");
				warnRecoveryDesc.append(checkTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
				warnRecoveryDesc.append(",上报时间：");
				warnRecoveryDesc.append(upTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
				//检测时钟异常,情况1，上报时间比服务器时间晚，时钟错误
				if (upTime.isAfter(checkTime)) {
					long min = ChronoUnit.MINUTES.between(upTime, checkTime);
					if (min > clockFailureDuration) {
						isWarn = true;
						if (warnDesc.length() > 0) {
							warnDesc.append(",");
						}
						warnDesc.append("水位站时钟异常,服务器时间：");
						warnDesc.append(checkTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
						warnDesc.append(",上报时间：");
						warnDesc.append(upTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
						warnDesc.append(",时钟快");
						warnDesc.append(Func.toStr(min));
						warnDesc.append("分钟");
					}
				} else {
					//检测时钟异常,情况2，上报时间比数据库服务器（东华）时间晚，时钟错误
					if (upTime.isAfter(fromDate)) {
						long min = ChronoUnit.MINUTES.between(upTime, fromDate);
						if (min > clockFailureDuration) {
							isWarn = true;
							if (warnDesc.length() > 0) {
								warnDesc.append(",");
							}
							warnDesc.append("水位站时钟异常,服务器时间：");
							warnDesc.append(fromDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
							warnDesc.append(",上报时间：");
							warnDesc.append(upTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
							warnDesc.append(",时钟快");
							warnDesc.append(Func.toStr(min));
							warnDesc.append("分钟");
						}
					}
				}
			}
		}
		if (rtuInfoEntity.getIsRes() != null && rtuInfoEntity.getIsRes() == 1) {

			String key = RedisBusinessConstant.KEY_ETL_RSVR_UP_LAST + rtuInfoEntity.getRtuCode();
			String lastRsvrInfo = ops.get(key);
			if (null != lastRsvrInfo && lastRsvrInfo.length() > 0) {
				EtlRsvrDataEntity etlRsvrDataEntity = JSONObject.parseObject(lastRsvrInfo, EtlRsvrDataEntity.class);
				LocalDateTime upTime = LocalDateTime.ofInstant(etlRsvrDataEntity.getTm().toInstant(), ZoneId.systemDefault());
				LocalDateTime fromDate = LocalDateTime.ofInstant(etlRsvrDataEntity.getFromDate().toInstant(), ZoneId.systemDefault());
				if (warnRecoveryDesc.length() > 0) {
					warnRecoveryDesc.append(",");
				}
				warnRecoveryDesc.append("水位站，服务器时间：");
				warnRecoveryDesc.append(checkTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
				warnRecoveryDesc.append(",上报时间：");
				warnRecoveryDesc.append(upTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
				//检测时钟异常,情况1，上报时间比服务器时间晚，时钟错误
				if (upTime.isAfter(checkTime)) {
					long min = ChronoUnit.MINUTES.between(upTime, checkTime);
					if (min > clockFailureDuration) {
						isWarn = true;
						if (warnDesc.length() > 0) {
							warnDesc.append(",");
						}
						warnDesc.append("水位站时钟异常,服务器时间：");
						warnDesc.append(checkTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
						warnDesc.append(",上报时间：");
						warnDesc.append(upTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
						warnDesc.append(",时钟快");
						warnDesc.append(Func.toStr(min));
						warnDesc.append("分钟");
					}
				} else {
					//检测时钟异常,情况2，上报时间比数据库服务器（东华）时间晚，时钟错误
					if (upTime.isAfter(fromDate)) {
						long min = ChronoUnit.MINUTES.between(upTime, fromDate);
						if (min > clockFailureDuration) {
							isWarn = true;
							if (warnDesc.length() > 0) {
								warnDesc.append(",");
							}
							warnDesc.append("水位站时钟异常,服务器时间：");
							warnDesc.append(fromDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
							warnDesc.append(",上报时间：");
							warnDesc.append(upTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
							warnDesc.append(",时钟快");
							warnDesc.append(Func.toStr(min));
							warnDesc.append("分钟");
						}
					}
				}
			}
		}
		if (rtuInfoEntity.getIsGround() != null && rtuInfoEntity.getIsGround() == 1) {

			String key = RedisBusinessConstant.KEY_ETL_GROUND_UP_LAST + rtuInfoEntity.getRtuCode();
			String lastGroundInfo = ops.get(key);
			if (null != lastGroundInfo && lastGroundInfo.length() > 0) {
				EtlGroundDataEntity etlGroundDataEntity = JSONObject.parseObject(lastGroundInfo, EtlGroundDataEntity.class);
				LocalDateTime upTime = LocalDateTime.ofInstant(etlGroundDataEntity.getTm().toInstant(), ZoneId.systemDefault());
				LocalDateTime fromDate = LocalDateTime.ofInstant(etlGroundDataEntity.getFromDate().toInstant(), ZoneId.systemDefault());
				if (warnRecoveryDesc.length() > 0) {
					warnRecoveryDesc.append(",");
				}
				warnRecoveryDesc.append("墒情站，服务器时间：");
				warnRecoveryDesc.append(checkTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
				warnRecoveryDesc.append(",上报时间：");
				warnRecoveryDesc.append(upTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
				//检测时钟异常,情况1，上报时间比服务器时间晚，时钟错误
				if (upTime.isAfter(checkTime)) {
					long min = ChronoUnit.MINUTES.between(upTime, checkTime);
					if (min > clockFailureDuration) {
						isWarn = true;
						if (warnDesc.length() > 0) {
							warnDesc.append(",");
						}
						warnDesc.append("墒情站时钟异常,服务器时间：");
						warnDesc.append(checkTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
						warnDesc.append(",上报时间：");
						warnDesc.append(upTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
						warnDesc.append(",时钟快");
						warnDesc.append(Func.toStr(min));
						warnDesc.append("分钟");
					}
				} else {
					//检测时钟异常,情况2，上报时间比数据库服务器（东华）时间晚，时钟错误
					if (upTime.isAfter(fromDate)) {
						long min = ChronoUnit.MINUTES.between(upTime, fromDate);
						if (min > clockFailureDuration) {
							isWarn = true;
							if (warnDesc.length() > 0) {
								warnDesc.append(",");
							}
							warnDesc.append("墒情站时钟异常,服务器时间：");
							warnDesc.append(fromDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
							warnDesc.append(",上报时间：");
							warnDesc.append(upTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
							warnDesc.append(",时钟快");
							warnDesc.append(Func.toStr(min));
							warnDesc.append("分钟");
						}
					}
				}
			}
		}
		HashOperations<String, String, String> hashops = redisTemplate.opsForHash();
		String key = RedisBusinessConstant.KEY_RTU_RUN_INFO + rtuInfoEntity.getRtuCode();
		String warnKindKey = RedisBusinessConstant.KEY_RTU_RUN_INFO_WARN_KIND + Func.toStr(WarnKindEnum.WARN_CLOCK.getCode());
		String warnStatus = hashops.get(key, warnKindKey);
		if (isWarn) {
			//测站时钟有异常，产生预警
			boolean isCreateWarn = false;
			if (null != warnStatus) {
				if (WarningStatusEnum.STATUS_CLOSE.getCode() == Func.toInt(warnStatus)) {
					isCreateWarn = true;
				}
			} else {
				LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
				warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, rtuInfoEntity.getRtuCode());
				warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
				warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_CLOCK.getCode());
				RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
				if (null == warningInfoEntity) {
					isCreateWarn = true;
				}
			}

			if (isCreateWarn) {
				RtuWarningInfoEntity entity = new RtuWarningInfoEntity();
				entity.setRtuCode(rtuInfoEntity.getRtuCode());
				entity.setWarningHappenTime(Date.from(checkTime.atZone(ZoneId.systemDefault()).toInstant()));
				entity.setWarningStatus(WarningStatusEnum.STATUS_HAPPEN.getCode());
				entity.setWarningKind(WarnKindEnum.WARN_CLOCK.getCode());
				entity.setWarningDesc(warnDesc.toString());
				this.save(entity);
				//更新预警状态
				hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_HAPPEN.getCode()));
				//预警通知
				kafkaTemplate.send(topicYwxtWarning, JsonUtil.toJson(entity));
				log.info("时钟异常 {} {} {} ", rtuInfoEntity.getRtuCode(), rtuInfoEntity.getRtuName(), warnDesc.toString());
			}

			if (null == warnStatus) {
				//更新预警状态
				hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_HAPPEN.getCode()));
			}
		} else {
			boolean isCloseWarn = false;
			if (null != warnStatus) {
				if (WarningStatusEnum.STATUS_CLOSE.getCode() == Func.toInt(warnStatus)) {
					isCloseWarn = true;
				}
			} else {
				LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
				warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, rtuInfoEntity.getRtuCode());
				warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
				warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_CLOCK.getCode());
				RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
				if (null != warningInfoEntity) {
					isCloseWarn = true;
				}
			}
			if (isCloseWarn) {
				LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
				warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, rtuInfoEntity.getRtuCode());
				warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
				warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_CLOCK.getCode());
				RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
				if (null != warningInfoEntity) {
					//恢复
					warningInfoEntity.setWarningRecoveryDesc(warnRecoveryDesc.toString());
					warningInfoEntity.setWarningRecoveryTime(Date.from(checkTime.atZone(ZoneId.systemDefault()).toInstant()));
					warningInfoEntity.setWarningStatus(WarningStatusEnum.STATUS_CLOSE.getCode());
					this.updateById(warningInfoEntity);
					//更新预警状态
					hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_CLOSE.getCode()));
					//预警通知
					kafkaTemplate.send(topicYwxtWarning, JsonUtil.toJson(warningInfoEntity));
					log.info("时钟异常恢复 {} {} {} ", rtuInfoEntity.getRtuCode(), rtuInfoEntity.getRtuName(), warnRecoveryDesc.toString());
				}
			}
			if (null == warnStatus) {
				//更新预警状态
				hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_CLOSE.getCode()));
			}
		}
		return true;
	}

	@Override
	public boolean checkRtuRainUpHourDelayStatus(RtuInfoEntity rtuInfoEntity, BaseWarnSettingEntity warnSettingEntity, LocalDateTime checkTime) {
//		if (rtuInfoEntity.getRtuCode().equals("40509005")) {
//			log.info("40509005");
//		}
		ValueOperations<String, String> ops = redisTemplate.opsForValue();
		if (rtuInfoEntity.getIsRain() != null && rtuInfoEntity.getIsRain() == 1) {
			String key = RedisBusinessConstant.KEY_ETL_RAIN_HOUR_UP_LAST + rtuInfoEntity.getRtuCode();
			String lastRainInfo = ops.get(key);
			if (null != lastRainInfo && lastRainInfo.length() > 0) {
				EtlRainDataEntity etlRainDataEntity = JSONObject.parseObject(lastRainInfo, EtlRainDataEntity.class);

				Date upTime = etlRainDataEntity.getTm();
				Date fromDate = etlRainDataEntity.getFromDate();
				LocalDateTime tm = checkTime.minusHours(2);
				LocalDateTime upTm = LocalDateTime.ofInstant(fromDate.toInstant(), ZoneId.systemDefault());
				if (upTm.isEqual(tm) || upTm.isAfter(tm)) {
					//只检测2小时前上报数据
					HashOperations<String, String, String> hashops = redisTemplate.opsForHash();
					String runInfokey = RedisBusinessConstant.KEY_RTU_RUN_INFO + rtuInfoEntity.getRtuCode();
					String warnKindKey = RedisBusinessConstant.KEY_RTU_RUN_INFO_WARN_KIND + Func.toStr(WarnKindEnum.WARN_RAIN_UP_HOUR_DELAY.getCode());
					String warnStatus = hashops.get(runInfokey, warnKindKey);
					if (upTime.before(fromDate)) {
						//延时时长，分
						long delayDuration = (fromDate.getTime() - upTime.getTime()) / 1000L / 60L;
						if (delayDuration >= warnSettingEntity.getWarnRainDelayHourDuration()) {
							//延时异常
							boolean isCreateWarn = false;
							if (null != warnStatus) {
								if (WarningStatusEnum.STATUS_CLOSE.getCode() == Func.toInt(warnStatus)) {
									isCreateWarn = true;
								}
							} else {
								LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
								warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, etlRainDataEntity.getRtuCode());
								warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
								warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_RAIN_UP_HOUR_DELAY.getCode());
								RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
								if (null == warningInfoEntity) {
									isCreateWarn = true;
								}
							}
							if (isCreateWarn) {
								RtuWarningInfoEntity entity = new RtuWarningInfoEntity();
								entity.setRtuCode(etlRainDataEntity.getRtuCode());
								entity.setWarningHappenTime(Date.from(checkTime.atZone(ZoneId.systemDefault()).toInstant()));
								entity.setWarningStatus(WarningStatusEnum.STATUS_HAPPEN.getCode());
								entity.setWarningKind(WarnKindEnum.WARN_RAIN_UP_HOUR_DELAY.getCode());
								entity.setWarningDesc("雨情整点上报延时异常,延时设定参数：" + Func.toStr(warnSettingEntity.getWarnRainDelayHourDuration()) + "分钟,上报时间：" + Func.formatDateTime(fromDate) + ",测站采集时间：" + Func.formatDateTime(upTime) + ",延时：" + Func.toStr(delayDuration) + "分钟");
								this.save(entity);
								//更新预警状态
								hashops.put(runInfokey, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_HAPPEN.getCode()));
								//预警通知
								kafkaTemplate.send(topicYwxtWarning, JsonUtil.toJson(entity));
								log.info("雨情整点上报延时异常 {} {} {} ", rtuInfoEntity.getRtuCode(), rtuInfoEntity.getRtuName(), entity.getWarningDesc());
							}

							if (null == warnStatus) {
								//更新预警状态
								hashops.put(runInfokey, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_HAPPEN.getCode()));
							}
						} else {
							//没有检测到预警发生，进行预警恢复操作
							boolean isCloseWarn = false;
							if (null != warnStatus) {
								if (WarningStatusEnum.STATUS_CLOSE.getCode() == Func.toInt(warnStatus)) {
									isCloseWarn = true;
								}
							} else {
								LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
								warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, etlRainDataEntity.getRtuCode());
								warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
								warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_RAIN_UP_HOUR_DELAY.getCode());
								RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
								if (null != warningInfoEntity) {
									isCloseWarn = true;
								}
							}
							if (isCloseWarn) {
								LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
								warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, etlRainDataEntity.getRtuCode());
								warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
								warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_RAIN_UP_HOUR_DELAY.getCode());
								RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
								if (null != warningInfoEntity) {
									//恢复
									warningInfoEntity.setWarningRecoveryDesc("雨情整点上报延时恢复,延时设定参数：" + Func.toStr(warnSettingEntity.getWarnRainDelayHourDuration()) + "分钟,上报时间：" + Func.formatDateTime(fromDate) + ",测站采集时间：" + Func.formatDateTime(upTime) + ",延时：" + Func.toStr(delayDuration) + "分钟");
									warningInfoEntity.setWarningRecoveryTime(Date.from(checkTime.atZone(ZoneId.systemDefault()).toInstant()));
									warningInfoEntity.setWarningStatus(WarningStatusEnum.STATUS_CLOSE.getCode());
									this.updateById(warningInfoEntity);
									//更新预警状态
									hashops.put(runInfokey, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_CLOSE.getCode()));
									//通知
									kafkaTemplate.send(topicYwxtWarning, JsonUtil.toJson(warningInfoEntity));
									log.info("雨情整点上报延时恢复 {} {} {} ", rtuInfoEntity.getRtuCode(), rtuInfoEntity.getRtuName(), warningInfoEntity.getWarningRecoveryDesc());
								}
							}
							if (null == warnStatus) {
								//更新预警状态
								hashops.put(runInfokey, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_CLOSE.getCode()));
							}
						}
					}
				}

			}
		}
		return true;
	}

	@Override
	public boolean checkRtuRiverUpHourDelayStatus(RtuInfoEntity rtuInfoEntity, BaseWarnSettingEntity warnSettingEntity, LocalDateTime checkTime) {
		ValueOperations<String, String> ops = redisTemplate.opsForValue();
		String key = RedisBusinessConstant.KEY_ETL_RIVER_HOUR_UP_LAST + rtuInfoEntity.getRtuCode();
		String lastRiverInfo = ops.get(key);
		if (null != lastRiverInfo && lastRiverInfo.length() > 0) {
			EtlRiverDataEntity etlRiverDataEntity = JSONObject.parseObject(lastRiverInfo, EtlRiverDataEntity.class);
			Date upTime = etlRiverDataEntity.getTm();
			Date fromDate = etlRiverDataEntity.getFromDate();
			LocalDateTime tm = checkTime.minusHours(2);
			LocalDateTime upTm = LocalDateTime.ofInstant(fromDate.toInstant(), ZoneId.systemDefault());
			if (upTm.isEqual(tm) || upTm.isAfter(tm)) {
				//只检测2小时前上报数据
				HashOperations<String, String, String> hashops = redisTemplate.opsForHash();
				String runInfokey = RedisBusinessConstant.KEY_RTU_RUN_INFO + rtuInfoEntity.getRtuCode();
				String warnKindKey = RedisBusinessConstant.KEY_RTU_RUN_INFO_WARN_KIND + Func.toStr(WarnKindEnum.WARN_WL_UP_HOUR_DELAY.getCode());
				String warnStatus = hashops.get(runInfokey, warnKindKey);
				if (upTime.before(fromDate)) {
					//延时时长，分
					long delayDuration = (fromDate.getTime() - upTime.getTime()) / 1000L / 60L;
					if (delayDuration >= warnSettingEntity.getWarnRiverDelayHourDuration()) {
						//延时异常
						boolean isCreateWarn = false;
						if (null != warnStatus) {
							if (WarningStatusEnum.STATUS_CLOSE.getCode() == Func.toInt(warnStatus)) {
								isCreateWarn = true;
							}
						} else {
							LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
							warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, etlRiverDataEntity.getRtuCode());
							warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
							warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_WL_UP_HOUR_DELAY.getCode());
							RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
							if (null == warningInfoEntity) {
								isCreateWarn = true;
							}
						}


						if (isCreateWarn) {
							RtuWarningInfoEntity entity = new RtuWarningInfoEntity();
							entity.setRtuCode(etlRiverDataEntity.getRtuCode());
							entity.setWarningHappenTime(Date.from(checkTime.atZone(ZoneId.systemDefault()).toInstant()));
							entity.setWarningStatus(WarningStatusEnum.STATUS_HAPPEN.getCode());
							entity.setWarningKind(WarnKindEnum.WARN_WL_UP_HOUR_DELAY.getCode());
							entity.setWarningDesc("水位整点上报延时异常,延时设定参数：" + Func.toStr(warnSettingEntity.getWarnRiverDelayHourDuration()) + "分钟,上报时间：" + Func.formatDateTime(fromDate) + ",测站采集时间：" + Func.formatDateTime(upTime) + ",延时：" + Func.toStr(delayDuration) + "分钟");
							this.save(entity);
							//更新预警状态
							hashops.put(runInfokey, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_HAPPEN.getCode()));
							//通知
							kafkaTemplate.send(topicYwxtWarning, JsonUtil.toJson(entity));
							log.info("水位整点上报延时异常 {} {} {} ", rtuInfoEntity.getRtuCode(), rtuInfoEntity.getRtuName(), entity.getWarningDesc());
						}
						if (null == warnStatus) {
							//更新预警状态
							hashops.put(runInfokey, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_HAPPEN.getCode()));
						}
					} else {
						//没有检测到预警发生，进行预警恢复操作
						boolean isCloseWarn = false;
						if (null != warnStatus) {
							if (WarningStatusEnum.STATUS_CLOSE.getCode() == Func.toInt(warnStatus)) {
								isCloseWarn = true;
							}
						} else {
							LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
							warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, etlRiverDataEntity.getRtuCode());
							warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
							warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_WL_UP_HOUR_DELAY.getCode());
							RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
							if (null != warningInfoEntity) {
								isCloseWarn = true;
							}
						}
						if (isCloseWarn) {
							LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
							warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, etlRiverDataEntity.getRtuCode());
							warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
							warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_WL_UP_HOUR_DELAY.getCode());
							RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
							if (null != warningInfoEntity) {
								//恢复
								warningInfoEntity.setWarningRecoveryDesc("水位整点上报延时恢复,延时设定参数：" + Func.toStr(warnSettingEntity.getWarnRiverDelayHourDuration()) + "分钟,上报时间：" + Func.formatDateTime(fromDate) + ",测站采集时间：" + Func.formatDateTime(upTime) + ",延时：" + Func.toStr(delayDuration) + "分钟");
								warningInfoEntity.setWarningRecoveryTime(Date.from(checkTime.atZone(ZoneId.systemDefault()).toInstant()));
								warningInfoEntity.setWarningStatus(WarningStatusEnum.STATUS_CLOSE.getCode());
								this.updateById(warningInfoEntity);
								//更新预警状态
								hashops.put(runInfokey, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_CLOSE.getCode()));
								//通知
								kafkaTemplate.send(topicYwxtWarning, JsonUtil.toJson(warningInfoEntity));
								log.info("水位整点上报延时恢复 {} {} {} ", rtuInfoEntity.getRtuCode(), rtuInfoEntity.getRtuName(), warningInfoEntity.getWarningRecoveryDesc());
							}
						}
						if (null == warnStatus) {
							//更新预警状态
							hashops.put(runInfokey, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_CLOSE.getCode()));
						}
					}
				}
			}
		}

		return true;
	}

	@Override
	public boolean checkRtuRsvrUpHourDelayStatus(RtuInfoEntity rtuInfoEntity, BaseWarnSettingEntity warnSettingEntity, LocalDateTime checkTime) {
		ValueOperations<String, String> ops = redisTemplate.opsForValue();

		String key = RedisBusinessConstant.KEY_ETL_RSVR_HOUR_UP_LAST + rtuInfoEntity.getRtuCode();
		String lastRsvrInfo = ops.get(key);
		if (null != lastRsvrInfo && lastRsvrInfo.length() > 0) {

			EtlRsvrDataEntity etlRsvrDataEntity = JSONObject.parseObject(lastRsvrInfo, EtlRsvrDataEntity.class);
			Date upTime = etlRsvrDataEntity.getTm();
			Date fromDate = etlRsvrDataEntity.getFromDate();
			LocalDateTime tm = checkTime.minusHours(2);
			LocalDateTime upTm = LocalDateTime.ofInstant(fromDate.toInstant(), ZoneId.systemDefault());
			if (upTm.isEqual(tm) || upTm.isAfter(tm)) {
				//只检测2小时前上报数据

				HashOperations<String, String, String> hashops = redisTemplate.opsForHash();
				String runInfokey = RedisBusinessConstant.KEY_RTU_RUN_INFO + rtuInfoEntity.getRtuCode();
				String warnKindKey = RedisBusinessConstant.KEY_RTU_RUN_INFO_WARN_KIND + Func.toStr(WarnKindEnum.WARN_WL_UP_HOUR_DELAY.getCode());
				String warnStatus = hashops.get(runInfokey, warnKindKey);

				if (upTime.before(fromDate)) {
					//延时时长，分
					long delayDuration = (fromDate.getTime() - upTime.getTime()) / 1000L / 60L;
					if (delayDuration >= warnSettingEntity.getWarnRsvrDelayHourDuration()) {
						//延时异常
						boolean isCreateWarn = false;
						if (null != warnStatus) {
							if (WarningStatusEnum.STATUS_CLOSE.getCode() == Func.toInt(warnStatus)) {
								isCreateWarn = true;
							}
						} else {
							LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();

							warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, etlRsvrDataEntity.getRtuCode());
							warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
							warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_WL_UP_HOUR_DELAY.getCode());
							RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
							if (null == warningInfoEntity) {
								isCreateWarn = true;
							}
						}


						if (isCreateWarn) {
							RtuWarningInfoEntity entity = new RtuWarningInfoEntity();
							entity.setRtuCode(etlRsvrDataEntity.getRtuCode());
							entity.setWarningHappenTime(Date.from(checkTime.atZone(ZoneId.systemDefault()).toInstant()));
							entity.setWarningStatus(WarningStatusEnum.STATUS_HAPPEN.getCode());
							entity.setWarningKind(WarnKindEnum.WARN_WL_UP_HOUR_DELAY.getCode());
							entity.setWarningDesc("水位整点上报延时异常,延时设定参数：" + Func.toStr(warnSettingEntity.getWarnRsvrDelayHourDuration()) + "分钟,上报时间：" + Func.formatDateTime(fromDate) + ",测站采集时间：" + Func.formatDateTime(upTime) + ",延时：" + Func.toStr(delayDuration) + "分钟");
							this.save(entity);
							//更新预警状态
							hashops.put(runInfokey, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_HAPPEN.getCode()));
							//通知
							kafkaTemplate.send(topicYwxtWarning, JsonUtil.toJson(entity));

							log.info("水位整点上报延时异常 {} {} {} ", rtuInfoEntity.getRtuCode(), rtuInfoEntity.getRtuName(), entity.getWarningDesc());
						}

						if (null == warnStatus) {
							//更新预警状态
							hashops.put(runInfokey, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_HAPPEN.getCode()));
						}
					} else {
						//没有检测到预警发生，进行预警恢复操作
						boolean isCloseWarn = false;
						if (null != warnStatus) {
							if (WarningStatusEnum.STATUS_CLOSE.getCode() == Func.toInt(warnStatus)) {
								isCloseWarn = true;
							}
						} else {
							LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();

							warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, etlRsvrDataEntity.getRtuCode());
							warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
							warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_WL_UP_HOUR_DELAY.getCode());
							RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
							if (null != warningInfoEntity) {
								isCloseWarn = true;
							}
						}

						if (isCloseWarn) {
							LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
							warningWrapper.eq(RtuWarningInfoEntity::getIsDeleted, 0);
							warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, etlRsvrDataEntity.getRtuCode());
							warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
							warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_WL_UP_HOUR_DELAY.getCode());
							RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
							if (null != warningInfoEntity) {
								//恢复
								warningInfoEntity.setWarningRecoveryDesc("水位整点上报延时恢复,延时设定参数：" + Func.toStr(warnSettingEntity.getWarnRsvrDelayHourDuration()) + "分钟,上报时间：" + Func.formatDateTime(fromDate) + ",测站采集时间：" + Func.formatDateTime(upTime) + ",延时：" + Func.toStr(delayDuration) + "分钟");
								warningInfoEntity.setWarningRecoveryTime(Date.from(checkTime.atZone(ZoneId.systemDefault()).toInstant()));
								warningInfoEntity.setWarningStatus(WarningStatusEnum.STATUS_CLOSE.getCode());
								this.updateById(warningInfoEntity);
								//更新预警状态
								hashops.put(runInfokey, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_CLOSE.getCode()));
								//通知
								kafkaTemplate.send(topicYwxtWarning, JsonUtil.toJson(warningInfoEntity));

								log.info("水位整点上报延时恢复 {} {} {} ", rtuInfoEntity.getRtuCode(), rtuInfoEntity.getRtuName(), warningInfoEntity.getWarningRecoveryDesc());
							}
						}

						if (null == warnStatus) {
							//更新预警状态
							hashops.put(runInfokey, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_CLOSE.getCode()));
						}
					}
				}
			}
		}

		return true;
	}

	/**
	 * 5分钟雨量站上报延时检测
	 *
	 * @param rtuInfoEntity
	 * @param warnSettingEntity
	 * @param checkTime
	 * @return
	 */
	@Override
	public boolean checkRtuRainUpDelayStatus(RtuInfoEntity rtuInfoEntity, BaseWarnSettingEntity warnSettingEntity, LocalDateTime checkTime) {
//		if (rtuInfoEntity.getRtuCode().equals("40517675")) {
//			log.info("40517675");
//		}

		LocalDateTime startTime = checkTime.minusHours(1);
		RtuDataRainDTO dataRainDTO = new RtuDataRainDTO();
		dataRainDTO.setRtuCode(rtuInfoEntity.getRtuCode());
		Instant instant = startTime.atZone(ZoneId.systemDefault()).toInstant();
		dataRainDTO.setBeginTime(Date.from(instant));
		List<RtuDataRainStoreEntity> rainStoreEntityList = this.rainStoreService.selectList(dataRainDTO);
		if (null != rainStoreEntityList && rainStoreEntityList.size() >= 2) {
			boolean isWarn = false;
			Date firstUpTime = new Date();
			Date firstFromTime = new Date();
			Date secondUpTime = new Date();
			Date secondFromTime = new Date();
			long secondDelayDuration = 0;
			long firstDelayDuration = 0;
			for (int i = rainStoreEntityList.size(); i > 1; i--) {
				RtuDataRainStoreEntity firstUp = rainStoreEntityList.get(i - 2);
				boolean isBeforeWarn = false;
				firstUpTime = firstUp.getTm();
				firstFromTime = firstUp.getFromTime();
				firstDelayDuration = 0;
				if (firstUpTime.before(firstFromTime)) {
					//延时时长
					firstDelayDuration = (firstFromTime.getTime() - firstUpTime.getTime()) / 1000L;
					if (firstDelayDuration > warnSettingEntity.getWarnRainDelayMinDuration() * 60) {
						isBeforeWarn = true;
					}
				}
				RtuDataRainStoreEntity secondUp = rainStoreEntityList.get(i - 1);
				boolean isNowWarn = false;
				secondUpTime = secondUp.getTm();
				secondFromTime = secondUp.getFromTime();
				secondDelayDuration = 0;
				if (secondUpTime.before(secondFromTime)) {
					//延时时长，秒
					secondDelayDuration = (secondFromTime.getTime() - secondUpTime.getTime()) / 1000L;
					if (secondDelayDuration > warnSettingEntity.getWarnRainDelayMinDuration() * 60) {
						isNowWarn = true;
					}
				}
				if (isBeforeWarn && isNowWarn) {
					isWarn = true;
					break;
				}
			}
			HashOperations<String, String, String> hashops = redisTemplate.opsForHash();
			String key = RedisBusinessConstant.KEY_RTU_RUN_INFO + rtuInfoEntity.getRtuCode();
			String warnKindKey = RedisBusinessConstant.KEY_RTU_RUN_INFO_WARN_KIND + Func.toStr(WarnKindEnum.WARN_UP_MIN_DELAY.getCode());
			String warnStatus = hashops.get(key, warnKindKey);
			if (isWarn) {
				//延时异常
				boolean isCreateWarn = false;
				if (null != warnStatus) {
					if (WarningStatusEnum.STATUS_CLOSE.getCode() == Func.toInt(warnStatus)) {
						isCreateWarn = true;
					}
				} else {
					LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
					warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, rtuInfoEntity.getRtuCode());
					warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
					warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_UP_MIN_DELAY.getCode());
					RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
					if (null == warningInfoEntity) {
						isCreateWarn = true;
					}
				}
				if (isCreateWarn) {
					RtuWarningInfoEntity warningInfoEntity = new RtuWarningInfoEntity();
					warningInfoEntity.setRtuCode(rtuInfoEntity.getRtuCode());
					warningInfoEntity.setWarningHappenTime(Date.from(checkTime.atZone(ZoneId.systemDefault()).toInstant()));
					warningInfoEntity.setWarningStatus(WarningStatusEnum.STATUS_HAPPEN.getCode());
					warningInfoEntity.setWarningKind(WarnKindEnum.WARN_UP_MIN_DELAY.getCode());
					String desc = "雨情5分钟上报延时异常,延时设定参数：" + Func.toStr(warnSettingEntity.getWarnRainDelayMinDuration()) + "分钟";
					desc += ",第一个报文上报时间：" + Func.formatDateTime(firstFromTime) + " 采集时间：" + Func.formatDateTime(firstUpTime) + " 延时：" + Func.toStr(firstDelayDuration / 60L) + "分";
					desc += ",第二个报文上报时间：" + Func.formatDateTime(secondFromTime) + " 采集时间：" + Func.formatDateTime(secondUpTime) + " 延时：" + Func.toStr(secondDelayDuration / 60L) + "分";
					warningInfoEntity.setWarningDesc(desc);
					this.save(warningInfoEntity);
					//更新预警状态
					hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_HAPPEN.getCode()));
					//预警通知
					kafkaTemplate.send(topicYwxtWarning, JsonUtil.toJson(warningInfoEntity));
					log.info("雨情5分钟上报延时异常 {} {} {}", rtuInfoEntity.getRtuCode(), rtuInfoEntity.getRtuName(), desc);
				}
				if (null == warnStatus) {
					//更新预警状态
					hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_HAPPEN.getCode()));
				}
			} else {
				//没有检测到预警发生，进行预警恢复操作
				boolean isCloseWarn = false;
				if (null != warnStatus) {
					if (WarningStatusEnum.STATUS_HAPPEN.getCode() == Func.toInt(warnStatus)) {
						isCloseWarn = true;
					}
				} else {
					LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
					warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, rtuInfoEntity.getRtuCode());
					warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
					warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_UP_MIN_DELAY.getCode());
					RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
					if (null != warningInfoEntity) {
						isCloseWarn = true;
					}
				}
				if (isCloseWarn) {
					LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
					warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, rtuInfoEntity.getRtuCode());
					warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
					warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_UP_MIN_DELAY.getCode());
					RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
					if (null != warningInfoEntity) {
						//恢复
						warningInfoEntity.setWarningRecoveryTime(Date.from(checkTime.atZone(ZoneId.systemDefault()).toInstant()));
						warningInfoEntity.setWarningStatus(WarningStatusEnum.STATUS_CLOSE.getCode());
						String desc = "雨情5分钟上报延时恢复,延时设定参数：" + Func.toStr(warnSettingEntity.getWarnRainDelayMinDuration()) + "分钟";
						desc += ",第一个报文上报时间：" + Func.formatDateTime(firstFromTime) + " 采集时间：" + Func.formatDateTime(firstUpTime) + " 延时：" + Func.toStr(firstDelayDuration / 60L) + "分";
						desc += ",第二个报文上报时间：" + Func.formatDateTime(secondFromTime) + " 采集时间：" + Func.formatDateTime(secondUpTime) + " 延时：" + Func.toStr(secondDelayDuration / 60L) + "分";
						warningInfoEntity.setWarningRecoveryDesc(desc);
						this.updateById(warningInfoEntity);
						//更新预警状态
						hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_CLOSE.getCode()));
						//预警通知
						kafkaTemplate.send(topicYwxtWarning, JsonUtil.toJson(warningInfoEntity));
						log.info("雨情5分钟上报延时恢复 {} {} {}", rtuInfoEntity.getRtuCode(), rtuInfoEntity.getRtuName(), desc);
					}
				}
				if (null == warnStatus) {
					//更新预警状态
					hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_CLOSE.getCode()));
				}
			}
		}

		return true;
	}

	/**
	 * 离线检测
	 *
	 * @param rtuInfoEntity
	 * @param warnSettingEntity
	 * @param checkTime
	 * @return
	 */
	@Override
	public boolean checkRtuOfflineStatus(RtuInfoEntity rtuInfoEntity, BaseWarnSettingEntity warnSettingEntity, LocalDateTime checkTime) {

		boolean isOffline = false;
		int checkCount = 0;
		int warnCount = 0;
		StringBuilder offlineDurationSettingText = new StringBuilder();
		StringBuilder offlineDurationText = new StringBuilder();
		boolean hasUp = false;
		HashOperations<String, String, String> hashops = redisTemplate.opsForHash();
		String key = RedisBusinessConstant.KEY_RTU_RUN_INFO + rtuInfoEntity.getRtuCode();
		String lastDatetimeText = hashops.get(key, RedisBusinessConstant.KEY_RTU_RUN_INFO_LAST_TIME);

//		if (rtuInfoEntity.getRtuCode().equals("1507000057")) {
//			log.info("1507000057");
//			hashops.put(key, RedisBusinessConstant.KEY_RTU_RUN_INFO_OFFLINE_CHECK_POINT_TIME, "2023-11-15 10:00:00");
//		}

		if (null != lastDatetimeText && lastDatetimeText.length() > 0) {
			hasUp = true;
			LocalDateTime lastDateTime = LocalDateTime.parse(lastDatetimeText, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
			if (checkTime.isEqual(lastDateTime) || checkTime.isAfter(lastDateTime)) {
				long day = ChronoUnit.DAYS.between(lastDateTime, checkTime);
				offlineDurationText.append(Func.toStr(day)).append("天");
				long hours = ChronoUnit.HOURS.between(lastDateTime, checkTime);
				if (hours > 0) {
					offlineDurationText.append(Func.toStr(hours % 24)).append("小时");
				}
				//雨量站
//				if (rtuInfoEntity.getIsRain() != null && rtuInfoEntity.getIsRain() == 1) {
//					checkCount += 1;
//					if (hours >= warnSettingEntity.getWarnRainOfflineDuration()) {
//						warnCount += 1;
//						offlineDurationSettingText += "雨量站阀值(小时)：" + Func.toStr(warnSettingEntity.getWarnRainOfflineDuration());
//					}
//				}
				//河道水位站,水库水位站
			//	if (rtuInfoEntity.getIsRiver() != null && rtuInfoEntity.getIsRiver() == 1) {
					//checkCount += 1;
					if (hours >= warnSettingEntity.getWarnRiverOfflineDuration()) {
						warnCount += 1;
//						if (offlineDurationSettingText.length() > 0) {
//							offlineDurationSettingText += ",";
//						}
						offlineDurationSettingText.append("阀值(小时)：").append(Func.toStr(warnSettingEntity.getWarnRiverOfflineDuration()));
					}
				//}

//				else if (rtuInfoEntity.getIsRes() != null && rtuInfoEntity.getIsRes() == 1) {
//					checkCount += 1;
//					if (hours >= warnSettingEntity.getWarnRsvrOfflineDuration()) {
//						warnCount += 1;
//						if (offlineDurationSettingText.length() > 0) {
//							offlineDurationSettingText += ",";
//						}
//						offlineDurationSettingText += "水位站阀值(小时)：" + Func.toStr(warnSettingEntity.getWarnRsvrOfflineDuration());
//					}
//				}
				//墒情站
//				if (rtuInfoEntity.getIsGround() != null && rtuInfoEntity.getIsGround() == 1) {
//					checkCount += 1;
//					if (hours >= warnSettingEntity.getWarnGroundOfflineDuration()) {
//						warnCount += 1;
//						if (offlineDurationSettingText.length() > 0) {
//							offlineDurationSettingText += ",";
//						}
//						offlineDurationSettingText += "墒情站阀值(小时)：" + Func.toStr(warnSettingEntity.getWarnGroundOfflineDuration());
//					}
//				}
			}
		} else {
			String offlineCheckLastTimeText = hashops.get(key, RedisBusinessConstant.KEY_RTU_RUN_INFO_OFFLINE_CHECK_POINT_TIME);
			if (null != offlineCheckLastTimeText && offlineCheckLastTimeText.length() > 0) {
				LocalDateTime lastDateTime = LocalDateTime.parse(offlineCheckLastTimeText, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
				long hours = ChronoUnit.HOURS.between(lastDateTime, checkTime);
				//雨量站
//				if (rtuInfoEntity.getIsRain() != null && rtuInfoEntity.getIsRain() == 1) {
//					checkCount += 1;
//					if (hours >= warnSettingEntity.getWarnRainOfflineDuration()) {
//						warnCount += 1;
//						offlineDurationSettingText += "雨量站阀值(小时)：" + Func.toStr(warnSettingEntity.getWarnRainOfflineDuration());
//					}
//				}
				//河道水位站,水库水位站
				//if (rtuInfoEntity.getIsRiver() != null && rtuInfoEntity.getIsRiver() == 1) {
				//	checkCount += 1;
					if (hours >= warnSettingEntity.getWarnRiverOfflineDuration()) {
						warnCount += 1;
//						if (offlineDurationSettingText.length() > 0) {
//							offlineDurationSettingText += ",";
//						}
						offlineDurationSettingText.append("水位站阀值(小时)：").append(Func.toStr(warnSettingEntity.getWarnRiverOfflineDuration()));
					}
			//	}

//				else if (rtuInfoEntity.getIsRes() != null && rtuInfoEntity.getIsRes() == 1) {
//					checkCount += 1;
//					if (hours >= warnSettingEntity.getWarnRsvrOfflineDuration()) {
//						warnCount += 1;
//						if (offlineDurationSettingText.length() > 0) {
//							offlineDurationSettingText += ",";
//						}
//						offlineDurationSettingText += "水位站阀值(小时)：" + Func.toStr(warnSettingEntity.getWarnRsvrOfflineDuration());
//					}
//				}
				//墒情站
//				if (rtuInfoEntity.getIsGround() != null && rtuInfoEntity.getIsGround() == 1) {
//					checkCount += 1;
//					if (hours >= warnSettingEntity.getWarnGroundOfflineDuration()) {
//						warnCount += 1;
//						if (offlineDurationSettingText.length() > 0) {
//							offlineDurationSettingText += ",";
//						}
//						offlineDurationSettingText += "墒情站阀值(小时)：" + Func.toStr(warnSettingEntity.getWarnGroundOfflineDuration());
//					}
//				}
			} else {

				hashops.put(key, RedisBusinessConstant.KEY_RTU_RUN_INFO_OFFLINE_CHECK_POINT_TIME, checkTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
			}
		}
		String warnKindKey = RedisBusinessConstant.KEY_RTU_RUN_INFO_WARN_KIND + Func.toStr(WarnKindEnum.WARN_OFFLINE.getCode());
		String warnStatus = hashops.get(key, warnKindKey);
		//if (checkCount > 0) {
			//所有检测对像都已经离线时，产生离线预警
			if (1 == warnCount) {
				//触发预警
				boolean isCreateWarn = false;
				if (null != warnStatus) {
					if (WarningStatusEnum.STATUS_CLOSE.getCode() == Func.toInt(warnStatus)) {
						isCreateWarn = true;
					}
				} else {
					LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
					warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, rtuInfoEntity.getRtuCode());
					warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
					warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_OFFLINE.getCode());
					RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
					if (null == warningInfoEntity) {
						isCreateWarn = true;
					}
				}

				if (isCreateWarn) {
					RtuWarningInfoEntity entity = new RtuWarningInfoEntity();
					entity.setRtuCode(rtuInfoEntity.getRtuCode());
					entity.setWarningHappenTime(Date.from(checkTime.atZone(ZoneId.systemDefault()).toInstant()));
					entity.setWarningStatus(WarningStatusEnum.STATUS_HAPPEN.getCode());
					entity.setWarningKind(WarnKindEnum.WARN_OFFLINE.getCode());
					if (null != lastDatetimeText && lastDatetimeText.length() > 0) {
						LocalDateTime lastDateTime = LocalDateTime.parse(lastDatetimeText, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
						entity.setRtuLastTime(Date.from(lastDateTime.atZone(ZoneId.systemDefault()).toInstant()));
						entity.setWarningDesc("测站离线异常,检测时间：" + Func.formatDateTime(entity.getWarningHappenTime()) + ",测站最后上线时间：" + Func.formatDateTime(entity.getRtuLastTime()) + ",离线设定参数：" + offlineDurationSettingText);
					} else {
						entity.setWarningDesc("测站离线异常,检测时间：" + Func.formatDateTime(entity.getWarningHappenTime()) + ",未检测到数据上报,离线设定参数：" + offlineDurationSettingText);
					}
					this.save(entity);
					//更新预警状态
					hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_HAPPEN.getCode()));
					//预警通知
					kafkaTemplate.send(topicYwxtWarning, JsonUtil.toJson(entity));
					log.info("测站离线异常 {} {} {}", rtuInfoEntity.getRtuCode(), rtuInfoEntity.getRtuName(), entity.getWarningDesc());
				}
				if (null == warnStatus) {
					//更新预警状态
					hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_HAPPEN.getCode()));
				}
				isOffline = true;
			} else {
				if (hasUp) {
					boolean isCloseWarn = false;
					if (null != warnStatus) {
						if (WarningStatusEnum.STATUS_HAPPEN.getCode() == Func.toInt(warnStatus)) {
							isCloseWarn = true;
						}
					} else {
						LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
						warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, rtuInfoEntity.getRtuCode());
						warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
						warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_OFFLINE.getCode());
						RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
						if (null != warningInfoEntity) {
							isCloseWarn = true;
						}
					}
					if (isCloseWarn) {
						//恢复
						LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
						warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, rtuInfoEntity.getRtuCode());
						warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
						warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_OFFLINE.getCode());
						RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
						if (null != warningInfoEntity) {
							String warningRecoveryDesc = "";
							LocalDateTime lastDateTime = LocalDateTime.parse(lastDatetimeText, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
							warningRecoveryDesc = "测站离线异常恢复,检测时间：" + Func.formatDateTime(Date.from(checkTime.atZone(ZoneId.systemDefault()).toInstant())) + ",测站恢复上线时间：" + Func.formatDateTime(Date.from(lastDateTime.atZone(ZoneId.systemDefault()).toInstant())) + ",离线设定参数：" + offlineDurationSettingText + ",测站离线时长：" + offlineDurationText;
							warningInfoEntity.setWarningRecoveryDesc(warningRecoveryDesc);
							warningInfoEntity.setWarningRecoveryTime(Date.from(checkTime.atZone(ZoneId.systemDefault()).toInstant()));
							warningInfoEntity.setWarningStatus(WarningStatusEnum.STATUS_CLOSE.getCode());
							this.updateById(warningInfoEntity);
							//更新预警状态
							hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_CLOSE.getCode()));
							//预警通知
							kafkaTemplate.send(topicYwxtWarning, JsonUtil.toJson(warningInfoEntity));
							log.info("测站离线异常恢复 {} {} {}", rtuInfoEntity.getRtuCode(), rtuInfoEntity.getRtuName(), warningRecoveryDesc);
						}
					}
				}
				if (null == warnStatus) {
					//更新预警状态
					hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_CLOSE.getCode()));
				}
			}
		//}
		return isOffline;
	}

	@Override
	public boolean checkRtuRainMissOutStatus(RtuInfoEntity rtuInfoEntity, BaseWarnSettingEntity warnSettingEntity, LocalDateTime checkTime) {
//		if (rtuInfoEntity.getRtuCode().equals("01718550")) {
//			log.info("01718550");
//		}
		//为了处理补报的情况，前推12小时进行检测
		LocalDateTime endTime = checkTime.minusHours(12).withMinute(0);
		LocalDateTime startTime = endTime.minusDays(1);
		RtuDataRainDTO dataRainDTO = new RtuDataRainDTO();
		dataRainDTO.setRtuCode(rtuInfoEntity.getRtuCode());
		dataRainDTO.setIntv(1.0);
		Instant instant = startTime.atZone(ZoneId.systemDefault()).toInstant();
		dataRainDTO.setBeginTime(Date.from(instant));
		instant = endTime.atZone(ZoneId.systemDefault()).toInstant();
		dataRainDTO.setEndTime(Date.from(instant));
		List<RtuDataRainStoreEntity> rainStoreEntityList = this.rainStoreService.selectList(dataRainDTO);
		if (null != rainStoreEntityList && rainStoreEntityList.size() > 0) {
			HashOperations<String, String, String> hashops = redisTemplate.opsForHash();
			String key = RedisBusinessConstant.KEY_RTU_RUN_INFO + rtuInfoEntity.getRtuCode();
			String warnKindKey = RedisBusinessConstant.KEY_RTU_RUN_INFO_WARN_KIND + Func.toStr(WarnKindEnum.WARN_RAIN_MISS_OUT.getCode());
			String warnStatus = hashops.get(key, warnKindKey);
			//漏报的报文数量
			int upCount = rainStoreEntityList.size();
			int missCount = 24 - upCount;
			if (missCount >= warnSettingEntity.getWarnMissNum()) {
				//检测是否上报过,避免是新上线测站误报
				instant = startTime.atZone(ZoneId.systemDefault()).toInstant();
				dataRainDTO.setEndTime(Date.from(instant));
				List<RtuDataRainStoreEntity> lastRainStoreEntityList = this.rainStoreService.selectLast(dataRainDTO);
				if (null != lastRainStoreEntityList && lastRainStoreEntityList.size() > 0) {
					//触发预警
					boolean isCreateWarn = false;
					if (null != warnStatus) {
						if (WarningStatusEnum.STATUS_CLOSE.getCode() == Func.toInt(warnStatus)) {
							isCreateWarn = true;
						}
					} else {
						LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
						warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, rtuInfoEntity.getRtuCode());
						warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
						warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_RAIN_MISS_OUT.getCode());
						RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
						if (null == warningInfoEntity) {
							isCreateWarn = true;
						}
					}
					if (isCreateWarn) {
						StringBuilder upTimeMessage = new StringBuilder();
						for (RtuDataRainStoreEntity rainStoreEntity : rainStoreEntityList) {
							String tmText = Func.formatDateTime(rainStoreEntity.getTm());
							if (upTimeMessage.length() > 0) {
								upTimeMessage.append(",");
							}
							upTimeMessage.append(tmText);
						}
						RtuWarningInfoEntity entity = new RtuWarningInfoEntity();
						entity.setRtuCode(rtuInfoEntity.getRtuCode());
						entity.setWarningHappenTime(Date.from(checkTime.atZone(ZoneId.systemDefault()).toInstant()));
						entity.setWarningStatus(WarningStatusEnum.STATUS_HAPPEN.getCode());
						entity.setWarningKind(WarnKindEnum.WARN_RAIN_MISS_OUT.getCode());
						entity.setWarningDesc("测站雨量漏报异常,检测时间：" + Func.formatDateTime(entity.getWarningHappenTime()) + ",24小时内漏报数量:" + missCount + ",24小时内上报时间：" + upTimeMessage.toString());
						this.save(entity);
						//更新预警状态
						hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_HAPPEN.getCode()));
						//预警通知
						kafkaTemplate.send(topicYwxtWarning, JsonUtil.toJson(entity));
						log.info("测站雨量漏报异常 {} {} {} ", rtuInfoEntity.getRtuCode(), rtuInfoEntity.getRtuName(), entity.getWarningDesc());
					}
					if (null == warnStatus) {
						//更新预警状态
						hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_HAPPEN.getCode()));
					}
				}
			} else {
				//恢复
				boolean isCloseWarn = false;
				if (null != warnStatus) {
					if (WarningStatusEnum.STATUS_HAPPEN.getCode() == Func.toInt(warnStatus)) {
						isCloseWarn = true;
					}
				} else {
					LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
					warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, rtuInfoEntity.getRtuCode());
					warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
					warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_RAIN_MISS_OUT.getCode());
					RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
					if (null != warningInfoEntity) {
						isCloseWarn = true;
					}
				}
				if (isCloseWarn) {
					LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
					warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, rtuInfoEntity.getRtuCode());
					warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
					warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_RAIN_MISS_OUT.getCode());
					RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
					if (null != warningInfoEntity) {
						//恢复
						warningInfoEntity.setWarningRecoveryDesc("测站雨量漏报恢复,检测时间：" + Func.formatDateTime(Date.from(checkTime.atZone(ZoneId.systemDefault()).toInstant())) + ",24小时内上报数量:" + upCount);
						warningInfoEntity.setWarningRecoveryTime(Date.from(checkTime.atZone(ZoneId.systemDefault()).toInstant()));
						warningInfoEntity.setWarningStatus(WarningStatusEnum.STATUS_CLOSE.getCode());
						this.updateById(warningInfoEntity);
						//更新预警状态
						hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_CLOSE.getCode()));
						//预警通知
						kafkaTemplate.send(topicYwxtWarning, JsonUtil.toJson(warningInfoEntity));
						log.info("测站雨量漏报恢复 {} {} {} ", rtuInfoEntity.getRtuCode(), rtuInfoEntity.getRtuName(), warningInfoEntity.getWarningRecoveryDesc());
					}
				}
				if (null == warnStatus) {
					//更新预警状态
					hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_CLOSE.getCode()));
				}
			}
		}
		return true;
	}

	@Override
	public boolean checkRtuRiverMissOutStatus(RtuInfoEntity rtuInfoEntity, BaseWarnSettingEntity warnSettingEntity, LocalDateTime checkTime) {
//		if (rtuInfoEntity.getRtuCode().equals("01710140")) {
//			log.info("01710140");
//		}
		//为了处理补报的情况，前推12小时进行检测
		LocalDateTime endTime = checkTime.minusHours(12).withMinute(0);
		LocalDateTime startTime = endTime.minusDays(1);
		RtuDataRiverDTO dataRiverDTO = new RtuDataRiverDTO();
		dataRiverDTO.setRtuCode(rtuInfoEntity.getRtuCode());
		Instant instant = startTime.atZone(ZoneId.systemDefault()).toInstant();
		dataRiverDTO.setBeginTime(Date.from(instant));
		instant = endTime.atZone(ZoneId.systemDefault()).toInstant();
		dataRiverDTO.setEndTime(Date.from(instant));
		List<RtuDataRiverStoreEntity> riverStoreEntityList = this.riverStoreService.selectList(dataRiverDTO);
		if (null != riverStoreEntityList && riverStoreEntityList.size() > 0) {
			StringBuilder upTimeMessage = new StringBuilder();
			int upCount = 0;
			for (int d = 0; d < 24; d++) {
				LocalDateTime hourDateTime = startTime.plusHours(d);
				for (RtuDataRiverStoreEntity riverStoreEntity : riverStoreEntityList) {
					LocalDateTime upHourDateTime = LocalDateTime.ofInstant(riverStoreEntity.getTm().toInstant(), ZoneId.systemDefault());
					if (hourDateTime.isEqual(upHourDateTime)) {
						upCount += 1;
						String tmText = Func.formatDateTime(riverStoreEntity.getTm());
						if (upTimeMessage.length() > 0) {
							upTimeMessage.append(",");
						}
						upTimeMessage.append(tmText);
						break;
					}
				}
			}
			HashOperations<String, String, String> hashops = redisTemplate.opsForHash();
			String key = RedisBusinessConstant.KEY_RTU_RUN_INFO + rtuInfoEntity.getRtuCode();
			String warnKindKey = RedisBusinessConstant.KEY_RTU_RUN_INFO_WARN_KIND + Func.toStr(WarnKindEnum.WARN_WL_MISS_OUT.getCode());
			String warnStatus = hashops.get(key, warnKindKey);
			//漏报的报文数量
			int missCount = 24 - upCount;
			if (missCount >= warnSettingEntity.getWarnMissNum()) {

				//检测是否上报过,避免是新上线测站误报
				instant = startTime.atZone(ZoneId.systemDefault()).toInstant();
				dataRiverDTO.setEndTime(Date.from(instant));
				List<RtuDataRiverStoreEntity> lastRiverStoreEntityList = this.riverStoreService.selectLast(dataRiverDTO);
				if (null != lastRiverStoreEntityList && lastRiverStoreEntityList.size() > 0) {

					//触发预警
					boolean isCreateWarn = false;
					if (null != warnStatus) {
						if (WarningStatusEnum.STATUS_CLOSE.getCode() == Func.toInt(warnStatus)) {
							isCreateWarn = true;
						}
					} else {
						LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
						warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, rtuInfoEntity.getRtuCode());
						warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
						warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_WL_MISS_OUT.getCode());
						RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
						if (null == warningInfoEntity) {
							isCreateWarn = true;
						}
					}

					if (isCreateWarn) {
						RtuWarningInfoEntity entity = new RtuWarningInfoEntity();
						entity.setRtuCode(rtuInfoEntity.getRtuCode());
						entity.setWarningHappenTime(Date.from(checkTime.atZone(ZoneId.systemDefault()).toInstant()));
						entity.setWarningStatus(WarningStatusEnum.STATUS_HAPPEN.getCode());
						entity.setWarningKind(WarnKindEnum.WARN_WL_MISS_OUT.getCode());
						entity.setWarningDesc("测站水位漏报异常,检测时间：" + Func.formatDateTime(entity.getWarningHappenTime()) + ",24小时内漏报数量:" + missCount + ",24小时内上报时间：" + upTimeMessage.toString());
						this.save(entity);
						//更新预警状态
						hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_HAPPEN.getCode()));
						//预警通知
						kafkaTemplate.send(topicYwxtWarning, JsonUtil.toJson(entity));
						log.info("测站水位漏报异常 {} {} {}", rtuInfoEntity.getRtuCode(), rtuInfoEntity.getRtuName(), entity.getWarningDesc());
					}
					if (null == warnStatus) {
						//更新预警状态
						hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_HAPPEN.getCode()));
					}
				}
			} else {
				//恢复
				boolean isCloseWarn = false;
				if (null != warnStatus) {
					if (WarningStatusEnum.STATUS_HAPPEN.getCode() == Func.toInt(warnStatus)) {
						isCloseWarn = true;
					}
				} else {
					LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
					warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, rtuInfoEntity.getRtuCode());
					warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
					warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_WL_MISS_OUT.getCode());
					RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
					if (null != warningInfoEntity) {
						isCloseWarn = true;
					}
				}
				if (isCloseWarn) {
					LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
					warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, rtuInfoEntity.getRtuCode());
					warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
					warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_WL_MISS_OUT.getCode());
					RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
					if (null != warningInfoEntity) {
						//恢复
						warningInfoEntity.setWarningRecoveryDesc("测站水位漏报恢复,检测时间：" + Func.formatDateTime(Date.from(checkTime.atZone(ZoneId.systemDefault()).toInstant())) + ",24小时内上报数量:" + upCount);
						warningInfoEntity.setWarningRecoveryTime(Date.from(checkTime.atZone(ZoneId.systemDefault()).toInstant()));
						warningInfoEntity.setWarningStatus(WarningStatusEnum.STATUS_CLOSE.getCode());
						this.updateById(warningInfoEntity);
						//更新预警状态
						hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_CLOSE.getCode()));
						//预警通知
						kafkaTemplate.send(topicYwxtWarning, JsonUtil.toJson(warningInfoEntity));
						log.info("测站水位漏报恢复 {} {} {}", rtuInfoEntity.getRtuCode(), rtuInfoEntity.getRtuName(), warningInfoEntity.getWarningRecoveryDesc());
					}
				}

				if (null == warnStatus) {
					//更新预警状态
					hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_CLOSE.getCode()));
				}
			}
		}
		return true;
	}

	@Override
	public boolean checkRtuRsvrMissOutStatus(RtuInfoEntity rtuInfoEntity, BaseWarnSettingEntity warnSettingEntity, LocalDateTime checkTime) {
//		if (rtuInfoEntity.getRtuCode().equals("01710140")) {
//			log.info("01710140");
//		}
		//为了处理补报的情况，前推12小时进行检测
		LocalDateTime endTime = checkTime.minusHours(12).withMinute(0);
		LocalDateTime startTime = endTime.minusDays(1);
		RtuDataRsvrDTO dataRsvrDTO = new RtuDataRsvrDTO();
		dataRsvrDTO.setRtuCode(rtuInfoEntity.getRtuCode());
		Instant instant = startTime.atZone(ZoneId.systemDefault()).toInstant();
		dataRsvrDTO.setBeginTime(Date.from(instant));
		instant = endTime.atZone(ZoneId.systemDefault()).toInstant();
		dataRsvrDTO.setEndTime(Date.from(instant));
		List<RtuDataRsvrStoreEntity> rsvrStoreEntityList = this.rsvrStoreService.selectList(dataRsvrDTO);
		if (null != rsvrStoreEntityList && rsvrStoreEntityList.size() > 0) {
			StringBuilder upTimeMessage = new StringBuilder();
			int upCount = 0;
			for (int d = 0; d < 24; d++) {
				LocalDateTime hourDateTime = startTime.plusHours(d);
				for (RtuDataRsvrStoreEntity rsvrStoreEntity : rsvrStoreEntityList) {
					LocalDateTime upHourDateTime = LocalDateTime.ofInstant(rsvrStoreEntity.getTm().toInstant(), ZoneId.systemDefault());
					if (hourDateTime.isEqual(upHourDateTime)) {
						upCount += 1;
						String tmText = Func.formatDateTime(rsvrStoreEntity.getTm());
						if (upTimeMessage.length() > 0) {
							upTimeMessage.append(",");
						}
						upTimeMessage.append(tmText);
						break;
					}
				}
			}
			HashOperations<String, String, String> hashops = redisTemplate.opsForHash();
			String key = RedisBusinessConstant.KEY_RTU_RUN_INFO + rtuInfoEntity.getRtuCode();
			String warnKindKey = RedisBusinessConstant.KEY_RTU_RUN_INFO_WARN_KIND + Func.toStr(WarnKindEnum.WARN_WL_MISS_OUT.getCode());
			String warnStatus = hashops.get(key, warnKindKey);
			//漏报的报文数量
			int missCount = 24 - upCount;
			if (missCount >= warnSettingEntity.getWarnMissNum()) {
				//检测是否上报过,避免是新上线测站误报
				instant = startTime.atZone(ZoneId.systemDefault()).toInstant();
				dataRsvrDTO.setEndTime(Date.from(instant));
				List<RtuDataRsvrStoreEntity> lastRsvrStoreEntityList = this.rsvrStoreService.selectLast(dataRsvrDTO);
				if (null != lastRsvrStoreEntityList && lastRsvrStoreEntityList.size() > 0) {
					//触发预警
					boolean isCreateWarn = false;
					if (null != warnStatus) {
						if (WarningStatusEnum.STATUS_CLOSE.getCode() == Func.toInt(warnStatus)) {
							isCreateWarn = true;
						}
					} else {
						LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();

						warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, rtuInfoEntity.getRtuCode());
						warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
						warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_WL_MISS_OUT.getCode());
						RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
						if (null == warningInfoEntity) {
							isCreateWarn = true;
						}
					}

					if (isCreateWarn) {
						RtuWarningInfoEntity entity = new RtuWarningInfoEntity();
						entity.setRtuCode(rtuInfoEntity.getRtuCode());
						entity.setWarningHappenTime(Date.from(checkTime.atZone(ZoneId.systemDefault()).toInstant()));
						entity.setWarningStatus(WarningStatusEnum.STATUS_HAPPEN.getCode());
						entity.setWarningKind(WarnKindEnum.WARN_WL_MISS_OUT.getCode());
						entity.setWarningDesc("测站水位漏报异常,检测时间：" + Func.formatDateTime(entity.getWarningHappenTime()) + ",24小时内漏报数量:" + missCount + ",24小时内上报时间：" + upTimeMessage.toString());
						this.save(entity);
						//更新预警状态
						hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_HAPPEN.getCode()));
						//预警通知
						kafkaTemplate.send(topicYwxtWarning, JsonUtil.toJson(entity));
						log.info("测站水位漏报异常 {} {} {}", rtuInfoEntity.getRtuCode(), rtuInfoEntity.getRtuName(), entity.getWarningDesc());
					}
					if (null == warnStatus) {
						//更新预警状态
						hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_HAPPEN.getCode()));
					}
				}
			} else {
				//恢复
				boolean isCloseWarn = false;
				if (null != warnStatus) {
					if (WarningStatusEnum.STATUS_HAPPEN.getCode() == Func.toInt(warnStatus)) {
						isCloseWarn = true;
					}
				} else {
					LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
					warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, rtuInfoEntity.getRtuCode());
					warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
					warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_WL_MISS_OUT.getCode());
					RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
					if (null != warningInfoEntity) {
						isCloseWarn = true;
					}
				}

				if (isCloseWarn) {
					LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
					warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, rtuInfoEntity.getRtuCode());
					warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
					warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_WL_MISS_OUT.getCode());
					RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
					if (null != warningInfoEntity) {
						//恢复
						warningInfoEntity.setWarningRecoveryDesc("测站水位漏报恢复,检测时间：" + Func.formatDateTime(Date.from(checkTime.atZone(ZoneId.systemDefault()).toInstant())) + ",24小时内上报数量:" + upCount);
						warningInfoEntity.setWarningRecoveryTime(Date.from(checkTime.atZone(ZoneId.systemDefault()).toInstant()));
						warningInfoEntity.setWarningStatus(WarningStatusEnum.STATUS_CLOSE.getCode());
						this.updateById(warningInfoEntity);
						//更新预警状态
						hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_CLOSE.getCode()));
						//预警通知
						kafkaTemplate.send(topicYwxtWarning, JsonUtil.toJson(warningInfoEntity));
						log.info("测站水位漏报恢复 {} {} {}", rtuInfoEntity.getRtuCode(), rtuInfoEntity.getRtuName(), warningInfoEntity.getWarningRecoveryDesc());
					}
				}
				if (null == warnStatus) {
					//更新预警状态
					hashops.put(key, warnKindKey, Func.toStr(WarningStatusEnum.STATUS_CLOSE.getCode()));
				}
			}
		}
		return true;
	}

	@Override
	public boolean checkRtuOutlierValueStatus(RtuInfoEntity rtuInfoEntity, BaseWarnSettingEntity warnSettingEntity, LocalDateTime checkTime) {
		Date checkTm = new Date();
		String rtuCode = rtuInfoEntity.getRtuCode();
		HashOperations<String, String, String> ops = redisTemplate.opsForHash();
		String surfkey = RedisBusinessConstant.KEY_SURF_DATA + rtuCode;
		String surfTmValue = ops.get(surfkey, "upTime");
		if (null == surfTmValue) {
			return true;
		}
		String value1 = ops.get(surfkey, "lefttop.value");
		String value2 = ops.get(surfkey, "leftbottom.value");
		String value3 = ops.get(surfkey, "righttop.value");
		String value4 = ops.get(surfkey, "rightbottom.value");
		if (null == value1 || null == value2 || null == value3 || null == value4) {
			log.info("surf info is null");
			return true;
		}
		LocalDateTime surfTm = LocalDateTime.parse(surfTmValue, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")).withMinute(0);
		LocalDateTime endTime = surfTm.plusHours(1);
		RtuDataRainDTO dataRainDTO = new RtuDataRainDTO();
		dataRainDTO.setRtuCode(rtuInfoEntity.getRtuCode());
		dataRainDTO.setIntv(1.0);
		Instant instant = surfTm.atZone(ZoneId.systemDefault()).toInstant();
		dataRainDTO.setBeginTime(Date.from(instant));
		instant = endTime.atZone(ZoneId.systemDefault()).toInstant();
		dataRainDTO.setEndTime(Date.from(instant));
		List<RtuDataRainStoreEntity> rainStoreEntityList = this.rainStoreService.selectList(dataRainDTO);
		if (null != rainStoreEntityList && rainStoreEntityList.size() > 0) {
			for (RtuDataRainStoreEntity entity : rainStoreEntityList) {
				LocalDateTime hourDateTime = LocalDateTime.ofInstant(entity.getTm().toInstant(), ZoneId.systemDefault()).withMinute(0);
				if (surfTm.isEqual(hourDateTime)) {
					float count = Func.toFloat(value1) + Func.toFloat(value2) + Func.toFloat(value3) + Func.toFloat(value4);
					if (count > 0) {
						count = count / 4;
					}
					Double drp = entity.getDrp();
					if (drp != null) {
						double baseValue = drp.doubleValue() - count;
						if (baseValue >= (double) outlierValue) {
							//疑似异常值
							LambdaQueryWrapper<RtuWarningInfoEntity> warningWrapper = Wrappers.<RtuWarningInfoEntity>query().lambda();
							warningWrapper.eq(RtuWarningInfoEntity::getIsDeleted, 0);
							warningWrapper.eq(RtuWarningInfoEntity::getRtuCode, rtuInfoEntity.getRtuCode());
							warningWrapper.eq(RtuWarningInfoEntity::getWarningStatus, WarningStatusEnum.STATUS_HAPPEN.getCode());
							warningWrapper.eq(RtuWarningInfoEntity::getWarningKind, WarnKindEnum.WARN_OUTLIER_VALUE.getCode());
							RtuWarningInfoEntity warningInfoEntity = this.getOne(warningWrapper);
							if (null == warningInfoEntity) {
								RtuWarningInfoEntity warningInfoEntity1 = new RtuWarningInfoEntity();
								warningInfoEntity1.setRtuCode(rtuInfoEntity.getRtuCode());
								warningInfoEntity1.setWarningHappenTime(checkTm);
								warningInfoEntity1.setWarningStatus(WarningStatusEnum.STATUS_HAPPEN.getCode());
								warningInfoEntity1.setWarningKind(WarnKindEnum.WARN_OUTLIER_VALUE.getCode());
								String desc = "测站采集雨量大于面雨量30mm，疑似异常值，";
								desc += "雨量采集时间：" + Func.formatDateTime(entity.getTm());
								desc += "，时段降雨：" + Func.toStr(entity.getDrp());
								desc += "，平均面雨量：" + Func.toStr(count);
								warningInfoEntity1.setWarningDesc(desc);
								this.save(warningInfoEntity1);
								//触发预警
								kafkaTemplate.send(topicYwxtWarning, JsonUtil.toJson(warningInfoEntity1));
							}
						}
					}
					break;
				}
			}
		}
		return true;
	}
}
