class Jt808EncoderCmd extends MessageToByteEncoder<Cmd> {
    private final static Logger log = LoggerFactory.getLogger(Jt808EncoderCmd.class);

    @Override
    protected void encode(ChannelHandlerContext ctx, Cmd cmd, ByteBuf out) throws Exception {
        Session session = ctx.channel().attr(Session.KEY).get();
        Rs msg = cmd.getRs();
        ByteBuf encode = encode(msg, session, cmd.getPackageNo().intValue());
        if (encode != null) {
            log.info("< {} hex:{}", session, ByteBufUtil.hexDump(encode));
            out.writeBytes(encode);
        }
    }


    public static ByteBuf encode(Rs msg, Session session, Integer packageNo) {<FILL_FUNCTION_BODY>}


    private static final ByteProcessor searcher = value -> !(value == 0x7d || value == 0x7e);

    //转义与校验
    public static ByteBuf escapeAndCheck0(ByteBuf source) {

        sign(source);

        int low = source.readerIndex();
        int high = source.writerIndex();

        LinkedList<ByteBuf> bufList = new LinkedList<>();
        int mark, len;
        while ((mark = source.forEachByte(low, high - low, searcher)) > 0) {

            len = mark + 1 - low;
            ByteBuf[] slice = slice(source, low, len);
            bufList.add(slice[0]);
            bufList.add(slice[1]);
            low += len;
        }

        if (bufList.size() > 0) {
            bufList.add(source.slice(low, high - low));
        } else {
            bufList.add(source);
        }

        ByteBuf delimiter = Unpooled.buffer(1, 1).writeByte(0x7e).retain();
        bufList.addFirst(delimiter);
        bufList.addLast(delimiter);

        CompositeByteBuf byteBufLs = Unpooled.compositeBuffer(bufList.size());
        byteBufLs.addComponents(true, bufList);
        return byteBufLs;
    }

    public static void sign(ByteBuf buf) {
        byte checkCode = bcc(buf);
        buf.writeByte(checkCode);
    }

    public static byte bcc(ByteBuf byteBuf) {
        byte cs = 0;
        while (byteBuf.isReadable())
            cs ^= byteBuf.readByte();
        byteBuf.resetReaderIndex();
        return cs;
    }

    protected static ByteBuf[] slice(ByteBuf byteBuf, int index, int length) {
        byte first = byteBuf.getByte(index + length - 1);

        ByteBuf[] byteBufList = new ByteBuf[2];
        byteBufList[0] = byteBuf.retainedSlice(index, length);

        if (first == 0x7d) {
            byteBufList[1] = Unpooled.buffer(1, 1).writeByte(0x01);
        } else {
            byteBuf.setByte(index + length - 1, 0x7d);
            byteBufList[1] = Unpooled.buffer(1, 1).writeByte(0x02);
        }
        return byteBufList;
    }
}

        String id = msg.getClass().getAnnotation(MsgId.class).id();
        if (!StringUtils.hasLength(id)) {
            log.error("Not find msgId");
            return null;
        }

        ByteBuf byteBuf = Unpooled.buffer();

        byteBuf.writeBytes(ByteBufUtil.decodeHexDump(id));

        ByteBuf encode = msg.encode();

        Header header = msg.getHeader();
        if (header == null) {
            header = session.getHeader();
        }

        if (header.is2019Version()) {
            // 消息体属性
            byteBuf.writeShort(encode.readableBytes() | 1 << 14);

            // 版本号
            byteBuf.writeByte(header.getVersion());

            // 终端手机号
            byteBuf.writeBytes(ByteBufUtil.decodeHexDump(Bin.strHexPaddingLeft(header.getDevId(), 20)));
        } else {
            // 消息体属性
            byteBuf.writeShort(encode.readableBytes());

            byteBuf.writeBytes(ByteBufUtil.decodeHexDump(Bin.strHexPaddingLeft(header.getDevId(), 12)));
        }

        // 消息体流水号
        byteBuf.writeShort(packageNo);

        // 写入消息体
        byteBuf.writeBytes(encode);

        // 计算校验码，并反转义
        byteBuf = escapeAndCheck0(byteBuf);
        return byteBuf;
    
<no_super_class>