C++實現cat021(0.26版)報文解析
阿新 • • 發佈:2019-01-12
最近接觸了一個小專案,使用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