From 3393089eee0a292f14ca6a33aec68a76a8db4544420244358e5b19a0a5a40b7a Mon Sep 17 00:00:00 2001 From: PC <2413103649@qq.com> Date: Fri, 30 Jan 2026 11:22:20 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=B5=E9=87=8F=E8=AE=A1=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cdzy/report/component/ReoprtHandler.java | 11 +- .../cdzy/report/utils/SOCVoltageMapper.java | 181 ++++++++++++++++++ 2 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 ebike-report/src/main/java/com/cdzy/report/utils/SOCVoltageMapper.java diff --git a/ebike-report/src/main/java/com/cdzy/report/component/ReoprtHandler.java b/ebike-report/src/main/java/com/cdzy/report/component/ReoprtHandler.java index 38e7285..c73c475 100644 --- a/ebike-report/src/main/java/com/cdzy/report/component/ReoprtHandler.java +++ b/ebike-report/src/main/java/com/cdzy/report/component/ReoprtHandler.java @@ -7,6 +7,7 @@ import com.cdzy.common.utils.CoordinateUtil; import com.cdzy.report.enums.BitSwitch; import com.cdzy.report.utils.BinaryUtil; import com.cdzy.report.utils.RedisUtil; +import com.cdzy.report.utils.SOCVoltageMapper; import com.ebike.feign.clients.OperationsFeignClient; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; @@ -75,6 +76,12 @@ public class ReoprtHandler { //生成换电工单 operateFeignClient.batterySwapOrder(deviceId,Boolean.FALSE); } + //静止状态电量上报为0异常处理 + if (resGpsDto.getSoc() == 0 && isMoving == '0'){ + double voltage = resGpsDto.getVoltage() / 13000.0; + double socFromVoltage = SOCVoltageMapper.getSOCFromVoltage(voltage); + resGpsDto.setSoc((int) socFromVoltage); + } resGpsDto.setEcuSn(deviceId); resGpsDto.setHelmetExit(helmet); resGpsDto.setAccOn(acc); @@ -89,12 +96,12 @@ public class ReoprtHandler { boolean outOfChina = CoordinateUtil.outOfChina(doubles[0], doubles[1]); if (!outOfChina) { EbikeTracking ebikeTracking = new EbikeTracking(deviceId, doubles[1], doubles[0]); - operateFeignClient.saveEbikeTracking(ebikeTracking); +// operateFeignClient.saveEbikeTracking(ebikeTracking); //车辆静止,直接落库 if (isMoving == '0') { //TODO:优化为算法计算存储,计算拐点等关键位置,而非单纯的等待2min的静止上报 log.info("记录中控绑定的车辆位置,中控编号:{}", deviceId); - operateFeignClient.changeLocation(deviceId,doubles[0], doubles[1]); +// operateFeignClient.changeLocation(deviceId,doubles[0], doubles[1]); } } diff --git a/ebike-report/src/main/java/com/cdzy/report/utils/SOCVoltageMapper.java b/ebike-report/src/main/java/com/cdzy/report/utils/SOCVoltageMapper.java new file mode 100644 index 0000000..694e56b --- /dev/null +++ b/ebike-report/src/main/java/com/cdzy/report/utils/SOCVoltageMapper.java @@ -0,0 +1,181 @@ +package com.cdzy.report.utils; + +/** + * SOC电压映射工具类 + * 根据电池开路电压值计算对应的SOC百分比 + */ +public class SOCVoltageMapper { + + // SOC-电压对应表(典型值) + private static final double[][] SOC_VOLTAGE_TABLE = { + {0.0, 3.000}, // 0% SOC + {5.0, 3.100}, // 5% SOC + {10.0, 3.225}, // 10% SOC + {15.0, 3.350}, // 15% SOC + {20.0, 3.475}, // 20% SOC + {25.0, 3.600}, // 25% SOC + {30.0, 3.675}, // 30% SOC + {35.0, 3.710}, // 35% SOC + {40.0, 3.736}, // 40% SOC + {45.0, 3.766}, // 45% SOC + {50.0, 3.796}, // 50% SOC + {55.0, 3.826}, // 55% SOC + {60.0, 3.856}, // 60% SOC + {65.0, 3.886}, // 65% SOC + {70.0, 3.934}, // 70% SOC + {75.0, 3.969}, // 75% SOC + {80.0, 4.004}, // 80% SOC + {85.0, 4.039}, // 85% SOC + {90.0, 4.074}, // 90% SOC + {95.0, 4.109}, // 95% SOC + {100.0, 4.144} // 100% SOC + }; + + // 关键点的电压范围校验(SOC, 最小电压, 最大电压) + private static final double[][] VOLTAGE_RANGE_CHECK = { + {0.0, 2.95, 3.05}, // 0% SOC范围 + {10.0, 3.20, 3.25}, // 10% SOC范围 + {20.0, 3.46, 3.49}, // 20% SOC范围 + {30.0, 3.67, 3.68}, // 30% SOC范围 + {50.0, 3.791, 3.801}, // 50% SOC范围 + {100.0, 4.14, 4.20} // 100% SOC范围 + }; + + /** + * 根据开路电压值获取对应的SOC百分比 + * @param voltage 测量的开路电压值(V) + * @return 对应的SOC百分比(0-100) + */ + public static double getSOCFromVoltage(double voltage) { + // 边界检查 + if (voltage < SOC_VOLTAGE_TABLE[0][1]) { + return 0.0; // 电压过低,返回0% + } + if (voltage > SOC_VOLTAGE_TABLE[SOC_VOLTAGE_TABLE.length - 1][1]) { + return 100.0; // 电压过高,返回100% + } + + // 查找电压所在的区间 + for (int i = 0; i < SOC_VOLTAGE_TABLE.length - 1; i++) { + double currentSOC = SOC_VOLTAGE_TABLE[i][0]; + double currentVoltage = SOC_VOLTAGE_TABLE[i][1]; + double nextSOC = SOC_VOLTAGE_TABLE[i + 1][0]; + double nextVoltage = SOC_VOLTAGE_TABLE[i + 1][1]; + + // 如果电压正好匹配某个点 + if (Math.abs(voltage - currentVoltage) < 0.001) { + return currentSOC; + } + + // 如果电压在两点之间,进行线性插值 + if (voltage >= currentVoltage && voltage <= nextVoltage) { + return linearInterpolation(voltage, currentVoltage, nextVoltage, currentSOC, nextSOC); + } + } + + // 默认返回 + return linearInterpolation(voltage, + SOC_VOLTAGE_TABLE[0][1], + SOC_VOLTAGE_TABLE[SOC_VOLTAGE_TABLE.length - 1][1], + 0.0, 100.0); + } + + /** + * 线性插值计算 + */ + private static double linearInterpolation(double voltage, double v1, double v2, double soc1, double soc2) { + double ratio = (voltage - v1) / (v2 - v1); + return soc1 + ratio * (soc2 - soc1); + } + + /** + * 获取BMS校准推荐度 + * @param soc SOC百分比 + * @return 校准推荐度描述 + */ + public static String getBMSCalibrationRecommendation(double soc) { + if (soc <= 0.1 || soc >= 99.9) { + return "★★★★★ (强制校准点)"; + } else if (soc <= 5.1 || soc >= 95.1) { + return "★★★★☆"; + } else if (soc <= 10.1 || (soc >= 20.1 && soc <= 20.9) || + (soc >= 90.1 && soc <= 90.9) || soc >= 80.1) { + return "★★★★☆"; + } else if (soc <= 15.1 || soc <= 25.1 || + (soc >= 70.1 && soc <= 75.1) || soc >= 85.1) { + return "★★★☆☆"; + } else if (soc <= 30.1 || (soc >= 50.1 && soc <= 60.1)) { + return "★★☆☆☆"; + } else { + return "★☆☆☆☆ (平台区,不推荐校准)"; + } + } + + /** + * 检查电压是否在合理偏差范围内 + * @param voltage 测量的电压 + * @param soc 对应的SOC + * @return 是否在合理范围内 + */ + public static boolean isVoltageInRange(double voltage, double soc) { + for (double[] range : VOLTAGE_RANGE_CHECK) { + if (Math.abs(soc - range[0]) < 0.5) { + return voltage >= range[1] && voltage <= range[2]; + } + } + return true; // 非关键点默认认为合理 + } + + /** + * 获取关键SOC点的描述 + * @param soc SOC百分比 + * @return 关键点描述 + */ + public static String getKeyPointDescription(double soc) { + if (soc <= 0.5) { + return "强制保护点"; + } else if (Math.abs(soc - 10.0) < 0.5) { + return "低电量报警点"; + } else if (Math.abs(soc - 20.0) < 0.5) { + return "建议充电点"; + } else if (Math.abs(soc - 30.0) < 0.5) { + return "平台区开始"; + } else if (Math.abs(soc - 40.0) < 0.5) { + return "最平区域"; + } else if (Math.abs(soc - 50.0) < 0.5) { + return "标称电压点"; + } else if (Math.abs(soc - 70.0) < 0.5) { + return "平台区结束"; + } else if (Math.abs(soc - 80.0) < 0.5) { + return "高电量区"; + } else if (soc >= 99.5) { + return "满电标志"; + } else { + return "正常区域"; + } + } + + /** + * 测试示例 + */ + public static void main(String[] args) { + // 测试不同电压值 + double[] testVoltages = {3.0, 3.225, 3.475, 3.675, 3.736, 3.796, 4.004, 4.144}; + + System.out.println("SOC-电压映射测试:"); + System.out.println("========================================="); + + for (double voltage : testVoltages) { + double soc = getSOCFromVoltage(voltage); + String calibration = getBMSCalibrationRecommendation(soc); + String description = getKeyPointDescription(soc); + + System.out.printf("电压: %.3fV -> SOC: %.1f%%\n", voltage, soc); + System.out.printf(" 校准推荐度: %s\n", calibration); + System.out.printf(" 关键点描述: %s\n", description); + System.out.printf(" 电压范围检查: %s\n", + isVoltageInRange(voltage, soc) ? "正常" : "异常"); + System.out.println("-----------------------------------------"); + } + } +} \ No newline at end of file