liu
20 小时以前 f57a9de2dbe69e7f867b39c25abdab58b401a2df
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/telemetry/MesDvTelemetryServiceImpl.java
@@ -38,6 +38,8 @@
@Slf4j
public class MesDvTelemetryServiceImpl implements MesDvTelemetryService {
    static final long MAX_FUTURE_SKEW_MINUTES = 5;
    @Resource
    private MesDvTelemetryMapper telemetryMapper;
    @Resource
@@ -53,7 +55,12 @@
        // 取最近一批数据,按设备+信号去重保留最新,用于实时监控视图
        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);
@@ -149,10 +156,17 @@
                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);
        }
        telemetryMapper.insertBatch(saveList);
        if (CollUtil.isNotEmpty(saveList)) {
            telemetryMapper.insertBatch(saveList);
        }
        // 6. 返回统计
        result.setRecordCount(saveList.size());
        result.setDeviceCount((int) saveList.stream()
@@ -204,4 +218,13 @@
        }
    }
    /**
     * 遥测时间必须存在,且不能明显晚于本次拉取/查询时间。
     * 保留 5 分钟容差,兼容设备时钟与应用服务器之间的轻微偏差。
     */
    static boolean isAcceptableTelemetryTime(LocalDateTime telemetryTime, LocalDateTime referenceTime) {
        return telemetryTime != null && referenceTime != null
                && !telemetryTime.isAfter(referenceTime.plusMinutes(MAX_FUTURE_SKEW_MINUTES));
    }
}