十六进制指令FF转义FE01

数据帧格式如下表所示,数据帧开始标志和帧结束标志为FFH,其他字段不能出现FFH,如果数据确实为FFH,需对其进行转义处理。

发送数据时,如果在其它字段中出现FFH字节时,将FFH分解为FEH和01H这两个字节发送,如果在其它字段出现FEH字节时,需将FEH分解为FEH和00H这两个字节来发送。

接收数据时,如果出现“FE 01”这样连续两个字节时将之合为一个字节FFH;如果出现“FE 00”这样连续两个字节时将之合为一个字节FEH。

注:发送数据帧时:先校验,后做转义处理;接收数据帧时:先做转义处理,再做校验。

/**
 * 指令内容转义工具类
 */
public class ESCUtil {

    /**
     * 数据帧编码,添加帧头,添加帧尾,添加校验,校验方式:异或校验
     *
     * @param ibuf        传入数组,不含帧序号
     * @param fram_num_yn 是否添加帧序号,0:添加帧序号,非0:不添加帧序号
     * @return
     */
    public static byte[] ptkCode(byte[] ibuf, int fram_num_yn) {

        /**
         * 校验位
         */
        byte chk;

        /**
         * 数组下标
         */
        int slen = 0;

        /**
         * 转义前数组长度
         */
        int ilen;

        /**
         *  帧内容数据最大长度
         */
        int SENDBUF_SIZE = 36;

        /**
         * 转义后的数组
         */
        byte[] returnBytes;

        /**
         * 中间量,动态添加
         */
        List<Byte> temp;

        /**
         * 传入参数检验
         */
        if (ibuf == null) {
            throw new IllegalInstructException("解析数据为空");
        }
        ilen = ibuf.length;

        //检查数据长度是否正确
        if (ilen > SENDBUF_SIZE) {
            throw new IllegalInstructException("解析数据长度不正确");//发送字节数超长
        }
        temp = new ArrayList<>();

        //加入帧头
//        temp[slen++] = -1;
//        temp[slen++] = -1;
        temp.add((byte) -1);
        temp.add((byte) -1);

        //添加帧序号
        if (fram_num_yn == 0) {
            temp.add((byte) 19);
            chk = 19;
        } else {
            chk = 00;
        }

        //拷贝数据,转义
        for (int i = temp.size(); i < ilen - 2; i++) {
            chk ^= ibuf[i];//异或校验
            if (ibuf[i] == -1) {
                temp.add((byte) -2);
                temp.add((byte) 1);
            } else if (ibuf[i] == -2) {
                temp.add((byte) -2);
                temp.add((byte) 0);
            } else {
                temp.add(ibuf[i]);
            }
        }

        // 校验位编码
        if (chk == -1) {
            temp.add((byte) -2);
            temp.add((byte) 1);
        } else if (chk == -2) {
            temp.add((byte) -2);
            temp.add((byte) 0);
        } else {
            temp.add(chk);
        }

//         添加帧尾
        temp.add((byte) -1);

        Object[] objs = temp.toArray();
        returnBytes = new byte[objs.length];
        for (int i = 0; i < objs.length; i++) {
            Byte bbyte = (Byte) objs[i];
            returnBytes[i] = bbyte.byteValue();
        }
        return returnBytes;
    }

    /**
     * 解析上传指令:进行数据包的解码工作,去头去尾,通过校验码判断数据包数据是否正确
     *
     * @param ibuf        传入的回复指令数组
     * @param fram_num_yn 解码后的帧内容是否包含帧序号,0:不包含帧序号,非0:包含帧序号
     * @throws Exception
     */
    public static byte[] pktDecode(byte[] ibuf, int fram_num_yn) {

        /**
         *转义前原始指令数组长度
         */
        int ilen;

        /**
         * 输入指令最大长度:全部为转义指令时
         */
        int PARSE_FRM_MAXLEN = 80;

        /**
         * 转义后帧内容长度
         */
        int SENDBUF_SIZE = 41;

        /**
         * 转移后帧内容
         */
        byte[] ReceiveBuf = new byte[SENDBUF_SIZE];


        /**
         * 回复指令下标
         */
        int slen = 0;

        /**
         * 校验码
         */
        byte Chk = 0;

        /**
         *帧内容开始位置
         */
        char start = 0;

        /**
         * 输出帧内容数组,不包含/帧序号
         */
        byte[] obuf;

        /**
         * 临时变量
         */
        List<Byte> tempList;

        if (ibuf == null) {
            throw new IllegalInstructException("传入数据为空");
        }
        ilen = ibuf.length;

        // 原始帧长度至少为5:2个字节帧头,1 个字节帧序号,1个字节校验位,1个字节帧尾
        if ((ilen < 5) || (ilen > PARSE_FRM_MAXLEN)) {
            throw new IllegalInstructException("解析数据长度不正确");
        }

        //检验帧头和者帧尾
        if (-1 != ibuf[0] || -1 != ibuf[ibuf.length - 1]) {
            throw new IllegalInstructException("无效的帧头或帧尾");
        }

        //检验是否包含帧序号,生成不同长度的帧内容数组
        if (fram_num_yn != 0) {
            obuf = new byte[SENDBUF_SIZE];
        } else {
            obuf = new byte[SENDBUF_SIZE - 1];
        }

        //帧内容开始位置下标
        if (ibuf[2] == -1) {
            start = 3;
        } else if (ibuf[1] == -1) {
            start = 2;
        } else {
            start = 1;
        }

        //取帧内容,去除帧头,帧尾
        for (int i = start; i < ibuf.length - 1; i++) {
            ReceiveBuf[slen] = ibuf[i];
            //转义操作:或
            if (-2 == ibuf[i]) {
                ReceiveBuf[slen] |= ibuf[i + 1];
                i++;
            }
            slen++;
        }


        //异或校验码
        for (int i = 0; i < slen - 1; i++) {
            Chk ^= ReceiveBuf[i];
        }

        //验证校验码
        if (Chk == ReceiveBuf[slen - 1]) {
            if (fram_num_yn != 0) {//包含帧序号
                for (int i = 0; i < slen; i++) {
                    obuf[i] = ReceiveBuf[i];
                }
            } else {//不包含帧序号{
                for (int i = 1; i < slen; i++) {
                    obuf[i - 1] = ReceiveBuf[i];
                }
            }
            //增加帧头、帧尾
            byte[] out = new byte[obuf.length + start + 1];
            for (int i = 0; i < start; i++) {
                out[i] = -1;
            }
            System.arraycopy(obuf, 0, out, 2, obuf.length);
            out[out.length - 1] = -1;
            return out;
        } else {
            throw new IllegalInstructException("校验失败!");
        }

    }
}

 

转载于:https://my.oschina.net/u/3761898/blog/1624449

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值