From 80fb741692d7c022b2892a97c597f41a70c7e51f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=AB=E4=B8=87?= <920444250@qq.com> Date: Wed, 13 Aug 2025 10:47:49 +0000 Subject: [PATCH] =?UTF-8?q?!18=20=E8=BF=9C=E7=A8=8B=E6=9B=B4=E6=96=B0=20?= =?UTF-8?q?=E8=BF=9C=E7=A8=8B=E6=9B=B4=E6=96=B0=E5=BA=94=E7=AD=94=20*=20?= =?UTF-8?q?=E8=BF=9C=E7=A8=8B=E6=9B=B4=E6=96=B0=E5=BA=94=E7=AD=94=20?= =?UTF-8?q?=E8=A1=A5=E5=85=85=20onRemoteUpdate=20=20=E5=8E=BB=E6=8E=89=20U?= =?UTF-8?q?pgradeStatusEnum=20=E6=9E=9A=E4=B8=BE=20=E7=94=A8hashMap=20?= =?UTF-8?q?=E5=A4=84=E7=90=86=E5=8D=87=E7=BA=A7=E7=BB=93=E6=9E=9C=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=20=E9=A2=86=E5=9F=9F=E6=A8=A1=E5=9E=8B=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96=20*=20Merge=20?= =?UTF-8?q?branch=20'master'=20of=20gitee.com:san-bing/JChargePointProtoco?= =?UTF-8?q?l=20into=20Feat=5F=E8=BF=9C=E7=A8=8B=E6=9B=B4=E6=96=B0=20*=20?= =?UTF-8?q?=E8=BF=9C=E7=A8=8B=E6=9B=B4=E6=96=B0=20=E8=BF=9C=E7=A8=8B?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=BA=94=E7=AD=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jcpp/app/adapter/TestController.java | 22 +++++++ .../jcpp/app/service/PileProtocolService.java | 11 ++++ .../impl/DefaultPileProtocolService.java | 33 ++++++++++ .../ProtocolUplinkConsumerService.java | 4 ++ .../src/main/proto/protocol.proto | 22 +++++++ .../jcpp/protocol/domain/DownlinkCmdEnum.java | 2 + .../AbstractYunKuaiChongCmdExe.java | 18 ++++++ .../enums/YunKuaiChongDownlinkCmdEnum.java | 5 +- .../YunKuaiChongV150RemoteUpdateAckULCmd.java | 62 +++++++++++++++++++ .../YunKuaiChongV150RemoteUpdateDLCmd.java | 52 ++++++++++++++++ 10 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150RemoteUpdateAckULCmd.java create mode 100644 jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150RemoteUpdateDLCmd.java diff --git a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/TestController.java b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/TestController.java index bd9c408..94831fe 100644 --- a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/TestController.java +++ b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/TestController.java @@ -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 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"); + } + } \ No newline at end of file diff --git a/jcpp-app/src/main/java/sanbing/jcpp/app/service/PileProtocolService.java b/jcpp-app/src/main/java/sanbing/jcpp/app/service/PileProtocolService.java index 2f36010..9f1a6d1 100644 --- a/jcpp-app/src/main/java/sanbing/jcpp/app/service/PileProtocolService.java +++ b/jcpp-app/src/main/java/sanbing/jcpp/app/service/PileProtocolService.java @@ -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); diff --git a/jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileProtocolService.java b/jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileProtocolService.java index e70dac6..a901ff3 100644 --- a/jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileProtocolService.java +++ b/jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileProtocolService.java @@ -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; } + + + + } \ No newline at end of file diff --git a/jcpp-app/src/main/java/sanbing/jcpp/app/service/queue/consumer/ProtocolUplinkConsumerService.java b/jcpp-app/src/main/java/sanbing/jcpp/app/service/queue/consumer/ProtocolUplinkConsumerService.java index e98d7e8..72e26ec 100644 --- a/jcpp-app/src/main/java/sanbing/jcpp/app/service/queue/consumer/ProtocolUplinkConsumerService.java +++ b/jcpp-app/src/main/java/sanbing/jcpp/app/service/queue/consumer/ProtocolUplinkConsumerService.java @@ -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(); diff --git a/jcpp-infrastructure-proto/src/main/proto/protocol.proto b/jcpp-infrastructure-proto/src/main/proto/protocol.proto index 68cc4b5..3ea8ed1 100644 --- a/jcpp-infrastructure-proto/src/main/proto/protocol.proto +++ b/jcpp-infrastructure-proto/src/main/proto/protocol.proto @@ -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; diff --git a/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/domain/DownlinkCmdEnum.java b/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/domain/DownlinkCmdEnum.java index 39767f6..31957f3 100644 --- a/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/domain/DownlinkCmdEnum.java +++ b/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/domain/DownlinkCmdEnum.java @@ -28,4 +28,6 @@ public enum DownlinkCmdEnum { REMOTE_PARALLEL_START_CHARGING, REMOTE_RESTART_PILE, + + REMOTE_UPDATE, } \ No newline at end of file diff --git a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/AbstractYunKuaiChongCmdExe.java b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/AbstractYunKuaiChongCmdExe.java index 4a3497b..efdebfe 100644 --- a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/AbstractYunKuaiChongCmdExe.java +++ b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/AbstractYunKuaiChongCmdExe.java @@ -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; + } + } \ No newline at end of file diff --git a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/enums/YunKuaiChongDownlinkCmdEnum.java b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/enums/YunKuaiChongDownlinkCmdEnum.java index 09f5a71..2f94d1b 100644 --- a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/enums/YunKuaiChongDownlinkCmdEnum.java +++ b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/enums/YunKuaiChongDownlinkCmdEnum.java @@ -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; } \ No newline at end of file diff --git a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150RemoteUpdateAckULCmd.java b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150RemoteUpdateAckULCmd.java new file mode 100644 index 0000000..60c6036 --- /dev/null +++ b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150RemoteUpdateAckULCmd.java @@ -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 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); + } + +} diff --git a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150RemoteUpdateDLCmd.java b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150RemoteUpdateDLCmd.java new file mode 100644 index 0000000..971f05e --- /dev/null +++ b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150RemoteUpdateDLCmd.java @@ -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); + } + + +}