fix: 电话通知报警,逻辑完善,改为报警电话列表获取电话号码,通知成功后24小时不再打电话等等。

This commit is contained in:
tianyongbao
2026-03-09 23:37:33 +08:00
parent abadce8318
commit 1676ef7599
7 changed files with 355 additions and 89 deletions

View File

@@ -48,4 +48,13 @@ public interface WarnCallNoticeService {
* @return 清理的记录数量
*/
int cleanupExpiredNotifications();
/**
* 扫描到期待发的通知记录,调用 VMS 发送语音通知
* 对应注释:“如失败则后续通知记录会在定时任务中按时间发送”
* 触发条件callStatus=0 且 callTime <= 当前时间
*
* @return 发送成功的数量
*/
int processPendingNotifications();
}

View File

@@ -4,8 +4,10 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.intc.iot.domain.AquWarnCallNotice;
import com.intc.iot.domain.VmsCallback;
import com.intc.iot.domain.VmsNoticeResponse;
import com.intc.iot.mapper.AquWarnCallNoticeMapper;
import com.intc.iot.mapper.VmsCallbackMapper;
import com.intc.iot.service.VmsNoticeService;
import com.intc.iot.service.WarnCallNoticeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -15,7 +17,9 @@ import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 告警电话通知服务实现
@@ -30,6 +34,7 @@ public class WarnCallNoticeServiceImpl implements WarnCallNoticeService {
private final AquWarnCallNoticeMapper warnCallNoticeMapper;
private final VmsCallbackMapper vmsCallbackMapper;
private final VmsNoticeService vmsNoticeService;
/**
* 呼叫状态枚举(对应 C# EnumCallNoticeStatus
@@ -48,9 +53,9 @@ public class WarnCallNoticeServiceImpl implements WarnCallNoticeService {
/**
* 回执超时时间(分钟)
* 对应 C# CallNoticeMinuteInterval = 3
* VMS 回执延迟较长,改为 5 分钟,避免回执未到就被标记为超时
*/
private static final int CALLBACK_TIMEOUT_MINUTES = 3;
private static final int CALLBACK_TIMEOUT_MINUTES = 5;
@Override
@Transactional(rollbackFor = Exception.class)
@@ -65,6 +70,7 @@ public class WarnCallNoticeServiceImpl implements WarnCallNoticeService {
// 优先从 outId格式ALARM_{callNoticeId}_{timestamp})中解析主键直接查询
// 若解析失败则回退到 callId 匹配
// 注意:不限制 callStatus避免超时清理后回执仍可被处理
AquWarnCallNotice callNotice = null;
String outId = callback.getOutId();
if (outId != null && outId.startsWith("ALARM_")) {
@@ -76,10 +82,9 @@ public class WarnCallNoticeServiceImpl implements WarnCallNoticeService {
callNotice = warnCallNoticeMapper.selectOne(
new LambdaQueryWrapper<AquWarnCallNotice>()
.eq(AquWarnCallNotice::getId, noticeId)
.eq(AquWarnCallNotice::getCallStatus, CALL_STATUS_CALL_SUCCESS)
);
if (callNotice != null) {
log.debug("[告警通知] 通过 outId 找到通知记录 - 记录ID: {}", noticeId);
log.debug("[告警通知] 通过 outId 找到通知记录 - 记录ID: {}, 当前状态: {}", noticeId, callNotice.getCallStatus());
}
}
} catch (NumberFormatException e) {
@@ -87,12 +92,11 @@ public class WarnCallNoticeServiceImpl implements WarnCallNoticeService {
}
}
// 回退:通过 callId 匹配
// 回退:通过 callId 匹配(同样不限制 callStatus
if (callNotice == null) {
callNotice = warnCallNoticeMapper.selectOne(
new LambdaQueryWrapper<AquWarnCallNotice>()
.eq(AquWarnCallNotice::getCallId, callback.getCallId())
.eq(AquWarnCallNotice::getCallStatus, CALL_STATUS_CALL_SUCCESS)
);
}
@@ -175,6 +179,11 @@ public class WarnCallNoticeServiceImpl implements WarnCallNoticeService {
return count;
}
/**
* 清理超时的通知记录
* 对应 C# CleanupExpiredNotifications
* 清理规则已呼叫成功callStatus=1但超过超时时间未收到回执的记录
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int cleanupExpiredNotifications() {
@@ -224,6 +233,85 @@ public class WarnCallNoticeServiceImpl implements WarnCallNoticeService {
return cleanedCount;
}
/**
* 扫描到期待发的通知记录,调用 VMS 发送语音通知
* 触发条件callStatus=0 且 callTime <= 当前时间
*/
@Override
public int processPendingNotifications() {
LocalDateTime now = LocalDateTime.now();
List<AquWarnCallNotice> pendingList = warnCallNoticeMapper.selectDuePendingNotices(now);
if (pendingList.isEmpty()) {
return 0;
}
log.info("[待发通知] 发现 {} 条到期待发通知记录,开始处理", pendingList.size());
int sentCount = 0;
for (AquWarnCallNotice notice : pendingList) {
try {
// 查询关联的告警消息内容,用于构建 TTS 参数
String rawMessage = warnCallNoticeMapper.selectWarnMessageByCallNoticeId(notice.getId());
String warnMessageShort = parseWarnMessageShort(rawMessage);
// 构建 TTS 参数
Map<String, String> ttsParams = new HashMap<>();
ttsParams.put("pondName", notice.getPondName() != null ? notice.getPondName() : "未知塘口");
ttsParams.put("deviceName", "设备");
ttsParams.put("warnMessage", warnMessageShort);
String outId = "ALARM_" + notice.getId() + "_" + System.currentTimeMillis();
VmsNoticeResponse response = vmsNoticeService.sendTtsCall(
notice.getMobilePhone(),
ttsParams,
outId
);
if (response != null && response.isSuccess()) {
notice.setCallStatus(CALL_STATUS_CALL_SUCCESS);
notice.setCallId(response.getCallId());
notice.setOutId(outId);
warnCallNoticeMapper.updateById(notice);
sentCount++;
log.info("[待发通知] 呼叫成功: {} - 记录ID: {}", notice.getMobilePhone(), notice.getId());
} else {
notice.setCallStatus(CALL_STATUS_CALL_FAIL);
notice.setStatusMsg(response != null ? response.getMessage() : "呼叫失败");
warnCallNoticeMapper.updateById(notice);
log.warn("[待发通知] 呼叫失败: {} - 原因: {}", notice.getMobilePhone(), notice.getStatusMsg());
}
} catch (Exception e) {
log.error("[待发通知] 处理待发通知异常 - 记录ID: {}, 电话: {}, 异常: {}",
notice.getId(), notice.getMobilePhone(), e.getMessage(), e);
try {
notice.setCallStatus(CALL_STATUS_CALL_FAIL);
notice.setStatusMsg("异常:" + e.getMessage());
warnCallNoticeMapper.updateById(notice);
} catch (Exception ex) {
log.error("[待发通知] 更新失败状态异常: {}", ex.getMessage());
}
}
}
log.info("[待发通知] 处理完成 - 成功: {}, 总数: {}", sentCount, pendingList.size());
return sentCount;
}
/**
* 解析告警消息为简短形式(取 ':' 前的部分)
* 与 DeviceDataHandler.sendVoiceNotification 保持一致
*/
private String parseWarnMessageShort(String rawMessage) {
if (rawMessage == null) {
return "异常";
}
return rawMessage.contains(":")
? rawMessage.substring(0, rawMessage.indexOf(":")).trim()
: rawMessage;
}
/**
* 更新电话通知的回执信息
* 对应 C# UpdateCallNoticeFromCallback
@@ -232,7 +320,12 @@ public class WarnCallNoticeServiceImpl implements WarnCallNoticeService {
* @param callback VMS 回执
*/
private void updateCallNoticeFromCallback(AquWarnCallNotice callNotice, VmsCallback callback) {
LocalDateTime now = LocalDateTime.now();
// 如果记录已是回执成功状态,跳过不再更新,防止重复回执覆盖
if (callNotice.getCallStatus() != null && callNotice.getCallStatus() == CALL_STATUS_CALLBACK_SUCCESS) {
log.info("[告警通知] 记录已是成功状态,跳过重复回执 - 记录ID: {}, 电话: {}",
callNotice.getId(), callNotice.getMobilePhone());
return;
}
// 更新回执详细信息(直接映射字段)
callNotice.setStatusCode(callback.getStatusCode());