C++实现cat021(0.26版)报文解析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qingfengleerge/article/details/81102854

最近接触了一个小项目,使用C++对cat021(0.26)报文进行解析。刚开始没有头绪,之后在参考了CSDN博主TimiWang的文章:https://blog.csdn.net/wangtingming/article/details/52400656(十分感谢)和阅读了英文文档之后,磕磕绊绊完成了这个小项目。在此,做一个小结。
1:预备知识
cat021报文格式(布局):

说明:
数据类型(cat)=021,占1个字节,表示数据块含有ADSB报文。
长度标志(LEN)占2个字节,表示整个数据块的总长度(包括cat和LEN字段)占有的字节数。
FSPEC表示字段说明(标志位所在)。
注:详细的报文解释说明请查阅官方文档。http://www.eurocontrol.int/publications/cat021-automatic-dependent-surveillance-broadcast-ads-b-messages-part-12

2:核心程序编写
首先声明并定义了两个类对解析数据进行封装保护。
 

class DatagramUap
{
private:
    int frn,len;
    std::string dataitemname;//数据名
    std::string dataitemNum;//数据编号
    std::vector<BYTE>databytes;//解析之后每个数据项对应的字节存放处(容器)
public:
    void setFrn(int value3)
    {
        len=value3;
    }
    int getfrn(){return frn;}
    void setLen(int value4)
    {
        len=value4;
    }
    int getLen(){return len;}
    void setDataitemname(std::string value5)
    {
        dataitemname=value5;
    }
    std::string& getDataitemname(){return dataitemname;}
    void setDataitemNum(std::string value6){dataitemNum=value6;}
    std::string& getDataitemNum(){return dataitemNum;}
    void setDatabytes(std::vector<BYTE> value)
    {
        databytes=value;
    }
    std::vector<BYTE> getDatabytes(){return databytes;}
}
class DataBlock
{
private:
    int cat,len;
    std::<DatagramUap> dataitem;
public:
    void setCat(int value1){cat=value1;}
    int getCat(){return cat;}
    void setLen(int value2){len=value2;}
    int getLen(){return len;}
    void setDataitem(std::list<DatagramUap> v1)
    {
        dataitem=v1;
    }
    std::list<DatagramUap> getDataitem(){return dataitem;}
}

接下来开始编写数据包解析函数:
 

DataBlock DataParser(BYTE datas[])
{
    int cat=0;//初始化
    int len=0;
    std::vector<BYTE> fspecbytes;//创建一个空的容器
    BYTE temp[4];//创建临时数组
    DataBlock datablock;
    for(auto i=0;i<1;++i){temp[i]=data[i];}
    cat=temp1[0];
    for(auto i=0;i<sizeof(temp1);++i)
    {
        temp1[i]=0;//重置数组,每个元素置零
    }
    for(auto i=0;i<2;++i}
    {
        temp1[i]=datas[i+1];
    }
    BYTE c;
    c=temp1[0];
    temp1[0]=temp1[1];
    temp1[1]=c;
    len=temp1[0];//LEN占两个字节,一般后一个字节即可表示数据总长度
    for(auto i=0;i<sizeof(temp1);++i) {temp[i]=0;}
    fspecbytes=getFspecBytes(datas);//获取标志符所占字节
    std::list<DatagramUap> dataitems=DatagramParser(fspecbytes,len,datas);//解析出数据项的实体列表
    
    datablock.setCat(cat);
    datalock.setLen(len);
    datablock.setDataitem(dataitem);

    return datablock;
}

上述程序中,在对cat和LEN进行对应分析之后,紧接着开始对标示符所占字节数进行分析。

//解析出标志符所占字节
std::vector<BYTE> getFspecBytes(BYTE datas[])
{
    int count=3;
    std::vector<BYTE> fspecbytes;//定义一个空容器
    //如果下一个字节是标识符
    while(IsMoreFspec(datas[count]))
    {
        ++count;
    }
    //确定标识符字节数
    std::vector<BYTE> lhs(count-2);
    fspecbytes=lhs;
    for(auto i=0;i<(count-2);++i)
    {
        fspecbytes[i]=datas[i+3];
    }
    return fspecbytes;
}

