| | |
| | | @Slf4j |
| | | public class MesDvTelemetryServiceImpl implements MesDvTelemetryService { |
| | | |
| | | static final long MAX_FUTURE_SKEW_MINUTES = 5; |
| | | |
| | | @Resource |
| | | private MesDvTelemetryMapper telemetryMapper; |
| | | @Resource |
| | |
| | | // 取最近一批数据,按设备+信号去重保留最新,用于实时监控视图 |
| | | List<MesDvTelemetryDO> list = telemetryMapper.selectLatest(reqVO, 5000); |
| | | Map<String, MesDvTelemetryDO> latestMap = new LinkedHashMap<>(); |
| | | LocalDateTime queryTime = LocalDateTime.now(); |
| | | for (MesDvTelemetryDO row : list) { |
| | | // 双重防护:即使数据库中已有未来时间的脏数据,也不能作为实时数据返回 |
| | | if (!isAcceptableTelemetryTime(row.getTelemetryDataTime(), queryTime)) { |
| | | continue; |
| | | } |
| | | String key = StrUtil.blankToDefault(row.getTbDeviceId(), "") |
| | | + ":" + StrUtil.blankToDefault(row.getParamKeyName(), ""); |
| | | latestMap.putIfAbsent(key, row); |
| | |
| | | continue; |
| | | } |
| | | MesDvTelemetryDO data = convert((Map<?, ?>) rowObj); |
| | | if (!isAcceptableTelemetryTime(data.getTelemetryDataTime(), pullTime)) { |
| | | log.warn("[pullTelemetry][忽略异常遥测时间,deviceId({}),telemetryDataTime({}),pullTime({})]", |
| | | data.getTbDeviceId(), data.getTelemetryDataTime(), pullTime); |
| | | continue; |
| | | } |
| | | data.setPullTime(pullTime); |
| | | saveList.add(data); |
| | | } |
| | | if (CollUtil.isNotEmpty(saveList)) { |
| | | telemetryMapper.insertBatch(saveList); |
| | | } |
| | | // 6. 返回统计 |
| | | result.setRecordCount(saveList.size()); |
| | | result.setDeviceCount((int) saveList.stream() |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 遥测时间必须存在,且不能明显晚于本次拉取/查询时间。 |
| | | * 保留 5 分钟容差,兼容设备时钟与应用服务器之间的轻微偏差。 |
| | | */ |
| | | static boolean isAcceptableTelemetryTime(LocalDateTime telemetryTime, LocalDateTime referenceTime) { |
| | | return telemetryTime != null && referenceTime != null |
| | | && !telemetryTime.isAfter(referenceTime.plusMinutes(MAX_FUTURE_SKEW_MINUTES)); |
| | | } |
| | | |
| | | } |