!18 远程更新 远程更新应答

* 远程更新应答 补充 onRemoteUpdate  去掉 UpgradeStatusEnum 枚举 用hashMap 处理升级结果返回 领域模型优化 代码优化
* Merge branch 'master' of gitee.com:san-bing/JChargePointProtocol into Feat_远程更新
* 远程更新 远程更新应答
This commit is contained in:
八万
2025-08-13 10:47:49 +00:00
committed by 三丙
parent ca536a55f2
commit 80fb741692
10 changed files with 230 additions and 1 deletions

View File

@@ -11,6 +11,7 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import sanbing.jcpp.app.service.PileProtocolService;
import sanbing.jcpp.proto.gen.ProtocolProto;
import sanbing.jcpp.proto.gen.ProtocolProto.*;
import java.math.BigDecimal;
@@ -152,4 +153,25 @@ public class TestController {
return ResponseEntity.ok("success");
}
@GetMapping("/api/remoteUpdate")
public ResponseEntity<String> remoteUpdate() {
pileProtocolService.remoteUpdate(ProtocolProto.OtaRequest.newBuilder()
.setAddress("http://127.0.0.1")
.setExecutionControl(1)
.setDownloadTimeout(1)
.setPassword("123123")
.setFilePath("/user/data")
.setPileCode("20231212000010")
.setPileModel(1)
.setPilePower(200)
.setPort(8080)
.setUsername("bawan")
.build());
return ResponseEntity.ok("success");
}
}

View File

