Telink BLE SIG Mesh GATT 配网功能

目录

1:准备工作

1.1:抓包工具

1.2:telink BLE SIG Mesh SDK 

1.3:BLE SIG Mesh Spec

1.4:调试设备

2:配网过程概述

3:设备发现

3.1:unprovisioned dev beacon

3.2:scan for unprovisioned dev beacons

4:设备连接与服务发现

4.1:app发起BLE连接与获取服务

4.2:设备端BLE连接的处理

4.3:异常情况备忘

5:配网

5.1:provisioning invite

5.2:provisioning capabilities

5.3:provisioning start

6:绑定app key


简单理一下泰凌微电子BLE SigMesh SDK V2.8.2通过手机对设备节点进行配网的过程,为今后的开发工作做一个参考的文档。因为SDK并不是开源的,因此有些部分可能出现谬误,欢迎指正;未完成部分等出现问题再看吧,目前实在是太懒得去看了。

配网(provision)功能是将一个未分配的节点加入到Mesh网络使之成为某个Mesh网络节点的功能。根据SIG Mesh spec的定义,配网过程会将Mesh网络的Network Key,IV Index以及分配给节点的unicast addr传输给节点。

1:准备工作

1.1抓包工具

采用韦东山安卓视频蓝牙教程部分推荐的wireshark + nRF sniffer

1.2:telink BLE SIG Mesh SDK 

泰凌微电子BLE SIG Mesh SDK下载地址:http://www.telink-semi.cn/viewtopic.php?f=7&t=100

包含固件SDK与android app sdk,其中有两个相对重要的参考文档:

<1>《AN_17090701-C1_Usage and Development Guide for Android APP TelinkSigMesh》

<2>《AN_17120401-C2_Telink SIG Mesh SDK Developer Handbook.pdf》

1.3:BLE SIG Mesh Spec

BLE SIG Mesh协议文档可以到官方网站下载,这里主要涉及第5章provisioning下的PB-GATT相关内容

1.4:调试设备

telink 8269 usb dongle + vivo

telink 8269 usb dongle MAC:AB:CD:04:0A:93:89

tlsr8269 usb dongle烧录BLE SIG Mesh SDK V2.8.2 release的固件

vivo手机通过android app对未配网的usb dongle进行扫描、连接、配网的操作

2:配网过程概述

本节主要参考BLE SIG Mesh Spec V1.0以及telink固件开发手册以下部分:Telink BLE SIG Mesh GATT 配网功能_第1张图片

整理telink SIG Mesh SDK GATT配网模式流程如下:

Telink BLE SIG Mesh GATT 配网功能_第2张图片

3:设备发现

app为设备进行配网,首先要发现周围的未配网设备,设备发现主要分为以下三步:

<1>未配网的设备开机后会一直向外发送unprovisioned beacon(可连接类型)广播包;

<2>用户打开APP扫描周围的未配网设备;

<3>app扫描到设备的unprovisioned beacon,并向该设备发出SCAN_REQ;设备接收到SCAN_REQ后回复SCAN_RSP;

SCAN_RSP内附带有必要的自定义信息,可帮助app识别设备。

3.1:unprovisioned dev beacon

3.1.1:设备端beacon/广播初始化

设备端上电后在user_init函数内有对设备的广播进行初始化,主要步骤:

bls_ll_setAdvParam:设置广播间隔10ms,非定向广播类型,37,38,39三个信道

blc_ll_setAdvCustomedChannel:自定义广播使用的信道。SIG Mesh要求同时使用37,38,39三个广播信道,调试时为了抓包方便可以修改。

bls_ll_setAdvEnable:使能广播

rf_set_power_level_index:RF功率设置

3.1.2:设备端beacon数据解析

未配网的设备上电后开始不停向外发送unprovisioned dev beacon;

unprovisioned beacon是可连接类型广播包(ADV_IND),且已经被BLE SIG Mesh定义完毕全部字段,对应固件SDK代码内的结构体类型PB_GATT_ADV_DAT:

Telink BLE SIG Mesh GATT 配网功能_第3张图片

未配网的设备通过unprovision dev beacon向外广播mesh provisioning GATT service的数据service_data,service_data内包含设备的MAC地址及其它数据。Provisioner(APP)可以通过这些数据唯一地识别到发送该beacon的设备;

unprovision beacon必要时会带有oob_info;oob_info用于提示provisoner在进行下一步配网动作之前需要收集oob(附带数据);uuid 0x1827为16位mesh provisioning GATT service UUID

3.2:scan for unprovisioned dev beacons

3.2.1:app扫描unprovisioned dev beacon

