电量计算
This commit is contained in:
parent
0e9f83c84a
commit
3393089eee
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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("-----------------------------------------");
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user