//判断下一个字节是否是符号字节
bool IsMoreFspec(BYTE temp)
{
    bool ismore=false;
    BYTE tempbytes[4];
    temp<<=7;//按位左移7位
    temp>>=7;
    tempbytes[0]=temp;
    if(0==tempbytes[0]) {ismore=false;}
    else
    {
        ismore=true;
    }
    return ismore;
}

而后再解析出数据项的实体列表

std::list<DatagramUap> DatagramParser(std::vector<BYTE> fspecbytes,int len,BYTE datas[])
{
    int count=0;
    std::list<DatagramUap> dataitems;
    std::list<DatagramUap>::iterator iter;
    int rhs=fspecbytes.size();
    while(count<rhs)
    {
        int index=7;
        while(index>0)
        {
            std::vector<BYTE> tempbytes(rhs);
            for(auto i=0;i<rhs;++i)
            {
                tempbytes[i]=fspecbytes[i];
            }
            tempbytes[count]<<=7-index;
            tempbytes[count]>>=7;
            BYTE temp2[4];
            temp2[0]=tempbytes[count];
            if(temp2[0]!=0)
            {
                DatagramUap datagramuap=InitDatagram(count,index);
                dataitems.push_back(datagramuap);//依次从列尾增加元素
            }
            index--;
        }
        ++count;
    }
    int currentbytenum=0;
    std::vector<BYTE> databytes(len-3-rhs);
    for(auto i=0;i<(len-3-rhs);++i)
    {
        databytes[i]=datas[i+3+rhs];
    }
    //遍历容器,封装数据
    for(iter=dataitems.begin();iter!=dataitems.end();iter++)
    {
        int temp5=(*iter).getLen();
        std::vector<BYTE> bytes(temp5);
        for(auto i=0;i<temp5;++i)
        {
            bytes[i]=databytes[i+currentbytenum];
        }
        (*iter).setDatabytes(bytes);//将每一项数据段对应字节存入容器中封装起来
        currentbytenum+=(*iter).getLen();
    }
return dataitems;
}
//根据位置确定数据项
//参数解释:count——标识符字节中的第几个字节;index——字节第几位
DatagramUap InitDatagram(int count,int index)
{
    DatagramUap datagram;
    switch(count)
    {
    case 0:
        Datagram0(index,datagram);
        break;
    case 1:
        Datagram1(index,datagram);
        break;
    case 2:
        Datagram2(index,datagram);
        break;
    case 3:
        Datagram3(index,datagram);
        break;
    case 4:
        Datagram4(index,datagram);
        break;
    case 5:
        Datagram5(index,datagram);
        break;
    case 6:
        Datagram6(index,datagram);
        break;
    }
    return datagram;
}
//符合条件时,初始化对象
void Datagram0(int index,DatagramUap& datagram)
{
    switch(index)
    {
    case 7:
        datagram.setDataitemname("数据源识别");//设置数据项名
        datagram.setDataitemNum("1021/010");//设置数据项参考编号
        datagram.setFrn(1);//设置字段参考编号
        datagram.setLen(2);//设置该数据段对应字节的字节数
        break;
    case 6:
        datagram.setDataitemname("目标报告描述符");
        datagram.setDataitemNum("1021/040");
        datagram.setFrn(2);
        datagram.setLen(2);
        break;
    case 5:
        datagram.setDataitemname("日时间");
        datagram.setDataitemNum("1021/030");
        datagram.setFrn(3);
        datagram.setLen(3);
        break;
    case 4:
        datagram.setDataitemname("在WGS-84坐标中的位置");
        datagram.setDataitemNum("1021/130");
        datagram.setFrn(4);
        datagram.setLen(8);
        break;
    case 3:
        datagram.setDataitemname("目标地址");
        datagram.setDataitemNum("1021/080");
        datagram.setFrn(5);
        datagram.setLen(3);
        break;
    case 2:
        datagram.setDataitemname("几何高度");
        datagram.setDataitemNum("1021/140");
        datagram.setFrn(6);
        datagram.setLen(2);
        break;
    case 1:
        datagram.setDataitemname("品质因素");
        datagram.setDataitemNum("1021/090");
        datagram.setFrn(7);
        datagram.setLen(2);
        break;
    }
}