@@ -7,6 +7,7 @@
package sanbing.jcpp.app.service;
import sanbing.jcpp.infrastructure.queue.Callback;
import sanbing.jcpp.proto.gen.ProtocolProto;
import sanbing.jcpp.proto.gen.ProtocolProto.SetPricingRequest;
import sanbing.jcpp.proto.gen.ProtocolProto.UplinkQueueMessage;
@@ -112,6 +113,16 @@ public interface PileProtocolService {
void onBmsAbort(UplinkQueueMessage uplinkQueueMessage, Callback callback);
/**
* 远程更新
*/
void remoteUpdate(ProtocolProto.OtaRequest request);
/**
* 远程更新应答
*/
void onRemoteUpdate(UplinkQueueMessage uplinkQueueMessage, Callback callback);
/*
* BMS充电握手
*/
void onBmsHandshake(UplinkQueueMessage uplinkQueueMessage, Callback callback);

View File

@@ -378,6 +378,35 @@ public class DefaultPileProtocolService implements PileProtocolService {
callback.onSuccess();
}
@Override
public void remoteUpdate(OtaRequest request) {
UUID messageId = UUID.randomUUID();
UUID requestId = UUID.randomUUID();
DownlinkRequestMessage.Builder downlinkRequestMessageBuilder = DownlinkRequestMessage.newBuilder()
.setMessageIdMSB(messageId.getMostSignificantBits())
.setMessageIdLSB(messageId.getLeastSignificantBits())
.setPileCode(request.getPileCode())
.setRequestIdMSB(requestId.getMostSignificantBits())
.setRequestIdLSB(requestId.getLeastSignificantBits())
.setDownlinkCmd(DownlinkCmdEnum.REMOTE_UPDATE.name())
.setOtaRequest(request);
downlinkCallService.sendDownlinkMessage(downlinkRequestMessageBuilder,request.getPileCode());
}
@Override
public void onRemoteUpdate(UplinkQueueMessage uplinkQueueMessage, Callback callback) {
log.info("接收到充电桩更新应答 {}", uplinkQueueMessage);
// TODO 处理相关业务逻辑
callback.onSuccess();
}
@Override
public void onBmsHandshake(UplinkQueueMessage uplinkQueueMessage, Callback callback) {
log.info("接收到BMS充电握手信息 {}", uplinkQueueMessage);
@@ -424,4 +453,8 @@ public class DefaultPileProtocolService implements PileProtocolService {
builder.setRequestData(uplinkQueueMessage.getRequestData());
return builder;
}
}

View File

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

View File

@@ -72,6 +72,7 @@ message UplinkQueueMessage {
BmsAbortProto bmsAbortProto = 35;
RestartPileResponse restartPileResponse = 36;
BmsHandshakeProto bmsHandshakeProto = 37;
OtaResponse otaResponse = 38;
}
@@ -94,6 +95,7 @@ message DownlinkRequestMessage {
RemoteStopChargingRequest remoteStopChargingRequest = 26;
TransactionRecordAck transactionRecordAck = 27;
RestartPileRequest restartPileRequest = 28;
OtaRequest otaRequest = 29;
}
message DownlinkResponseMessage {
@@ -370,6 +372,26 @@ message BmsChargingInfoProto {
optional string additionalInfo = 20;
}
message OtaRequest {
string pileCode = 1; // 桩编号
int32 pileModel = 2; // 桩型号
int32 pilePower = 3; // 桩功率
string address = 4; // 升级服务器地址
int32 port = 5; // 升级服务器端口
string username = 6; // 用户名
string password = 7; // 密码
string filePath = 8; // 文件路径
int32 executionControl = 9; // 执行控制
int32 downloadTimeout = 10; // 下载超时时间
}
message OtaResponse {
string pileCode = 1; // 桩编号
bool success = 2;
optional string errorMsg = 3;
}
message BmsAbortProto {
int64 ts = 1; // 时间戳
string pileCode = 4;

View File

@@ -28,4 +28,6 @@ public enum DownlinkCmdEnum {
REMOTE_PARALLEL_START_CHARGING,
REMOTE_RESTART_PILE,
REMOTE_UPDATE,
}

View File

@@ -153,4 +153,22 @@ public class AbstractYunKuaiChongCmdExe {
return new BigDecimal(value).divide(new BigDecimal(magnification), scale, RoundingMode.HALF_UP);
}
protected static ByteBuf writeParamFillZero(String param,int maxLength) {
if (param.length() > maxLength) {
throw new IllegalArgumentException(String.format("云快充1.5.0 param: %s too large",param));
}
ByteBuf msgBody = Unpooled.buffer(maxLength);
msgBody.writeBytes(param.getBytes());
msgBody.writeZero(maxLength-param.length());
return msgBody;
}
protected static ByteBuf writeParamFillZero(int param,int maxLength) {
ByteBuf msgBody = Unpooled.buffer(maxLength);
msgBody.writeByte(param);
int index = msgBody.writerIndex();
msgBody.writeZero(maxLength-index);
return msgBody;
}
}

View File

@@ -36,8 +36,11 @@ public enum YunKuaiChongDownlinkCmdEnum {
REMOTE_PARALLEL_START_CHARGING(0xA4),
REMOTE_RESTART_PILE(0x92);
REMOTE_RESTART_PILE(0x92),
REMOTE_UPDATE(0x94),
;
private final Integer cmd;
}

View File

@@ -0,0 +1,62 @@
package sanbing.jcpp.protocol.yunkuaichong.v150.cmd;
import java.util.Map;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.extern.slf4j.Slf4j;
import sanbing.jcpp.infrastructure.util.codec.BCDUtil;
import sanbing.jcpp.proto.gen.ProtocolProto;
import sanbing.jcpp.protocol.ProtocolContext;
import sanbing.jcpp.protocol.listener.tcp.TcpSession;
import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongUplinkCmdExe;
import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongUplinkMessage;
import sanbing.jcpp.protocol.yunkuaichong.annotation.YunKuaiChongCmd;
/**
* 云快充1.5.0 远程更新应答
*
* @author bawan
*/
@Slf4j
@YunKuaiChongCmd(0x93)
public class YunKuaiChongV150RemoteUpdateAckULCmd extends YunKuaiChongUplinkCmdExe {
private static final Map<Byte, String> UPGRADE_STATUS;
static {
UPGRADE_STATUS = Map.of(
(byte) 0x00,"成功",
(byte) 0x01,"编号错误",
(byte) 0x02,"程序与桩型号不符",
(byte) 0x03, "下载更新文件超时"
);
}
@Override
public void execute(TcpSession tcpSession, YunKuaiChongUplinkMessage message, ProtocolContext ctx) {
log.info("{} 云快充1.5.0 远程更新应答", tcpSession);
ByteBuf byteBuf = Unpooled.wrappedBuffer(message.getMsgBody());
// 桩编号
byte[] pileCodeBytes = new byte[7];
byteBuf.readBytes(pileCodeBytes);
String pileCode = BCDUtil.toString(pileCodeBytes);
// 升级状态 // 0x00成功 0x01编号错误 0x01程序与桩型号不符 0x01下载更新文件超时
byte upgradeStatus = byteBuf.readByte();
ProtocolProto.UplinkQueueMessage queueMessage = uplinkMessageBuilder(pileCode, tcpSession, message)
.setOtaResponse(ProtocolProto.OtaResponse.newBuilder()
.setPileCode(pileCode)
.setSuccess(upgradeStatus == 0x00)
.setErrorMsg(UPGRADE_STATUS.get(upgradeStatus))
.build())
.build();
// 转发到后端
tcpSession.getForwarder().sendMessage(queueMessage);
}
}

View File

@@ -0,0 +1,52 @@
package sanbing.jcpp.protocol.yunkuaichong.v150.cmd;
import static sanbing.jcpp.protocol.yunkuaichong.enums.YunKuaiChongDownlinkCmdEnum.REMOTE_UPDATE;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.extern.slf4j.Slf4j;
import sanbing.jcpp.proto.gen.ProtocolProto;
import sanbing.jcpp.protocol.ProtocolContext;
import sanbing.jcpp.protocol.listener.tcp.TcpSession;
import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongDownlinkCmdExe;
import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongDwonlinkMessage;
import sanbing.jcpp.protocol.yunkuaichong.annotation.YunKuaiChongCmd;
/**
* 云快充1.5.0 远程更新
* @author bawan
*/
@Slf4j
@YunKuaiChongCmd(0x94)
public class YunKuaiChongV150RemoteUpdateDLCmd extends YunKuaiChongDownlinkCmdExe {
@Override
public void execute(TcpSession tcpSession, YunKuaiChongDwonlinkMessage message, ProtocolContext ctx) {
log.info("{} 云快充1.5.0 远程更新", tcpSession);
// check
if (message.getMsg().hasOtaRequest()) {
log.error("云快充1.5.0 远程更新消息体为空");
return;
}
// 初始化 buf
ByteBuf msgBody = Unpooled.buffer(94);
// buf 转换
ProtocolProto.OtaRequest request = message.getMsg().getOtaRequest();
msgBody.writeBytes(encodePileCode(request.getPileCode()));
msgBody.writeByte(request.getPileModel());
msgBody.writeBytes(writeParamFillZero(request.getPilePower(),2));
msgBody.writeBytes(writeParamFillZero(request.getAddress(),16));
msgBody.writeBytes(writeParamFillZero(request.getPort(),2));
msgBody.writeBytes(writeParamFillZero(request.getUsername(),16));
msgBody.writeBytes(writeParamFillZero(request.getPassword(),16));
msgBody.writeBytes(writeParamFillZero(request.getFilePath(),32));
msgBody.writeByte(request.getExecutionControl());
msgBody.writeByte(request.getDownloadTimeout());
super.encodeAndWriteFlush(REMOTE_UPDATE,msgBody,tcpSession);
}
}