<!--

前言

我相信读过小编前面章节内容的读者,或多或少已经对整个BLE Mesh的入网过程,Mesh Packet的各个层的作用以及在Mesh网络中数据是如何交互的有一定的了解;那么,接下来我们继续讲解Mesh中的基础模型 (Foundation Model)之一的Configuration Model。然而,Configuration Model又分两种类型:

然而,需要注意的是:不管是Server还是Client,在节点中都是强制要求必须有的一个模型

Configuration Server Model

在上面的前言中,小编也说了这个配置服务是强制要求的,是不可以省略的一个模式;那么该模型为什么这么重要,以至于每个节点都必须要有?其主要有以下几个特性:

那么,该模型又存放了哪些 “宝贝” 呢,如下表所示:

Configuration Server States Bound States
State Instance Model State Instance
Secure Network Beacon Primary - - -
Composition Data Primary - - -
Default TTL Primary - - -
GATT Proxy Primary Configuration Server Node Identity Primary
Friend Primary - - -
Relay Primary - - -
Model Publication Primary - - -
Subscription List Primary - - -
NetKey List Primary - - -
AppKey List Primary - - -
Model to AppKey List Primary - - -
Node Identity Primary - - -
Key Refresh Phase Primary - - -
Heartbeat Publish Primary - - -
Heartbeat Subscription Primary - - -
Network Transmit Primary - - -
Relay Retransmit Primary - - -

从上表可知,洋洋洒洒共17项内容;可能有读者会发现有一个“腰间突出”的,即GATT Proxy这项内容;对于这个不知道大家还有没有印象:

而这个GATT ProxyNode Identity的关系就是,如果proxy feature被支持且mesh proxy server被公开。在入网完成之后,就会将在广播包中携带有Node Identity这个域值。

既然Configuration Server Model存放的是节点的配置内容,那用户应该如何去获取这个内容呢?具体如下所示:

Element SIG Model ID States Messages Rx Tx
Primary 0x0000
Secure Network Beacon
Config Beacon Get M
Config Beacon Set
M
Config Beacon Status - M
Composition Data Config Composition Data Get M
Config Composition Data Status M
Default TTL Config Default TTL Get M
Config Default TTL Set M
Config Default TTL Status - M
GATT Proxy Config GATT Proxy Get M
Config GATT Proxy Set M
Config GATT Proxy Status - M
Friend Config Friend Get M
Config Friend Set M
Config Friend Status - M
Relay and Relay Retransmit Config Relay Get M
Config Relay Set M
Config Relay Status - M
Model Publication Config Model Publication Get M
Config Model Publication Set M
Config Model Publication Virtual Address Set M
Config Model Publication Status M
Subscription List Config Model Subscription Add M
Config Model Subscription Virtual Address Add M
Config Model Subscription Delete M
Config Model Subscription Virtual
Address Delete
M
Config Model Subscription Virtual
Address Overwrite
M
Config Model Subscription
Overwrite
M
Config Model Subscription Delete
All
M
Config Model Subscription Status M
Config SIG Model Subscription Get M
Config SIG Model Subscription List M
Config Vendor Model Subscription Get M
Config Vendor Model Subscription List M
NetKey List Config NetKey Add M
Config NetKey Update M
Config NetKey Delete M
Config NetKey Status M
Config NetKey Get M
Config NetKey List M
AppKey List Config AppKey Add M
Config AppKey Update M
Config AppKey Delete M
Config AppKey Status M
Config AppKey Get M
Config AppKey List M
Model to AppKey List Config Model App Bind M
Config Model App Unbind M
Config Model App Status M
Config SIG Model App Get M
Config SIG Model App List M
Config Vendor Model App Get M
Config Vendor Model App List M
Node Identity Config Node Identity Get M
Config Node Identity Set M
Config Node Identity Status M
N/A Config Node Reset M
Config Node Reset Status M
Key Refresh Phase Config Key Refresh Phase Get M
Config Key Refresh Phase Set M
Config Key Refresh Phase Status M
Heartbeat Publication Config Heartbeat Publication Get M
Config Heartbeat Publication Set M
Config Heartbeat Publication Status M
Heartbeat Subscription Config Heartbeat Subscription Get M
Config Heartbeat Subscription Set M
Config Heartbeat Subscription Status M
Network Transmit Config Network Transmit Get M
Config Network Transmit Set M
Config Network Transmit Status M

 

从上表可以看到,一个State对应多个Message;那么,State与Message的关系就类似于 “手机现在都支持BLE,那么就有打开BLE、关闭BLE以及查看当前BLE的状态的动作”;其中,手机支持BLE就等同于State,而那些动作就是Message。所以,如果你想要获取或者配置相关的内容,就可以通过Message去实现。对于,RXTX是相对于节点本身为参考体。这里举个例子 “就Network Transmit状态而言,Config Network Transmit Get/Set表示该节点可以接收这些Messages;而节点在接收到这些消息之后,就会返回Config Network Transmit Status即发送回给源地址的设备”;那么,紧接着我们继续解析每一个State以及其对应的Message的作用。

Secure Network Beacon

该状态用于表示节点是否在周期性广播Secure Network Beacon,这个比较简单好理解;其具体的状态如下表所示:

ValuesDescription
0x00The node is not broadcasting a Secure Network beacon
0x01The node is broadcasting a Secure Network beacon
0x02–0xFFProhibited

Config Beacon Get

该消息用于获取当前安全网络信标的状态,当节点的configuration server model接收到了该消息后,会用Config Beacon Status去响应该消息。

Config Beacon Set

跟上述的Config Beacon Get相似,只不过该消息用于设置当前的安全网格信标;当节点的configuration server model接收到了该消息后,将设置的新值通过Config Beacon Status去响应该消息;其中该消息的帧格式如下所示:

FieldSize(octets)Notes
Beacon1New Secure Network Beacon state

Config Beacon Status

对于Config Beacon Get/Set这两个Message就是为了设置或者获取节点上述所描述的状态;不管是Get还是Set的Message,收到之后都会给其响应该消息。

