mirror of
https://codeup.aliyun.com/67c68d4e484ca2f0a13ac3c1/ydc/jsowell-charger-web.git
synced 2026-04-20 19:15:35 +08:00
118 lines
3.9 KiB
Java
118 lines
3.9 KiB
Java
package com.jsowell.netty.decoder;
|
||
|
||
|
||
import com.jsowell.netty.domain.ProtocolDnyMessage;
|
||
import io.netty.buffer.ByteBuf;
|
||
import io.netty.channel.ChannelHandlerContext;
|
||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||
import lombok.extern.slf4j.Slf4j;
|
||
|
||
import java.nio.ByteOrder;
|
||
import java.util.List;
|
||
|
||
@Slf4j
|
||
public class ProtocolDnyDecoder extends ByteToMessageDecoder {
|
||
private static final int HEADER_LENGTH = 3; // 包头长度
|
||
private static final int LENGTH_FIELD_LENGTH = 2; // 长度字段长度
|
||
private static final int PHYSICAL_ID_LENGTH = 4; // 物理ID长度
|
||
private static final int MESSAGE_ID_LENGTH = 2; // 消息ID长度
|
||
private static final int COMMAND_LENGTH = 1; // 命令长度
|
||
private static final int CHECKSUM_LENGTH = 2; // 校验字段长度
|
||
|
||
private static final int MIN_FRAME_LENGTH = HEADER_LENGTH + LENGTH_FIELD_LENGTH + PHYSICAL_ID_LENGTH + MESSAGE_ID_LENGTH + COMMAND_LENGTH + CHECKSUM_LENGTH;
|
||
|
||
@Override
|
||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
|
||
// 检查是否有足够的数据来读取最小帧长度
|
||
if (in.readableBytes() < MIN_FRAME_LENGTH) {
|
||
return;
|
||
}
|
||
|
||
// 标记当前读位置
|
||
in.markReaderIndex();
|
||
|
||
// 检查包头
|
||
byte[] header = new byte[HEADER_LENGTH];
|
||
in.readBytes(header);
|
||
if (header[0] != 'D' || header[1] != 'N' || header[2] != 'Y') {
|
||
in.resetReaderIndex();
|
||
throw new IllegalStateException("Invalid start bytes: " + new String(header));
|
||
}
|
||
|
||
// 读取长度字段
|
||
in.order(ByteOrder.LITTLE_ENDIAN); // 确保使用小端模式
|
||
int length = in.readUnsignedShort();
|
||
if (in.readableBytes() < length) {
|
||
in.resetReaderIndex();
|
||
return;
|
||
}
|
||
|
||
// 读取物理ID
|
||
byte[] physicalId = new byte[PHYSICAL_ID_LENGTH];
|
||
in.readBytes(physicalId);
|
||
|
||
// 读取消息ID
|
||
int messageId = in.readUnsignedShort();
|
||
|
||
// 读取命令
|
||
byte command = in.readByte();
|
||
|
||
// 读取数据
|
||
int dataLength = length - (PHYSICAL_ID_LENGTH + MESSAGE_ID_LENGTH + COMMAND_LENGTH + CHECKSUM_LENGTH);
|
||
byte[] data = new byte[dataLength];
|
||
in.readBytes(data);
|
||
|
||
// 读取校验字段
|
||
int checksum = in.readUnsignedShort();
|
||
|
||
// 计算校验值并验证
|
||
if (!verifyChecksum(header, length, physicalId, messageId, command, data, checksum)) {
|
||
in.resetReaderIndex();
|
||
throw new IllegalStateException("Invalid checksum");
|
||
}
|
||
|
||
// 创建协议消息对象
|
||
ProtocolDnyMessage message = new ProtocolDnyMessage(header, length, physicalId, messageId, command, data, checksum);
|
||
|
||
// 将解码后的消息添加到输出列表中
|
||
out.add(message);
|
||
}
|
||
|
||
// 校验帧校验域的函数
|
||
private boolean verifyChecksum(byte[] header, int length, byte[] physicalId, int messageId, byte command, byte[] data, int checksum) {
|
||
// 这里需要实现校验逻辑,假设我们有一个累加和校验函数sumCheck
|
||
int calculatedChecksum = sumCheck(header, length, physicalId, messageId, command, data);
|
||
return calculatedChecksum == checksum;
|
||
}
|
||
|
||
// 累加和校验函数,计算从包头到数据的累加和
|
||
private int sumCheck(byte[] header, int length, byte[] physicalId, int messageId, byte command, byte[] data) {
|
||
int sum = 0;
|
||
|
||
for (byte b : header) {
|
||
sum += b & 0xFF;
|
||
}
|
||
|
||
sum += length & 0xFF;
|
||
sum += (length >> 8) & 0xFF;
|
||
|
||
for (byte b : physicalId) {
|
||
sum += b & 0xFF;
|
||
}
|
||
|
||
sum += messageId & 0xFF;
|
||
sum += (messageId >> 8) & 0xFF;
|
||
|
||
sum += command & 0xFF;
|
||
|
||
for (byte b : data) {
|
||
sum += b & 0xFF;
|
||
}
|
||
|
||
return sum & 0xFFFF; // 返回16位结果
|
||
}
|
||
}
|
||
|
||
|
||
|