Newer
Older
HX_DK_FOR_NORDIC_52840_BLE_MESH_PUBLIC / 新手入门 / PB-ADV入网过程.md

前言

我相信看过我们PB-GATT入网过程的读者,应该对入网的全过程有了一个相对程度的了解吧;当然啦,如果短期间看不明白也没有关系,那就多看几遍。接下来,小编仍然还是给大家讲解Mesh入网的全过程,只不过此次是PB-ADV的方式入网;那么,接下来先讲讲什么是PB-ADV。

  • 什么是PB-ADV? 对于有一些了解的读者,看到这个名词时肯定会说“这不就是通过广播包互相收发数据,从而配置入网嘛”,其实对于总的概括来说是没有错的。但是,我们有一些关键的地方我们仍然还要注意:
    1. 与PB-GATT不同的是,PB-ADV使用Generic Provisioning PDUs配置new device,而PB-GATT则是通过Proxy PDUs,这两种是完全不同的PDUs;前者是通过37,38,39的广播通道进行通讯,而后者则是通过Proxy service进行数据收发,也就是数据通道进行通讯;
    2. PB-GATT是基于连接的模型进行一序列的入网操作,而PB-ADV则基于会话的模型进行相应的入网操作;前者,传输配置数据的最大PDU是由ATT的MTU的大小来决定;而后者的MTU则是最大就只有24个字节,且使用连接建立程序 (Link Establishment procedure) 进行会话的建立;

讲了这么多,接下来我们还是采用同样的套路,先看PB-ADV的帧格式,之后再分别层层剖析。

由上图可知,PB-ADV PDU主要由Link IDTransaction NumberGeneric Provisioning PDU三个部分组成;

该字段所表示的含义比较好理解,其起到的就是一个标识符的作用;主要用于在配置过程辨别同一个LINK ID下,Provisioner与unprovisioned device的数据交互;不同LINK ID的packets会被彼此忽略,因为一个会话的生命周期时有且仅有一个Link ID,不同的会话其LINK ID是不一样的。注意,LINK ID是由Provisioner随机产生的

Transaction Number

该字段主要用于辨别每个单独的Generic Provisioning PDU;即从0x00开始,该值在每个新的Generic Provisioning PDU上累加 (对于Provisioning Bearer Control PDU,其Transaction Number一直都是0x00),如果累加到最大值时,则又从0x00重新开始;对于Provisioner和Unprovisioned device它们两者的最大值是不一样的:

  • Provisioner

    最大只能达到0x7F;

  • Unprovisioned Device

    最大可能达到0xFF;

但是,也有两种情况是不需要累加的:

  1. 如果一个Provisioning PDU放不下去时,所有的分包均是同样的Transaction Number的,不需要累加;
  2. 如果Provisioning PDU需要被重传,那么也是不需要累加的,还是使用旧的Transaction Number;

    Generic Provisioning PDU

    该PDU的详细情况,小编不在此处展开,准备将其放在Generic Mesh Provisioning ControlGeneric Mesh Provisioning Payload两个章节中细述。

    入网流程

    同理,这个步骤跟我们上一章节PB-GATT入网过程中的入网流程小章节所细述的内容是一模一样,小编这里就不再细述;下图所示的是PB-ADV方式入网的全过程:

与PB-GATT相比之下,多了Generic Mesh Provisioning Link Open、Generic Mesh Provisioning Link Ack、Generic Mesh Provisioning Link Close,那么这三者之间有什么关联呢?我们在上述的内容也有提到这一点,PB-ADV是采用会话的模型进行配置数据的收发,那么会话模型就需要这三个PDU来建立,具体如下图所示:

注意:上述的这三个PDU均属于Provisioning Bearer Control PDU的范畴,也就是说这三个PDU根据不同的场景所组装成不同的PDU就表示Provisioning Bearer Control PDU

Link Open消息用于在Provisioner和Unprovisioned Device之间建立链接,Unprovisioned Device如果接收到该消息,应使用Link ACK消息应答此消息。具体的帧格式如下:

其中Device UUID指的是选中的Unprovisioned Device的UUID。

该消息用于发送应答消息,表示其收到Link Open的消息了,具体的帧格式如下:

这里值得注意的是:应答消息是不携带任何参数的。

该消息用于关闭Link会话,由于该消息是没有被应答的,因此为了保险起见,Link关闭消息最少要发送3次且Provisioner和Unprovisioned Device均可以发送该消息,并且携带关闭原因这个参数。具体的帧格式如下图所示:

注意:关于Link Establishment procedure我们还有以下几点需要大家了解下:

  1. 对于Provisioner而言,其在准备建立Link会话时会先设置一个60秒的定时器,接着发送Link Open消息;如果在60秒后没有收到Unprovisioned Device的Link Ack的消息,则认为此次Link会话建立失败;
  2. 对于Unprovisioned Device而言,其在收到Link Open消息之后,会给Provisioner回应Link Ack的消息,紧接着同样也开启一个60秒定时器;如果在60秒后没有收到任何的Provisioning PDU,则认为此次Link会话建立失败;

Generic Provisioning PDU

除了上述的之外,这两种方式最大的不同是:

  • PB-GATT 通过Proxy PDUs进行配置数据的收发
  • PB-ADV 通过Generic Provisioning PDUs进行配置数据的收发

至于Proxy PDUs,我们在PB-GATT入网过程已经细述过,该小章节我们着重描绘Generic Provisioning PDUs的内容,如下图所示:

