From a3e2751933ca71028389501162d167296ae55626 Mon Sep 17 00:00:00 2001 From: "3067418132@qq.com" Date: Fri, 24 Apr 2026 18:07:14 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E4=BF=AE=E5=A4=8DdataResult=E4=BF=9D?= =?UTF-8?q?=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mh/user/mapper/DeviceInstallMapper.java | 12 +- .../service/impl/DataResultServiceImpl.java | 212 ++++++++++++++---- .../mh/user/strategy/EleMeterStrategy.java | 6 +- 3 files changed, 180 insertions(+), 50 deletions(-) diff --git a/user-service/src/main/java/com/mh/user/mapper/DeviceInstallMapper.java b/user-service/src/main/java/com/mh/user/mapper/DeviceInstallMapper.java index bc1529d..e5dfb56 100644 --- a/user-service/src/main/java/com/mh/user/mapper/DeviceInstallMapper.java +++ b/user-service/src/main/java/com/mh/user/mapper/DeviceInstallMapper.java @@ -307,12 +307,12 @@ public interface DeviceInstallMapper extends BaseMapper { @Param("buildingId") String buildingId); //更新基表初始值 - @Update("update device_install set init_value=#{initValue} where id = #{id} ") - void updateInitValue(@Param("deviceAddr") String deviceAddr, - @Param("deviceType") String deviceType, - @Param("buildingId") String buildingId, - @Param("initValue") String initValue, - @Param("id") Long id); + @Update("update device_install set init_value=#{initValue} where id = #{id}") + void updateInitValue(@Param("deviceAddr") String deviceAddr, + @Param("deviceType") String deviceType, + @Param("buildingId") String buildingId, + @Param("initValue") String initValue, + @Param("id") Long id); //查询最后一次采集时间 @Select("select last_date from device_install where device_type=#{deviceType} and device_addr=#{deviceAddr} and building_id=#{buildingId}") diff --git a/user-service/src/main/java/com/mh/user/service/impl/DataResultServiceImpl.java b/user-service/src/main/java/com/mh/user/service/impl/DataResultServiceImpl.java index bcc2ddc..1f2989e 100644 --- a/user-service/src/main/java/com/mh/user/service/impl/DataResultServiceImpl.java +++ b/user-service/src/main/java/com/mh/user/service/impl/DataResultServiceImpl.java @@ -45,6 +45,10 @@ public class DataResultServiceImpl implements DataResultService { private static final double OTHER_MAX_INCREMENT = 300; private static final double ELEC_DAY_VALUE = 1000; private static final double OTHER_DAY_VALUE = 100; + + // 仪表最大值常量(用于检测翻转) + private static final double METER_MAX_VALUE = 999999.99; // 常见仪表最大值 + private static final double METER_ROLLOVER_THRESHOLD = 0.1; // 翻转后新值应该很小 @Override public void saveDataResult(DataResultEntity dataResultEntity) { @@ -63,7 +67,7 @@ public class DataResultServiceImpl implements DataResultService { Date formattedDate = formatToFiveMinuteInterval(dataResultEntity.getCurDate()); dataResultEntity.setCurDate(formattedDate); - // 从安装表获取设备信息 + // 从安装表获取设备信息(使用最新数据) DeviceInstallEntity deviceInstallEntity = deviceInstallMapper.selectDevice( dataResultEntity.getDeviceAddr(), dataResultEntity.getDeviceType(), @@ -87,8 +91,31 @@ public class DataResultServiceImpl implements DataResultService { double maxIncrement = isElectricMeter ? ELEC_MAX_INCREMENT : OTHER_MAX_INCREMENT; dayValue = isElectricMeter ? ELEC_DAY_VALUE : OTHER_DAY_VALUE; - // 检查增量是否异常 - if (dataResultEntity.getCurValue() - lastValueFromInstall > maxIncrement) { + // 检查当前值是否有效(防止0值或负值) + if (dataResultEntity.getCurValue() <= 0) { + logger.warn("saveDataResult: curValue is invalid (<=0), skip. curValue={}, deviceAddr={}", + dataResultEntity.getCurValue(), dataResultEntity.getDeviceAddr()); + return; + } + + // 检测仪表翻转(rollover):从最大值归零重新计数 + boolean isRollover = false; + if (lastValueFromInstall > 0 && dataResultEntity.getCurValue() < lastValueFromInstall) { + // 判断是否为正常翻转:旧值接近最大值,新值很小 + if (lastValueFromInstall >= (METER_MAX_VALUE * 0.9) && dataResultEntity.getCurValue() <= METER_ROLLOVER_THRESHOLD) { + isRollover = true; + logger.info("saveDataResult: detected meter rollover. lastValue={}, curValue={}, deviceAddr={}", + lastValueFromInstall, dataResultEntity.getCurValue(), dataResultEntity.getDeviceAddr()); + } else { + // 非翻转情况,视为异常数据回退 + logger.warn("saveDataResult: curValue less than lastValue (not rollover), skip. curValue={}, lastValue={}, deviceAddr={}", + dataResultEntity.getCurValue(), lastValueFromInstall, dataResultEntity.getDeviceAddr()); + return; + } + } + + // 检查增量是否异常(翻转时跳过此检查) + if (!isRollover && lastValueFromInstall > 0 && (dataResultEntity.getCurValue() - lastValueFromInstall) > maxIncrement) { logger.info("saveDataResult: increment too large, skip. curValue={}, lastValue={}, deviceAddr={}", dataResultEntity.getCurValue(), lastValueFromInstall, dataResultEntity.getDeviceAddr()); return; @@ -118,53 +145,81 @@ public class DataResultServiceImpl implements DataResultService { shouldSave = validateAndSaveData(newData, calcValue, dayValue, days, true); -// if (shouldSave) { -// lastValue = newData.getLastValue(); -// } } else { - // 修改现有记录 - DataResultEntity existingData = dataResultMapper.selectDataResult( - curDateStr, + // 修改现有记录 - 重新查询最新数据避免并发问题 + DeviceInstallEntity latestDeviceInstall = deviceInstallMapper.selectDevice( dataResultEntity.getDeviceAddr(), dataResultEntity.getDeviceType(), dataResultEntity.getBuildingId()); - - if (existingData != null) { - double lastValue = existingData.getLastValue(); - calcValue = (dataResultEntity.getCurValue() - lastValue) * ratio; - calcValue = formatDouble(calcValue); - - existingData.setCurDate(formattedDate); - existingData.setCurValue(dataResultEntity.getCurValue()); - existingData.setCalcValue(calcValue); - - Date lastDate = existingData.getLastDate(); - int days = (int) ExchangeStringUtil.daysBetween(formattedDate, lastDate); - - shouldSave = validateAndSaveData(existingData, calcValue, dayValue, days, false); + + if (latestDeviceInstall != null) { + DataResultEntity existingData = dataResultMapper.selectDataResult( + curDateStr, + dataResultEntity.getDeviceAddr(), + dataResultEntity.getDeviceType(), + dataResultEntity.getBuildingId()); + + if (existingData != null) { + double lastValue = existingData.getLastValue(); + + // 验证lastValue有效性 + if (lastValue <= 0) { + logger.warn("saveDataResult: existing lastValue is invalid, use device install lastValue. lastValue={}, deviceAddr={}", + lastValue, dataResultEntity.getDeviceAddr()); + lastValue = latestDeviceInstall.getLastValue(); + } + + // 检测是否为仪表翻转 + boolean isUpdateRollover = false; + if (dataResultEntity.getCurValue() < lastValue && lastValue >= (METER_MAX_VALUE * 0.9)) { + isUpdateRollover = true; + logger.info("saveDataResult: detected rollover in update. curValue={}, lastValue={}, deviceAddr={}", + dataResultEntity.getCurValue(), lastValue, dataResultEntity.getDeviceAddr()); + } + + double updateCalcValue; + if (isUpdateRollover) { + // 翻转情况:计算值 = (最大值 - 上次值 + 当前值) * 倍率 + updateCalcValue = (METER_MAX_VALUE - lastValue + dataResultEntity.getCurValue()) * ratio; + logger.info("saveDataResult: calculated rollover value in update. ({} - {} + {}) * {} = {}", + METER_MAX_VALUE, lastValue, dataResultEntity.getCurValue(), ratio, updateCalcValue); + } else { + // 正常情况:计算值 = (当前值 - 上次值) * 倍率 + updateCalcValue = (dataResultEntity.getCurValue() - lastValue) * ratio; + } + + updateCalcValue = formatDouble(updateCalcValue); + + existingData.setCurDate(formattedDate); + existingData.setCurValue(dataResultEntity.getCurValue()); + existingData.setCalcValue(updateCalcValue); + + Date lastDate = existingData.getLastDate(); + int days = (int) ExchangeStringUtil.daysBetween(formattedDate, lastDate); + + shouldSave = validateAndSaveData(existingData, updateCalcValue, dayValue, days, false); + } } } - // 更新安装表中的lastValue和lastDate + // 只有在数据验证通过时才更新安装表中的lastValue和lastDate if (shouldSave) { deviceInstallMapper.updateLastValue( deviceInstallEntity.getId(), String.valueOf(dataResultEntity.getCurValue()), currentDate); - } - - // 第一次采集时初始化initValue - if (initValue == 0) { - deviceInstallMapper.updateLastValue( - deviceInstallEntity.getId(), - String.valueOf(dataResultEntity.getCurValue()), - currentDate); - deviceInstallMapper.updateInitValue( - dataResultEntity.getDeviceAddr(), - dataResultEntity.getDeviceType(), - dataResultEntity.getBuildingId(), - String.valueOf(dataResultEntity.getCurValue()), - deviceInstallEntity.getId()); + + // 第一次采集时初始化initValue(必须在更新lastValue成功后) + if (initValue == 0 || initValue < 0) { + deviceInstallMapper.updateInitValue( + dataResultEntity.getDeviceAddr(), + dataResultEntity.getDeviceType(), + dataResultEntity.getBuildingId(), + String.valueOf(dataResultEntity.getCurValue()), + deviceInstallEntity.getId()); + logger.info("saveDataResult: initialized initValue for deviceAddr={}, initValue={}", + dataResultEntity.getDeviceAddr(), dataResultEntity.getCurValue()); + } } } catch (Exception e) { @@ -201,12 +256,29 @@ public class DataResultServiceImpl implements DataResultService { dataResultEntity.getBuildingId()); double lastValue; + boolean isRollover = false; + if (lastData != null) { data.setLastDate(lastData.getCurDate()); data.setLastValue(lastData.getCurValue()); lastValue = lastData.getCurValue(); + + // 验证lastValue的有效性 + if (lastValue <= 0) { + logger.warn("createNewDataResult: lastData has invalid lastValue={}, use device install value", + lastValue); + lastValue = deviceInstallEntity.getLastValue(); + } } else { lastValue = deviceInstallEntity.getLastValue(); + + // 如果deviceInstall的lastValue也无效,使用当前值作为初始值 + if (lastValue <= 0) { + logger.info("createNewDataResult: device install lastValue is invalid, use curValue as initial. curValue={}, deviceAddr={}", + dataResultEntity.getCurValue(), dataResultEntity.getDeviceAddr()); + lastValue = dataResultEntity.getCurValue(); + } + Date lastDate = deviceInstallEntity.getLastDate(); if (lastDate == null) { lastDate = new Date(); @@ -215,8 +287,32 @@ public class DataResultServiceImpl implements DataResultService { data.setLastValue(lastValue); } - double calcValue = (dataResultEntity.getCurValue() - lastValue) * ratio; + // 检测是否为仪表翻转(当前值 < 上次值) + if (dataResultEntity.getCurValue() < lastValue && lastValue >= (METER_MAX_VALUE * 0.9)) { + isRollover = true; + logger.info("createNewDataResult: detected rollover in calculation. curValue={}, lastValue={}, deviceAddr={}", + dataResultEntity.getCurValue(), lastValue, dataResultEntity.getDeviceAddr()); + } + + double calcValue; + if (isRollover) { + // 翻转情况:计算值 = (最大值 - 上次值 + 当前值) * 倍率 + calcValue = (METER_MAX_VALUE - lastValue + dataResultEntity.getCurValue()) * ratio; + logger.info("createNewDataResult: calculated rollover value. ({} - {} + {}) * {} = {}", + METER_MAX_VALUE, lastValue, dataResultEntity.getCurValue(), ratio, calcValue); + } else { + // 正常情况:计算值 = (当前值 - 上次值) * 倍率 + calcValue = (dataResultEntity.getCurValue() - lastValue) * ratio; + } + calcValue = formatDouble(calcValue); + + // 验证计算值(翻转时允许较大的正值) + if (calcValue < 0) { + logger.warn("createNewDataResult: calcValue is negative after calculation. curValue={}, lastValue={}, ratio={}, calcValue={}, isRollover={}", + dataResultEntity.getCurValue(), lastValue, ratio, calcValue, isRollover); + } + data.setCalcValue(calcValue); return data; @@ -231,11 +327,44 @@ public class DataResultServiceImpl implements DataResultService { double dayValue, int days, boolean isNew) { + // 验证calcValue有效性 if (calcValue < 0) { - logger.warn("calcValue is negative: {}", calcValue); + logger.warn("validateAndSaveData: calcValue is negative: {}, deviceAddr={}", + calcValue, dataResultEntity.getDeviceAddr()); + return false; + } + + // 验证curValue有效性 + if (dataResultEntity.getCurValue() <= 0) { + logger.warn("validateAndSaveData: curValue is invalid: {}, deviceAddr={}", + dataResultEntity.getCurValue(), dataResultEntity.getDeviceAddr()); return false; } + // 检测是否为翻转情况(calcValue可能很大) + boolean isRollover = calcValue > dayValue * 10; // 如果计算值超过日值的10倍,可能是翻转 + + if (isRollover) { + // 翻转情况:只要calcValue为正且合理,就允许保存 + // 这里假设翻转后的用量不会超过30天的正常用量 + double maxRolloverValue = dayValue * 30; + if (calcValue <= maxRolloverValue) { + if (isNew) { + dataResultMapper.saveDataResult(dataResultEntity); + } else { + dataResultMapper.updateDataResult(dataResultEntity); + } + logger.info("validateAndSaveData: saved rollover data. calcValue={}, dayValue={}, deviceAddr={}", + calcValue, dayValue, dataResultEntity.getDeviceAddr()); + return true; + } else { + logger.warn("validateAndSaveData: rollover calcValue too large: calcValue={}, maxValue={}, deviceAddr={}", + calcValue, maxRolloverValue, dataResultEntity.getDeviceAddr()); + return false; + } + } + + // 正常情况的验证逻辑 if (calcValue <= dayValue) { if (isNew) { dataResultMapper.saveDataResult(dataResultEntity); @@ -248,7 +377,8 @@ public class DataResultServiceImpl implements DataResultService { return true; } - logger.warn("calcValue exceeds dayValue: calcValue={}, dayValue={}, days={}", calcValue, dayValue, days); + logger.warn("validateAndSaveData: calcValue exceeds dayValue: calcValue={}, dayValue={}, days={}, deviceAddr={}", + calcValue, dayValue, days, dataResultEntity.getDeviceAddr()); return false; } diff --git a/user-service/src/main/java/com/mh/user/strategy/EleMeterStrategy.java b/user-service/src/main/java/com/mh/user/strategy/EleMeterStrategy.java index def5e07..7492e82 100644 --- a/user-service/src/main/java/com/mh/user/strategy/EleMeterStrategy.java +++ b/user-service/src/main/java/com/mh/user/strategy/EleMeterStrategy.java @@ -179,9 +179,9 @@ public class EleMeterStrategy implements DeviceStrategy { // 将数值按指定小数位数格式化 dataStr = originalValue.divide(power, 2, RoundingMode.HALF_UP).toString(); - if (Double.parseDouble(dataStr)-deviceInstallEntity.getLastValue()>1000 || Double.parseDouble(dataStr)-deviceInstallEntity.getLastValue()<0) { - dataStr = String.valueOf(deviceInstallEntity.getLastValue()); - } +// if (Double.parseDouble(dataStr)-deviceInstallEntity.getLastValue()>1000 || Double.parseDouble(dataStr)-deviceInstallEntity.getLastValue()<0) { +// dataStr = String.valueOf(deviceInstallEntity.getLastValue()); +// } log.info("电表表号:{},电表读数:{}", deviceInstallEntity.getDeviceAddr(), dataStr); try { DataResultEntity dataResultEntity = new DataResultEntity();