FieldSize(octets)Notes
Beacon1Secure Network Beacon state

Composition Data

这个状态包含了节点的信息,如其元素以及模型的信息。这些信息可以由多个信息页组成;但是目前SIG只规定了Page0的内容,其他信息页内容是可选的。那些,SIG规定的Composition Data Page0有哪些内容呢?我想信很多一直看我们PB-GATT入网过程教程的读者应该对这些内容比较熟悉。没错!这些就是节点的元素、模型以及其所支持的特性等信息,入网成功之后Provisioner向节点获取得到的内容;

FieldSize(octets)Notes
CID2Contains a 16-bit company identifier assigned by the Bluetooth SIG
PID2Contains a 16-bit vendor-assigned product identifierVID2 Contains a 16-bit vendor-assigned product version identifier
VID2Contains a 16-bit vendor-assigned product version identifier
CRPL2Contains a 16-bit value representing the minimum number of replay protection list entries in a device
Features2Contains a bit field indicating the device features
ElementsvariableContains a sequence of element descriptions

Config Composition Data Get

该消息一般都是Provisioner发出,用于获取入网之后节点设备的一些设备参数,具体的帧格式如下所示:

FieldSize(octets)Notes
Page1Page number of the Composition Data

以下是小编通过ellisys抓取得到的Mesh数据包:

这个可能会有读者有疑问 “上述的帧格式不是表明Page域的内容,就是想要读的Composition Data的页数吗?而且目前Specification也只规定了Page0的内容,为什么抓包图显示出来却是读的255页的内容呢?”

有这样疑问的读者,都是有认真思考过的同学,而不是被我的文章带着走。这个问题问得很好,没有错这个的确是读第255页的composition data;所以这里就分两种情况:

  1. 所有255页的内容都是有效,那么就会从255递减直至0页的数据都返回给该消息;
  2. 如果是恶意读不存在有效数据的一页,那么节点收到之后首先就会返回它自身所支持的最大页数的数据,直到0页为止。如上述的抓包图就是这种情况:当节点接收到的是255这个页数的命令,而自身最大只支持第0页,所以就只响应了第0页的composition data给provisioner,如Composition Data Status中所示;

Config Composition Data Status

这个时候我们再来看响应的Composition Data Status内容就轻松多了,如下所示:

但是,有一点我们需要注意的是Composition Data的大小不能大于Access Payload的大小,即下述表格所示:

Default TTL

顾名思义,该State表示当message发送时所使用的默认TTL值是多少;当然,你可以手工更改该值而不用这个默认的TTL值也是没有什么问题的。关于TTL的详情,可以参考《BLE Mesh各层帧包格式详解》;其具体的数据帧格式如下所示:

ValueDescription
0x00,0x02-0x7FThe Default TTL state
0x01,0x80-0xFFProhibited

Config Default TTL Get

该命令用于获取当前节点默认的TTL值,当对端设备接收到该Message之后就会将其默认的TTL值通过Config Default TTL Status返回。

Config Default TTL Set

毫无疑问,该命令用于设置当前节点默认的TTL值,其帧格式如下所示:

ParameterSize(octets)Notes
TTL1New Default TTL value

当节点收到这条message之后,然后就会将新的默认TTL值通过Config Default TTL Status返回。

Config Default TTL Status

主要用于响应上述Config Default TTL Get/Set的命令,其帧格式如下所示:

ParametersSize(octets)Notes
TTL1Default TTL

GATT Proxy

该状态的作用为:表示当前的节点是否支持代理特性(Proxy feature),如果是支持的话还可以控制是打开还是关闭该特性。其具体值的含义如下表所示:

ValueDescription
0x00The Proxy feature is supported and disabled
0x01The Proxy feature is supported and enabled
0x02The Proxy feature is not supported
0x03–0xFFProhibited

这里有一点小编觉得还是有必要说明一下,虽然我在之前的篇章中《BLE Mesh各层帧包格式详解》讲过这个问题。节点支持代理特性只是表示节点有这个功能;但是如果没有打开这个功能,就想把相关的数据通过GATT传到Mesh网络中是不可能的,你还必须把代理特性使能了才行。换一句话说:支持proxy特性只是表示你跟普通的BLE一样,只有使能了才能通过GATT跟Mesh网络中的其他设备通讯。因为这个时候Proxy Server已经生效了,你可以通过它跟其他节点愉快地进行数据交互了。为了巩固这个理解,小编举一个生活中的例子 “我们都知道现在的智能手机都支持BLE功能,但是你想要跟你手环通讯是不是要把蓝牙打开才行,如果我把蓝牙关了你不能说我的手机不支持BLE啊”

Config GATT Proxy Get

获取当前节点的GATT Proxy的状态,具体值的含义如GATT Proxy所示;如果对端设备收到该消息的话,就会响应Config GATT Proxy Status。

Config GATT Proxy Set

与Get的操作相反,该消息用于设置GATT Proxy的状态,其帧格式如下所示:

FieldSize(octets)Notes
GATT Proxy1New GATT Proxy state

这条命令发送出去,也是有响应数据的;如果设置成功,就会收到更新过后的Config GATT Proxy Status。

针对上述抓包图,如果将Proxy feature除能了,这个时候节点在没有断开连接之前,它与gatt client还是可以通过gatt通道进行数据交互的。在这个时候,一旦断开那么节点就会将proxy service除能,同时节点此时不再发出可连接的广播。这里可能会有读者会问了 “那么是不是就不能将proxy feature使能回去了?” 显然,通过GATT通道将其配置为原状是不可能了,但是你可以利用其他的proxy节点 (同时proxy feature enabled) 将其proxy feature再次使能 (通过广播通道接收使能的命令)

Config GATT Proxy Status

向对端设备报告当前GATT Proxy的状态,其帧格式如下所示:

FieldSize(octets)Notes
GATT Proxy1GATT Proxy state

Friend

