package com.ard.tianyu.netty.handler;// MessageProtocolDecoder.java import com.ard.tianyu.netty.command.*; import com.ard.tianyu.netty.command.camera.CameraModeReplyCmd; import com.ard.tianyu.netty.command.camera.CapturePicReplyCmd; import com.ard.tianyu.netty.command.camera.RecordStartReplyCmd; import com.ard.tianyu.netty.command.camera.RecordStopReplyCmd; import com.ard.tianyu.netty.command.notice.BoxPowerStatusReplyCmd; import com.ard.tianyu.netty.command.notice.FlyWayEndReplyCmd; import com.ard.tianyu.netty.command.notice.UavReadyReplyCmd; import com.ard.tianyu.netty.command.real.SignalInfoCmd; import com.ard.tianyu.netty.command.real.UavStateCmd; import com.ard.tianyu.netty.command.real.UavTelemetryDataCmd; import com.ard.tianyu.netty.command.register.HeartbeatReplyCmd; import com.ard.tianyu.netty.command.register.RegisterReplyCmd; import com.ard.tianyu.netty.command.register.UavInitReplyCmd; 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(); BaseCmd baseCmd = null; switch (cmdCode) { case 0x01: byte success = in.readByte(); // 读取是否成功 log.warn("注册回复: {}", success == 0x01 ? "成功" : "失败"); baseCmd = new RegisterReplyCmd(success); break; case 0x02: long timestamp = in.readLong(); // 读取时间戳 baseCmd = new HeartbeatReplyCmd(timestamp); log.debug("心跳回复: 时间戳 {}", timestamp); break; case 0x03: case 0x04: break; case 0x0A: byte status = in.readByte(); baseCmd = new BoxPowerStatusReplyCmd(status); log.debug("云盒开机/关机通知回复: 状态 {}", String.format("0x%02X", status & 0xFF)); break; case (byte) 0xA8: byte[] uavStatus = new byte[dataLength - 1]; in.readBytes(uavStatus); // 读取 ProtoBuf 数据 TelemetryDataPB.UavState uavState = TelemetryDataPB.UavState.parseFrom(uavStatus); baseCmd = new UavStateCmd(uavState); log.debug("无人机状态数据: {}", uavState.getBoxSn()); break; case (byte) 0xA9: byte[] uavData = new byte[dataLength - 1]; in.readBytes(uavData); TelemetryDataPB.TelemetryData telemetryData = TelemetryDataPB.TelemetryData.parseFrom(uavData); baseCmd = new UavTelemetryDataCmd(telemetryData); log.debug("遥测数据: {}", telemetryData.getBoxSn()); break; case (byte) 0x0C: int delayTime = in.readInt(); uavData = new byte[15]; in.readBytes(uavData); // String boxSn12 = new String(uavData); uavData = new byte[dataLength - 20]; in.readBytes(uavData); TelemetryDataPB.SignalInfo signalInfo = TelemetryDataPB.SignalInfo.parseFrom(uavData); baseCmd = new SignalInfoCmd(signalInfo); log.debug("信道质量数据: {}", delayTime); break; case (byte) 0xD1: byte encryptionFlag = in.readByte(); byte actionCode = in.readByte(); switch (actionCode) { case 0x22: byte result = in.readByte(); int errorCode = in.readInt(); uavData = new byte[15]; in.readBytes(uavData); String boxSn = new String(uavData); baseCmd = new CameraModeReplyCmd(boxSn, result, errorCode); log.debug("设置相机模式回复: {}", boxSn); break; case 0x23: result = in.readByte(); errorCode = in.readInt(); uavData = new byte[15]; in.readBytes(uavData); boxSn = new String(uavData); baseCmd = new CapturePicReplyCmd(boxSn, result, errorCode); log.debug("拍照回复: {}", boxSn); break; case 0x24: result = in.readByte(); errorCode = in.readInt(); uavData = new byte[15]; in.readBytes(uavData); boxSn = new String(uavData); baseCmd = new RecordStartReplyCmd(boxSn, result, errorCode); log.debug("开始录像回复: {}", boxSn); break; case 0x25: result = in.readByte(); errorCode = in.readInt(); uavData = new byte[15]; in.readBytes(uavData); boxSn = new String(uavData); baseCmd = new RecordStopReplyCmd(boxSn, result, errorCode); log.debug("停止录像回复: {}", boxSn); break; case 0x2E: result = in.readByte(); errorCode = in.readInt(); uavData = new byte[15]; in.readBytes(uavData); boxSn = new String(uavData); baseCmd = new FlyWayEndReplyCmd(boxSn, result, errorCode); log.debug("航线结束通知回复: {}", boxSn); break; case 0x3D: byte batteryPower = in.readByte(); double longitude = in.readDouble(); double latitude = in.readDouble(); int altitude = in.readInt(); uavData = new byte[dataLength - 24]; in.readBytes(uavData); boxSn = new String(uavData); baseCmd = new UavReadyReplyCmd(boxSn, batteryPower, longitude, latitude, altitude); log.debug("无人机准备完成通知回复: 电池电量 {}", String.format("0x%02X", batteryPower & 0xFF)); break; case 0x42: byte[] uavData1 = new byte[dataLength - 18]; in.readBytes(uavData1); byte[] uavData2 = new byte[15]; in.readBytes(uavData2); boxSn = new String(uavData2); TelemetryDataPB.UavInitInfo uavInitInfo = TelemetryDataPB.UavInitInfo.parseFrom(uavData1); baseCmd = new UavInitReplyCmd(boxSn, uavInitInfo); log.debug("无人机初始化数据: {}", boxSn); break; default: log.warn("无法识别的命令码动作编号:{}", String.format("0x%02X", actionCode & 0xFF)); break; } break; default: encryptionFlag = in.readByte(); actionCode = in.readByte(); log.warn("无法识别的命令码: {},加密标志:{},动作编号:{}", String.format("0x%02X", cmdCode & 0xFF), String.format("0x%02X", encryptionFlag & 0xFF), String.format("0x%02X", actionCode & 0xFF));//String.format("0x%02X", cmdCode & 0xFF) } if (baseCmd != null) { out.add(baseCmd); } } }