fix: 太阳能网控,离线报警问题修复。
This commit is contained in:
@@ -891,8 +891,9 @@ public class DeviceDataHandler {
|
|||||||
|
|
||||||
// 查询设备类型,太阳能网控(type=3)使用独立的延迟时长
|
// 查询设备类型,太阳能网控(type=3)使用独立的延迟时长
|
||||||
int offlineDelayMinutes = aliyunIotProperties.getOfflineWarnDelayMinutes();
|
int offlineDelayMinutes = aliyunIotProperties.getOfflineWarnDelayMinutes();
|
||||||
|
Device deviceForType = null;
|
||||||
try {
|
try {
|
||||||
Device deviceForType = deviceMapper.selectOne(
|
deviceForType = deviceMapper.selectOne(
|
||||||
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Device>()
|
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Device>()
|
||||||
.eq(Device::getSerialNum, deviceName)
|
.eq(Device::getSerialNum, deviceName)
|
||||||
.select(Device::getDeviceType)
|
.select(Device::getDeviceType)
|
||||||
@@ -908,7 +909,11 @@ public class DeviceDataHandler {
|
|||||||
|
|
||||||
String offlineTime = LocalDateTime.now().format(DATETIME_FORMATTER);
|
String offlineTime = LocalDateTime.now().format(DATETIME_FORMATTER);
|
||||||
int ttlMinutes = offlineDelayMinutes * OFFLINE_WAIT_TTL_MULTIPLIER;
|
int ttlMinutes = offlineDelayMinutes * OFFLINE_WAIT_TTL_MULTIPLIER;
|
||||||
RedisUtils.setCacheObject(redisKey, offlineTime, Duration.ofMinutes(ttlMinutes));
|
// value 格式:{offlineTime}|{deviceType},定时任务根据设备类型使用对应延迟阈值
|
||||||
|
int deviceTypeForRedis = (deviceForType != null && deviceForType.getDeviceType() != null)
|
||||||
|
? deviceForType.getDeviceType() : 0;
|
||||||
|
String redisValue = offlineTime + "|" + deviceTypeForRedis;
|
||||||
|
RedisUtils.setCacheObject(redisKey, redisValue, Duration.ofMinutes(ttlMinutes));
|
||||||
log.info("[离线告警] 设备离线,已记录等待标记,将在 {} 分钟后触发告警: {}", offlineDelayMinutes, deviceName);
|
log.info("[离线告警] 设备离线,已记录等待标记,将在 {} 分钟后触发告警: {}", offlineDelayMinutes, deviceName);
|
||||||
|
|
||||||
// 同步更新 Device.warnCode,写入离线标志位
|
// 同步更新 Device.warnCode,写入离线标志位
|
||||||
|
|||||||
@@ -28,6 +28,12 @@ public class DeviceOfflineWarnTask {
|
|||||||
|
|
||||||
private static final String OFFLINE_WAIT_KEY_PREFIX = "device:offline:wait:";
|
private static final String OFFLINE_WAIT_KEY_PREFIX = "device:offline:wait:";
|
||||||
|
|
||||||
|
/** Redis value 分隔符,格式:{offlineTime}|{deviceType} */
|
||||||
|
private static final String VALUE_SEPARATOR = "|";
|
||||||
|
|
||||||
|
/** 太阳能网控设备类型值 */
|
||||||
|
private static final int SOLAR_CONTROLLER_TYPE = 3;
|
||||||
|
|
||||||
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
private final DeviceDataHandler deviceDataHandler;
|
private final DeviceDataHandler deviceDataHandler;
|
||||||
@@ -36,7 +42,8 @@ public class DeviceOfflineWarnTask {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 每分钟扫描一次离线等待标记
|
* 每分钟扫描一次离线等待标记
|
||||||
* 对超过配置的 offline-warn-delay-minutes 分钟的设备触发告警
|
* 对超过配置的延迟时长的设备触发告警
|
||||||
|
* Redis value 格式:{offlineTime}|{deviceType},根据设备类型使用对应延迟时长
|
||||||
*/
|
*/
|
||||||
@Scheduled(fixedDelay = 60000)
|
@Scheduled(fixedDelay = 60000)
|
||||||
public void checkOfflineWaitAndTrigger() {
|
public void checkOfflineWaitAndTrigger() {
|
||||||
@@ -49,22 +56,42 @@ public class DeviceOfflineWarnTask {
|
|||||||
LocalDateTime now = LocalDateTime.now();
|
LocalDateTime now = LocalDateTime.now();
|
||||||
for (String key : keys) {
|
for (String key : keys) {
|
||||||
try {
|
try {
|
||||||
String offlineTimeStr = RedisUtils.getCacheObject(key);
|
String value = RedisUtils.getCacheObject(key);
|
||||||
if (offlineTimeStr == null) {
|
if (value == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 解析 value,兼容旧格式(纯时间字符串)和新格式(时间|设备类型)
|
||||||
|
String offlineTimeStr;
|
||||||
|
int deviceType = 0;
|
||||||
|
if (value.contains(VALUE_SEPARATOR)) {
|
||||||
|
String[] parts = value.split("\\" + VALUE_SEPARATOR, 2);
|
||||||
|
offlineTimeStr = parts[0];
|
||||||
|
try {
|
||||||
|
deviceType = Integer.parseInt(parts[1]);
|
||||||
|
} catch (NumberFormatException ignore) {
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 旧格式兼容:纯时间字符串,设备类型未知,使用默认延迟
|
||||||
|
offlineTimeStr = value;
|
||||||
|
}
|
||||||
|
|
||||||
LocalDateTime offlineTime = LocalDateTime.parse(offlineTimeStr, FORMATTER);
|
LocalDateTime offlineTime = LocalDateTime.parse(offlineTimeStr, FORMATTER);
|
||||||
long elapsedMinutes = java.time.Duration.between(offlineTime, now).toMinutes();
|
long elapsedMinutes = java.time.Duration.between(offlineTime, now).toMinutes();
|
||||||
|
|
||||||
if (elapsedMinutes >= aliyunIotProperties.getOfflineWarnDelayMinutes()) {
|
// 根据设备类型选择对应的延迟时长
|
||||||
|
int delayMinutes = (deviceType == SOLAR_CONTROLLER_TYPE)
|
||||||
|
? aliyunIotProperties.getSolarOfflineWarnDelayMinutes()
|
||||||
|
: aliyunIotProperties.getOfflineWarnDelayMinutes();
|
||||||
|
|
||||||
|
if (elapsedMinutes >= delayMinutes) {
|
||||||
// 提取 deviceName(去掉前缀)
|
// 提取 deviceName(去掉前缀)
|
||||||
String deviceName = key.substring(OFFLINE_WAIT_KEY_PREFIX.length());
|
String deviceName = key.substring(OFFLINE_WAIT_KEY_PREFIX.length());
|
||||||
|
|
||||||
// 触发告警前先删除标记,防止重复触发
|
// 触发告警前先删除标记,防止重复触发
|
||||||
RedisUtils.deleteObject(key);
|
RedisUtils.deleteObject(key);
|
||||||
|
|
||||||
log.info("[离线告警] 设备离线已超过 {} 分钟,触发告警: {}", elapsedMinutes, deviceName);
|
log.info("[离线告警] 设备离线已超过 {} 分钟(阈值{}分钟),触发告警: {}", elapsedMinutes, delayMinutes, deviceName);
|
||||||
deviceDataHandler.triggerOfflineAlarm(deviceName);
|
deviceDataHandler.triggerOfflineAlarm(deviceName);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user