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. 绑定委托输出,作为服务器的发送数据进行输出。

其中第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<uint, int> _candidateICAOs 和
 Dictionary<uint, ulong> _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 = (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);//补充形成32bits

            for (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;2private static void RtlSdrSamplesAvailable(byte* buf, uint len, IntPtr ctx);3private 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 Callback

        private 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);
            }
        }

        #endregion10)后续的解码
               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 = (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 : 780d58

Extended Squitter Type: 11

Extended Squitter Sub : 0

Extended Squitter Name: Airborne Position (Baro Altitude)

F flag : odd

T flag : non-UTC

Altitude : 21575 feet

Latitude : 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 : 780d58

Extended Squitter Type: 19

Extended Squitter Sub : 1

Extended Squitter Name: Airborne Velocity

EW direction : 0

EW velocity : 161

NS direction : 0

NS velocity : 394

Vertical rate src : 0

Vertical rate sign: 1

Vertical 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 : 780d4b

Extended Squitter Type: 11

Extended Squitter Sub : 0

Extended Squitter Name: Airborne Position (Baro Altitude)

F flag : even

T flag : non-UTC

Altitude : 27600 feet

Latitude : 109664 (not decoded)

Longitude: 62408 (not decoded)

四、

主程序

你可能感兴趣的:(Adsb,1090)