由上图可知,该PDU主要由Generic Provisioning ControlGeneric Provisioning Payload组成。

Generic Mesh Provisioning Control

该字段主要表明Generic Provisioning Control域包含的是哪一种类型的GPCF,至于一共有哪几种类型的Generic Provisioning Control,上述的Generic Provisioning PDU示意图已经描述地很清楚了:

  • Transaction Start -0b00
  • Transaction Acknowledgment - 0b01
  • Transaction Continuation - 0b10
  • Provisioning Bearer Control - 0b11

Transaction Start

Transaction Start PDU用于启动分段消息的转输,也就是说每一个Provisioning PDU的消息传输都是使用该PDU开始传输。而Provisioning PDU到底都是些什么帧格式呢?在上一章节PB-GATT入网过程中已经详述过,即

Type Name
0x00 Provisioning Invite
0x01 Provisioning Capabilities
0x02 Provisioning Start
0x03 Provisioning Public Key
0x04 Provisioning Input Complete
0x05 Provisioning Confirmation
0x06 Provisioning Random
0x07 Provisioning Data
0x08 Provisioning Complete
0x09 Provisioning Failed
0x0A-0xFF RFU

该PDU的具体帧格式如下表所示:

Field Size (bits) Description
SegN 6 The last segment number
GPCF 2 0b00 = Transaction Start
TotalLength 16 The number of octets in the Provisioning PDU
FCS 8 Frame Check Sequence of the Provisioning PDU
SegN

该字段其实就是表示除了Transaction Start中携带了一些Provisioning PDU,剩下的Provisioning PDU还需要多少个分段的包才能发送完成;

GPCF

对于该PDU,该字段固定为0x00

TotalLength

表示要表达的Provisioning PDU总有多少字节

FCS

该字段则表示对Provisioning PDU进行计算后的帧检验值

为了上述更易于理解,我们可以查看如下所示的捉包图:

Transaction Acknowledgment

Transaction应答PDU用于应答接收到的Provisioning PDU,跟其他的应答消息一样,它也是不携带任何参数的。

Field Size (bits) Description
Padding 6 0b000000; all other values Prohibited
GPCF 2 0b01 = Transaction Acknowledgment

Transaction Continuation

使用Transaction Start PDU没有办法将整个Provisioning PDU传送完成,就应该使用该字段传输分包的Provisioning PDU。具体的帧格式如下所示:

Field Size (bits) Description
SegmentIndex 6 Segment number of the transaction
GPCF 2 0b10 = Transaction Continuation
SegmentIndex

该字段表示当前的Provisioning PDU是第几个分包;

GPCF

固定为0b10,表示Transaction Continuation;

Data

表示各个分包Provisioning PDU的内容;

Provisioning Bearer Control

该类型的PDU是上述的Generic Mesh Provisioning Link OpenGeneric Mesh Provisioning Link AckGeneric Mesh Provisioning Link Close的统称,这也就是说该PDU是由根据不同的BearerOpcode类型来表示不同的PDU。

Generic Mesh Provisioning Payload

该字段所描述的PDU内容其实是根据Generic Mesh Provisioning Control设置的不同而不同,其本质就是用来传输Provisioning PDU,至于怎么传输,传输哪些内容则是看当前处于入网的哪个阶段,Provisioning PDU有多少字节。例如:当前Provisioner与Unprovisioned Device进入到交换公钥的阶段,这个时候就必须使用Transaction Start PDUTransaction Continuation PDU来传输Provisioning PDU

同时,我们在刚看上面前言中的PB-ADV图时,肯定会有读者在想“Generic Provisioning PDU不是最大只支持24字节吗?为什么下面的Generic Provisioning Payload是0~64字节,这不是比24字节还大吗?” 我想有这样疑问的读者,现在应该知道为什么了吧?没错,放不下去我还可以分包啊

总结

入网流程中的最前面提及到整个PB-ADV流程中可以看出,基本上跟PB-GATT是一模一样的,所以这个章节就不再重复。不同的点我在上述也已经一一细述。但是还有一些细节,小编觉得还是有必要要了解一下:

  • 跟普通的广播包一样,Generic Provisioning PDU的发送也是要插入一个20~50ms的随机时间,这样就可以大大降低信道冲突的可能性,从而提高鲁棒性;
  • 当收到Transaction Acknowledgment的消息,表示Provisioning PDU传输完成。尤其对于需要分包发送的场合,Unprovisioned Device接收完Provisioning PDU之后会给Provisioner发送这个应答,这个时候可能读者会问 “Unprovisioned Device怎么知道已经接收完Provisioning PDU呢?”不知道读者还有没有印象,在Transaction Start中有个SegN字段,Unprovisioned Device可以根据它判断整个Provisioning PDU是否已传输完成;

  • 在一些需要应答的数据交互,双方将第一条消息发送出去之后,如果在30秒内没有收到应答,那么此次入网失败;

  • 当Unprovisioned Device接收完Provisioning PDU之后,它会计算Provisioning PDU的FCS,并与Transaction Start中的FCS字段的内容相比较,如果匹配则发送应答消息;

  • 当且仅当Provisioner发送给Unprovisioned Device Provisioning PDU时,才需要发送应答。否则是不需要发送应答信息的;也就是说Unprovisioned Device给Provisioner发送的消息是不需要发送应答的;