该状态基本上跟GATT Proxy是类似的,表示当前的节点是否支持朋友特性,如果支持的话则可以配置朋友特性是使能还是除能;其中Friend的状态值含义如下表所示:

ValueDescription
0x00The node supports Friend feature that is disabled
0x01The node supports Friend feature that is enabled
0x02The Friend feature is not supported
0x03–0xFFProhibited

注意: 如果节点之前支持friend特性且该特性是使能的,且与几个低功耗节点(LPN)建立了朋友关系;但是,之后Friend特性被除能了。那么朋友节点将解除所有与LPN的关系以及清除所有的为LPN保留的缓存。

Config Friend Get

获取节点当前的friend状态,其具体的状态值如Friend中所示;如果对端设备收到该消息的话,就会响应Config Friend Status。

Config Friend Set

与Get的操作相反,该消息用于设置Friend的状态,其帧格式如下所示:

FieldSize(octets)Notes
Friend1New Friend state

这条命令发送出去,也是有响应数据的;如果设置成功,就会收到更新过后的Config Friend Status。

Config Friend Status

向对端设备报告当前Friend的状态,其帧格式如下所示:

FieldSize(octets)Notes
Friend1Friend state

Relay & Relay Retransmit

Config Relay Get

之所以将上述的两个状态放在一起,就是因为该消息一旦发出就会收到带有上述两个状态的信息 (Config Relay Status) 回复,即当前节点的中继和中继重复的状态信息。

Config Relay Set

同理,这个消息与上述的Get消息相反;其用于设置RelayRelay Retransmit的状态,其帧格式如下所示:

FieldSize(bits)Notes
Relay8Relay
RelayRetransmitCount3Number of retransmissions on advertising bearer for each Network PDU relayed by the node
RelayRetransmitIntervalSteps5Number of 10-millisecond steps between retransmissions

当设置完成之后,如果一切正常的话,那么就会收到带有设置后的值的 (Config Relay Status)

Config Relay Status

该消息是被动响应的,只有收到Set/Get消息之后,该消息才会被发送出去。该条消息的帧格式跟Config Relay Set是一模一样的。

Model Publication

该状态所包含的内容就比较多了,基本上覆盖了Model发布消息的方方面面:

对于整个Model Publication的State消息,其主要用于配置指定某个模型周期性发布Status消息;但是,我估计有很多读着会对Publish Retransmit Interval StepsPublish Retransmission Count以及Publish Period它们之间的关系很感兴趣,但是又有很多疑问。废话不多说,先直接上图:

从上图我们可以清晰地看到,Publish Retransmission相关的动作均是在Publish Period期间中进行的。那么就有如下几种可能:

Config Model Publication Get

跟上述的所有Get消息一样,该状态为了获得相对应State的相关参数;以下是其获取得到的数据:

FieldSize(octets)Notes
Element Address2Address of the element
Model Identifier2 or 4SIG Model ID or Vendor Model ID

其中元素地址一定是单播地址,其他类型的地址无效。

Config Model Publication Set

同样的“配方”,设置相对应State的参数,其对应的帧格式如下所示:

FieldSize(bits)Notes
Element Address16Address of the element
Publish Address16Value of the publish address
AppKey Index12Index of the application key
CredentialFlag1Value of the Friendship Credential Flag
RFU3Reserved for Future Use
Publish TTL8IDefault TTL value for the outgoing messages
Publish Period8Period for periodic status publishing
Publish Period8Period for periodic status publishing
Publish Retransmit Count3Number of retransmissions for each published message
Publish Retransmit IntervalSteps5Number of 50-millisecond steps between retransmissions
Model Identifier16 or 32SIG Model ID or Vendor Model ID

上表所述的各个域值所代表的具体含义,请参考Model Publication;其中Publish Address在该命令中不能配置为虚拟地址,因为它有专门的命令来设置。

Config Model Publication Virtual Address Set

这条消息的内容基本上跟Config Model Publication Set是完全一样的,唯一不同的就是Publish Address这里只能为虚拟地址且其长度为128Bits。

Config Model Publication Status

这个State是配合上述的GetSet使用的,但凡收到它们的消息就会返回该Status消息,但应答的内容有些许不同。同样的,其具体的内容跟Config Model Publication Set是一模一样的,至于Publish Address是16bits还是128bits,则根据发送过来的Set命令的情况而定。

Subscription List

首先,订阅列表只是组地址或者虚拟地址的集合;当节点收到Access Messages时,就会去匹配目标地址;如果存在于订阅列表中,就会做出所对应的Opcode的动作;每个模型都一个自己的订阅列表,但是每个元素中的所有扩展模型共用一个订阅列表。对于模型与元素的相关概念,请参考红旭之前写的教程《什么是Element和Model》

Config Model Subscription Add

该Message用于新增目标地址至订阅列表,其具体的帧格式如下所示:

FieldSize(octets)Notes
Element Address2Address of the element
Address2Value of the address
Model Identifier2 or 4SIG Model ID or Vendor Model ID

其中元素地址只能为单播地址,新增的地址也是只能为组地址(包括SIG规定的组地址),如果想要新增虚拟地址至订阅列表则需要用Config Model Subscription Virtual Address Add消息;下图为当前该消息的实际捉包图:

该Message是带应答的命令,其应答消息所对应的具体内容如Config Model Subscription Status所示。

Config Model Subscription Delete

这个操作跟上述的Config Model Subscription Add是相反的,此消息用于从订阅列表(Subscription List)中删除订阅地址。同样的,要删除的订阅地址只能是组地址(包括SIG规定的组地址),具体的帧格式内容跟Get是完全一样的,也是一个带应答的消息 (应答消息所对应的具体内容如Config Model Subscription Status所示)

Config Model Subscription Overwrite

其实小编认为该命令称为 “Config Model Subscription Update” 更为贴切,因为OverWrite的意思就是说将订阅列表中的之前的组地址丢弃,并替换为一个新的地址,本质上跟Update的意思没啥区别;同样的,该消息的格式以及域值的定义跟Config Model Subscription Add如出一辙。

