package com.ard.work.sdk.fjr.netty; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.socket.DatagramPacket; import io.netty.handler.codec.MessageToMessageEncoder; import java.net.InetSocketAddress; import java.util.List; /** * FJR 协议编码器 * 负责将 ThermalCommand 对象转换为符合 FJR 协议的 UDP 数据包 */ public class FjrProtocolEncoder extends MessageToMessageEncoder { @Override protected void encode(ChannelHandlerContext ctx, ThermalCommand msg, List out) throws Exception { // 1. 构建原始数据体:地址 + 指令ID + 数据 // 注意:cameraId 是业务字段,不包含在协议包中 byte[] rawData = new byte[1 + 1 + (msg.getData() != null ? msg.getData().length : 0)]; rawData[0] = ThermalCommand.DEVICE_ADDR; // 0x26 rawData[1] = msg.getCmdId(); if (msg.getData() != null) { System.arraycopy(msg.getData(), 0, rawData, 2, msg.getData().length); } // 2. 计算校验和 (基于原始数据) // 规则:所有数据字节相加,取低8位 int sum = 0; for (byte b : rawData) { sum += (b & 0xFF); } byte checkSum = (byte) (sum & 0xFF); // 3. 数据区转义处理 // 规则: // F0 -> F5 00 // FF -> F5 0F // F5 -> F5 05 ByteBuf escapedBuf = ctx.alloc().buffer(); for (byte b : rawData) { if (b == (byte) 0xF0) { escapedBuf.writeByte(0xF5); escapedBuf.writeByte(0x00); } else if (b == (byte) 0xFF) { escapedBuf.writeByte(0xF5); escapedBuf.writeByte(0x0F); } else if (b == (byte) 0xF5) { escapedBuf.writeByte(0xF5); escapedBuf.writeByte(0x05); } else { escapedBuf.writeByte(b); } } // 4. 组装最终数据包 // 结构:F0(1) + Length(1) + Data(Escaped) + CheckSum(1) + FF(1) ByteBuf packetBuf = ctx.alloc().buffer(); packetBuf.writeByte(0xF0); // 起始标志 packetBuf.writeByte(rawData.length); // 数据长度 (注意:这里是原始数据的长度,不是转义后的长度) packetBuf.writeBytes(escapedBuf); // 转义后的数据 packetBuf.writeByte(checkSum); // 校验和 packetBuf.writeByte(0xFF); // 结束标志 // 释放中间 buffer escapedBuf.release(); // 5. 包装成 UDP DatagramPacket // 获取当前 Channel 绑定的远程地址 InetSocketAddress remoteAddress = (InetSocketAddress) ctx.channel().remoteAddress(); DatagramPacket packet = new DatagramPacket(packetBuf, remoteAddress); out.add(packet); // 可选:打印调试日志 // System.out.println(">>> 发送指令: " + msg.getCmdId()); } }