Adsb|ADSBsharp程序解析

一、ADSBsharp (前言:NativeMethods 原生方法)
主程序(与sdrsharp类似)
可以很容易发现这些文件夹里的程序对应的就是你要使用到的SDR设备,它们也会有简单的硬件配置界面的代码,但是更重要的是,它们的内部都分别有NativeMethods.cs这个文件代码开头都会DllImport,这是用来读入设备对应的.dll文件的(相当于linux中的.so文件,如果是hackrf就相当于在读libhackrf.so),这样就可以在c#里直接调用设备驱动提供的函数接口了。
RTLSDR文件夹中调用的层级结构是:RTLControllerDialog.cs(界面代码)->RTLSDRIO.cs->RtlDevice.cs->NativeMethods.cs->rtlsdr的驱动dll(这个dll是librtlsdr.c及其配套程序在Windows下编译出来的)。
其实,如果是初学者自己写程序的话,完全可以把中间的RTLSDRIO.cs、RtlDevice.cs、NativeMethods合并到界面代码中,直接在界面代码里调硬件驱动的API函数也是可以的。
第三类是纯算法的文件夹,如DNR(语音降噪)、Radio(各类解调算法)。这一类算法代码是SDR的精华,我们会重点讲解。
除这三类之外,还有一些文件夹也挺有意思,比如WavRecorder,主要用于实现录音功能,包括界面和对磁盘的写入代码。Common文件夹实现了一些接口,用于给其它新加入的模块集成,这样程序更加模块化,这样要对这个SDRSharp增加删除一些自定义模块时会更加灵活一些。初学者不需要太关心这个文件夹。
二、AdsbSharp程序解析 (1) 1090ES模式下ADS-B接收机解码系统设计 【作者】 张成龙;
【导师】 张朝柱;
【作者基本信息】 哈尔滨工程大学 , 信息与通信工程, 2015, 硕士
主题思想:

  1. 从硬件获得指定长度的数据,数据是byte*类型(数据范围为(0~2^8=255),因为是AD的量化位数位 8bits),长度readLength = 16 * 1024;
  2. 数据由byte*类型转换成Complex *形式,ptr->Imag = *buf++ * 10 - 1275, ptr->Real = *buf++ * 10 - 1275,(数据范围为(0255)*10-1275=(-1275+1275)), 长度为 readLength/2 = 8 * 1024=8192;
  3. 对数据进行处理;包括:(1)复数转换成模值的平方;(2)判断帧头的位置(即提取前导符);(3)提取帧头后面对应长度的消息(112 bits(长码)或56 bits(短码)对该消息进行提出处理(提取不同的类型和获取ICAO号以及长短码校验等));
  4. 绑定委托输出,作为服务器的发送数据进行输出。
【Adsb|ADSBsharp程序解析】其中第3点对消息的处理由很多技巧:
(1)把每次由复数转换成的当前模值循环存储在一个数组中,数组长度位 帧长加消息位长度 即16+1122=240;
(2)判断当前模值所在数组的下一数据是否是帧头的开始(判断该数据和后面的数据共16位,是否满足帧头校验)(注意: 该数组初值为0,该数组要填充满后才开始,且该数据(帧头首位)与0比较,是否满足对应的帧头要求);
(3)确定帧头的首位位置后,对模值数组数据(112
2个)进行PPM解调,且解调的数据(0或者1,共112个)放在帧数组 _frame[112/8=14](8解调数据个组成_frame数组的一个数据) 中;
(4)然后在根据数据的定义,解码数据帧。此处用到ICAO号作用唯一标识构建字典类型
Dictionary _candidateICAOs 和 Dictionary _icaos

_candidateICAOs 用来存储ICAO号和对应的飞机航机点数;其中界面中的 confidenceLevel 对应于飞机航迹点数。其中,如果 if (_candidateICAOs.Count > 500000),即存储的飞机数大于5W条,则更新该字典,更新规则是
_candidateICAOs = _candidateICAOs.Where(pair => pair.Value > 1).ToDictionary (pair => pair.Key, pair => pair.Value - 1);