Config Model Subscription Virtual Address Add

这是SIG专门为虚拟地址增加至订阅列表中所设的一条命令。其帧格式基本上跟Config Model Subscription Add是一样,唯一不同的地方就是此消息新增至Subscription List中的地址为16字节,详情如下所示:

FieldSize(octets)Notes
Element Address2Address of the element
Label16Value of the Label UUID
Model Identifier2 or 4SIG Model ID or Vendor Model ID

同样的,元素地址只能为单播地址,而Label为16字节的Label UUID。

Config Model Subscription Virtual Address Delete

Config Model Subscription Delete

Config Model Subscription Virtual Address Overwrite

Config Model Subscription Overwrite

Config Model Subscription Delete All

该命令用于删除指定元素下的指定模型的所有订阅列表的内容,帧格式如下所示:

FieldSize(octets)Notes
Element Address2Address of the element
Model Identifier2 or 4SIG Model ID or Vendor Model ID

同样,它也是一个带应答的消息 (应答消息所对应的具体内容如Config Model Subscription Status所示)

Config SIG Model Subscription Get

该命令用于获取指定元素地址,且在该元素下的指定SIG模型的订阅列表信息,其帧格式如下所示:

FieldSize(octets)Notes
Element Address2Address of the element
Model Identifier2SIG Model ID

这也是一个带应答的消息,其应答消息如Config SIG Model Subscription List所示。

Config SIG Model Subscription List

专门用于应答Config SIG Model Subscription Get消息,其内容主要为指定元素的指定SIG模型的订阅列表内容,其帧格式内容如下表所示:

FieldSize(octets)Notes
Status1Status Code for the requesting message
Element Address2Address of the element
Model Identifier2SIG Model ID
AddressesvariableA block of all addresses from the Subscription List

其中,Addresses域的值表示的是该指定元素下所指定的模型所订阅的全部地址:

然而,该消息的具体内容又分成如下几种情况:

Config Vendor Model Subscription Get

Config SIG Model Subscription Get一样,只是该消息是用于获取指定元素下的指定的Vendor模型的订阅列表信息,帧格式如下表所示:

FieldSize(octets)Notes
Element Address2Address of the element
Model Identifier4Vendor Model ID

Config Vendor Model Subscription List

专门用于应答Config Vendor Model Subscription Get消息,其内容主要为指定元素的指定Vendor模型的订阅列表内容,其帧格式内容如下表所示:

FieldSize(octets)Notes
Status1Status Code for the requesting message
Element Address2Address of the element
Model Identifier4Vendor Model ID
AddressesvariableA block of all addresses from the Subscription List

其中,Addresses域的值表示的是该指定元素下所指定的模型所订阅的全部地址:

然而,该消息的具体内容又分成如下几种情况:

Config Model Subscription Status

该状态消息用于应答Config Model Subscription AddConfig Model Subscription DeleteConfig Model Subscription OverwriteConfig Model Subscription Virtual Address AddConfig Model Subscription Virtual Address DeleteConfig Model Subscription Virtual Address OverwriteConfig Model Subscription Delete All等消息,其帧格式内容如下所示:

FieldSize(octets)Notes
Status1Status Code for the requesting message

| Element Address | 2 |Address of the element | Address | 2 |Value of the address | | Model Identifier | 2 or 4 |Vendor Model ID or SIG Model ID|

针对上述的表格,可能读者会有这样一个疑问:“如果我新增的地址是Label UUID,那么为什么返回的应答消息是2字节而不是16个字节?”,其实这跟下述的NetKey/AppKey List是类似的;如果将Label UUID放入网络封包的话就太占资源了,所以通过算法将Label UUID压缩为2个字节的虚拟地址;具体的计算方法如下所示:

SALT = s1 (“vtad”)

hash = AES-CMACSALT (Label UUID) mod 214

其中虚拟地址的第15个bit为1,第14个bit为0,其余的13~0 bit则是上述的hash值。然而,该消息的具体内容又分成如下几种情况:

相关出错的原因,如下表所示:

Error ConditionStatus Code Name
The model defined by ElementAddress and ModelIdentifier does not support subscription mechanismNot a Subscribe Model
The device cannot store new address due to insufficient resources on deviceInsufficient Resources
The unicast address provided in ElementAddress is not known to the nodeInvalid Address
The model identified by SIG Model ID or Vendor Model ID is not found in a given elementInvalid Model

Address域的内容是组地址还是虚拟地址,则是由发送方携带的订阅订表中的地址域所决定。

NetKey List

该状态表示网络密钥的索引列表,每个入口最多只能容纳两个NetKey,一个是旧的密钥,另外一个是新的密钥。小编一直都在强调,由于NetKey的长度一般都很长,将其塞入网络消息中不太实现;然而,使用一个索引值就可以找到相对应的NetKey的方式无疑是最佳的。一些消息可能有一个或者多个索引值,比如说:节点使用“Config NetKey Add”添加了多个NetKey,现在通过“Config NetKey Get”获取当前的NetKey索引值,这个时候“Config NetKey List”就会携带多个NetKey索引值了。然而,每个索引值的长度均为12Bits,不是8的倍数;这个时候就需要根据索引值个数的奇偶来重新组成这个索引值了,具体的实现方式如下所示:

Config NetKey Add

顾名思义,该消息是新增网络密钥至节点的NetKey列表,其帧格式如下表所示:

FieldSize(octets)Notes
NetKeyIndex2NetKey Index
NetKey16NetKey

跟上面以往的Add一样,这是一个带应答的消息,具体应答的内容请参考Config NetKey Status。其中NetKeyIndex与NetKey是对应关系,“我就是它,它就是我”

Config NetKey Update

该消息用于更新节点的NetKey,其帧格式及其含义跟上述的Config NetKey Add一样。

Config NetKey Delete

该消息用于从节点的NetKey列表中删除NetKey,其帧格式如下表所示:

FieldSize(octets)Notes
NetKeyIndex2NetKey Index

