一、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, 硕士
主题思想:
- 从硬件获得指定长度的数据,数据是byte*类型(数据范围为(0~2^8=255),因为是AD的量化位数位 8bits),长度readLength = 16 * 1024;
- 数据由byte*类型转换成Complex *形式,ptr->Imag = *buf++ * 10 - 1275, ptr->Real = *buf++ * 10 - 1275,(数据范围为(0255)*10-1275=(-1275+1275)), 长度为 readLength/2 = 8 * 1024=8192;
- 对数据进行处理;包括:(1)复数转换成模值的平方;(2)判断帧头的位置(即提取前导符);(3)提取帧头后面对应长度的消息(112 bits(长码)或56 bits(短码)对该消息进行提出处理(提取不同的类型和获取ICAO号以及长短码校验等));
- 绑定委托输出,作为服务器的发送数据进行输出。
(1)把每次由复数转换成的当前模值循环存储在一个数组中,数组长度位 帧长加消息位长度 即16+1122=240;
(2)判断当前模值所在数组的下一数据是否是帧头的开始(判断该数据和后面的数据共16位,是否满足帧头校验)(注意: 该数组初值为0,该数组要填充满后才开始,且该数据(帧头首位)与0比较,是否满足对应的帧头要求);
(3)确定帧头的首位位置后,对模值数组数据(1122个)进行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)
文章图片
文章图片
// 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)
四、 主程序