最近接触了一个小项目,使用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::vectordatabytes;//解析之后每个数据项对应的字节存放处(容器)
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 value)
{
databytes=value;
}
std::vector getDatabytes(){return databytes;}
}
class DataBlock
{
private:
int cat,len;
std:: 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 v1)
{
dataitem=v1;
}
std::list getDataitem(){return dataitem;}
}
接下来开始编写数据包解析函数:
DataBlock DataParser(BYTE datas[])
{
int cat=0;//初始化
int len=0;
std::vector 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 dataitems=DatagramParser(fspecbytes,len,datas);//解析出数据项的实体列表
datablock.setCat(cat);
datalock.setLen(len);
datablock.setDataitem(dataitem);
return datablock;
}
上述程序中,在对cat和LEN进行对应分析之后,紧接着开始对标示符所占字节数进行分析。
//解析出标志符所占字节
std::vector getFspecBytes(BYTE datas[])
{
int count=3;
std::vector fspecbytes;//定义一个空容器
//如果下一个字节是标识符
while(IsMoreFspec(datas[count]))
{
++count;
}
//确定标识符字节数
std::vector 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 DatagramParser(std::vector fspecbytes,int len,BYTE datas[])
{
int count=0;
std::list dataitems;
std::list::iterator iter;
int rhs=fspecbytes.size();
while(count0)
{
std::vector tempbytes(rhs);
for(auto i=0;i>=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 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 bytes(temp5);
for(auto i=0;i
//根据位置确定数据项
//参数解释: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::iterator iter0;
list temp0;
temp0=datalock.getDataitem();
int i = 1;
for (iter0 = temp0.begin(); iter0 != temp0.end(); iter0++)
{
//int i = 1;
cout << "第" << std::dec< 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