//在此只列出部分对应函数。
对于完整的代码,请下载底部文件查阅。

int main()
{
	//测试数据
	BYTE temp[] = { 0x15,0x00,0x32,0xff,0xa1,0xdb,0x86,0xff,0xff,0x01,0x21,0x2d,0x15,0xa3,0x00,0x3f,
		0xa2,0xb3,0x01,0x45,0x0b,0xc8,0x89,0x91,0xa7,0x03,0xb4,0x00,0x07,0x48,0x00,0xea,
		0x00,0x9a,0x03,0x3a,0xcd,0xf6,0x34,0x40,0x71,0xe3,0x1d,0xe0,0x00,0x00,0x00,0x05,
		0x8f,0xb0
	};

	DataBlock datalock = DataParser(temp);
	list<DatagramUap>::iterator iter0;
	list<DatagramUap> temp0;
	
	temp0=datalock.getDataitem();
	int i = 1;
	for (iter0 = temp0.begin(); iter0 != temp0.end(); iter0++)
	{
		//int i = 1;
		cout << "第" << std::dec<<i << "个数据。" << endl;
		cout << "数据条款名:"<< (*iter0).getDataitemname().c_str() << endl;
		cout << "数据编号:" << (*iter0).getDataitemNum().c_str() << endl;
		string num = (*iter0).getDataitemNum();
		vector<BYTE> temp10 = (*iter0).getDatabytes();

		//加入条件判断,符合则输出数据项对应的值
		if (num =="1021/010")//注意相等的表示
		{
			DataSourceIdentifiction(temp10);
		}
		else if (num == "1021/020")
		{
			EmitterCategory(temp10);
		}
		else if (num == "1021/030")
		{
			TimeOfDay(temp10);
		}
		else if (num == "1021/032")
		{
			TimeofDayAccuracy(temp10);
		}
		else if (num == "1021/040")
		{
			Target(temp10);
		}
		else if (num == "1021/070")
		{
			Mode3_ACodeinOctalRepresentation(temp10);
		}
		else if (num == "1021/080")
		{
			TargetAddress(temp10);
		}
		else if (num == "1021/090")
		{
			FigureOfMerit(temp10);
		}
		else if (num == "1021/095")
		{
			VelocityAccuracy(temp10);
		}
		else if (num == "1021/110")
		{

		}
		else if (num == "1021/130")
		{
			PositionWGS_84(temp10);
		}
		else if (num == "1021/131")
		{
			SignalAmplitude(temp10);
		}
		else if (num == "1021/140")
		{
			GeometricAltitude(temp10);
		}
		else if (num == "1021/145")
		{
			FlightLevel(temp10);
		}
		else if (num == "1021/146")
		{
			IntermediateStateSelectedAltitude(temp10);
		}
		else if (num == "1021/148")
		{
			FinalStateSelectedAltitude(temp10);
		}
		else if (num == "1021/157")
		{
			GeometricVerticalRate(temp10);
		}
		else if (num == "1021/160")
		{
			GroundVector(temp10);
		}
		else if (num == "1021/170")
		{
			TargetIdentification(temp10);
		}
		else if (num == "1021/200")
		{
			TargetStatus(temp10);
		}
		else if (num == "1021/210")
		{
			LinkTechnologyIndicator(temp10);
		}
		++i;

	}
	return 0;
}

对于该版本的报文的常规数据段解析方式在附件中有指出,在本文中没有讲述。

最后,欢迎大家讨论指正,不足之处请一定指出,谢谢。

链接如下:https://download.csdn.net/download/qingfengleerge/10581608

猜你喜欢

转载自blog.csdn.net/qingfengleerge/article/details/81102854