利用PC和蓝牙dongle实现ibeacon
第一次写技术博客,既当做对自己的技术总结,也当作和广大网友们分享讨论的一个平台吧。
最近在研究BLE技术,而ibeacon是其中比较简单的一个应用。虽然由苹果公司推出已经四五年了,网上的资料还是稍显的零散。下面就从理论和实践两个方面来总结一下这项技术,力求刚刚接触这个的朋友也能很快的了解并且能自己动手实现ibeacon,毕竟我觉得自己动手实践才能真正的学会。当然,不足或者错漏之处请大家不吝赐教。
一:ibeacon的基本原理和数据包结构
ibeacon是由苹果公司在2013年推出的,其初衷是解决室内定位的问题。因为GPS在室内很难发挥作用,而现在手机上标配蓝牙。利用低功耗的BLE多点定位来解决室内(大型商场、停车场、医院等)定位的问题也就理所应当了。
ibeacon本质上就是BLE的广播,不涉及到BLE设备间的链接,不过这里的广播包有特定的格式。这里需要两个设备,ibeacon基站和带蓝牙4.0以上的手机,而整个定位过程的实现涉及三个方面。除了基站和手机之外,还有个远程的服务器提供的服务,这里一般以APP的方式存在于手机之上。
整个的过程是这样的:
ibeacon基站一直在广播,广播包里包含的主要是1、本基站的设备类型。 2、本基站的编号。3、本基站的发射功率。三个重要信息;
打开蓝牙的手机靠近基站之后收到了广播包的信息,通过广播包的设备类型判断出这是个ibeacon设备,通过广播包里记载的发射功率与自己接受到的信号功率对比得出和基站的距离(经验公式D =10^((abs(RSSI)-A)/(10*n),其中D是得出的距 离, A是发射设备和接收设备相距一米时的信号强度,n为环境因子)。然后通过手机上特定的APP将基站编号发送给服务器(这个过程要求手机一定要能联网),服务器查询该编号返回该基站所在的具体详细地址;
根据服务器返回的具体基站地址,加上前面测算的和该基站的距离,就能够定位自己位置啦!当然,多个基站存在时,多点定位就能更加准确确定自己的位置了。
苹果ibeacon的定位功能在国内实用的例子还不太多,反倒是借助于Ibeacon的微信摇一摇火爆了起来。相比于室内定位,微信摇一摇更加侧重于商家用来展示广告和促销信息等。前面讲到了需要一个手机上的APP,这里国内的超级APP微信就承担了这样一个角色。其基本原理和过程与上述相同,但是这里微信后台查询基站编号之后返回的是一个网页地址。商家在此网页上配置自己的促销信息,优惠券以及其他广告。这样一来,客户一旦走近商家店铺,手机上就自动能够得到该商家优惠信息等等。
说完了原理,现在来详细的解析ibeacon广播包的数据结构。ibeacon基于BLE的广播,而BLE广播限定数据长度不能超过31 Bytes。ibeacon将广播包的长度固定为30 Bytes。
这30个Bytes分为两个AD structure(这是BLE广播数据的一种组织形式)。每个AD structure由 1字节的length+1字节的AD Type+用户数据 构成。下面拿一个实例来说明:
02 01 06 1a ff 4c 00 02 15 fd a5 06 93 a4 e2 4f b1 af cf c6 eb 07 64 78 25 29 11 30 39 1c
这是一个ibeacon包的payload,其中“02 01 06”是第一个AD structure,“1a ff 4c 00 02 15 fd a5 06 93 a4 e2 4f b1 af cf c6 eb 07 64 78 25 29 11 30 39 1c”是第二个AD structure的内容。
对第一个AD structure,
1 02 ,// AD structure的长度 这里表示接下来还有两个字节 2 01, //AD Type 这是由蓝牙联盟定义的标识,这里表示蓝牙支持类型 3 06, //0x06=0000 0110 每个位的意义如下 4 bit0=0 OFF // LE Limited Discoverable Mode 5 bit1=1 ON // LE General Discoverable Mode 6 bit2=1 ON // BR/EDR Not Supported 7 bit3=0 OFF // Simultaneous LE and BR/EDR to Same Device Capable (controller) 8 bit4=0 OFF //Simultaneous LE and BR/EDR to Same Device Capable (Host)
对第二个AD structure,
1a, // AD structure长度,这里是26个字节 ff, // ADType. 因为ibeacon并未写入官方协议,这里使用自定义类型Manufacturer Specific Data 4c, 00, //这个指公司, 00 4c是APPLE 02, 15, //这是ibeacon的标识,指示这个广播是ibeacon广播 fd,a5,06,93,a4,e2,4f,b1,af,cf,c6,eb,07,64,78,25,//16字节的proximity UUID 由设备厂商和设备用途决定,这里用的是微信的UUID 29,11, // Major 30, 39 //Minor Major和Minor共同决定设备的编号 1c //1米距离上的信号功率
二:利用Bluez的协议栈和工具集实现ibeacon
了解完ibeacon的理论知识之后,现在我们利用linux下的蓝牙官方协议栈Bluez和它提供的工具集来实现Ibeacon。因为我用的不是苹果的手机,我们最后用微信摇一摇来检测ibeacon。周围没有ibeacon设备的时候,微信摇一摇是没有“周边”这个选项的,当检测到ibeacon设备时,摇一摇之后就会出现“周边”这一项,点进去会出现商家配置的页面。而之所以选用PC 上的Linux和Bluez协议栈来实现是因为对我们试验性质来讲他们足够简便,你需要的硬件设备是一台Linux的PC(我用的是Ubuntu的虚拟机),以及一个蓝牙适配器(蓝牙dongle),蓝牙适配器十几块于淘宝上购得。软件上你不需要写代码,因为Bluez已经帮你集成了一套的工具集,你只要使用相应指令就可以。
第一步:插入蓝牙dongle(要支持蓝牙4.0以上的),直到Linux下看到蓝牙设备的图标
第二部:在命令行下输入 hciconfig 检查输出的结果
如果是这样显示“DOWN”表示适配器还未启动,需要输入 hciconfig hci0 up 来启动该适配器。直到出现下图
接下来使用Bluez的工具 hcitool,输入以下指令:
sudo hcitool -i hci0 cmd 0x08 0x0008 1e 02 01 06 1a ff 4c 00 02 15 fd a5 06 93 a4 e2 4f b1 af cf c6 eb 07 64 78 25 29 11 30 39 cd 00 这里hcitool cmd是Bluez提供的操作蓝牙HCI层的指令,-i hci0是指定使用哪个适配器,0x08是OGF指令、这里指BLE而不是BE/EDR的操作,0x0008是OCF指令、这里是指设置广播数据,后面1e之后到最后00之前的部分正是我们前面讲的ibeacon广播的数据。这里有个小坑注意,1e后面必须跟31个字节的数据,不够的补 00(因为BLE广播数据的长度是31),而1e(30)指的是有效数据的长度,ibeacon的数据长度是30所以这里是1e。更多的hcitool 和hciconfig命令的信息可以在网上搜索,关于OGF OCF指令以及蓝牙HCI层操作的方法可以参见蓝牙核心协议。(BLE操作的部分在core 5.0协议的7.8)
之后在输入 sudo hcitool -i hci0 cmd 0x08 0x000a 01 这里的0x000a是蓝牙广播使能的指令,写入01是开启,写入00是关闭。输入之后的结果如下;
到这里ibeacon的配置已经全部完成了!
打开手机蓝牙你会看到一个"ubuntu"的蓝牙设备(可能根据具体设备名字不同),打开微信->发现->摇一摇, 然后摇一摇你会发现出现了一个“周边”的栏目,如果你配置的Major,和Minor是向微信申请的正式编号,这里就会显示出相应的商家页面。
我随便编的所以是黑屏:)