电量计算
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.enums.BitSwitch;
|
||||||
import com.cdzy.report.utils.BinaryUtil;
|
import com.cdzy.report.utils.BinaryUtil;
|
||||||
import com.cdzy.report.utils.RedisUtil;
|
import com.cdzy.report.utils.RedisUtil;
|
||||||
|
import com.cdzy.report.utils.SOCVoltageMapper;
|
||||||
import com.ebike.feign.clients.OperationsFeignClient;
|
import com.ebike.feign.clients.OperationsFeignClient;
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
@ -75,6 +76,12 @@ public class ReoprtHandler {
|
|||||||
//生成换电工单
|
//生成换电工单
|
||||||
operateFeignClient.batterySwapOrder(deviceId,Boolean.FALSE);
|
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.setEcuSn(deviceId);
|
||||||
resGpsDto.setHelmetExit(helmet);
|
resGpsDto.setHelmetExit(helmet);
|
||||||
resGpsDto.setAccOn(acc);
|
resGpsDto.setAccOn(acc);
|
||||||
@ -89,12 +96,12 @@ public class ReoprtHandler {
|
|||||||
boolean outOfChina = CoordinateUtil.outOfChina(doubles[0], doubles[1]);
|
boolean outOfChina = CoordinateUtil.outOfChina(doubles[0], doubles[1]);
|
||||||
if (!outOfChina) {
|
if (!outOfChina) {
|
||||||
EbikeTracking ebikeTracking = new EbikeTracking(deviceId, doubles[1], doubles[0]);
|
EbikeTracking ebikeTracking = new EbikeTracking(deviceId, doubles[1], doubles[0]);
|
||||||
operateFeignClient.saveEbikeTracking(ebikeTracking);
|
// operateFeignClient.saveEbikeTracking(ebikeTracking);
|
||||||
//车辆静止,直接落库
|
//车辆静止,直接落库
|
||||||
if (isMoving == '0') {
|
if (isMoving == '0') {
|
||||||
//TODO:优化为算法计算存储,计算拐点等关键位置,而非单纯的等待2min的静止上报
|
//TODO:优化为算法计算存储,计算拐点等关键位置,而非单纯的等待2min的静止上报
|
||||||
log.info("记录中控绑定的车辆位置,中控编号:{}", deviceId);
|
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