Telink BLE SIG Mesh android APP 对设备是扫描发现一个配网一个的,其扫描与配网相关的代码实现均在DeviceProvisionActivity方法,本节只关注扫描设备相关:

<1>DeviceProvisionActivity.onCreate监听ScanEvent.DEVICE_FOUND与SCAN_TIMEOUT事件;

<2>DeviceProvisionActivity.onCreate调用startScan方法启动设备扫描;

<3>DeviceProvisionActivity.startScan首先生成默认扫描配置参数ScanParameters ,然后将已经配网的设备排除,最后调用MeshService.getInstance().startScan(parameters)启动Mesh服务扫描蓝牙设备;

<4>DeviceProvisionActivity.perfomed内对ScanEvent.DEVICE_FOUND事件进行监听,将扫描到的设备数据AdvertisingDevice device传给onDeviceFound处理(进行下一步配网)

<5>至此可知,APP扫描unprovisioned beacon获得的数据被缓存在了AdvertisingDevice device:

Telink BLE SIG Mesh GATT 配网功能_第4张图片

上图蓝色部分与3.1.2设备端unprovisioned beacon数据一致。

3.2.2:app获取设备信息

AdvertisingDevice内除了unprovisoned dev beacon还有一包数据,是app接收到设备端的unprovisoned dev beacon包后发给设备一个SCAN_REQ再由设备在SCAN_RSP返回的。设备端SCAN_RSP的内容在mesh_scan_rsp_t结构体内定义,抓包数据如下:

Telink BLE SIG Mesh GATT 配网功能_第5张图片

用户可以(或者说必须)在这个SCAN_RSP附带自定义的数据回复给app,例如用以区分识别厂家设备的信息(不是自家的设备不进行连接)。至此,app已发现并获取了周围某个未配网设备的必要信息,下一步将建立与设备的BLE连接。

 

4:设备连接与服务发现

app通过unprovisioned dev beacon扫描到未配网设备后,在正式配网之前,app需与设备建立BLE连接、扫描设备服务(属性表)、向设备写入CCC数据。

4.1:app发起BLE连接与获取服务

4.1.1:app发起BLE连接

app通过unprovisioned dev beacon获取到AdvertisingDevice 数据后会在onDeviceFound内继续调用直到MeshService.getInstance().startProvision(...);

startProvision调用this.device.connectGatt(...)向设备发起BLE连接请求。配网若出现失败,手机app的CONNECT_REQ没有收到回复是常见原因,因此CONNECT_REQ几个参数标出备查:

Telink BLE SIG Mesh GATT 配网功能_第6张图片

