增加充电BMS握手转发逻辑

This commit is contained in:
三丙
2025-08-07 23:03:18 +08:00
parent 74ef755dac
commit 3d441d75a3
10 changed files with 115 additions and 27 deletions

View File

@@ -111,4 +111,9 @@ public interface PileProtocolService {
*/
void onBmsAbort(UplinkQueueMessage uplinkQueueMessage, Callback callback);
/**
* BMS充电握手
*/
void onBmsHandshake(UplinkQueueMessage uplinkQueueMessage, Callback callback);
}

View File

@@ -378,6 +378,29 @@ public class DefaultPileProtocolService implements PileProtocolService {
callback.onSuccess();
}
@Override
public void onBmsHandshake(UplinkQueueMessage uplinkQueueMessage, Callback callback) {
log.info("接收到BMS充电握手信息 {}", uplinkQueueMessage);
BmsHandshakeProto bmsHandshakeProto = uplinkQueueMessage.getBmsHandshakeProto();
String tradeNo = bmsHandshakeProto.getTradeNo();
String pileCode = bmsHandshakeProto.getPileCode();
String gunCode = bmsHandshakeProto.getGunCode();
String carVinCode = bmsHandshakeProto.getCarVinCode();
String bmsProtocolVersion = bmsHandshakeProto.getBmsProtocolVersion();
int bmsBatteryType = bmsHandshakeProto.getBmsBatteryType();
int bmsPowerCapacity = bmsHandshakeProto.getBmsPowerCapacity();
String additionalInfo = bmsHandshakeProto.getAdditionalInfo();
log.info("BMS充电握手信息: 交易流水号: {}, 桩编码: {}, 枪号: {}, 车辆VIN: {}, BMS协议版本: {}, " +
"电池类型: {}, 电池容量: {}Ah, 附加信息: {}",
tradeNo, pileCode, gunCode, carVinCode, bmsProtocolVersion,
bmsBatteryType, bmsPowerCapacity, additionalInfo);
// TODO 处理相关业务逻辑,比如保存握手信息到数据库
callback.onSuccess();
}
private static Period createPeriod(int sn, LocalTime beginTime, LocalTime endTime, PricingModelFlag flag) {
Period period = new Period();
period.setSn(sn);

View File

@@ -212,6 +212,10 @@ public class ProtocolUplinkConsumerService extends AbstractConsumerService imple
pileProtocolService.onRestartPileResponse(uplinkQueueMsg, callback);
} else if (uplinkQueueMsg.hasBmsHandshakeProto()) {
pileProtocolService.onBmsHandshake(uplinkQueueMsg, callback);
} else {
callback.onSuccess();

View File

@@ -71,6 +71,7 @@ message UplinkQueueMessage {
BmsChargingInfoProto bmsChargingInfoProto = 34;
BmsAbortProto bmsAbortProto = 35;
RestartPileResponse restartPileResponse = 36;
BmsHandshakeProto bmsHandshakeProto = 37;
}
@@ -335,15 +336,38 @@ message BmsParamConfigReport {
}
message BmsChargingInfoProto {
string pileCode = 1;
string gunCode = 2;
string tradeNo = 3;
optional string additionalInfo = 4;
}
message BmsAbortProto {
int64 ts = 1; // 时间戳
string pileCode = 4;
string gunCode = 5;
string tradeNo = 6;
optional string additionalInfo = 20;
}
message BmsAbortProto {
int64 ts = 1; // 时间戳
string pileCode = 4;
string gunCode = 5;
string tradeNo = 6;
optional string additionalInfo = 20;
}
message BmsHandshakeProto {
int64 ts = 1; // 时间戳
string pileCode = 2; // 桩编码
string gunCode = 3; // 枪编码
string tradeNo = 4; // 交易流水号
string bmsProtocolVersion = 5; // BMS通信协议版本号
int32 bmsBatteryType = 6; // BMS电池类型
int32 bmsPowerCapacity = 7; // BMS整车动力蓄电池系统额定容量
int32 bmsPowerMaxVoltage = 8; // BMS整车动力蓄电池系统额定总电压
string bmsFactory = 9; // BMS电池生产厂商名称
int32 bmsSerialNo = 10; // BMS电池组序号
int32 bmsCreateYear = 11; // BMS电池组生产日期年
int32 bmsCreateMonth = 12; // BMS电池组生产日期月
int32 bmsCreateDay = 13; // BMS电池组生产日期日
int32 bmsChargeCount = 14; // BMS电池组充电次数
int32 bmsPropertyRightLabel = 15; // BMS电池组产权标识
string carVinCode = 16; // 车辆识别码(VIN)
string bmsSoftwareVersion = 17; // BMS软件版本号
optional string additionalInfo = 20; // 附加信息
}

View File

@@ -134,7 +134,7 @@ public class JCPPLengthFieldBasedFrameDecoder extends ByteToMessageDecoder {
// frameLengthInt exist , just check buf
if (in.readableBytes() < frameLengthInt) {
log.debug("{} 可读长度小于帧长,因此跳过 {}", ctx.channel(), frameLengthInt);
log.debug("{} 可读长度小于帧长 {},因此跳过", ctx.channel(), frameLengthInt);
return BREAK;
}

View File

@@ -40,6 +40,11 @@
---
#### 0x15 充电握手
`68 4d 00 15 00 15 32 01 02 00 00 00 00 11 15 11 16 15 55 35 02 60 20 23 12 12 00 00 10 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 b8 a1`
---
#### 0x34 下发启动充电
`68 30 01 00 00 34 00 00 00 00 00 00 12 34 56 78 90 12 34 56 78 90 20 23 12 12 00 00 10 01 56 78 90 12 34 56 78 90 56 78 90 12 34 56 78 90 10 27 00 00 5f d9`
#### 0x33 上行启动应答

View File

@@ -109,7 +109,7 @@ public class YunKuaiChongProtocolMessageProcessor extends ProtocolMessageProcess
if (!checkResult.getFirst()) {
if (log.isDebugEnabled()) { // 日志惰性计算
log.debug("{} 云快充校验域一次校验失败 CMD:{} 校验和0x{} 期望校验和:0x{}",
session, frameType, Integer.toHexString(checkSumBE), Integer.toHexString(checkSumLE));
session, frameType, Integer.toHexString(checkSumLE), Integer.toHexString(checkResult.getSecond()));
}
checkResult = checkCrcSum(checkData, checkSumBE);
}

View File

@@ -14,6 +14,7 @@ import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import sanbing.jcpp.infrastructure.util.codec.BCDUtil;
import sanbing.jcpp.infrastructure.util.jackson.JacksonUtil;
import sanbing.jcpp.infrastructure.util.trace.TracerContextUtil;
import sanbing.jcpp.proto.gen.ProtocolProto.BmsAbortProto;
import sanbing.jcpp.proto.gen.ProtocolProto.UplinkQueueMessage;
import sanbing.jcpp.protocol.ProtocolContext;
@@ -37,6 +38,9 @@ public class YunKuaiChongV150BmsAbortULCmd extends YunKuaiChongUplinkCmdExe {
log.debug("{} 云快充1.5.0充电阶段BMS中止", tcpSession);
ByteBuf byteBuf = Unpooled.wrappedBuffer(yunKuaiChongUplinkMessage.getMsgBody());
// 从Tracer总获取当前时间
long ts = TracerContextUtil.getCurrentTracer().getTracerTs();
ObjectNode additionalInfo = JacksonUtil.newObjectNode();
// 1.交易流水号
byte[] tradeNoBytes = new byte[16];
@@ -65,6 +69,7 @@ public class YunKuaiChongV150BmsAbortULCmd extends YunKuaiChongUplinkCmdExe {
additionalInfo.put("BMS中止充电错误原因", parseErrorReasons(errorReasonByte));
BmsAbortProto proto = BmsAbortProto.newBuilder()
.setTs(ts)
.setPileCode(pileCode)
.setGunCode(gunCode)
.setTradeNo(tradeNo)

View File

@@ -12,6 +12,7 @@ import io.netty.buffer.Unpooled;
import lombok.extern.slf4j.Slf4j;
import sanbing.jcpp.infrastructure.util.codec.BCDUtil;
import sanbing.jcpp.infrastructure.util.jackson.JacksonUtil;
import sanbing.jcpp.infrastructure.util.trace.TracerContextUtil;
import sanbing.jcpp.proto.gen.ProtocolProto.BmsChargingInfoProto;
import sanbing.jcpp.proto.gen.ProtocolProto.UplinkQueueMessage;
import sanbing.jcpp.protocol.ProtocolContext;
@@ -32,6 +33,9 @@ public class YunKuaiChongV150BmsChargingInfoULCmd extends YunKuaiChongUplinkCmdE
public void execute(TcpSession tcpSession, YunKuaiChongUplinkMessage yunKuaiChongUplinkMessage, ProtocolContext ctx) {
log.debug("{} 云快充1.5.0充电过程BMS信息", tcpSession);
ByteBuf byteBuf = Unpooled.wrappedBuffer(yunKuaiChongUplinkMessage.getMsgBody());
// 从Tracer总获取当前时间
long ts = TracerContextUtil.getCurrentTracer().getTracerTs();
ObjectNode additionalInfo = JacksonUtil.newObjectNode();
// 1.交易流水号
byte[] tradeNoBytes = new byte[16];
@@ -73,6 +77,7 @@ public class YunKuaiChongV150BmsChargingInfoULCmd extends YunKuaiChongUplinkCmdE
byteBuf.skipBytes(2);
BmsChargingInfoProto bmsCharingInfoProto = BmsChargingInfoProto.newBuilder()
.setTs(ts)
.setPileCode(pileCode)
.setTradeNo(tradeNo)
.setGunCode(gunCode)

View File

@@ -13,6 +13,9 @@ import io.netty.buffer.Unpooled;
import lombok.extern.slf4j.Slf4j;
import sanbing.jcpp.infrastructure.util.codec.BCDUtil;
import sanbing.jcpp.infrastructure.util.jackson.JacksonUtil;
import sanbing.jcpp.infrastructure.util.trace.TracerContextUtil;
import sanbing.jcpp.proto.gen.ProtocolProto.BmsHandshakeProto;
import sanbing.jcpp.proto.gen.ProtocolProto.UplinkQueueMessage;
import sanbing.jcpp.protocol.ProtocolContext;
import sanbing.jcpp.protocol.listener.tcp.TcpSession;
import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongUplinkCmdExe;
@@ -34,71 +37,60 @@ public class YunKuaiChongV150BmsHandshakeULCmd extends YunKuaiChongUplinkCmdExe
log.debug("{} 云快充1.5.0充电握手", tcpSession);
ByteBuf byteBuf = Unpooled.wrappedBuffer(yunKuaiChongUplinkMessage.getMsgBody());
// 从Tracer总获取当前时间
long ts = TracerContextUtil.getCurrentTracer().getTracerTs();
ObjectNode additionalInfo = JacksonUtil.newObjectNode();
// 1.交易流水号
byte[] tradeNoBytes = new byte[16];
byteBuf.readBytes(tradeNoBytes);
String tradeNo = BCDUtil.toString(tradeNoBytes);
additionalInfo.put("交易流水号", tradeNo);
// 2.桩编号
byte[] pileCodeBytes = new byte[7];
byteBuf.readBytes(pileCodeBytes);
String pileCode = BCDUtil.toString(pileCodeBytes);
additionalInfo.put("桩编号", pileCode);
// 3.抢号
byte gunCodeByte = byteBuf.readByte();
String gunCode = BCDUtil.toString(gunCodeByte);
additionalInfo.put("抢号", gunCode);
// 4.BMS 通信协议版本号
byte[] bmsConnectVersionBytes = new byte[3];
byteBuf.readBytes(bmsConnectVersionBytes);
additionalInfo.put("BMS 通信协议版本号", HexUtil.encodeHexStr(bmsConnectVersionBytes));
// 5.BMS 电池类型
int bmsBatteryType = byteBuf.readUnsignedByte();
additionalInfo.put("BMS电池类型", bmsBatteryType);
// 6.BMS 整车动力蓄电池系统额定容量
int bmsPowerCapacity = byteBuf.readUnsignedShortLE();
additionalInfo.put("BMS整车动力蓄电池系统额定容量", bmsPowerCapacity);
// 7.BMS 整车动力蓄电池系统额定总电压
int bmsPowerMaxVoltage = byteBuf.readUnsignedShortLE();
additionalInfo.put("BMS整车动力蓄电池系统额定总电压", bmsPowerMaxVoltage);
// 8.BMS 电池生产厂商名称
byte[] bmsFactoryBytes = new byte[4];
byteBuf.readBytes(bmsFactoryBytes);
String bmsFactory = new String(bmsFactoryBytes, StandardCharsets.US_ASCII);
additionalInfo.put("BMS电池生产厂商名称", bmsFactory);
// 9.BMS 电池组序号
int bmsSerialNo = byteBuf.readIntLE();
additionalInfo.put("BMS 电池组序号", bmsSerialNo);
// 10.BMS 电池组生产日期年
int bmsCreateYear = byteBuf.readUnsignedByte();
additionalInfo.put("BMS 电池组生产日期年", bmsCreateYear);
// 11.BMS 电池组生产日期月
int bmsCreateMonth = byteBuf.readUnsignedByte();
additionalInfo.put("BMS 电池组生产日期月", bmsCreateMonth);
// 12.BMS 电池组生产日期日
int bmsCreateDay = byteBuf.readUnsignedByte();
additionalInfo.put("BMS 电池组生产日期日", bmsCreateDay);
// 13.BMS 电池组充电次数
int bmsChargeCount = byteBuf.readUnsignedMedium();
additionalInfo.put("BMS 电池组充电次数", bmsChargeCount);
// 14.BMS 电池组产权标识
int bmsPropertyRightLabel = byteBuf.readUnsignedByte();
additionalInfo.put("BMS 电池组产权标识", bmsPropertyRightLabel);
// 15.预留位
byteBuf.skipBytes(1);
@@ -107,14 +99,39 @@ public class YunKuaiChongV150BmsHandshakeULCmd extends YunKuaiChongUplinkCmdExe
byte[] carVINBytes = new byte[17];
byteBuf.readBytes(carVINBytes);
String bmsVinCode = new String(carVINBytes, StandardCharsets.US_ASCII);
additionalInfo.put("电动汽车唯一标识", bmsVinCode);
// 17.BMS 软件版本号
byte[] bmsSoftVersionBytes = new byte[8];
byteBuf.readBytes(bmsSoftVersionBytes);
additionalInfo.put("BMS 软件版本号", HexUtil.encodeHexStr(bmsSoftVersionBytes));
// TODO 先打印日志,暂不转发
log.debug("{} 云快充1.5.0充电握手信息解析完成:{}", tcpSession, additionalInfo);
// 构建BmsHandshakeProto对象
BmsHandshakeProto bmsHandshakeProto = BmsHandshakeProto.newBuilder()
.setTs(ts)
.setPileCode(pileCode)
.setGunCode(gunCode)
.setTradeNo(tradeNo)
.setBmsProtocolVersion(HexUtil.encodeHexStr(bmsConnectVersionBytes))
.setBmsBatteryType(bmsBatteryType)
.setBmsPowerCapacity(bmsPowerCapacity)
.setBmsPowerMaxVoltage(bmsPowerMaxVoltage)
.setBmsFactory(bmsFactory)
.setBmsSerialNo(bmsSerialNo)
.setBmsCreateYear(bmsCreateYear)
.setBmsCreateMonth(bmsCreateMonth)
.setBmsCreateDay(bmsCreateDay)
.setBmsChargeCount(bmsChargeCount)
.setBmsPropertyRightLabel(bmsPropertyRightLabel)
.setCarVinCode(bmsVinCode)
.setBmsSoftwareVersion(HexUtil.encodeHexStr(bmsSoftVersionBytes))
.setAdditionalInfo(additionalInfo.toString())
.build();
// 构建上行队列消息
UplinkQueueMessage uplinkQueueMessage = uplinkMessageBuilder(pileCode, tcpSession, yunKuaiChongUplinkMessage)
.setBmsHandshakeProto(bmsHandshakeProto)
.build();
// 转发到应用层
tcpSession.getForwarder().sendMessage(uplinkQueueMessage);
}
}