fix: 应该每次电话报警,就新增条消息,不能每次超过阈值就生成一条报警。

This commit is contained in:
tianyongbao
2026-03-18 22:36:13 +08:00
parent 01c039f249
commit c16580ac82
2 changed files with 68 additions and 5 deletions

View File

@@ -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) {
messageWarnMapper.insert(warn);
// 跳过已加入电话通知列表的告警(由 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
// 立即尝试发送第一个号码;若失败则后续通知记录会在定时任务中按时间发送