同样这也是一个带应答的消息,具体应答的内容请参考Config NetKey Status;其中NetKey Index为12Bits,但是会填充至16Bits再发送出去。

Config NetKey Status

该消息用于应答上述的Config NetKey AddConfig NetKey UpdateConfig NetKey Delete的命令,帧格式如下所示:

FieldSize(octets)Notes
Status1Status Code for the requesting message
NetKeyIndex2Index of the NetKey

但是有如下几例特殊的情况也是返回成功的状态:

除此之外,该消息的内容根据不同的情况不同而不同,如果发送方是Config NetKey Add或者Config NetKey Update或者Config NetKey Delete

Config NetKey Get

主要用于获取当前节点所有已知的NetKey,该消息是一个带应答的消息,而应答的内容如Config NetKey List所示。

Config NetKey List

专门用于应答Config NetKey Get消息,其帧格式如下所示:

FieldSize(octets)Notes
NetKeyIndexesvariableA list of NetKey Indexes known to the node

我们可以看看相关的实际捉包图是怎么样的:

相关出错的原因,如下表所示:

Error ConditionStatus Code Name
The NetKey identified by NetKeyIndex is already stored in the node and the new NetKey value is differentKey Index Already Stored
The key identified by NetKeyIndex is not valid for this device for Config NetKey Update messageInvalid NetKey Index
The node cannot store the new key due to insufficient resourcesInsufficient Resources
The requested delete operation cannot be performed due to general constraintsCannot Remove
The requested update operation cannot be performed due to general constraintsCannot Update

AppKey List

该State跟上述的NetKey List的描述基本上是一致的,只不过这个是AppKey的索引值列表;同样,每个AppKey列表的条目都只包括一个索引值以及最大两个AppKey值,其中一个是旧的AppKey,另外一个是新的AppKey。其中AppKey Index与NetKey Index是一样的,它们都是12Bits。

Config AppKey Add

还是一样的配方,该消息用于新添AppKey至AppKey列表。然而,跟Config NetKey Add不一样的是,除了AppKey索引值以及AppKey之外,还需要绑定一个NetKey (也就是NetKey Index,因为你通过索引也能找到相应的NetKey值),其具体的帧格式如下所示:

FieldSize(octets)Notes
NetKeyIndexAndAppKeyIndex3Index of the NetKey and index of the AppKey
AppKey16AppKey value

其中NetKey IndexAppKey Index总共24bits (NetKey Index是第一个Key Index,AppKey Index是第二个Key Index),组成了一个3字节的字段;如果这个时候有多个NetKey,你可以设置想要的NetKey Index (NetKey) 与AppKey进行绑定。之所以要这样,我在SIG MESH协议各个层的作用中就已经提过,NetWork PDU是由 NetKey加密而Upper Transport Layer由DevKey或者AppKey加密,所以如果将AppKey与NetKey绑定在一样时,只要我收到NetWork PDU那么我就知道接下来的Upper Transport PDU用哪个AppKey加解密。这个时候可能又有读者会问:“为什么不绑定DevKey,这是因为自始自终它就只有一个,不允许在一个节点中存在多个DevKey。同时,它只会在Configuration Model Server 与 Configuration Model Client之间使用,因此不需要绑定”;这也是一个带应答的消息,具体的应答消息内容如Config AppKey Status所示。

Config AppKey Update

该消息用于更新节点上的AppKey列表上已有的AppKey,其帧格式如下所示:

FieldSize(octets)Notes
NetKeyIndexAndAppKeyIndex3Index of the NetKey and index of the AppKey
AppKey16New AppKey value

具体的应答消息内容如Config AppKey Status所示。

Config AppKey Delete

该消息是从节点上的AppKey列表中删除AppKey,其帧格式如下所示:

FieldSize(octets)Notes
NetKeyIndexAndAppKeyIndex3Index of the NetKey and index of the AppKey

如果某个Model绑定了某个AppKey用于周期发布Status信息,但是该AppKey被这条消息删除了,那么Model周期Status信息的动作则无效;具体的应答消息内容如Config AppKey Status所示。

Config AppKey Status

该消息用于应答Config AppKey AddConfig AppKey UpdateConfig AppKey Delete,但是有如下几例特殊的情况也是返回成功的状态:

除此之外,该消息的内容根据不同的情况不同而不同,如果发送方是Config AppKey Add或者Config AppKey Update或者Config AppKey Delete

Config AppKey Get

该消息用于获取指定绑定的NetKey所对应的AppKey,其帧格式如下所示:

FieldSize(octets)Notes
NetKeyIndex2Index of the NetKey

由于NetKeyIndex是12bits,所以会填充至16bits,具体的应答消息内容如Config AppKey List所示。

Config AppKey List

该消息主要用于应答Config AppKey Get,其帧格式如下所示:

FieldSize(octets)Notes
Status1Status Code for the requesting message
NetKeyIndex2NetKey Index of the NetKey that the AppKeys are bound to
AppKeyIndexesvariableA list of AppKey indexes that are bound to the NetKey identified by NetKeyIndex

除此之外,该消息的内容根据不同的情况不同而不同,如果发送方是Config AppKey Get

相关出错的原因,如下表所示:

Error ConditionStatus Code Name
The AppKey identified by AppKeyIndex is already stored in the node and the new AppKey is differentKey Index Already Stored
The node cannot store the new key due to insufficient resourcesInsufficient Resources
The key identified by AppKeyIndex is not valid for this deviceInvalid AppKey Index
The key identified by NetKeyIndex is not valid for this deviceInvalid NetKey Index
The requested update operation cannot be performed due to general constraintsCannot Update
The NetKeyIndexAndAppKeyIndex combination is not valid for a Config AppKey Update messageInvalid Binding

Model to AppKey List

该状态用于阐述模型与AppKey的关系,也就是说模型绑定了哪些AppKey,怎么解绑,怎么获取绑定的内容等等。

Config Model App Bind

