360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)

摘要:
稍后将进行整理。)最近,编写了一组gnuradio OOT模块。比特规则是关于比特流传输的顺序。0x8E89BED6用于表示广播频道的AccessAddress地址,该地址是标准广播频道的分组格式的一部分。我没有使用上面的BLE_转储方法需要根据以下规则声明。我不理解set_output_ multiple的功能是声明异步输出端口的pmt,如下所示:

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

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

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

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

 360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第1张

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

 360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第2张

在表述中,使用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  作为输出数据流。这里的输出端口的声明和常规的例子是不一样的,需要按照如下的规则声明

 360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第3张

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

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

 360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第4张

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

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

 360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第5张

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

 360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第6张

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

数据的获取和处理如下:

 360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第7张

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

 360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第8张

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

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

 360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第9张

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

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

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

360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第10张

我们先看看扰码的位置:

360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第11张

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

360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第12张

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

360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第13张

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

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

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

360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第14张

前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,那么我需要首先

360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第15张

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

360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第16张

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

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

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

360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第17张

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

360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第18张

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

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

360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第19张

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

 360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第20张

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

360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第21张

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

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

360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第22张

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

360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第23张

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

好处是什么呢?

360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第24张

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

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

360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第25张

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

360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第26张

先import gr_ble和zmq,之后在下面

360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第27张

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

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

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

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

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

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

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

360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第28张

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

360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)第29张

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

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

免责声明:文章转载自《360独角兽实习,连载周记(gnuradio 低功耗蓝牙BLE 综合工具模块编写)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇查询表空间总大小(dba_data_files和dba_segments,dba_free_space区别)css div上下左右居中下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

设计模式之动态代理

在了解什么是动态代理模式,以及怎么实现动态代理模式之前,我们先明确一个场景,那就是当我们需要对一类实现类增加一些额外处理对其中的某些方法做一些增强时。譬如增加日志打印,参数校验,鉴权等。这些功能很重要,但是又具有一定的独立性(与业务代码不相关)。针对这种情况, 我们就可以采用动态代理模式来实现。 动态代理顾名思义,就是动态的对方法实现代理。要真正理解动态代...

抢购(秒杀)业务的技术要点

 本文为原创文章,转载希望注明出处。 抢购业务数据库需要考虑的点如下: 一、超卖现象 场景如下:    库存数是5。现在3个用户来购买,a用户购买2个,b用户购买3个,c用户购买1个。合起来就是准备购买6个。    如果三个用户是同时并发购买,会出现怎样的情况呢?   每个用户进行减库存的时候,语句类似于: update goods set amount=...

C++语言体系设计哲学的一些随想(未完待续)

对于静态类型语言,其本质目标在于恰当地操作数据,得到期望的值。具体而言,需要: (1)定义数据类型 你定义的数据是什么,是整形还是浮点还是字符。该类型的数据可以包含的值的范围是什么。 (2)定义操作的含义 操作是严格数据类型相关的。操作表明了对了一个具有特定类型的数据,执行操作后产生什么样结果。  =============================...

SQL基础02

昨日内容回顾 存储数据的演变过程 """ 1 随意建文件、数据格式也是千差万别的 jason|123 egon~123 tank+123 ​ 2 软件开发目录规范 明确了数据存放的大致位置 3 从单机变成联网 如何操作 数据统一存放并且格式固定 将原本存放于本地的数据全部存放到某一个基于...

SQLserver 获取当前时间

1. 获取当前日期 select GETDATE() 格式化: select CONVERT(varchar,GETDATE(),120) --2017-05-12 16:33:10 2. 获取当前年  --2017 select DATENAME(YYYY,GETDATE()) --2017 select DATENAME(YEAR,GETDATE())...

在Prism 框架中,实现主程序与模块间 UI 的通信

背景:    在模块的UI中包含 TreeView 控件,在该树形控件的每一节点前面定义了一个复选框,如图 需求:    在两个不同的应用程序中使用该控件,而它在不同应用程序中的外观则并不一致,按照本例,即一个显示复选框,一个不显示。 问题:     解决该问题的一个难处在于,Prism框架本身的设计原则——此 View 会被添加到主程序的 Shell...