这里以一个无线扫描枪设备为例,这个设备会通过蓝牙通讯协议连接一个底座,使用的是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端口。