fix: 应该每次电话报警,就新增条消息,不能每次超过阈值就生成一条报警。
This commit is contained in:
@@ -1,8 +1,12 @@
|
||||
package com.intc.fishery.mapper;
|
||||
package com.intc.fishery.mapper;
|
||||
|
||||
import com.intc.common.mybatis.core.mapper.BaseMapperPlusJoin;
|
||||
import com.intc.fishery.domain.MessageWarn;
|
||||
import com.intc.fishery.domain.vo.MessageWarnVo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 设备告警记录Mapper接口
|
||||
@@ -12,4 +16,18 @@ import com.intc.fishery.domain.vo.MessageWarnVo;
|
||||
*/
|
||||
public interface MessageWarnMapper extends BaseMapperPlusJoin<MessageWarn, MessageWarnVo> {
|
||||
|
||||
/**
|
||||
* 查询指定设备、告警标题、时间范围内的告警消息数量
|
||||
* 用于对未开启电话通知的告警类型做时间窗口抑制,避免每次超阈值都重复写入记录
|
||||
*
|
||||
* @param deviceId 设备ID
|
||||
* @param title 告警标题
|
||||
* @param afterTime 起始时间
|
||||
* @return 满足条件的告警消息数量
|
||||
*/
|
||||
@Select("SELECT COUNT(1) FROM aqu_message_warn WHERE device_id = #{deviceId} AND title = #{title} AND create_time >= #{afterTime}")
|
||||
long countByDeviceAndTitleAfter(@Param("deviceId") Long deviceId,
|
||||
@Param("title") String title,
|
||||
@Param("afterTime") Date afterTime);
|
||||
|
||||
}
|
||||
|
||||
@@ -441,16 +441,55 @@ public class DeviceDataHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// 如果有告警,保存全部报警消息记录
|
||||
// 如果有告警,处理报警消息记录
|
||||
if (hasAlarm) {
|
||||
log.warn("[告警] {} - {}", deviceName, alarmMessage);
|
||||
|
||||
// 批量保存报警消息(无论是否开启电话通知,告警记录始终生成)
|
||||
// 计算抑制时间窗口(与电话通知保持一致)
|
||||
LocalDateTime suppressTime = LocalDateTime.now().minusHours(aliyunIotProperties.getCallSuccessSuppressHours());
|
||||
java.util.Date suppressDate = java.util.Date.from(suppressTime.atZone(java.time.ZoneId.systemDefault()).toInstant());
|
||||
int maxBatchMinutesForCheck = CALL_NOTICE_RETRY_COUNT * CALL_NOTICE_MINUTE_INTERVAL * 2;
|
||||
LocalDateTime activeBatchStartForCheck = LocalDateTime.now().minusMinutes(maxBatchMinutesForCheck);
|
||||
LocalDateTime periodStartForCheck = getCurrentPeriodStart();
|
||||
|
||||
// 对未开启电话通知的告警类型,做时间窗口抑制后再插入消息记录
|
||||
// 对开启了电话通知的类型,MessageWarn 由 triggerAlarmNotification 在通过抑制判断后统一插入
|
||||
for (MessageWarn warn : warnList) {
|
||||
// 跳过已加入电话通知列表的告警(由 triggerAlarmNotification 负责插入)
|
||||
if (callWarnList.contains(warn)) {
|
||||
continue;
|
||||
}
|
||||
// 判断该类型告警是否开启了免打扰
|
||||
boolean noDisturbForWarn = false;
|
||||
if (ALARM_TYPE_DISSOLVED_OXYGEN.equals(warn.getTitle()) &&
|
||||
device.getOxyWarnCallNoDis() != null && device.getOxyWarnCallNoDis() == 1) {
|
||||
noDisturbForWarn = true;
|
||||
} else if ((ALARM_TYPE_TEMPERATURE_HIGH.equals(warn.getTitle()) || ALARM_TYPE_TEMPERATURE_LOW.equals(warn.getTitle())) &&
|
||||
device.getTempWarnCallNoDis() != null && device.getTempWarnCallNoDis() == 1) {
|
||||
noDisturbForWarn = true;
|
||||
} else if (ALARM_TYPE_BATTERY.equals(warn.getTitle()) &&
|
||||
device.getBatteryWarnCallNoDis() != null && device.getBatteryWarnCallNoDis() == 1) {
|
||||
noDisturbForWarn = true;
|
||||
}
|
||||
// 按抑制规则判断是否应跳过
|
||||
boolean shouldSkip;
|
||||
if (noDisturbForWarn) {
|
||||
java.util.Date periodStartDate = java.util.Date.from(periodStartForCheck.atZone(java.time.ZoneId.systemDefault()).toInstant());
|
||||
shouldSkip = messageWarnMapper.countByDeviceAndTitleAfter(deviceId, warn.getTitle(), periodStartDate) > 0;
|
||||
} else {
|
||||
java.util.Date activeBatchStartDate = java.util.Date.from(activeBatchStartForCheck.atZone(java.time.ZoneId.systemDefault()).toInstant());
|
||||
shouldSkip = messageWarnMapper.countByDeviceAndTitleAfter(deviceId, warn.getTitle(), activeBatchStartDate) > 0
|
||||
|| messageWarnMapper.countByDeviceAndTitleAfter(deviceId, warn.getTitle(), suppressDate) > 0;
|
||||
}
|
||||
if (!shouldSkip) {
|
||||
messageWarnMapper.insert(warn);
|
||||
log.debug("[告警] {} title={} 新增消息记录", deviceName, warn.getTitle());
|
||||
} else {
|
||||
log.debug("[告警] {} title={} 抑制期内已有记录,跳过消息写入", deviceName, warn.getTitle());
|
||||
}
|
||||
}
|
||||
|
||||
// 仅对开启了电话通知开关的告警触发电话通知
|
||||
// 仅对开启了电话通知开关的告警触发电话通知(MessageWarn 由通知方法内部插入)
|
||||
if (!callWarnList.isEmpty()) {
|
||||
triggerAlarmNotification(device, alarmMessage.toString(), sensorData, callWarnList);
|
||||
}
|
||||
@@ -565,6 +604,12 @@ public class DeviceDataHandler {
|
||||
// 告警内容(取该类型第一条)
|
||||
String typeAlarmMessage = typeWarnList.get(0).getMessage();
|
||||
|
||||
// 通过抑制判断,先插入 MessageWarn 记录(每次电话报警才新增一条消息)
|
||||
for (MessageWarn warn : typeWarnList) {
|
||||
messageWarnMapper.insert(warn);
|
||||
}
|
||||
log.debug("[告警] {} title={} 通过抑制,已插入 {} 条告警消息记录", deviceName, title, typeWarnList.size());
|
||||
|
||||
// 为每个手机号 × 重试次数,创建通知记录,callTime 按间隔错开
|
||||
// 参考 C#: CallNoticeRetryCount=3, CallNoticeMinuteInterval=3
|
||||
// 立即尝试发送第一个号码;若失败则后续通知记录会在定时任务中按时间发送
|
||||
|
||||
Reference in New Issue
Block a user