feat(device): 新增设备在线状态和屏幕状态SSE广播,并修复Redis反序列化问题

- MqttMessageHandler 收到心跳后通过 SseService 广播设备在线状态(含屏幕状态)
- SseService/SseSessionManager 新增设备在线状态和屏幕状态的广播方法
- DeviceOnlineServiceImpl 修复 Redis 反序列化为 LinkedHashMap 时的类型转换问题
- DeviceOnlineServiceImpl 修复批量查询时空 SN 导致索引不对齐的问题
This commit is contained in:
TongTongStudio
2026-08-09 20:06:03 +08:00
parent ba5b9eddc8
commit 369a940344
5 changed files with 111 additions and 4 deletions

View File

@@ -9,6 +9,7 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import tools.jackson.databind.ObjectMapper;
import java.time.LocalDateTime;
import java.util.ArrayList;
@@ -33,6 +34,7 @@ public class DeviceOnlineServiceImpl implements DeviceOnlineService {
private final RedisTemplate<String, Object> redisTemplate;
private final MqttProperties mqttProperties;
private final ObjectMapper objectMapper;
@Override
public void reportHeartbeat(String sn, String ip) {
@@ -101,6 +103,14 @@ public class DeviceOnlineServiceImpl implements DeviceOnlineService {
if (value instanceof DeviceOnlineVO vo) {
return vo;
}
// GenericJacksonJsonRedisSerializer 反序列化后可能为 LinkedHashMap需手动转换
if (value != null) {
try {
return objectMapper.convertValue(value, DeviceOnlineVO.class);
} catch (Exception e) {
log.warn("转换设备在线状态失败, sn={}", sn, e);
}
}
// 离线
DeviceOnlineVO offline = new DeviceOnlineVO();
offline.setSerialno(sn);
@@ -115,12 +125,15 @@ public class DeviceOnlineServiceImpl implements DeviceOnlineService {
return result;
}
List<String> keys = new ArrayList<>(sns.size());
// 记录有效 SN 的索引映射,避免空 SN 导致 keys 和 sns 索引不对齐
List<String> validSns = new ArrayList<>(sns.size());
for (String sn : sns) {
if (StrUtil.isBlank(sn)) {
continue;
}
String key = RedisConstants.Device.ONLINE.replace("{}", sn);
keys.add(key);
validSns.add(sn);
// 预置离线状态,供缺失 key 时填充
DeviceOnlineVO offline = new DeviceOnlineVO();
offline.setSerialno(sn);
@@ -132,10 +145,19 @@ public class DeviceOnlineServiceImpl implements DeviceOnlineService {
if (values != null) {
for (int i = 0; i < values.size(); i++) {
Object value = values.get(i);
String sn = sns.get(i);
if (value instanceof DeviceOnlineVO vo) {
result.put(sn, vo);
String sn = validSns.get(i);
if (value == null) {
continue;
}
// GenericJacksonJsonRedisSerializer 反序列化 multiGet 结果时
// 返回 LinkedHashMap需手动转换为 DeviceOnlineVO
DeviceOnlineVO vo;
if (value instanceof DeviceOnlineVO v) {
vo = v;
} else {
vo = objectMapper.convertValue(value, DeviceOnlineVO.class);
}
result.put(sn, vo);
}
}
} catch (Exception e) {