即点数大于1飞机ICAO重新写入(小于2个点的都舍弃),对应的点数值都减去1。 _candidateICAOs的主要作用是用来判断某架飞机(对应的ICAO)的航迹点数是否满足大于等于confidenceLevel,(即点数大于4.用来完成数据的校验),然后才能采取后续操作输出对应的数据帧_frame。
_icaos用来存储ICAO号和当前时间(利用对应的数据量等效于时间,含义即该飞机出现的时间);
//即10秒钟更新一次字典,更新的规则是 把120秒之内的数据重新写入字典,大于120秒的数据则舍弃。时间的控制用数据量来控制。(采样率为OneSecond=2M,120秒对应的采样点数位timeoutTicks = _timeout * OneSecond,_ticks 用来表示总共处理的采样点数)即用来保存120秒之内的飞机 ICAO。主要用来120秒没是否有数据(_icaos.ContainsKey(icao))。满足才能进行后续输出数据帧_frame。
if (_ticks % (10 * OneSecond) == 0) // Happens every 10sec达到十秒的数据量时 var timeoutTicks = _timeout * OneSecond; // 120s _icaos = _icaos.Where(pair => (int) (_ticks - pair.Value) < timeoutTicks).ToDictionary(pair => pair.Key, pair => pair.Value);

利用CRC对数据进行校验,无错误返回 0(共112bits 信息位88bits, 校验位 112-88=24bits)
Adsb|ADSBsharp程序解析
文章图片

Adsb|ADSBsharp程序解析
文章图片

// CRC码计算及校验原理的最通俗诠释 https://blog.csdn.net/xianjuke008/article/details/109026335?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_utm_term~default-0.pc_relevant_baidujshouduan&spm=1001.2101.3001.4242 private static uint GetLongFrameParity(byte[] frame) { // frame的大小位 112bits,其中校验位 24bits信息位 112-24=88bits,利用移位法实现多项式的相除(异或)var data = https://www.it610.com/article/(uint)(frame[0] << 24) | (uint)(frame[1] << 16) | (uint)(frame[2] << 8) | frame[3]; var data1 = (uint)(frame[4] << 24) | (uint)(frame[5] << 16) | (uint)(frame[6] << 8) | frame[7]; var data2 = (uint)(frame[8] << 24) | (uint)(frame[9] << 16) | (uint)(frame[10] << 8); //补充形成32bitsfor (var i = 0; i < 88; i++) { if ((data & 0x80000000) != 0)//判断 data 首位是否位 1 { data ^= Polynomial; // 与生成多项式 异或 }data <<= 1; // 左移 1bit,后面补 0 if ((data1 & 0x80000000) != 0) { data |= 1; // 最后一bit 与1 或 }data1 <<= 1; // 左移 1bit if ((data2 & 0x80000000) != 0) { data1 |= 1; }data2 <<= 1; }var result0 = (byte)(data>> 24); // 取出前 8bits var result1 = (byte)((data >> 16) & 0xff); // 取出中间 8bits,关键是byte为8bits 对数据进行截断处理 只取8bits var result2 = (byte)((data >> 8) & 0xff); // 取出中间靠后 8bits// 验证与检验位的是否相等 var sum = (uint) ((result0 ^ frame[11]) << 16) | (uint) ((result1 ^ frame[12]) << 8) | (uint)(result2 ^ frame[13]); return sum; }