该消息用于在指定元素的情况下,将AppKey绑定至指定的模型;其具体的帧格式如下所示:

FieldSize(octets)Notes
ElementAddress2Address of the element
AppKeyIndex2Index of the AppKey
ModelIdentifier2 or 4SIG Model ID or Vendor Model ID

还有一点需要注意的是一个模型可以绑定多个AppKey,该消息的应答内容如Config Model App Status所示。

Config Model App Unbind

Config Model App Bind相反的操作,该消息是想要移除指定元素下的指定模型所绑定的AppKey,其具体的帧格式跟上述的Bind消息是一模一样的。

Config Model App Status

专门应答Config Model App BindConfig Model App Unbind消息:

FieldSize(octets)Notes
Status1Status Code for the requesting message
ElementAddress2Address of the element
AppKeyIndex2Index of the AppKey
ModelIdentifier2 or 4SIG Model ID or Vendor Model ID

返回的内容相比较于上述的消息,就是多了一个状态值用于指示BindUnbind的消息执行的结果,其中Status值除了0x00表示成功处理之外,还有如下几种情况:

Error ConditionStatus Code Name
The model identified by SIG Model ID or Vendor Model ID is not found for a given elementInvalid Model
The unicast address provided in ElementAddress is not used by the nodeInvalid Address
The key identified by AppKeyIndex is not stored in the nodeInvalid AppKey Index
The node cannot store new binding due to insufficient resourcesInsufficient Resources
The requested bind operation cannot be performed due to general constraintsCannot Bind

Config SIG Model App Get

该消息用于获取指定元素以及指定的SIG Model下,绑定了多少个AppKey;其应答消息如Config SIG Model App List所示,具体的帧格式如下表所述:

FieldSize(octets)Notes
ElementAddress2Address of the element
ModelIdentifier2SIG Model ID

Config SIG Model App List

用于应答Config SIG Model App Get消息,其帧格式如下所示:

FieldSize(octets)Notes
Status1Status Code for the requesting message
ElementAddress2Address of the element
ModelIdentifier2SIG Model ID
AppKeyIndexesvariableAll AppKey indexes bound to the Model

Config Vendor Model App Get

Config SIG Model App Get消息基本一样,只不过该消息获取的是Vendor Model下绑定的AppKey,其帧格式如下所示:

FieldSize(octets)Notes
ElementAddress2Address of the element
ModelIdentifier4Vendor Model ID

同样,该消息也是带应答的,具体的应答内容如Config Vendor Model App List所述。

Config Vendor Model App List

该消息只用于应答Config Vendor Model App Get,其帧格式的内容如下所示:

FieldSize(octets)Notes
Status1Status Code for the requesting message
ElementAddress2Address of the element
ModelIdentifier4Vendor Model ID
AppKeyIndexesvariableAll AppKey indexes bound to the Model

Node Identity

该状态的作用是配置是否使用Node Identity来广播 (可连接的非定向广播),其主要目的是当proxy node的Proxy Service在广播包中被暴露出来,可以根据proxy节点的首要元素的单播地址和该节点所属子网的网络密钥,来快速锁定想要连接的哪个proxy节点,尤其是周边有大量的节点的时候;其中,Node Identity有如下几种不同类型的值:

ValueDescription
0x00Advertising with Node Identity for a subnet is stopped
0x01Advertising with Node Identity for a subnet is running
0x02Advertising with Node Identity is not supported
0x03–0xFFProhibited

其中使用的比较多的一个实例就是:“如果Proxy Service在广播包中被暴露出来,那么当Provisioning Complete之后,节点会先主动断开,然后使用Node Identity来广播。这样provisioner就可以快速找到相对应的节点,从而可以更快速地完成配置”;这个时候,肯定会有不服的人站出来说:“为什么要搞这么复杂,我通过Mac address或者Device name也行啊”

因为这个在Spec已经强制规定好了,虽然Mac address和Device Name的确能起到一定的识别作用,但是貌似官方的这个规则更加精确定位且安全。接下来,让我们看看,Proxy Service暴露且使用Node Identity的广播包长什么样:

FieldSize(octets)Notes
Identification Type10x01 (Node Identity type)
Hash8Function of the included random number and identity information
Random864-bit random number

而上述的Hash值的计算公式如下所示:

Hash = e(IdentityKey, Padding || Random || Address) mod 2 64

其中:

而IdentityKey则是根据相对应的NetKey由下述的公式生成:

除了上述之外,这里还存在两种情况:

但是,不管是哪种情况,这两种情况的广播的持续时长均被限制在60杪;至于这两种类型的广播的广播间隔是多少则根据各大芯片原厂的不同而不同,Nordic Mesh SDK该值最小为200ms

Config Node Identity Get

显然,该消息用于获取节点当前子网的Node Identity状态,其帧格式如下所示:

FieldSize(octets)Notes
NetKeyIndex2Index of the NetKey

其中,NetKeyIndex填充的是当前子网所使用的NetKey的索引值。这是一个带应答的消息,具体的应答内容如Config NetKey Status

Config Node Identity Set

该消息用于设置节点当前子网的Node Identity状态,其帧格式如下所示:

FieldSize(octets)Notes
NetKeyIndex2Index of the NetKey
Identity1New Node Identity state

NetKeyIndex填充的值跟上述的Get是一样的,Identity填充的值则如Node Identity所述。

Config Node Identity Status

主要用于应答Config Node Identity Get以及Config Node Identity Set的消息,其帧格式如下所示:

FieldSize(octets)Notes
Status1Status Code for the requesting message
NetKeyIndex2Index of the NetKey
Identity1Node Identity state

对于Get消息而言,Identity域的值就是当前所对应子网的NetKey的节点的值,而Set消息则是设置后的值 (前提是该消息要被成功处理,否则没有该域的值)。其中Status除了success值为0之外,其他的值如下表所示:

Error ConditionStatus Code Name
The key identified by the NetKeyIndex is not valid for this deviceInvalid NetKey Index
The node cannot start advertising with Node Identity since the maximum number of parallel advertising is reachedTemporarily Unable to Change State

