C#实现 CAT021报文格式解析

这几天接到一个小项目,需要解析 CAT021报文。费了九牛二虎之力终于看懂了报文解析的规则,接下来我就对我从二进制数据到实例出各数据项相应的对象的过程做一个小结,希望能帮到有需要的朋友。

下载地址:https://download.csdn.net/download/wangtingming/9619187

首先是总体方法:  

 

 /// <summary>
        /// 接收到的数据解析
        /// </summary>
        /// <param name="datas"></param>
        /// <returns></returns>
        private static DataBlock DateParser(byte[] datas)
        {
            int cat = 0;
            int len = 0;
            byte[] fspecbytes;
            byte[] temp = new byte[4];
            DataBlock datablock = new DataBlock();
            Array.Copy(datas, 0, temp, 0, 1);
            cat = BitConverter.ToInt32(temp, 0);
            Array.Clear(temp, 0, temp.Length);

            Array.Copy(datas, 1, temp, 0, 2);
            Array.Reverse(temp, 0, 2);
            len = BitConverter.ToInt32(temp, 0);
            Array.Clear(temp, 0, temp.Length);

            fspecbytes = getFspecBytes(datas);
            List<DatagramUap> dataitems = DatagramParser(fspecbytes, len,datas);

            datablock.Cat = cat;
            datablock.Len = len;
            datablock.Dataitem = dataitems;

            return datablock;
        }

 

 

 

 

 

接下来是核心方法:

  

/// <summary>
        /// 解析出数据项的实体列表
        /// </summary>
        /// <param name="fspecbytes"></param>
        /// <param name="len"></param>
        /// <param name="datas"></param>
        /// <returns></returns>
        private static List<DatagramUap> DatagramParser(byte[] fspecbytes, int len, byte[] datas)
        {
            int count = 0;
            List<DatagramUap> dataitems = new List<DatagramUap>();
            while (count < fspecbytes.Length)
            {
                int index = 7;
                while (index > 0)
                {
                    byte[] tempbytes = new byte[fspecbytes.Length];
                    Array.Copy(fspecbytes, tempbytes, fspecbytes.Length);
                    tempbytes[count] <<= 7 - index;
                    tempbytes[count] >>= 7;
                    byte[] temp1 = new byte[4];
                    temp1[0] = tempbytes[count];
                    if (BitConverter.ToInt32(temp1, 0) != 0)
                    {
                        DatagramUap datagramuap = InitDategram(count, index);
                        dataitems.Add(datagramuap);
                    }
                    index--;
                }
                count++;
            }

            int currnetbytenum = 0;
             byte[] databytes = new byte[len - 3 - fspecbytes.Length];
            Array.Copy(datas, 3 + fspecbytes.Length, databytes, 0, databytes.Length);
            foreach (DatagramUap dataitem in dataitems)
            {
                byte[] bytes = new byte[dataitem.Len];
                Array.Copy(databytes, currnetbytenum, bytes, 0, bytes.Length);
                dataitem.Databytes = bytes;
                currnetbytenum += dataitem.Len;
            }

            return dataitems;
        }

 

 

 

 

 

根据位置确定数据项:

 

    /// <summary>
        /// 根据位置确定数据项
        /// </summary>
        /// <param name="count">符号字节第几个字节</param>
        /// <param name="index">字节第几位</param>
        /// <returns></returns>
        private static DatagramUap InitDategram(int count, int index)
        {
            DatagramUap datagram = new DatagramUap();
            switch (count)
            {
                case 0:
                    Dategram0(index,datagram);
                    break;
                case 1:
                    Dategram1(index, datagram);
                    break;
                case 2:
                    Dategram2(index, datagram);
                    break;
                case 3:
                    Dategram3(index, datagram);
                    break;
                case 4:
                    Dategram4(index, datagram);
                    break;

            }
            return datagram;
        }

 

 

 

 

 

解析出标识符所占的字节:

    

    /// <summary>
        /// 解析出标识符所占的字节
        /// </summary>
        /// <param name="dates"></param>
        /// <returns></returns>
        private static byte[] getFspecBytes(byte[] dates)
        {
            int count = 3;
            byte[] fspecbytes;
            //如果下一个字节是标识符
            while (IsMoreFspec(dates[count]))
            {
                count++;
            }
            //确定标识符字节数
            fspecbytes = new byte[count - 2];
            Array.Copy(dates, 3, fspecbytes, 0, fspecbytes.Length);
            return fspecbytes;
        }

 

 

 

 

 

判断下一个字节是否是符号字节:

     

  /// <summary>
        /// 判断下一个字节是否是符号字节
        /// </summary>
        /// <param name="temp"></param>
        /// <returns></returns>
        private static Boolean IsMoreFspec(byte temp)
        {
            Boolean ismore = false;
            byte[] tempbytes = new byte[4];
            temp <<= 7;
            temp >>= 7;
            tempbytes[0] = temp;
            if (BitConverter.ToInt32(tempbytes, 0) == 0)
            {
                ismore = false;
            }
            else { ismore = true; }
            return ismore;
        }

 

 

 

 

 

当为第1个描述符字节时,初始化对象,其他初始化对象过程一样,看源代码就知道:

 

 /// <summary>
        /// 当为第1个描述符字节时,初始化对象
        /// </summary>
        /// <param name="index"></param>
        /// <param name="datagram"></param>
        private static void Dategram0(int index, DatagramUap datagram)
        {
            switch (index)
            {
                case 7:
                    datagram.Dateitemname = "数据源识别";
                    datagram.DateitemNum = "1021/010";
                    datagram.Fra = 1;
                    datagram.Len = 2;
                    break;
                case 6:
                    datagram.Dateitemname = "目标报告描述符";
                    datagram.DateitemNum = "1021/040";
                    datagram.Fra = 2;
                    datagram.Len = 2;
                    break;
                case 5:
                    datagram.Dateitemname = "日时间";
                    datagram.DateitemNum = "1021/030";
                    datagram.Fra = 3;
                    datagram.Len = 3;
                    break;
                case 4:
                    datagram.Dateitemname = "在WGS-84坐标中的位置";
                    datagram.DateitemNum = "1021/130";
                    datagram.Fra = 4;
                    datagram.Len = 8;
                    break;
                case 3:
                    datagram.Dateitemname = "目标地址";
                    datagram.DateitemNum = "1021/080";
                    datagram.Fra = 5;
                    datagram.Len = 3;
                    break;
                case 2:
                    datagram.Dateitemname = "几何高度";
                    datagram.DateitemNum = "1021/140";
                    datagram.Fra = 6;
                    datagram.Len = 2;
                    break;
                case 1:
                    datagram.Dateitemname = "品质因素";
                    datagram.DateitemNum = "1021/090";
                    datagram.Fra = 7;
                    datagram.Len = 2;
                    break;
            }
        }

 

 

 

 

 

最后再测试一下:

 

    static void Main(string[] args)
        {
            byte[] temp = { 0x15, 0x00, 0x18, 0xE9, 0x95, 0x80, 0x00, 0x00, 0x01, 0x21, 0x00, 0x00, 0x00, 0x78, 0x0A, 0x4E, 0x10, 0x08, 0x7D, 0xFB, 0xD8, 0x7F, 0xF6, 0xF6 };
            DataBlock datablock = DateParser(temp);
        }

 

 

 

 

 

其他方法或类如果需要可以留言。这个解析过程,从看文档到写这个demo花了大概一下午时间,所以肯定有很多地方考虑不周,希望大家不要吐槽~~

具体到每个数据项的值我还没有做,不过这个都解析出来了,那后面的也就渣渣呐~~~

评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值