## 程序解析(数据传输流程:从两头往中间过度)private static readonly uint _readLength = 16 * 1024; //每次处理的数据量 (1) NativeMethods.rtlsdr_read_async(_dev, _rtlCallback, (IntPtr) _gcHandle, 0, _readLength); _rtlCallback=RtlSdrSamplesAvailable; (2) private static void RtlSdrSamplesAvailable(byte* buf, uint len, IntPtr ctx); (3) private void ComplexSamplesAvailable(Complex* buffer, int length); //数据长度已经变为 _readLength/2=8*1024=8192 (4) SamplesAvailable(this, _eventArgs); 实现由byte*类型的数据到 Complex*类型的数据,由三个参数变成两个参数。输出 (this, _eventArgs)参数。(this没有意义,SamplesAvailable 是 public delegate void SamplesAvailableDelegate(object sender, SamplesAvailableEventArgs e)类型的事件) (5)该委托事件绑定的函数是 _rtlDevice.SamplesAvailable += rtlDevice_SamplesAvailable; (6)对应的实现函数为: private void rtlDevice_SamplesAvailable(object sender, SamplesAvailableEventArgs e) { _callback(this, e.Buffer, e.Length); } (7)_callback是该委托的实例化 public unsafe delegate void SamplesReadyDelegate(object sender, Complex *data, int length); (8)_callback = callback; callback是 委托类型 (SamplesReadyDelegate callback); (9)_callback的类型来自于 _rtlDevice.Start(rtl_SamplesAvailable); 的输入函数rtl_SamplesAvailable;#region Samples Callbackprivate void rtl_SamplesAvailable(object sender, Complex* buf, int length) { for (var i = 0; i < length; i++) {//length=8192=8*1024 var real = buf[i].Real; var imag = buf[i].Imag; var mag = real * real + imag * imag; _decoder.ProcessSample(mag); } }#endregion (10)后续的解码 public void ProcessSample(int mag) { _ticks++; if (_ticks % (10 * OneSecond) == 0) // Happens every 10sec十秒处理更新一次 { var timeoutTicks = _timeout * OneSecond; //只刷新保存不同飞机的 最近 120S 的数据,最近120秒的飞机进行保存,即只保存最近120S的飞机ICAO _icaos = _icaos.Where(pair => (int) (_ticks - pair.Value) < timeoutTicks).ToDictionary(pair => pair.Key, pair => pair.Value); }if (_reset) { _icaos.Clear(); _candidateICAOs.Clear(); _reset = false; }_candidate[_candidateHead] = mag; //每次处理的数据点都放在数组_candidate[16+112*8],循环填充,长度不变 _candidateHead = (_candidateHead + 1) % _candidate.Length; //校验下个数据是否是帧头(数据处理的很有技巧性NB)if (IsPreambleValid()) { ReadData(); } } (11)解码后输出对应的满足条件的数据帧 FrameReceived(_frame, frameBitLength / 8); (12)完成数据的传输导出 _decoder.FrameReceived += delegate(byte[] frame, int length) { Interlocked.Increment(ref _frameCount); _frameSink.FrameReady(frame, length); };

// 帧头校验 public bool IsPreambleValid() { var lastOne = 0; var lastZero = 0; var queuePtr = _candidateHead; for (var i = 0 ; i < _preamble.Length ; i++) { var mag = _candidate[queuePtr]; queuePtr = (queuePtr + 1) % _candidate.Length; if (_preamble[i] == 1) { if (mag > lastZero) { lastOne = mag; } else { return false; } } else { if (mag < lastOne) { lastZero = mag; } else { return false; } } }return true; }

// 数据解调 即 PPM(脉冲编码调制解码) private void ReadData() { var queuePtr = (_candidateHead + PreambleLengthBits) % _candidate.Length; Array.Clear(_frame, 0, _frame.Length); var frameBitLength = 0; var lastMag = 0f; var lastAvg = 0f; for (var i = 0; i < LongFrameLengthBits * 2; i++) { var mag = (float) _candidate[queuePtr]; queuePtr = (queuePtr + 1) % _candidate.Length; if (i % 2 != 0) { //if (i == frameBitLength * 2 - 1 && _frame[0] == 0x5d && _frame[1] == 0x3c && _frame[2] == 0x4d && _frame[3] == 0xd2) //{ //Console.WriteLine("Ba333"); //}var avg = (mag + lastMag) * 0.5f; if (lastAvg > 0f) { var correction = -CorrectionFactor * (avg - lastAvg) / avg; if (correction > 0) { mag += correction; avg = (mag + lastMag) * 0.5f; } } lastAvg = avg; var bit = lastMag > mag ? 1 : 0; var frameBitPosition = i / 2; if (bit == 1) { var index = frameBitPosition / 8; var shift = 7 - (frameBitPosition % 8); _frame[index] += (byte) (1 << shift); }if (frameBitPosition == 7) { if (_frame[0] == 0) { return; } var df = (_frame[0] >> 3) & 0x1f; frameBitLength = df >= 16 ? LongFrameLengthBits : ShortFrameLengthBits; }#region 已经运行到该数据帧的末端,形成完整的一帧if (frameBitLength > 0 && frameBitPosition == frameBitLength - 1) { var length = frameBitLength / 8; if (_frame[length - 1] == 0 && _frame[length - 2] == 0 && _frame[length - 3] == 0) { return; } var icao = GetICAOAddress(_frame); var df = (_frame[0] >> 3) & 0x1f; if (df == 17 || df == 18) { if (GetLongFrameParity(_frame) != 0) { UpdateConfidenceList(icao); return; } } else if (df == 11) { if (GetShortFrameParity(_frame) != 0) { UpdateConfidenceList(icao); return; } } else if (!_icaos.ContainsKey(icao)) { if (!UpdateConfidenceList(icao)) { return; } } _icaos[icao] = _ticks; _candidateICAOs.Remove(icao); if (FrameReceived != null) { FrameReceived(_frame, frameBitLength / 8); //数据委托输出 绑定函数输出 } return; }// #endregion }lastMag = mag; } }

