|
@@ -0,0 +1,268 @@
|
|
|
+package com.huaxu.quartz.service;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.huaxu.client.UserCenterClient;
|
|
|
+import com.huaxu.common.CalcUtil;
|
|
|
+import com.huaxu.dao.alarm.DataAlarmAnalysisMapper;
|
|
|
+import com.huaxu.dao.alarm.DataAlarmDetailMapper;
|
|
|
+import com.huaxu.dao.alarm.DataAlarmManageMapper;
|
|
|
+import com.huaxu.dto.DeviceCheckAlarmDto;
|
|
|
+import com.huaxu.entity.Message;
|
|
|
+import com.huaxu.entity.alarm.DataAlarmAnalysisEntity;
|
|
|
+import com.huaxu.entity.alarm.DataAlarmDetailEntity;
|
|
|
+import com.huaxu.entity.alarm.DataAlarmManageEntity;
|
|
|
+import com.huaxu.util.DatesUtil;
|
|
|
+import com.huaxu.vo.DataAlarmManageVo;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.amqp.core.AmqpTemplate;
|
|
|
+import org.springframework.beans.BeanUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.util.CollectionUtils;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.time.LocalDate;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 数据报警处理
|
|
|
+ * @author lihui
|
|
|
+ * @date 2020-3-26
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+public abstract class AbstractDataAlarmJobService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ protected DataAlarmDetailMapper dataAlarmDetailMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ protected DataAlarmAnalysisMapper dataAlarmAnalysisMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ protected DataAlarmManageMapper dataAlarmManageMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ protected UserCenterClient userCenterClient;
|
|
|
+
|
|
|
+ @Resource(name = "messageRabbitTemplate")
|
|
|
+ private AmqpTemplate messageRabbitTemplate;
|
|
|
+
|
|
|
+ @Value("${receive.exchange.name}")
|
|
|
+ private String receiveExchangeName;
|
|
|
+
|
|
|
+ @Value("${dispath.routing.key}")
|
|
|
+ private String dispathRoutingKey;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 挂起
|
|
|
+ */
|
|
|
+ protected static final int HANG_UP = 1;
|
|
|
+
|
|
|
+ /***
|
|
|
+ * 执行入口
|
|
|
+ * @author lihui
|
|
|
+ * @date 18:48 2021/6/1
|
|
|
+ * @return void
|
|
|
+ **/
|
|
|
+ public void execute(){
|
|
|
+ List<DataAlarmManageVo> manageVoList = this.listDataAlarmManage();
|
|
|
+ if (CollectionUtils.isEmpty(manageVoList)) {
|
|
|
+ log.info("获取数据报警管理参数数据为空");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Map<Long, DataAlarmDetailEntity> alarmDetailsDtoMap = getMapDataAlarmDetail(manageVoList);
|
|
|
+ for (DataAlarmManageVo manageVo : manageVoList) {
|
|
|
+ DataAlarmManageEntity manageEntity = new DataAlarmManageEntity();
|
|
|
+ BeanUtils.copyProperties(manageVo, manageEntity);
|
|
|
+ DataAlarmDetailEntity nowDetailEntity = this.getAlarmValue(manageEntity);
|
|
|
+ if (nowDetailEntity == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ nowDetailEntity.setManageId(manageEntity.getId());
|
|
|
+ boolean isAlarm = isAlarm(nowDetailEntity, manageEntity);
|
|
|
+ // 必须先计算报警数据,才能执行保存数据报警分析操作,不然会丢失数据
|
|
|
+ this.saveDataAlarmAnalysis(nowDetailEntity);
|
|
|
+ // 计算出来属于报警,处理报警数据
|
|
|
+ if (isAlarm) {
|
|
|
+ handAlarm(alarmDetailsDtoMap, manageVo, nowDetailEntity);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // 存在报警信息,但已不报警,则更新为历史数据
|
|
|
+ if (alarmDetailsDtoMap.containsKey(manageEntity.getId())){
|
|
|
+ dataAlarmDetailMapper.updateHistoryData(alarmDetailsDtoMap.get(manageEntity.getId()).getId());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /***
|
|
|
+ * double转换BigDecimal
|
|
|
+ * @author lihui
|
|
|
+ * @date 11:48 2021/6/2
|
|
|
+ * @param receivedValue :
|
|
|
+ * @return java.math.BigDecimal
|
|
|
+ **/
|
|
|
+ protected BigDecimal toBigDecimal(Double receivedValue){
|
|
|
+ return receivedValue == null ? null : new BigDecimal(receivedValue.toString());
|
|
|
+ }
|
|
|
+
|
|
|
+ /***
|
|
|
+ * 保存报警数据
|
|
|
+ * @author lihui
|
|
|
+ * @date 11:09 2021/6/2
|
|
|
+ * @param detailEntity :
|
|
|
+ * @return void
|
|
|
+ **/
|
|
|
+ protected void saveDataAlarmDetail(DataAlarmDetailEntity detailEntity){
|
|
|
+ detailEntity.setAlarmStartTime(new Date());
|
|
|
+ detailEntity.setDateCreate(new Date());
|
|
|
+ detailEntity.setStatus(1);
|
|
|
+ dataAlarmDetailMapper.saveDataAlarmDetail(detailEntity);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /***
|
|
|
+ * 保存分析数据详情
|
|
|
+ * @author lihui
|
|
|
+ * @date 9:43 2021/6/2
|
|
|
+ * @param detailEntity :
|
|
|
+ * @return void
|
|
|
+ **/
|
|
|
+ protected void saveDataAlarmAnalysis(DataAlarmDetailEntity detailEntity){
|
|
|
+ DataAlarmAnalysisEntity analysisEntity = new DataAlarmAnalysisEntity();
|
|
|
+ BeanUtils.copyProperties(detailEntity, analysisEntity);
|
|
|
+ analysisEntity.setDateCreate(new Date());
|
|
|
+ analysisEntity.setStatus(1);
|
|
|
+ dataAlarmAnalysisMapper.saveDataAlarmAnalysis(analysisEntity);
|
|
|
+ }
|
|
|
+
|
|
|
+ /***
|
|
|
+ * 数据存在,需要根据当前设置的计算规则和正在报警的计算规则是否一样
|
|
|
+ * 一样:更新数据
|
|
|
+ * 不一样:更新该条正在报警的数据为历史数据,并新增一条新计算规则的报警数据
|
|
|
+ * this.sendMessage(manageEntity);
|
|
|
+ * @author lihui
|
|
|
+ * @date 11:06 2021/6/2
|
|
|
+ * @param alarmDetailsDtoMap : 现有报警数据
|
|
|
+ * @param manageVo : 报警设置数据
|
|
|
+ * @param nowDetailEntity : 当前报警数据
|
|
|
+ * @return void
|
|
|
+ **/
|
|
|
+ private void handAlarm(Map<Long, DataAlarmDetailEntity> alarmDetailsDtoMap, DataAlarmManageVo manageVo, DataAlarmDetailEntity nowDetailEntity){
|
|
|
+ if (!alarmDetailsDtoMap.containsKey(manageVo.getId())){
|
|
|
+ this.saveDataAlarmDetail(nowDetailEntity);
|
|
|
+ this.sendMessage(manageVo);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ DataAlarmDetailEntity dataAlarmDetailEntity = alarmDetailsDtoMap.get(manageVo.getId());
|
|
|
+ // 如果没有被挂起,就要发送消息提示
|
|
|
+ if (dataAlarmDetailEntity.getIsHangup() != HANG_UP){
|
|
|
+ this.sendMessage(manageVo);
|
|
|
+ }
|
|
|
+ // 检查计算规则是否有变更
|
|
|
+ if (manageVo.getMd5Query().equals(dataAlarmDetailEntity.getMd5Query())) {
|
|
|
+ dataAlarmDetailMapper.updateAlrarmData(dataAlarmDetailEntity);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 规则有变革,数据更新为历史数据,再添加一条新的历史报警记录
|
|
|
+ dataAlarmDetailMapper.updateHistoryData(dataAlarmDetailEntity.getId());
|
|
|
+ this.saveDataAlarmDetail(nowDetailEntity);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /***
|
|
|
+ * 获取报警数据
|
|
|
+ * @author lihui
|
|
|
+ * @date 10:58 2021/6/2
|
|
|
+ * @param manageVoList :
|
|
|
+ * @return java.util.Map<java.lang.Long,com.huaxu.entity.alarm.DataAlarmDetailEntity>
|
|
|
+ **/
|
|
|
+ private Map<Long, DataAlarmDetailEntity> getMapDataAlarmDetail(List<DataAlarmManageVo> manageVoList){
|
|
|
+ List<Long> manageIds = manageVoList.stream().map(DataAlarmManageVo::getId).collect(Collectors.toList());
|
|
|
+ List<DataAlarmDetailEntity> list = dataAlarmDetailMapper.listByManageId(manageIds);
|
|
|
+ if (CollectionUtils.isEmpty(list)){
|
|
|
+ return new HashMap<>();
|
|
|
+ }
|
|
|
+ return list.stream().collect(Collectors.toMap(DataAlarmDetailEntity::getManageId, a -> a,(k1, k2)->k1));
|
|
|
+ }
|
|
|
+
|
|
|
+ /***
|
|
|
+ * 判断是否触发报警
|
|
|
+ * @author lihui
|
|
|
+ * @date 18:22 2021/6/1
|
|
|
+ * @param dataAlarmDetailEntity :
|
|
|
+ * @param dataAlarmManageEntity :
|
|
|
+ * @return boolean
|
|
|
+ **/
|
|
|
+ private boolean isAlarm(DataAlarmDetailEntity dataAlarmDetailEntity, DataAlarmManageEntity dataAlarmManageEntity){
|
|
|
+ BigDecimal resultValue = CalcUtil.operation(dataAlarmDetailEntity.getBeAlarmValue(), dataAlarmManageEntity.getComputeRules(),
|
|
|
+ dataAlarmDetailEntity.getToAlarmValue());
|
|
|
+ dataAlarmDetailEntity.setResultAlarmValue(resultValue);
|
|
|
+ return CalcUtil.compareBySign(resultValue, dataAlarmManageEntity.getAlarmValue(), dataAlarmManageEntity.getAlarmRules());
|
|
|
+ }
|
|
|
+
|
|
|
+ /***
|
|
|
+ * 消息发送
|
|
|
+ * @author lihui
|
|
|
+ * @date 18:46 2021/6/1
|
|
|
+ * @param dataAlarmManageEntity :
|
|
|
+ * @return void
|
|
|
+ **/
|
|
|
+ private void sendMessage(DataAlarmManageVo dataAlarmManageEntity){
|
|
|
+ Message message = new Message();
|
|
|
+ message.setStatus(1);
|
|
|
+ message.setTenantId(dataAlarmManageEntity.getTenantId());
|
|
|
+ message.setMessageId(UUID.randomUUID().toString());
|
|
|
+ JSONObject jsonContent = new JSONObject();
|
|
|
+ // ${场景名称}${设备名称}【${报警字段}】异常报警
|
|
|
+ jsonContent.put("场景名称",dataAlarmManageEntity.getAlarmSettingRules());
|
|
|
+ jsonContent.put("设备名称","");
|
|
|
+ jsonContent.put("报警字段","");
|
|
|
+ // 消息内容,如果需要动态使用,配合模板使用{key:value}
|
|
|
+ message.setMessageContent(jsonContent.toJSONString());
|
|
|
+ // 消息类型、模板id、渠道
|
|
|
+ message.setMessageType(1);
|
|
|
+ message.setMessageTemplateId(1);
|
|
|
+ message.setChannel(0);
|
|
|
+ Integer companyOrgId = dataAlarmManageEntity.getCompanyOrgId();
|
|
|
+ Integer departmentOrgId = dataAlarmManageEntity.getDeptOrgId();
|
|
|
+ try{
|
|
|
+ List<Integer> taskUsers = userCenterClient.findUserIdsByPermissonOrg(dataAlarmManageEntity.getTenantId(),companyOrgId,departmentOrgId);
|
|
|
+ if (taskUsers == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ taskUsers.forEach(id -> {
|
|
|
+ message.setUserId(id);
|
|
|
+ this.send(message);
|
|
|
+ });
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error ("推送报警消息失败:{}",e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void send(Message message){
|
|
|
+ log.debug("消息发送 exchange={} routingkey={} 用户id={}",receiveExchangeName,dispathRoutingKey,message.getUserId());
|
|
|
+ messageRabbitTemplate.convertAndSend(receiveExchangeName, dispathRoutingKey, JSONObject.toJSONString(message));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /***
|
|
|
+ * 获取设置的报警参数
|
|
|
+ * @author lihui
|
|
|
+ * @date 18:15 2021/6/1
|
|
|
+ * @return java.util.List<com.huaxu.entity.alarm.DataAlarmManageEntity>
|
|
|
+ **/
|
|
|
+ protected abstract List<DataAlarmManageVo> listDataAlarmManage();
|
|
|
+
|
|
|
+ /***
|
|
|
+ * 获取报警值
|
|
|
+ * @author lihui
|
|
|
+ * @date 11:47 2021/6/2
|
|
|
+ * @param dataAlarmManageEntity : 报警设置参数
|
|
|
+ * @return com.huaxu.entity.alarm.DataAlarmDetailEntity
|
|
|
+ **/
|
|
|
+ protected abstract DataAlarmDetailEntity getAlarmValue(DataAlarmManageEntity dataAlarmManageEntity);
|
|
|
+
|
|
|
+}
|