Config Node Reset

该消息就是将当前节点从Mesh网络中移除出去,其应答的消息为Config Node Reset Status。该消息没有携带任何参数,所以除了Opcode也就没什么其他的帧格式了。复位之后,Provisioner可以重复使用该节点的所有单播地址,但是还要重复使用Sequence Numbers则需要等IV Index更新之后 (比删除前的IV Index值大就行) 才能使用这些单播地址。这是为什么呢?

小编不知道看过BLE Mesh各层帧包格式详解的小伙伴们,对那个Replay Attack List还有没有印象;如果你重用这些地址和Sequence Numbers,如果IV Index又小于或者等于当前的IV Index的话,那么就很有可能被误认为这是一个Replay攻击而直接被节点丢弃。

Config Node Reset Status

用于应答Config Node Reset该消息,同样除了OpCode之外,不携带任何的参数。当Configuration Server用该消息应答之后,就会将自身保存的Mesh相关的数据从Flash中清除,然后断开连接并转换为Unprovisioned Device。

Key Refresh Phase

显然,该状态用于节点的NetKey列表中的NetKey以及其相对应绑定的AppKey的刷新,其中Config NetKey UpdateConfig AppKey Update就在密钥刷阶段过程中才会使用,该状态有如下几种取值:

ValueDescription
0x00Normal operation; Key Refresh procedure is not active
0x01First phase of Key Refresh procedure
0x02Second phase of Key Refresh procedure
0x03–0xFFProhibited

除了上述的取值之外,该状态还可以控制密钥刷新阶段的所有可能的转换,具体如下表所示:

Old StateTransitionNew StateDescription
0x000x030x00Transition 3 from Key Refresh Phase 0x00 does not cause any state change
0x010x020x02Transition 2 from Key Refresh Phase 0x01 moves to Key Refresh Phase 0x02
0x010x030x00Transition 3 from Key Refresh Phase 0x01 invokes Key Refresh Phase 3 and then moves to Key Refresh Phase 0x00
0x020x020x02Transition 2 from Key Refresh Phase 0x02 does not cause any state change
0x020x030x00Transition 3 from Key Refresh Phase 0x02 invokes Key Refresh Phase 3 and then moves to Key Refresh Phase 0x00

除了上述表格所述的阶段转换,其他的转换均由协议栈内部处理。到这里,小编估计读者应该有无数个疑问,什么是阶段1?什么是阶段2?密钥刷新又是什么鬼?etc....

在谈及以上问题时,我们先来说一说为什么要发起密钥刷新这一动作:

在继续培析密钥刷新之前,还有几处关键点需要读者们注意:

接下来,让我们正式开始讲解密钥刷新做了什么事情,又有哪几个步骤:

Phase0(正常工作模式)

阶段0表示当前节点处于正常的状态,密钥刷新程序没有被激活。

Phase1(派发新密钥)

Phase2(切换到新的密钥)

Phase3(摒弃旧的密钥)

不管采用哪种方式,只要此时节点收到进入密钥刷新阶段3的消息,那么就摒弃旧的密钥;接下来就开始全面使用新的密钥进行数据的收发,同时将当前的Key Refresh Flag以及Phase重置为0;此时,就算使用新的密钥但是Key Refresh Flag仍然为1的安全网络信标以及Friend Update消息均将被忽略;

至此,整个密钥刷新过程就彻底完成了;但是,在这个过程中还是有几点是需要注意的:

这个时候,我们再回过头来看看上述的状态转换表格以及流程图是不是又多了几分了解甚至全解。

Config Key Refresh Phase Get

有了上面的长篇大论铺垫,那么该消息显然就是为了获取指定NetKey的当前节点处于密钥刷新过程的哪个阶段,应答消息的内容如Config Key Refresh Phase Status所示;其帧格式如下所示:

ParameterSize(octets)Notes
NetKeyIndex2Index of the NetKey

Config Key Refresh Phase Set

该消息设置指定NetKey的密钥刷新进程,其应答消息的内容同样如Config Key Refresh Phase Status所示;其帧格式如下所示:

ParameterSize(octets)Notes
NetKeyIndex2Index of the NetKey
Transition1New Key Refresh Phase Transition

对于Transition域的内容,需要根据状态转换表格所示的来设置相对应的密钥刷新进程,由表格中可以看出,只能设置0x02、0x03而其他值均无效。

Config Key Refresh Phase Status

该消息是应答上述的Config Key Refresh Phase SetConfig Key Refresh Phase Get,其帧格式如下所示:

ParameterSize(octets)Notes
Status1Status Code for the requesting message
NetKeyIndex2Index of the NetKey
Transition1Key Refresh Phase State

这里需要注意的还是Transition域的内容,根据状态转换表格所示只能为0x00或者0x02;其中Status除了Success为0x00,其他的状态值如下所示:

Error ConditionStatus Code Name
The key identified by the NetKeyIndex is not valid for this deviceInvalid NetKey Index

Heartbeat Publication

该状态跟上述的Model Publication有些类似,只是该状态用于控制心跳消息周期地发送以及发送相关内容的配置;既然讲到心跳消息,那么我们先看看心跳消息长得啥样:

FieldSize(bits)Notes
RFU1Reserved for Future Use
InitTTL7Initial TTL used when sending the message
Features16Bit field of currently active features of the node

根据上述的内容,我们可以很明显地知道心跳消息有如下几个作用:

介绍完心跳包内容,那么继续接下来看看配置心跳包的相关参数:

讲完上述的心跳包格式以及其配置,那么我们看看捉包得到的心跳包是怎么样的,如下图所示:

其中,多出来了一个Directed Forwardeding域,在Specv1.0.1是没有明确指出,其有可能是v1.1的内容(v1.1应该会在2020年下半年发布)。

Config Heartbeat Publication Get

该消息就是为了获取当前节点的心跳包的配置参数,其应答的内容如Config Heartbeat Publication Status所述。