```csharp //获取ICAO 号,数据帧的第1 2 3 字节 public static uint GetICAOAddress(byte[] frame) { uint icao; var df = (frame[0] >> 3) & 0x1f; if (df == 11 || df == 17 || df == 18) { icao = (uint) (frame[1] << 16) | (uint) (frame[2] << 8) | frame[3]; } else { icao = df >= 16 ? GetLongFrameParity(frame) : GetShortFrameParity(frame); if (icao == 0) { icao = (uint) (frame[1] << 16) | (uint) (frame[2] << 8) | frame[3]; } } return icao; }

//完成长帧校验 112bits,输出是否为 0 private static uint GetLongFrameParity(byte[] frame) { var data = https://www.it610.com/article/(uint)(frame[0] << 24) | (uint)(frame[1] << 16) | (uint)(frame[2] << 8) | frame[3]; var data1 = (uint)(frame[4] << 24) | (uint)(frame[5] << 16) | (uint)(frame[6] << 8) | frame[7]; var data2 = (uint)(frame[8] << 24) | (uint)(frame[9] << 16) | (uint)(frame[10] << 8); for (var i = 0; i < 88; i++) { if ((data & 0x80000000) != 0)//(与操作运算符) data 的首字节是否为 1 { data ^= Polynomial; //异或 } data <<= 1; //左移1位data =data<< 1; if ((data1 & 0x80000000) != 0) { data |= 1; //或 } data1 <<= 1; if ((data2 & 0x80000000) != 0) { data1 |= 1; } data2 <<= 1; }var result0 = (byte)(data>> 24); var result1 = (byte)((data >> 16) & 0xff); var result2 = (byte)((data >> 8) & 0xff); var sum = (uint) ((result0 ^ frame[11]) << 16) | (uint) ((result1 ^ frame[12]) << 8) | (uint)(result2 ^ frame[13]); return sum; }

// 有MainForm程序进入接收数据程序
(1) class MainForm 下有startBtn_Click事件
(2)StartDecoding方法,包括建立数据服务器和接收数据部分;
(3)接收数据并处理部分包括:
RtlSdrIO _rtlDevice = new RtlSdrIO(); // RtlSdrIO:Start进入硬件接收数据程序和rtl_SamplesAvailable数据的解析
_rtlDevice.Start(rtl_SamplesAvailable); //
private void rtl_SamplesAvailable(object sender, Complex* buf, int length) { _decoder.ProcessSample(mag); }//进入对数据的解析
//函数原型为:RtlSdrIO :
public void Start(SamplesReadyDelegate callback);
public unsafe delegate void SamplesReadyDelegate(object sender, Complex *data, int length); private SamplesReadyDelegate _callback; 由三参数转换成两个参数(为事件,为后续委托绑定奠定基础)

private void rtlDevice_SamplesAvailable(object sender, SamplesAvailableEventArgs e)
{
_callback(this, e.Buffer, e.Length);
}
// Start执行相应的接收数据线程,从硬件获取数据
class RtlDevice: _worker = new Thread(StreamProc);
NativeMethods.rtlsdr_read_async(_dev, _rtlCallback, (IntPtr) _gcHandle, 0, _readLength);
_rtlCallback:
private static readonly RtlSdrReadAsyncDelegate _rtlCallback = RtlSdrSamplesAvailable;
private static void RtlSdrSamplesAvailable(byte* buf, uint len, IntPtr ctx){ instance.ComplexSamplesAvailable(instance._iqPtr, instance._iqBuffer.Length); }; // 完成由byte* buf转换成Complex* buf类型,其中是两个参数
private void ComplexSamplesAvailable(Complex* buffer, int length)
{
if (SamplesAvailable != null)
{
_eventArgs.Buffer = buffer;
_eventArgs.Length = length;
SamplesAvailable(this, _eventArgs); //复数到事件的转换
}
}
public event SamplesAvailableDelegate SamplesAvailable;
public delegate void SamplesAvailableDelegate(object sender, SamplesAvailableEventArgs e);
上述是完成由硬件接收数据到事件函数的转换;
从硬件获取处理后的处理: (1)获取的是复数,转换成模值; (2)放在一个数组里面_candidate[16+112*2=240]; 循环填充对应的模值 (3) 首先判断帧头的存在及其位置 (4)找出帧头后,对后面的信息进行解码 (PPM解码规则:数据由高到低为1,由低到高为0),码元(bit)个数为112(长码)或56(短码). (5)数据解码到最后一帧完成后 委托输出 FrameReceived(_frame, frameBitLength / 8); (6)对接收到的数据帧变成字符串进行转发处理 var sb = new StringBuilder(); sb.Append("*"); for (var i = 0; i < actualLength; i++) { sb.Append(string.Format("{0:X2}", frame[i])); } sb.Append("; \r\n");

// AdsbReader的数据输出 不同的端口输出不同的格式, #781A23,B10ZK,34.769943,112.475561,2700,115.4,351.03,0,2021-07-25 21:17:28.675,$ #781038,CHB6265 ,35.677826,113.727379,24025,419.5,58.85,0,2021-07-25 21:17:30.134,$ #7818A2,CDC8980 ,34.860901,112.082800,28275,454.7,58.58,0,2021-07-25 21:17:30.310,$ #780450,CCA1307 ,34.978867,112.481895,40725,492.2,196.89,0,2021-07-25 21:17:30.401,$#7804D4,CBJ5810 ,35.284973,112.620621,29425,487.9,203.04,0,2021-07-25 21:17:30.302,$ #780E93,KNA8246 ,35.333176,112.639618,27100,461.0,238.48,-64,2021-07-25 21:17:31.154,$ #781038,CHB6265 ,35.679428,113.730640,24025,419.5,58.85,0,2021-07-25 21:17:31.249,$#781BA8,CES6386 ,35.014526,112.002140,29350,487.4,238.59,0,2021-07-25 21:17:24.048,$#781A23,B10ZK,34.771317,112.475225,2700,115.7,347.52,0,2021-07-25 21:17:31.351,$ #7804D4,CBJ5810 ,35.284103,112.620220,29425,487.9,203.04,0,2021-07-25 21:17:30.770,$ #7807F0,B9587,34.909149,112.366090,3425,109.2,183.67,-64,2021-07-25 21:17:29.401,$ #780450,CCA1307 ,34.974426,112.480213,40725,492.2,196.89,0,2021-07-25 21:17:32.097,$

$DISERVER:CLIENT:VATSIM FSD V3.09:abcdef@N:CDG4804:0343:1:34.76376:112.52982:26600:413:156:0$CRCDG4804:CLIENT:RN:B738 B-5516::1 @N:CDG4804:0343:1:34.76376:112.52982:26600:413:156:0 $CRCDG4804:CLIENT:RN:B738 B-5516::1 @N:B10ZK:0000:1:34.77072:112.36547:2400:103:2616:0 $CRB10ZK:CLIENT:RN: ::1 #PCSERVER:CLIENT:CCP:TA:B10ZK:2000 @N:B10ZK:0000:1:34.77072:112.36547:2400:103:2616:0 $CRB10ZK:CLIENT:RN: ::1 #PCSERVER:CLIENT:CCP:TA:B10ZK:2000 @N:B9587:0000:1:34.80050:112.35958:2925:111:2092:0 $CRB9587:CLIENT:RN: ::1 #PCSERVER:CLIENT:CCP:TA:B9587:2600 @N:B9587:0000:1:34.80050:112.35958:2925:111:2092:0 $CRB9587:CLIENT:RN: ::1 #PCSERVER:CLIENT:CCP:TA:B9587:2600 @N:CDC8980:7057:1:35.09238:112.54807:26600:453:668:0 $CRCDC8980:CLIENT:RN:A20N B-30DN::1 #PCSERVER:CLIENT:CCP:TA:CDC8980:26600 @N:CDC8980:7057:1:35.09238:112.54807:26600:453:668:0 $CRCDC8980:CLIENT:RN:A20N B-30DN::1 #PCSERVER:CLIENT:CCP:TA:CDC8980:26600 @N:CCA1356:4521:1:35.09459:112.47282:33100:436:656:0 $CRCCA1356:CLIENT:RN:A321 B-6385::1 @N:CCA1356:4521:1:35.09459:112.47282:33100:436:656:0 $CRCCA1356:CLIENT:RN:A321 B-6385::1 @N:KNA8246:2154:1:35.10030:112.17155:26075:461:2704:0 $CRKNA8246:CLIENT:RN:B738 B-6492::1 #PCSERVER:CLIENT:CCP:TA:KNA8246:27600 @N:KNA8246:2154:1:35.10030:112.17155:26075:461:2704:0 $CRKNA8246:CLIENT:RN:B738 B-6492::1 #PCSERVER:CLIENT:CCP:TA:KNA8246:27600 @N:CBJ5810:0020:1:34.83270:112.42904:30150:484:2204:0 $CRCBJ5810:CLIENT:RN:A319 B-6178::1 @N:CBJ5810:0020:1:34.83270:112.42904:30150:484:2204:0 $CRCBJ5810:CLIENT:RN:A319 B-6178::1 @N:CES7878:3777:1:35.86389:113.70902:23600:437:2704:0 $CRCES7878:CLIENT:RN:B738 B-5647::1 @N:CES7878:3777:1:35.86389:113.70902:23600:437:2704:0 $CRCES7878:CLIENT:RN:B738 B-5647::1 @N:CHB6265:5350:1:35.88782:114.15520:22600:420:656:0 $CRCHB6265:CLIENT:RN:A320 B-8642::1 @N:CHB6265:5350:1:35.88782:114.15520:22600:420:656:0 $CRCHB6265:CLIENT:RN:A320 B-8642::1

*930CF31B0CE038043E67FE6700FF; *930CF30B8CE03C040E27FE6700FF; *8D780C90F82100020049B8F4676E; *8D780490F83100020049B8F4676E; *019D9827698736947EF93FE3DBDA; *019C98276987BEC47EE11FE3C3DA; *CD3807F0EB0D97F8013C00E9481A; *C53C03F0EB0593FC019E006D6C1A; *8D780993F81320060049B8E1C767; *8D780993F813A006004998E1C767; *8E5801CD9910010CD12CC4E6EE40; *8E5801CD99100104D02CC4F6EE40; *02E615350E88BEEFE006041F3524; *02E615350E88BE7C0007C41FB124; *5D7BB13026597A371F07F3E183F7; *5D7BB13026597A071F07F3E183F7; *9C10B1D75E021F1A80C8A7FFCEE0; *C410B1D75E021F1A80C8A7FFEEE0; *5D78087C6A03229FFF3B801DE00F;

// AdsbSharp数据输出 TcpIP: 47806 *5D7809939EEAFB; *8D78059F9941751C00045A7FB967; *8D7809B29944A8B9A80C6286BC95; *5D78087C6A0323; *8D78099399102C8C502002C20F7B; *80E1971D58B9D36822A22E07676E; *80E19130588B0339AC7FBB0EF52C; *5D78059FD6F8A1; *8D78087C588B0339AC7FBBB71E5A; *80E18EB05877035A3C9A6A33B857; *8D780C905877035A3C9A6AC82822; *8D7807E15829732D1A9FF5CC891E; *8D78098D9910290C902486713C20; *8D7807E1F81320060049B8774EF7; *8D780C9099095B1A580432BECBA9; *8D78059F9941751C00045A7FB967; *505D470001169F; *8D7809B258B9D367FEA227A14DC2; *8D7809B29944A8B9A80C61795487; *8D78098D5819333ADC9B7E93F129; *80E1971D58B9D367FEA2276F44C0; *02E61534F17CB7; *8D78087CEA340858013C08A7DDAE; *02E19534294154; *0200049BEFBB53; *8D78099399102A8C7020028D4DF6; *0200049BEFBB53; *8D78087C588B06D6ABE0762C989B; *8D7807E1582976CA39FFFB7F196E; *8C78098A210B9DF3E60820FADC99; *8D7807E1210B9D77C208208DE853; *8C78098A396FB717C9DEFAF88027; *8D78087CF82300030049B8A5829D; *8D78087C99097E1D3804435E33D1; *8D7818EE5827C30B309E27FD28A6; *5D7809939EEAFB; *8D7807E1EA0D97F8013C00E9481A; *8C7809FB3EB9B7197DE17938E9AC; *5C7809FBB72514; *5D78087C6A0323; *02E1971DCB13AC; *8D78059F58AB4703C605539B5BAA; *8D7809B29944A7B9A80C6297DE8F; *5D780C90573969; *5D78059FD6F8A1; *8D7809939910288C7020028B586A; *8D7807E1582976CA3A00009211A4; *8D7807E199107E02300405CF3E5D; *8D78087C588B0339D87FDF90F5D3; *8D78028C250C3074D72DE009BAF8; *8D7807F49910778590100519B71E; *8D780C9099095B1A380432714FD2; *020005961E04E7; *02E61130C97F62; *8D780C90E11B9000000000A0691E; *8D7809B258B9D367B4A21AA02221; *8D78098D210B9DF4CE0820DD739E; *8D78059F9941751C00085A37E367; *167E6505D47000; *8D7807F499107685D00C0538C782; *8D78087C588B06D6D9E09A20FC38; *8D780C905877035A789A9B8FD1B5; *8D7807E1582976CA3C0007413806; *8D780C9099095B1A380432714FD2; *8D780C90F82100020049B8F4676E; *8D78087C99097E1D3804435E33D1; *8D78059F9941751C00085A37E367; *8D78059F58AB4367D4A59742DE1F; *5D78098D9E5E62; *5D7809939EEAFB; *02E19130114281; *02E1971DCB13AC; *0200049BEFBB53; *20001130179ACB; *80E19130588B06D6EDE0AA375F1B; *8D7809B29944A5B9C80C625E4F68; *8D78087C588B033A0680031674DA; *5D780C90573969; *8D78098D5819433AFC9B8440031F; *8D7807E199107F019004051F4BE2; *8D780C905877035A909AB03AAAA5; *8D7809939910258C90240281993A; *8D78087C99097E1D3804435E33D1; *A00012B4B8D80030A40000C36CE0; *8D780C9099095B1A380432714FD2; *8D78059F9941751C00085A37E367; *167E6505D47000; *8D78028CEA38E858013C086720CB; *8D78087CE104A500000000A1D2FC; *8D78098D9910290C902486713C20; *8D7809B2200D33B6D76C20E234B9; *A0001130B3F80030A400001E1C3F; *A0001130968A452CE02C002152B8; *8D78098D581946D7E9FB9D4F861B; *8D7807E15829732D20A013A00B19; *8D7807E199107F015004057FB71D; *02E19534294154; *06410135F7CAD5; *8D7807E1F81320060049B8774EF7; *A8001303FFF2A1367FFCE6DB5173; *5D7809939EEAFB; *8D78087C99097E1D3004433091D9; *A0001534969A1B2FA02C01FDC79E; *8D780993EA0D97F8013C007FC18A; *02E61534F17CB7; *8D78059F58AB4367FAA5B7443808; *800003145819433B0C9B870A7C4A; *8D780C9099095B1A380432714FD2; *8D78059F9941751C00085A37E367; *8D7809B258B9D3670CA1FD543E09; *2000171DCDCBE6; *02E1971DCB13AC; *5D7807E1C815E8; *5D7809B260DF42; *A0001534FFF2A1367FFCE67B47EE; *A0001534969A1B2FA054012FBF85; *8D78087CEA340858013C08A7DDAE; *5D78098D9E5E62; *5D78059FD6F8A1; *8D7807E15829732D20A0185F9367; *5D7809B260DF42; *8D78087C588B06D71FE0D3BB0317; *02E18EB0ACD42D; *8C78098AF9114106624938662F56; *02E61130C97F62; *5D780C90573969; *A0001534C0A8002FDC00001FA921; *A0001534FFF2A1367FFCE67B47EE; *A000171DC680002FF0000025E5DE; *A0000F37FFDA9D347FFCCF1F1E6C; *A0001534969A1B2FA01401533797; *A000171DFC58DD3D7FCCE5F1D4C8; *A000171DC789FD303FE400C447AC; *8D7809939910228C90240288AD50; *8D78087C99097E1D3004433091D9; *8D780C905877035ABE9AD63FEBFF; *8D78087CF82300030049B8A5829D; *8D7809B258B9D702FA01E9B0F245; *8D780C9099095B1A380432714FD2; *8D78098D9910280C9024867236EE; *8D78059F58AB47042E05A9064372; *8D7807E15829732D22A01DBBF7DA;

(一)查验可用设备 (二)配置设备及界面参数 (三)响应按钮单击事件 (1)完成服务器端的设定,以便于完成数据的发送
(2)接收从硬件端口传送的数据
//— RtlSdrIO _rtlDevice = new RtlSdrIO();
public void Start(SamplesReadyDelegate callback);
_rtlDevice.Start(rtl_SamplesAvailable);
(3)对接收的数据及进行解析
接收的数据:
*8D78144899096B1BB0043F0530C7; *8D781448588B06E5E5E78692DA93; *8D78144899096B1BB0043F0530C7; *8D781448E109B1000000000F2EC5; *02E19534294224; *02E19130115EB5; *5D781448C3987D; *02E61534F17FC7; *8D781448EA340864B13C08FF688E; *02E19534294224; *200011301786FF; *8D78144899096B1BB0043F0530C7; *5D7806EFC64C29; *02E19534294224; *8D78144899096B1BB0043F0530C7; *8D781448588B0349908747820B1C; *8D7806EF58AB435A36979B4C562C; *5D781448C3987D; *A000113010030A80F5000029264E; *A0001130B3F80030A8000047F307; *A000113080529D353FFCE1C49761; *A0001130963A4D2D600C005ED5C5; *02E19130115EB5; *5D7806EFC64C29; *8D78144899096B1BB0043F0530C7; *02E19130115EB5; *A0001534966A192FA024005B200E; *A0001130B3F80030A8000047F307; *8D781448588B0349BE876B84A551; *02E19130115EB5; *8D7806EF58AB46F6BFF7EAFB97C1; *02E61130C96356; *02E19130115EB5; *A0001130B3F80030A8000047F307; *8D78144899096B1BB0043F0530C7; *280009B1DFDEA7; *5D7806EFC64C29; *8D781448F82300060049B83B479F; *02E19534294224; *02E19534294624; *A0001534C0A8002F8C0000481613; *A000153480329F34FFFCE302C738;

三、dump 1090的使用
dump1090.exe --device-index 1 --interactive --net--net-beast

dump1090.exe--interactive*5d780d585dc125; CRC: 5dc125 (ok)DF 11: All Call Reply.Capability : Level 2+3+4 (DF0,4,5,11,20,21,24,code7 - is on airborne)ICAO Address: 780d58*8d780d58587176d9e653a62b36c3; CRC: 2b36c3 (ok)DF 17: ADS-B message.Capability : 5 (Level 2+3+4 (DF0,4,5,11,20,21,24,code7 - is on airborne))ICAO Address : 780d58Extended Squitter Type: 11Extended Squitter Sub : 0Extended Squitter Name: Airborne Position (Baro Altitude)F flag : oddT flag : non-UTCAltitude : 21575 feetLatitude : 93427 (not decoded)Longitude: 21414 (not decoded)*8d780d589940a131488c2c5ec41c; CRC: 5ec41c (ok)DF 17: ADS-B message.Capability : 5 (Level 2+3+4 (DF0,4,5,11,20,21,24,code7 - is on airborne))ICAO Address : 780d58Extended Squitter Type: 19Extended Squitter Sub : 1Extended Squitter Name: Airborne VelocityEW direction : 0EW velocity : 161NS direction : 0NS velocity : 394Vertical rate src : 0Vertical rate sign: 1Vertical rate : 35*8d780d4b588f8358c0f3c89d206f; CRC: 9d206f (ok)DF 17: ADS-B message.Capability : 5 (Level 2+3+4 (DF0,4,5,11,20,21,24,code7 - is on airborne))ICAO Address : 780d4bExtended Squitter Type: 11Extended Squitter Sub : 0Extended Squitter Name: Airborne Position (Baro Altitude)F flag : evenT flag : non-UTCAltitude : 27600 feetLatitude : 109664 (not decoded)Longitude: 62408 (not decoded)

四、 主程序

    推荐阅读