第八周工作总结——基于Gnuradio实现ibeacon接收机

1. 总述

该项目的最后一部分工作是用HackRF One接收ibeacon信号并在Gnuradio上对信号进行解析。利用Gnuradio中GFSK Demod block(相关介绍见第七周工作),我们只需要再额外实现一些简单的模块就可以得到完整的ibeacon信号的接收机。


2. 实现

第八周工作总结——基于Gnuradio实现ibeacon接收机_第1张图片

上图展示了ibeacon接收机的全貌,包括四个官方模块osmocom Source、GFSK Demod、Pack K Bits、Stream to Tagged Stream,以及一些自定义模块ble_alignment、ble_data_whitenting、ble_parse_pdu_header、ble_crc以及ibeacon_sink。该接收电路基本上是第五周工作中发射电路的逆过程,我们将按照信号的接收过程逐一介绍上述模块。

2.1 osmocom Source

该模块通过驱动访问HackRF One外设,接收采样信号。在该模块中,我们可以设置外设的工作频率和采样率。在这个例子中,采样率设置为4M,BLE协议规定信号的传输的符号率为1M,因此可以知道每个GFSK符号有4个采样,这对应着GFSK Demod模块中的Samples/Symbol参数。

2.2 GFSK Demod

信号处理的第一步是同步和解调,这些都在GFSK Demod模块中完成,关于模块中各个参数的含义,请参见第七周工作。另外,GFSK Demod模块的输入信号是复采样信号,输出信号是判决结果,即比特串。由于计算机中最小的存储单位是字节,因此输出信号的底层表示是字节串,每个字节为0或1,对应一个比特。

2.3 ble_alignment

获得比特串后,第一个工作是在其中定位出BLE数据包的起始位置和长度。依靠每个BLE数据包起始的preamble和access address(对于advertising packet,BLE协议规定了它们的access address值),我们能够在比特串中定位出每个preamble和access address被正确解调和判决的数据包。在解析出数据包的PDU的包头之前,我们是无法获得包的长度的,但是我们知道所有BLE数据包的最大长度,对于每个被定位的数据包,我们将从其开始位置的最大长度个比特作为一个数据包送到后续模块中处理,这样能保证该数据包的所有信息都包含在按照最大长度截取的数据包中。同时,由于BLE相邻数据包的传输时间间隔远大于传输几个字节的时间,因此按照最大长度截取不会影响到后续的数据包,

2.4 Pack K bits

该模块将连续K个字节中的最低位放入一个字节中低K位中,方便后面对数据包的处理(如CRC校验等)。

2.5 Stream to Tagged stream

该模块将输入的连续packet_len个字节流打上长度标签,这有助于简化以数据包为基本单元的信号处理。

2.6 ble_data_whitening

根据发射机的信号生成流程,接下来我们要对接收到的数据包进行data whitening的逆操作了。实际上,data whitening操作和其逆操作完全一样,因此我们直接用发射电路中用过的ble_data_whitening模块就可以了。

2.7 ble_parse_pdu_header

解扰之后,我们就得到了原始的PDU,或者说是从PDU开始的包含完整PDU的比特序列。下一步的工作就是确定PDU的长度,以便进行CRC冗余校验。PDU的长度信息包含在PDU的header中,因此通过解析header,我们可以提取出PDU,送到后面的模块。

2.8 ble_crc

出于方便的考虑,我将BLE CRC的生成和检查功能集成到了一个模块中,由一个下拉菜单设定要使用的功能。我们还是使用boost库中crc类实现检查的功能:

          d_crc_impl.reset();
          d_crc_impl.process_bytes(in, packet_length-3);
          unsigned int cal_crc = d_crc_impl.checksum() & 0xFFFFFF;
          unsigned int cny_crc = (((unsigned int)in[packet_length-3] & 0xFF) << 16)
                                | (((unsigned int)in[packet_length-2] & 0xFF) << 8)
                                | ((unsigned int)in[packet_length-1] & 0xFF);
          if(cal_crc == cny_crc){
            d_npass++;
            memcpy((void *)out, (const void *)in, packet_length-3);

通过将重新生成的crc值与数据包中携带的crc值比较,我们可以检查该数据包是不是正确的,并进而将正确的PDU的payload传输到后续模块。

2.9 ibeacon_sink

该模块接收PDU的payload并从中提取出ibeacon发射的信息,包括UUID、Major、Minor和RSSI。

3. 实验效果

我们使用iphone上的AirBeacon应用充当ibeacon发射机,具体参数设置如下图:

第八周工作总结——基于Gnuradio实现ibeacon接收机_第2张图片

当发射机开始工作后,我们在PC上运行接收机程序,程序会在终端中输出收集到的ibeacon数据:

第八周工作总结——基于Gnuradio实现ibeacon接收机_第3张图片

从终端输出数据中我们也可以看出,当在第37信道上监听的时候,我们每隔大约30ms收到一个BLE数据包,这与BLE协议规定是相符的。由于ibeacon使用的是ADV_IND类型的数据包,发射机会在3个广播信道中依次循环(37, 38, 39, 37, 38, ...)发送该类型的数据包,而相邻两个数据包的起始时间相差不超过10ms。

你可能感兴趣的:(开源夏令营)