Config Heartbeat Publication Set

Get的操作相反,设置心跳包的配置参数,如下表所示:

ParameterSize(octets)Notes
Destination2Destination address for Heartbeat messages
CountLog1Number of Heartbeat messages to be sent
PeriodLog1Period for sending Heartbeat messages
TTL1TTL to be used when sending Heartbeat messages
Features2Bit field indicating features that trigger Heartbeat messages when changed
NetKeyIndex2NetKey Index

以上各域的具体含义,我在Heartbeat Publication中已经细述;但是这里我还是需要再一次强调Features的作用:

类似于一个开关,如果相对应的特性被置1了;那么,当这个被置1的特性的状态发生变化时就会触发心跳包的周期发送;这个跟节点本身是否支不支持该特性没有关系,因为如果某特性节点本身就不支持,那么就不可能存在特性变化的可能;但是,如果某特性节点本身是支持的,那么该域中所对应的其位域,用户可以根据实际情况选择是否要置1;

由上述的捉包图可知,该心跳包总共发4次且时间间隔为4秒:

Config Heartbeat Publication Status

该消息是响应上述的GetSet消息,具体的帧格式内容如下所示:

ParameterSize(octets)Notes
Status1Status Code for the requesting message
Destination2Destination address for Heartbeat messages
CountLog1Number of Heartbeat messages to be sent
PeriodLog1Period for sending Heartbeat messages
TTL1TTL to be used when sending Heartbeat messages
Features2Bit field indicating features that trigger Heartbeat messages when changed
NetKeyIndex2NetKey Index

其中Status除了Success是0x00之外,其余的取值如下所示:

Error ConditionStatus Code Name
The key identified by the NetKeyIndex is not valid for this deviceInvalid NetKey Index

下图是实际的捉包图:

Heartbeat Subscription

该状态跟上一章节的Heartbeat Publication是相反的动作;Heartbeat Publication用于节点周期发送心跳包,而Heartbeat Subscription用于接收节点周期发送的心跳包。同时,该状态有如下几个参数:

Config Heartbeat Subscription Get

该消息是获取节点心跳订阅配置的参数,具体的应答内容如Config Heartbeat Subscription Status所示。

Config Heartbeat Subscription Set

该消息是设置节点心跳订阅的内容,具体的帧格式如下所示:

ParameterSize(octets)Notes
Source2Source address for Heartbeat messages
Destination2Destination address for Heartbeat messages
PeriodLog1Period for receiving Heartbeat messages

各域的含义参考上述的Heartbeat Subscription所示;但是,这里有一点需要特别注意的是:当接收到这条Set消息时,伴随会将上述的Heartbeat Subscription Count设置为0x00,Heartbeat Subscription Max Hops设置为0x00,Heartbeat Subscription Min Hops设置为0x7F

Config Heartbeat Subscription Status

该消息只是用于应答上述的SetGet消息,具体的内容如下所示:

ParameterSize(octets)Notes
Status1Status Code for the requesting message
Source2Source address for Heartbeat messages
Destination2Destination address for Heartbeat messages
PeriodLog1Remaining Period for processing Heartbeat messages
CountLog1Number of Heartbeat messages received
MinHops1Minimum hops when receiving Heartbeat messages
MaxHops1Maximum hops when receiving Heartbeat messages

其中Status的取值如下表所示:

Status CodeStatus Code Name
0x00Success
0x01Invalid Address
0x02Invalid Model
0x03Invalid AppKey Index
0x04Invalid NetKey Index
0x05Insufficient Resources
0x06Key Index Already Stored
0x07Invalid Publish Parameters
0x08Not a Subscribe Model
0x09Storage Failure
0x0AFeature Not Supported
0x0BCannot Update
0x0CCannot Remove
0x0DCannot Bind
0x0ETemporarily Unable to Change State
0x0FCannot Set
0x10Unspecified Error
0x11Invalid Binding
0x12-0xFFRFU

Network Transmit

该状态与上述的Relay Retransmit极其相似,只不过该状态用于配置节点发送NetWork PDU时的次数以及相对应的时间间隔,分别对应的参数如下所示:

其中高3bit为Network Transmit Count,低5bit是Network Transmit Interval Steps;为了更好的阐述这个问题,让我们看看Network Transmit实际的情况是怎么样的:

小编将上图做了3个标记:

  1. 表示配置节点的Network Transmit Count为2,且Network Transmit Interval Steps为1;
  2. 根据1中的设置,那么最终的发送次数为3也就是图示的9包广播数据 (37,38,39三个信道为一次)
  3. 由1中的配置可知,最终的发送的时间间隔为20ms+(0-10)ms的随机时间

通过上述的实际捉包图与理论结合是不是已经完全ojbk了😄

Config Network Transmit Get

该消息用于获取当前节点的Network Transmit的配置参数,其应答内容如Config Network Transmit Status所示。

Config Network Transmit Set

该消息是设置节点的Network Transmit的配置参数,具体的帧格式如下所示:

FieldSize(bits)Notes
NetworkTransmitCount3Number of transmissions for each Network PDU originating from the node
NetworkTransmitIntervalSteps5Number of 10-millisecond steps between transmissions

该消息帧数据各域含义请参考Network Transmit中所述。

Config Network Transmit Status

该消息只用于应答上述的SetGet消息,其帧格式跟Config Network Transmit Set是一模一样的。

Configuration Client Model

该模型跟Configuration Server Model是一样的:

至于,该模型对应的状态和消息;小编在Configuration Server Model中已经详述,无非就是Client扮演的是配置Server的角色,而Server扮演的是接收Client的配置命令的角色;同样的消息在client端则是发往server,在server端则变成接收client的设置命令;基本上拥有配置Client模型的都是Provisioner,而Server模型的则是节点。它们两者的数据交互拓扑图如下所示:

注意:同时支持Client模型和Server模型的叫控制端模型

至此,Configuration Model相关的内容就讲解完毕;以上篇幅内容耗费小编近三周的时间,差点吐了一身老血。