(有点乱,之后会有整理)

最近在用写一套gnuradio的OOT模块,主要用来进行BLE嗅探的,github上有了一些工具,可是他们并没有很好的模块化,于是打算自己写一个,这样以后做一些其他的项目,模块可以在grc流图里直接用,复用性会好很多。

我在github上找到了一个项目叫做BLE_dump,我参考了他的解调方式,事实证明这种解调方式的效果非常好,具体的细节可以参考我博客中转发的另外一篇文章。

先总的来看一下流图,目前可以输出二进制的BLE包,还没有解扰

首先就是bit规则,这点在蓝牙官方手册里说得并不太清晰(起码我没有看明白),bit 规则讲的是bit流是以何种顺序被发射出去,这是序列检查的关键,经过我很多天的尝试,大概确定了下来。以比较常见的广播信道为例。

在表述中,使用0x8E89BED6表示广播信道的Access Address地址,这是标准广播信道的部分数据包格式。于是就有了第一个模块——find_pack_by_preamble。检测前导码的时候,我没有采用上文中BLE_dump的方式,他的方式是先把二进制流转换为16进制,之后检查0xAA,但是这样可能会有同步的问题,前导码一半在一个16进制数里,另一半在后边。我使用了一个有376位的数组,每次从后往前位移,例如第375位的数,他是刚输入进来的,下一次被移动到375,然后374,最后到0,然后被丢弃。我检查从0位到7位,这8个bit是01010101,那么就是一个广播信道的前导码。按照BLE规则,无论什么信道,要保证9个的交替bit,所以前9个都可以作为识别。检查通过的话,就把这376位压缩为47个16进制数,交给下一个模块分析。

因为经过这个块之后,数据会变成异步,所以在使用gr_modtool创建的时候,选择的sink模板,这样是没有输出端口的。那么数据该如何异步输出呢,我使用了  Async Message  作为输出数据流。这里的输出端口的声明和常规的例子是不一样的,需要按照如下的规则声明

我还没有太搞懂set_output_multiple的作用,可能是缓冲区的设置,因为我把它删除之后,数据流会时不时发生异常,下面一句就是声明异步输出端口的其中pmt::mp(“out”)可以理解成端口的ID号码。

同时,对xml文件也要有所改动,如下图

手动添加了(makexml不可以)一个out端口,数据格式为message,也就是grc中灰色的小框。

下一个模块我用python写的,主要是根据access address对上级block过来的数据包再次筛选,首先,因为是接收异步数据,要多import一些东西

在获取数据之前,要声明一些东西

Message_port_register_in(pmt.inter(‘in’))是声明这个模块接收异步数据,下一个,是指示回调函数,第一个参数要pmt.inter(‘in’)保持一致,第二个参数是用来处理数据包的函数名,也就是相当于work函数,后面还有一个out端口,那是之后的任务,这里就把它留在那。

数据的获取和处理如下:

函数注意要和上文所提保持一致,上级模块发送过来的数据就在第二个参数里。数据传入之后,首先对数据调用pmt::cdr,这个函数在gnuradio-master\gnuradio-runtime\lib\pmt\pmt.cc中

查了一下,好像是有关梳理类型的转换和继承什么的,我不太熟悉,我这么写的原因是看很多模块都是这么写的,姑且先背下来,如果有哪位师傅知道请留言帮助补充,谢谢。

下面的函数也在gnuradio-master\gnuradio-runtime\lib\pmt\pmt.cc中,是一个类型检查。之后就是对广播信道的地址进行检查,

符合条件的,转变成字符串,去除头部的0x和尾部的L,并输出。

(2017,7,23)之后,我们开始解扰码。

我们现在先看一下解扰之后的效果:

我们先看看扰码的位置:

再读取了前导码之后和assess address之后,就是PDU包,PDU包整体是加扰的,我们先看看解扰码的序列生成:

这个生成器的初始bit详见蓝牙官方协议vol6的3.2,我写了一个简单的扰码生成序列,写的有点丑

他会生成一个二维数组,再解扰的时候,我直接调用这个二维数组作为查找表。

比起动态生成扰码序列,把值域和定义域都确定的函数做成查找表会节约很多耗时,我这里,大约可以节约0.3ms,占这个模块整体耗时的百分之60。

接下来,我们看看解完扰码之后的bit序列,下面是PDU包的定义:

前4bit是PDU类别,我们可以通过蓝牙官方协议确定这个包的种类。之前嗅探的是广播信道的数据包,所以很多是0000,这个代表是ADV_IND数据包,之后的RFU是保留位,为以后的预留,现在使用0代替,也就是说上图的第一个包,是有错的,之后是TxAdd和RxAdd,之后再说,之后的Length是表示长度,比如上文的第二个包,length是000110,LSB下是0b11000,就是24,表示整个PDU包不算PDU包头,有24个octets。

(2017,7,25)python模块异步输出

上面,我们已经留出了out端口用来输出,可是怎么进行输出呢?

比如,在我的流图中after_dewhite_str是我所需要从这个块输出的数据,类型位string,那么我需要首先

把它变成一个array类型,之后

after_dewhite_str就被通过异步的方式从模块中发送出去了

(2017,7,30)参数化函数

我们先来看一下一个可以被py脚本import导入的模块的流图应该是一个什么样子

