package com.ard.tianyu.netty.handler;// MessageProtocolDecoder.java import com.ard.tianyu.netty.command.*; import com.ard.tianyu.netty.protobuf.TelemetryDataPB; 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; @Slf4j public class MessageProtocolDecoder extends ByteToMessageDecoder { @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { // 检查可读字节数是否足够 if (in.readableBytes() < 4) { return; // 不足以读取头部 } in.markReaderIndex(); // 标记当前读取位置 short dataHead = in.readShort(); if (dataHead != 0x6A77) { return; } short dataLength = in.readShort(); if (in.readableBytes() < dataLength) { in.resetReaderIndex(); // 如果不足,重置读取位置 return; } byte cmdCode = in.readByte(); BaseCommand baseCommand = null; switch (cmdCode) { case 0x01: byte success = in.readByte(); // 读取是否成功 log.warn("注册回复: {}", success == 0x01 ? "成功" : "失败"); baseCommand = new RegisterReplyCommand(success); break; case 0x02: long timestamp = in.readLong(); // 读取时间戳 baseCommand = new HeartbeatReplyCommand(timestamp); log.debug("心跳回复: 时间戳 {}", timestamp); break; case 0x03: case 0x04: byte[] boxSn = new byte[dataLength - 1]; in.readBytes(boxSn); SubscribeReplyCommand subscribeReply = new SubscribeReplyCommand(new String(boxSn)); log.debug("订阅回复: {}", subscribeReply.getBoxSn()); break; case (byte) 0xA8: byte[] uavStatus = new byte[dataLength - 1]; in.readBytes(uavStatus); // 读取 ProtoBuf 数据 TelemetryDataPB.UavState uavState = TelemetryDataPB.UavState.parseFrom(uavStatus); baseCommand = new UavStateCommand(uavState); log.warn("无人机状态数据: {}", uavState.getBoxSn()); break; case (byte) 0xA9: byte[] uavData = new byte[dataLength - 1]; in.readBytes(uavData); TelemetryDataPB.TelemetryData telemetryData = TelemetryDataPB.TelemetryData.parseFrom(uavData); baseCommand = new UavDataCommand(telemetryData); log.warn("无人机遥测数据: {}", telemetryData.getBoxSn()); break; default: log.warn("无法识别的命令码: {}", String.format("0x%02X", cmdCode & 0xFF));//String.format("0x%02X", cmdCode & 0xFF) } if (baseCommand != null) { out.add(baseCommand); } } }