mirror of
https://codeup.aliyun.com/67c68d4e484ca2f0a13ac3c1/ydc/jsowell-charger-web.git
synced 2026-04-20 11:05:18 +08:00
update 电单车协议
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
package com.jsowell.netty.decoder;
|
||||
|
||||
import com.jsowell.netty.domain.EBikeMessage;
|
||||
import com.jsowell.netty.domain.ebike.EBikeMessage;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
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位结果
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
package com.jsowell.netty.decoder;
|
||||
|
||||
import com.jsowell.netty.domain.DnyMessage;
|
||||
import com.jsowell.netty.domain.Message68;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.List;
|
||||
@Deprecated
|
||||
@Slf4j
|
||||
public class StartAndLengthFieldFrameDecoder2 extends ByteToMessageDecoder {
|
||||
private static final int HEADER_LENGTH_DNY = 3; // "DNY" 包头的长度
|
||||
private static final int HEADER_LENGTH_68 = 1; // 68 包头的长度
|
||||
private static final int MAX_FRAME_LENGTH = 1024; // 最大帧长度,可以根据实际需求调整
|
||||
private static final byte[] DNY_HEADER = {'D', 'N', 'Y'};
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws Exception {
|
||||
while (buffer.readableBytes() > 0) {
|
||||
int headerIndex = findHeaderIndex(buffer);
|
||||
if (headerIndex == -1) {
|
||||
// 没有找到有效的包头,丢弃所有数据
|
||||
buffer.skipBytes(buffer.readableBytes());
|
||||
return;
|
||||
}
|
||||
|
||||
buffer.readerIndex(headerIndex);
|
||||
|
||||
if (isDnyHeader(buffer)) {
|
||||
if (decodeDnyMessage(buffer, out)) {
|
||||
return;
|
||||
}
|
||||
} else if (is68Header(buffer)) {
|
||||
if (decode68Message(buffer, out)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// 未知协议,跳过一个字节
|
||||
buffer.skipBytes(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int findHeaderIndex(ByteBuf buffer) {
|
||||
int dnyIndex = buffer.indexOf(buffer.readerIndex(), buffer.writerIndex(), DNY_HEADER[0]);
|
||||
int index68 = buffer.indexOf(buffer.readerIndex(), buffer.writerIndex(), (byte) 0x68);
|
||||
|
||||
if (dnyIndex == -1 && index68 == -1) {
|
||||
return -1;
|
||||
} else if (dnyIndex == -1) {
|
||||
return index68;
|
||||
} else if (index68 == -1) {
|
||||
return dnyIndex;
|
||||
} else {
|
||||
return Math.min(dnyIndex, index68);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isDnyHeader(ByteBuf buffer) {
|
||||
return buffer.readableBytes() >= HEADER_LENGTH_DNY &&
|
||||
buffer.getByte(buffer.readerIndex()) == 'D' &&
|
||||
buffer.getByte(buffer.readerIndex() + 1) == 'N' &&
|
||||
buffer.getByte(buffer.readerIndex() + 2) == 'Y';
|
||||
}
|
||||
|
||||
private boolean is68Header(ByteBuf buffer) {
|
||||
return buffer.readableBytes() >= HEADER_LENGTH_68 &&
|
||||
buffer.getByte(buffer.readerIndex()) == 0x68;
|
||||
}
|
||||
|
||||
private boolean decodeDnyMessage(ByteBuf buffer, List<Object> out) {
|
||||
if (buffer.readableBytes() < HEADER_LENGTH_DNY + 2) {
|
||||
return false; // 数据不足,等待更多数据
|
||||
}
|
||||
|
||||
int lengthFieldIndex = buffer.readerIndex() + HEADER_LENGTH_DNY;
|
||||
int length = buffer.getUnsignedShort(lengthFieldIndex);
|
||||
|
||||
if (length > MAX_FRAME_LENGTH) {
|
||||
log.warn("DNY frame length exceeds maximum allowed: {}", length);
|
||||
buffer.skipBytes(HEADER_LENGTH_DNY + 2);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buffer.readableBytes() < HEADER_LENGTH_DNY + 2 + length) {
|
||||
return false; // 数据不足,等待更多数据
|
||||
}
|
||||
|
||||
ByteBuf frame = buffer.readRetainedSlice(HEADER_LENGTH_DNY + 2 + length);
|
||||
out.add(new DnyMessage(frame));
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean decode68Message(ByteBuf buffer, List<Object> out) {
|
||||
if (buffer.readableBytes() < HEADER_LENGTH_68 + 1) {
|
||||
return false; // 数据不足,等待更多数据
|
||||
}
|
||||
|
||||
int length = buffer.getUnsignedByte(buffer.readerIndex() + HEADER_LENGTH_68);
|
||||
|
||||
if (length > MAX_FRAME_LENGTH) {
|
||||
log.warn("68 frame length exceeds maximum allowed: {}", length);
|
||||
buffer.skipBytes(HEADER_LENGTH_68 + 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buffer.readableBytes() < HEADER_LENGTH_68 + 1 + length) {
|
||||
return false; // 数据不足,等待更多数据
|
||||
}
|
||||
|
||||
ByteBuf frame = buffer.readRetainedSlice(HEADER_LENGTH_68 + 1 + length);
|
||||
out.add(new Message68(frame));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package com.jsowell.netty.domain;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public class DnyMessage {
|
||||
private final ByteBuf content;
|
||||
|
||||
public DnyMessage(ByteBuf content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public ByteBuf getContent() {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package com.jsowell.netty.domain;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public class Message68 {
|
||||
private final ByteBuf content;
|
||||
|
||||
public Message68(ByteBuf content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public ByteBuf getContent() {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package com.jsowell.netty.domain;
|
||||
|
||||
public class ProtocolDnyMessage {
|
||||
private final byte[] header;
|
||||
private final int length;
|
||||
private final byte[] physicalId;
|
||||
private final int messageId;
|
||||
private final byte command;
|
||||
private final byte[] data;
|
||||
private final int checksum;
|
||||
|
||||
public ProtocolDnyMessage(byte[] header, int length, byte[] physicalId, int messageId, byte command, byte[] data, int checksum) {
|
||||
this.header = header;
|
||||
this.length = length;
|
||||
this.physicalId = physicalId;
|
||||
this.messageId = messageId;
|
||||
this.command = command;
|
||||
this.data = data;
|
||||
this.checksum = checksum;
|
||||
}
|
||||
|
||||
public byte[] getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public byte[] getPhysicalId() {
|
||||
return physicalId;
|
||||
}
|
||||
|
||||
public int getMessageId() {
|
||||
return messageId;
|
||||
}
|
||||
|
||||
public byte getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public int getChecksum() {
|
||||
return checksum;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.jsowell.netty.domain;
|
||||
package com.jsowell.netty.domain.ebike;
|
||||
|
||||
import com.jsowell.common.YouDianUtils;
|
||||
import com.jsowell.common.util.BytesUtil;
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.jsowell.netty.server.electricbicycles;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.jsowell.netty.domain.EBikeMessage;
|
||||
import com.jsowell.netty.domain.ebike.EBikeMessage;
|
||||
import io.netty.channel.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
Reference in New Issue
Block a user