(参考:https://www.cnblogs.com/iini/p/8972635.html)

4.1.2:app获取设备服务

connectGatt接口的状态回调是onConnectionStateChange,app根据回调状态判断BLE连接建立是否成功;成功连接后app再通过gatt.discoverServices()获取设备支持的attribute table。抓包工具显示,master(手机app)递增attributes handle查询slave(BLE Mesh设备)支持的attribute table:

Telink BLE SIG Mesh GATT 配网功能_第7张图片

(本节参考:https://www.cnblogs.com/hzl6255/p/4141505.html)

 

discoverServices()的结果回调是onServicesDiscovered,onServicesDiscovered内app会向设备端写入CCC数据,CCC的用途是打开设备端的特征值nodify功能;见writeCCCForPv。

app使能设备端的数据上报后还需要调用enableNotifications使能app对设备PB_OUT_CHARACTERISTIC_UUID/PROXY_OUT_CHARACTERISTIC_UUID/CHARACTERISTIC_UUID_ONLINE_STATUS的nodify接收;当有数据上报时,onCharacteristicChanged接口被回调:

PB_OUT_CHARACTERISTIC_UUID:配网功能GATT Service数据输出特征值

PROXY_OUT_CHARACTERISTIC_UUID:代理功能GATT Service数据输出特征值CHARACTERISTIC_UUID_ONLINE_STATUS:Mesh网络状态上报功能GATT Service

CHARACTERISTIC_UUID_ONLINE_STATUS相关功能是telink为了实际产品开发状态同步问题加的,需要相关版本与宏打开;配网功能与代理功能的GATT services则是必须的,只是根据设备端是否已配网加载不同的属性表,详见4.2.2。

app会请求更新BLE传输的最大传输单元MTU(一个协议数据单元中能够传输的最大数据量),MTU默认最大23个字节,后续配网期间传输的数据远不止此。MTU实际变更的数值会在onMtuChanged回调内返回:

4.2设备端BLE连接的处理

4.2.1:设备端BLE连接状态回调

<1>设备端代码app.c app_event_handler下HCI_SUB_EVT_LE_CONNECTION_COMPLETE是app与设备端建立BLE连接时的处理,结构体event_connection_complete_t对应4.1.1 app端发送的连接请求指令CONNECT_REQ参数;

<2>bls_app_registerEventCallback接口用于为各类BLE连接事件注册回调函数,SDK代码暴露出来的回调是mesh_ble_connect_cb/mesh_ble_disconnect_cb/mesh_conn_param_update_req;

<3>需要说明的是在mesh_ble_connect_cb与mesh_conn_param_update_req内有一些处理:手机app与设备端的BLE连接建立后会设置need_conn_update_flag与att_service_discover_tick,两者共同作用在BLE连接建立的500ms后由设备端发起告知手机更新BLE连接参数bls_l2cap_requestConnParamUpdate(16, 32, 0, 200)。根据telink工程师的解释:手机处于扫描设备阶段与建立BLE连接后进行配网/通讯时宜使用的连接参数不同。建立BLE连接500ms后再更新此参数的原因是需要留给手机app读取全部attribute table的时间。这就有可能涉及到时序问题:更新参数的请求与配网流程中的指令发生碰撞。不过也可改为配网完毕再进行参数更新,具体还要视SDK版本迭代情况。

4.2.2:设备端BLE attribute table

如4.1.2节所述app有获取设备端BLE attribute table(实际上是发现GATT services)的操作,设备端相关代码在app_attr.c下。user_init时会在my_att_init加载bls_att_setAttributeTable,用户在此添加自定义的GATT service。设备端SDK默认的GATT服务示意如下:

Telink BLE SIG Mesh GATT 配网功能_第8张图片

手机app与设备建立BLE连接时,手机作为BLE master设备端作为BLE slave;发现设备端GATT server时,则是手机app作为GATT client,设备端作为GATT server。GATT server与client之间通过ATT PDUs进行通讯。GATT client访问GATT server的characterists值通过READ/WRITE操作;GATT server可以把自己的characterists值通过nodify或者indicate的方式告知client;indicate方式相对于nodify有ack回复,所以较为可靠。

GATT client(对应手机app)使能/禁用GATT server(对应设备端)nodify/indicate功能,是通过对characteristic descriptors的Client Characterist Configuration(CCC,对应UUID 0x2902,上图浅蓝色部分)进行写操作实现的。从设备端代码pb_gatt_Write与proxy_gatt_Write看,CCC数据若写入失败,手机app向设备端写入的配网数据/控制指令均不会生效。

4.3异常情况备忘

实际开发过程中,对于telink SIG Mesh的GATT配网方式,发现出现失败情况在主要发生本节所述的设备连接与服务发现阶段,这里稍微罗列下一些出现的异常情况:

<1>如4.1.1所述,手机发送给设备端的CONNECT_REQ没有响应。对应app端一般是出现BLE disconnect的回调发生。造成的原因各种各样,处理主要还是app重连。

<2>手机app对一个设备配网完毕后再配下一个,这个时序需要处理好,否则可能出现上一个设备配网的确认信息才处理,当前已连接的又是新的一个设备,误判新的设备配网情况。

<3>如4.1.2所述,手机app需要获取设备的attribute table。比较吊诡的是,android与iOS在底层获取atrribute table的具体顺序是不同的,因此对于attribute table何时获取完毕的判断条件是不同。当然这个情况是app可以处理的。具体抓包TBD。

<4>从获取attribute table到使能设备端GATT service的nodify(写入CCC数据)再到向设备端发送provision invite,三者之间需要满足一定的时序要求。具体原因与时序要求请请教telink原厂。

以上仅供参考备忘,应该随着SDK迭代都能fix这些情况。

5:配网

当手机APP与设备建立BLE & GATT连接成功,接下来就要开始对设备进行配网。

配网的详细过程参考BLE SIG Mesh Spec  5.4  Provisioning protocol 

5.1provisioning invite

           app向设备端写入CCC后,再满足一定的时间间隔后,会向设备端发起provisioning invite,随即设备端回复provisioning capabilities数据,这些在SIG Mesh Spec有详细定义。

provisioning invite参考BLE SIG Mesh Spec 5.4.1.1

           app通过startProvisionInvite向设备端发送provisioning invite,实际上就是3个字节的数据。

5.2provisioning capabilities

            provisioning capabilities参考BLE SIG Mesh Spec 5.4.1.2

设备端对于provisioning capabilities的定义是结构体:pro_trans_capa

对应BLE SIG Mesh Spec 5.4.1.2。绿框部分依次是写入CCC,app发起provisioning invite以及设备返回provisioning capabilities的抓包情况:

Telink BLE SIG Mesh GATT 配网功能_第9张图片

5.3provisioning start

啥时候想写再说吧

6:绑定app key

啥时候想写再说吧

你可能感兴趣的:(物联网)