在BLE中,有两个变量是很重要的,他们是Access Address和channel(信道编号),在链接过程中,Access Address会改变,而在跳频中,channel也会改变,所以我们需要在程序中留出动态设置他们的接口。

在流图中看起来,就是这个样子。

为了动态设置这两个参数,我们需要使用gr_modtool创建模块的时候对参数进行输入,

这样会在对这两个函数提供底层的支持,如果直接在已经创建好了的模块中修改,则会出现很多错误,很麻烦。

可以看到,_init_中在self之后多了两个参数,就是我们需要输入的,gr_modtool已经完成了底层的支持,在这里,我的channel是int型,而accaddr是string,这是为了在流图外更好的调用,所以进入模块之后要进行一些格式化,把最后的写入self.XXX,在后文就可以使用了。

在grc文件夹下的对应xml文件也需要进行修改,添加两个param标签。这样就完成了模块中的参数化。

接下来说一个小窍门,流图是没有办法完成跳频之类的任务的,它毕竟不如py脚本灵活,我们实际上是可以把流图作为一个py模块import进一个py脚本中的,这个时候,在使用流图生成py文件的时候,就需要大量的使用variable模块,下面是我给accaddr定义的variable模块。

ID是你需要代表的参数,value是值,但是,为什么我定义的accaddr是一个string,但是这里他是一int呢,

因为这个模块不支持string格式,支持string的我也没找到,所以只好用这种办法(逃。。。。)

好处是什么呢?

这样,我们就可以使用import XXX 来引入我们的流图,之后使用XXX.set_accaddr来在py脚本中动态改变这个值了,很方便。

现在我们已经可以动态改变流图的参数了,那么怎么获取数据呢,这时ZMQ异步消息机制就变得十分有用。

我们可以通过这种方式把grc流图中的数据送出来,进入消息队列。之后在py脚本中

先import gr_ble和zmq,之后在下面

进行一些设置,最后,函数socket.recv()的返回值就是流图中的数据了。

这里在使用的时候需要注意一下,由于channel是int,所以不能为空,如果空着流图会报错,而accaddr是string,控string是允许的,如果不填,流图不会报错,可是逻辑上是行不通的,运行会报错。使用其他模块的时候也要注意这一点。

(2017,8,3)模块动态参数支持

我之前以为模块会默认支持动态参数,可是在动态信道号设置的时候发现了解扰是有问题的,也就是跳频跳过去了,但是解扰信道号码没过去,换句话说,就是osm的源模块支持了动态参数而我自己的模块debugsink不支持,但是,这样我至少可以确定动态参数机制在grc中是支持的。

一般来说,动态参数有两种方式,第一是使用异步消息输入代替模块参数,就像我的grc流图中第二个模块那样,这样的好处是可以远程调用,但是我需要完成的是跳频,对之间精度要求比较高,我不知道zmq消息的时间精度,所以我使用了第二种方式。

gnuradio中提供了针对模块的回调机制,就是当发现参数被外部改变的时候,调用一个回调函数,在回调函数中完成对参数的动态设置。下面我说一下步骤。

首先,要在模块对应的xml文件中,在<make>块的下面,加入<callback>模块。(如果写在<make>上面,编译流图里就没这个模块,所以要注意一下顺序)

之后,在对应模块中要写这个两个回调函数,这两个回调函数有俩个参数(对于python模块),第一个是self,第二个是变量。

这样就完成了模块对动态参数的支持。对于C语言模块,gnuradio中有很多原生的模块都支持,可以参阅他们的代码。

(随时更新修改,爬虫网站上都是历史版本  http://www.cnblogs.com/backahasten/  随时查看更新)

最新文章

  1. - &gt; code vs 3038 3n+1问题(递归)
  2. 虚拟机中Linux系统盘空间不足
  3. MyEclipse10启动Tomcat8出错
  4. 张艾迪(创始人):发明Global.World.224C的天才
  5. rails bug
  6. HDU 4035Maze(概率DP)
  7. Niagara AX之BajaScript资料哪里找
  8. ubuntu18.04LTS修改键盘键位
  9. crond守护进程实现定时监控某进程占有内存的大小
  10. PAT A1074 Reversing Linked List (25 分)——链表,vector,stl里的reverse
  11. Child Process模块
  12. hadoop fs 命令使用
  13. JavaScript进阶系列04,函数参数个数不确定情况下的解决方案
  14. FIR基本型仿真_03
  15. 虚拟机创建及安装ELK
  16. MyEclipse持续性开发教程:用JPA和Spring管理数据(四)
  17. org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[]
  18. GridView自定义自增长的 序号 列
  19. C#基础编程试题 4
  20. Linux运维入门(二):网络基础知识梳理02

热门文章

  1. Apache 日志记录相关设置
  2. 物理机安装ESXI6.7提示No Network Adapters的解决方案
  3. python函数定义中引用外部变量的一个问题
  4. jSon和Ajax登录功能,ajax数据交互案例
  5. 【干货】Python基础——列表
  6. 如何使用 Vue-TCB 快速在 Vue 应用中接入云开发
  7. 手把手教你如何构建Vue前端组件库
  8. 小Z的袜子(hose) HYSBZ - 2038 莫队+分块
  9. 【学习笔记】B站-2019-NLP(自然语言处理)之 BERT 课程 -- 相关课程笔记
  10. spss——定义变量