修正云快充OTA升级中的一些BUG,并优化代码

This commit is contained in:
三丙
2025-08-13 20:02:41 +08:00
parent 80fb741692
commit b393f5b426
10 changed files with 110 additions and 44 deletions

View File

@@ -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);
}
}
}

View File

@@ -38,7 +38,7 @@ public enum YunKuaiChongDownlinkCmdEnum {
REMOTE_RESTART_PILE(0x92),
REMOTE_UPDATE(0x94),
OTA_REQUEST(0x94),
;
private final Integer cmd;

View File

@@ -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);
}
}

View File

@@ -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<Byte, String> UPGRADE_STATUS;