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 94831fe..63da233 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 @@ -155,11 +155,11 @@ public class TestController { } - @GetMapping("/api/remoteUpdate") - public ResponseEntity remoteUpdate() { + @GetMapping("/api/otaRequest") + public ResponseEntity otaRequest() { - pileProtocolService.remoteUpdate(ProtocolProto.OtaRequest.newBuilder() - .setAddress("http://127.0.0.1") + pileProtocolService.otaRequest(ProtocolProto.OtaRequest.newBuilder() + .setAddress("127.0.0.1") .setExecutionControl(1) .setDownloadTimeout(1) .setPassword("123123") 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 9f1a6d1..8b924de 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 @@ -115,12 +115,12 @@ public interface PileProtocolService { /** * 远程更新 */ - void remoteUpdate(ProtocolProto.OtaRequest request); + void otaRequest(ProtocolProto.OtaRequest request); /** * 远程更新应答 */ - void onRemoteUpdate(UplinkQueueMessage uplinkQueueMessage, Callback callback); + void onOtaResponse(UplinkQueueMessage uplinkQueueMessage, Callback callback); /* * BMS充电握手 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 a901ff3..011e5ef 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 @@ -379,7 +379,7 @@ public class DefaultPileProtocolService implements PileProtocolService { } @Override - public void remoteUpdate(OtaRequest request) { + public void otaRequest(OtaRequest request) { UUID messageId = UUID.randomUUID(); UUID requestId = UUID.randomUUID(); @@ -390,14 +390,14 @@ public class DefaultPileProtocolService implements PileProtocolService { .setPileCode(request.getPileCode()) .setRequestIdMSB(requestId.getMostSignificantBits()) .setRequestIdLSB(requestId.getLeastSignificantBits()) - .setDownlinkCmd(DownlinkCmdEnum.REMOTE_UPDATE.name()) + .setDownlinkCmd(DownlinkCmdEnum.OTA_REQUEST.name()) .setOtaRequest(request); downlinkCallService.sendDownlinkMessage(downlinkRequestMessageBuilder,request.getPileCode()); } @Override - public void onRemoteUpdate(UplinkQueueMessage uplinkQueueMessage, Callback callback) { + public void onOtaResponse(UplinkQueueMessage uplinkQueueMessage, Callback callback) { log.info("接收到充电桩更新应答 {}", uplinkQueueMessage); 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 72e26ec..50fd7dc 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 @@ -218,7 +218,7 @@ public class ProtocolUplinkConsumerService extends AbstractConsumerService imple } else if (uplinkQueueMsg.hasOtaResponse()) { - pileProtocolService.onRemoteUpdate(uplinkQueueMsg, callback); + pileProtocolService.onOtaResponse(uplinkQueueMsg, callback); } else { 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 31957f3..7c79fd7 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 @@ -29,5 +29,5 @@ public enum DownlinkCmdEnum { REMOTE_RESTART_PILE, - REMOTE_UPDATE, + OTA_REQUEST, } \ No newline at end of file diff --git a/jcpp-protocol-yunkuaichong/READMD.md b/jcpp-protocol-yunkuaichong/READMD.md index 583b54b..a690c08 100644 --- a/jcpp-protocol-yunkuaichong/READMD.md +++ b/jcpp-protocol-yunkuaichong/READMD.md @@ -91,4 +91,8 @@ --- +#### 0x94 远程更新 +`68 62 0300 00 94 20231212000010 01 c8 00 68 74 74 70 3a 2f 2f 31 32 37 2e 30 2e 30 2e 31 90 00 62 61 77 61 6e 00 00 00 00 00 00 00 00 00 00 00 31 32 33 31 32 33 00 00 00 00 00 00 00 00 00 00 2f 75 73 65 72 2f 64 61 74 61 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 01 53 b6` +#### 0x93 远程更新应答 +`68 0C 0300 00 93 20231212000010 00 7E9B` 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 efdebfe..0c49a3a 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 @@ -18,6 +18,7 @@ import sanbing.jcpp.protocol.yunkuaichong.enums.YunKuaiChongDownlinkCmdEnum; import java.math.BigDecimal; import java.math.RoundingMode; +import java.nio.charset.StandardCharsets; import java.text.DecimalFormat; import java.time.LocalTime; import java.util.List; @@ -153,22 +154,71 @@ 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,避免创建中间ByteBuf对象 + * 将字符串参数写入ByteBuf,不足指定长度用0填充(右侧填充) + * 使用ASCII编码,适用于协议中的字符串字段 + * + * @param target 目标ByteBuf + * @param param 要写入的字符串参数,可以为null + * @param maxLength 目标长度(字节数) + * @throws IllegalArgumentException 如果参数字节长度超过maxLength + */ + protected static void writeParamFillZero(ByteBuf target, String param, int maxLength) { + if (maxLength <= 0) { + throw new IllegalArgumentException("maxLength must be positive"); + } + + if (param == null) { + param = ""; + } + + // 使用ASCII编码,适用于协议字段 + byte[] paramBytes = param.getBytes(StandardCharsets.US_ASCII); + + // 检查长度 + if (paramBytes.length > maxLength) { + throw new IllegalArgumentException( + String.format("云快充1.5.0 参数: %s 字节长度 %d 超过最大长度 %d", + param, paramBytes.length, maxLength)); + } + + // 确保目标ByteBuf有足够的写入空间 + target.ensureWritable(maxLength); + + // 写入数据 + target.writeBytes(paramBytes); + + // 填充剩余空间 + int remainingBytes = maxLength - paramBytes.length; + if (remainingBytes > 0) { + target.writeZero(remainingBytes); } - 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; + /** + * 高性能版本:将整数参数作为字节值直接写入ByteBuf,不足指定长度用0填充(右侧填充) + * + * @param target 目标ByteBuf + * @param param 要写入的整数参数(将作为字节值写入,只使用低8位) + * @param maxLength 目标长度(字节数) + */ + protected static void writeParamFillZero(ByteBuf target, int param, int maxLength) { + if (maxLength <= 0) { + throw new IllegalArgumentException("maxLength must be positive"); + } + + // 确保目标ByteBuf有足够的写入空间 + target.ensureWritable(maxLength); + + // 将整数作为字节值写入(只使用低8位) + target.writeByte(param & 0xFF); + + // 计算剩余空间并填充0 + int remainingBytes = maxLength - 1; // 已经写入了1个字节 + if (remainingBytes > 0) { + target.writeZero(remainingBytes); + } } } \ 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 2f94d1b..7671fdc 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 @@ -38,7 +38,7 @@ public enum YunKuaiChongDownlinkCmdEnum { REMOTE_RESTART_PILE(0x92), - REMOTE_UPDATE(0x94), + OTA_REQUEST(0x94), ; private final Integer cmd; 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/YunKuaiChongV150OtaRequestDLCmd.java similarity index 54% rename from jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150RemoteUpdateDLCmd.java rename to jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OtaRequestDLCmd.java index 971f05e..1b62324 100644 --- 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/YunKuaiChongV150OtaRequestDLCmd.java @@ -1,52 +1,58 @@ +/** + * 开源代码,仅供学习和交流研究使用,商用请联系三丙 + * 微信:mohan_88888 + * 抖音:程序员三丙 + * 付费课程知识星球:https://t.zsxq.com/aKtXo + */ 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.proto.gen.ProtocolProto.OtaRequest; 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; +import static sanbing.jcpp.protocol.yunkuaichong.enums.YunKuaiChongDownlinkCmdEnum.OTA_REQUEST; + /** * 云快充1.5.0 远程更新 + * * @author bawan */ @Slf4j @YunKuaiChongCmd(0x94) -public class YunKuaiChongV150RemoteUpdateDLCmd extends YunKuaiChongDownlinkCmdExe { +public class YunKuaiChongV150OtaRequestDLCmd extends YunKuaiChongDownlinkCmdExe { @Override public void execute(TcpSession tcpSession, YunKuaiChongDwonlinkMessage message, ProtocolContext ctx) { log.info("{} 云快充1.5.0 远程更新", tcpSession); - // check - if (message.getMsg().hasOtaRequest()) { + + if (!message.getMsg().hasOtaRequest()) { log.error("云快充1.5.0 远程更新消息体为空"); return; } // 初始化 buf ByteBuf msgBody = Unpooled.buffer(94); - // buf 转换 - ProtocolProto.OtaRequest request = message.getMsg().getOtaRequest(); + // buf 转换 - 使用高性能版本直接写入,避免创建中间ByteBuf对象 + 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)); + writeParamFillZero(msgBody, request.getPilePower(), 2); + writeParamFillZero(msgBody, request.getAddress(), 16); + writeParamFillZero(msgBody, request.getPort(), 2); + writeParamFillZero(msgBody, request.getUsername(), 16); + writeParamFillZero(msgBody, request.getPassword(), 16); + writeParamFillZero(msgBody, request.getFilePath(), 32); msgBody.writeByte(request.getExecutionControl()); msgBody.writeByte(request.getDownloadTimeout()); - super.encodeAndWriteFlush(REMOTE_UPDATE,msgBody,tcpSession); + super.encodeAndWriteFlush(OTA_REQUEST, msgBody, tcpSession); } - } 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/YunKuaiChongV150OtaResponseULCmd.java similarity index 88% rename from jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150RemoteUpdateAckULCmd.java rename to jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OtaResponseULCmd.java index 60c6036..f018262 100644 --- 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/YunKuaiChongV150OtaResponseULCmd.java @@ -1,7 +1,11 @@ +/** + * 开源代码,仅供学习和交流研究使用,商用请联系三丙 + * 微信:mohan_88888 + * 抖音:程序员三丙 + * 付费课程知识星球:https://t.zsxq.com/aKtXo + */ 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; @@ -13,6 +17,8 @@ import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongUplinkCmdExe; import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongUplinkMessage; import sanbing.jcpp.protocol.yunkuaichong.annotation.YunKuaiChongCmd; +import java.util.Map; + /** * 云快充1.5.0 远程更新应答 @@ -21,7 +27,7 @@ import sanbing.jcpp.protocol.yunkuaichong.annotation.YunKuaiChongCmd; */ @Slf4j @YunKuaiChongCmd(0x93) -public class YunKuaiChongV150RemoteUpdateAckULCmd extends YunKuaiChongUplinkCmdExe { +public class YunKuaiChongV150OtaResponseULCmd extends YunKuaiChongUplinkCmdExe { private static final Map UPGRADE_STATUS;