这里以一个无线扫描枪设备为例,这个设备会通过蓝牙通讯协议连接一个底座,使用的是BLE SPP进行通讯。
扫描枪用来扫条码,解析出条码信息后,将数据通过无线传输给底座,底座再通过USB将数据传送给电脑。
底座是Central device,扫描枪是peripheral device,因为底座需要连接多个扫描枪。通常是扫描枪提供数据给底座,没数据可能会进入休眠状态。底座有USB供电,处于一直等待接收数据的状态。
也就是说扫描枪发布蓝牙广播信息,底座作为扫描方,接收蓝牙广播信息,发现扫描枪后,发起连接。
当底座连接多个扫描枪时,对Service的Characteristic进行读写操作,来实现串口通讯功能。一个通讯链路,需要一套用于数据通讯的Service和Characteristic。扫描枪和底座连接,这个Service和Characteristic实例放在扫描枪上。如果放在底座上,则会存在多个Service和Characteristic实例,会出现冲突,难以管理。故应由扫描枪来作为GATT Server,底座作为GATT Client。这里的Service和Characteristic指的是用于BLE SPP的,使用的是指定UUID,不同厂商(协议栈不同)使用的UUID可能是不同的。
本文使用的是Bluecode蓝牙协议栈,是和Telit公司提供的蓝牙模组一起使用的。参考的是此蓝牙扫描枪和蓝牙底座项目。
扫描枪的蓝牙操作
1,设置广播数据
在想连接的Target Device的地址发生变化时,才需要更新广播数据。
广播类型是非定向广播。
数据构造是小端顺序。
这里设置的数据分为广播数据及扫描响应数据,两个都是31字节。
-
广播数据里是Flags,16bit Service UUID,Manufacturer Specific Data。在Manufacturer Specific Data的数据格式为:VendorID、TIO Data ID、Data Version、Bondable and functional mode、connection requested、Connect option、BT Address。默认情况下,Connect option值为0,表示连接的是Base,即底座。
-
扫描响应数据里的数据是Complete local name。
扫描枪发布广播数据,底座想连接的话,收到广播数据,使用里面的地址,就可以连接扫描枪设备了。
Flags是0x06,16bit Service UUID是0xFEFB。Manufacturer Specific Data里,VendorID是0x008F。
2,注册相关服务。
在扫描枪这个产品中,注册了两个服务。一个DIS,Device Information service,160bit UUID是0x180A。
另一个就是BLE SPP service,即TIO profile了。
但具体的Service注册过程,在此项目中没有看到。需另外查询此协议栈的相关文档或SDK的demo。
底座的蓝牙操作
1,创建一个Periodic Scan Timer,作为GATT client设备,启动后就开始周期扫描,扫描方式是passive被动性扫描。
- 参数设置:
scanInterval,128 tick (0.625ms one tick),80ms。
scanWindows,128 tick (0.625ms one tick),80ms。
开启Duplicate Filter。
- 时序:
开始扫描,并启动一个300ms Timer;300ms Timer到了,停止扫描;Delay 300ms,等待协议栈线程的扫描结果处理;300ms时间到了,查询是否发现新设备;再等300ms;一个周期结束,重复上个周期操作,开始扫描。
大概就是900ms一个周期,有300ms的扫描时间。
2,收到并处理广播数据
进入被动扫描模式后,当接收到广播数据包,协议栈会发送事件,调用事件处理函数。
此处理函数是HandleBlueAPIMessage,处理的消息事件是blueAPI_EventLEScanInfo。
接受的数据就是31个字节,
要判断的条件有三个:
a, TIO Service UUID的值是否是0xFEFB,Telit Wireless Solutions (Formerly Stollmann E+V GmbH),在Assigned Numbers里能查到。
b, Vendor ID是否是0x008F(Telit Wireless Solutions GmbH),在Assigned Numbers里能查到。
c,Data ID是否是TIO ID,0xB009。
d,Connect option字节是否为0,表示请求连接。
然后将地址后面地址信息存储下来。
3,广播数据处理成功
在广播数据处理成功后,即得到了一个请求连接的蓝牙地址。在上面的Period Scan处理过程中,在查询是否发现新设备的处理中,使用得到的蓝牙设备地址请求一个GATT链接。
等待GATT链接请求的反馈结果,结果正确后,针对此蓝牙地址发送Discover Request,并等待反馈结果。
结果正确后,调用BLE SPP的请求连接的函数,反馈结果成功,则连接过程结束。
4,Discover过程
上面发送了Discover请求后,会收到协议栈反馈的Endpoint Indicate事件,里面包含了SPP的port信息。在BLE SPP请求连接时要使用这个信息,确定想连接的SPP port端口。