目录

1、Timing

2、建立 Friendship

2.1、大致过程

2.2、关键细节分析

2.2.1、Friend Request

2.2.2、Friend Offer

2.2.3、Friend Poll

2.2.4、Friend Update

2.2.5、建立过程图示

3、建立 Friendship 后

4、Friend-LPN 消息交互

4.1、Poll 消息

4.2、LPN 接收消息例子

4.3、LPN 发送消息例子

5、Friend-LPN 管理

5.1、Friend Subscription List Add

5.2、Friend Subscription List Remove

5.3、Friend Subscription List Confirm


 

在 BLE mesh 网络中存在一种节点,低功耗是他的主要功能(长时间维持,上电池的类型),它长时间处于休眠状态,偶尔(一天,几天)醒来发送(接收)一次消息(这里称之为 Poll 机制),这样的节点定义为 LPN(Low Power Node),他不能单独存在,必须依附于一个称之为 Friend Node 的玩意,Friend Node 为其所依附的 LPN 缓存消息,待 LPN 醒来后,与其进行交互;

BLE mesh 中,定义了一些 Friend Node 与其 LPN 之间的交互规则,这章我们就来看看他们的具体交互规则以及相应的交互;

注意,这里讨论的交互,已经默认的 Friend 和 LPN 均已入 mesh 网,具体的入网流程,后续章节详细介绍;

 

1、Timing

mesh 的 Spec 定义了 Friend Node 与 LPN 之间的交互时序,交互时序中,引入了三个参数来表达:

1、ReceiveDelay:定义了 LPN 从发送请求到开窗接收对方 Response 的时间;

2、ReceiveWindow:定义了 LPN 开窗接收对方 Response 的时间;

3、PollTimeout:定义了 LPN 的连续发送两个 request 的时间,如果 Friend Node 在超过 PollTimeout 还没收到 request 的话,那么 friendship 将会认为被终止;

文字介绍总是那么枯燥难懂,直接上图:

针对 ReceiveDelay 和 ReceiveWindow 两个参数的解释为:

BLE Mesh (8) —— Friendship

一眼看穿,LPN 发送 Request 后,等 ReceiveDelay 时间,开始开窗持续 ReceiveWindow 时间,然后 sleep;

针对 PollTimeout 解释为:

BLE Mesh (8) —— Friendship

定义了 LPN 的连续发送两个 request 的时间,如果 Friend Node 在超过 PollTimeout 还没收到 request 的话,那么 friendship 将会认为被终止;

 

2、建立 Friendship

注意:所有的由 Friend node 发起的 transport control messages 全部都是 Unsegment Control messages;同时,他的 SRC 字段都是该 Friend node 的 primary element 的单播地址;

2.1、大致过程

1、针对 LPN 这端,如果期望建立 Friendship,那么他的行为是:向空中发送 Friend Request 请求(地址类型是 all-friend

2、如果一个节点支持 Friend feature 同时开启了这个 feature 的话,那么当他接收到 Friend Request 消息的时候,代表有 LPN 向他发出了申请 Friend 的请求,此刻该 Friend Node 回复一个 Friend Offer 消息;

3、LPN 收到众多(也可能是一个)的带 Friend feature 的节点发送的 Friend Offer 消息后,选择其中希望建立 Friendship 的,使用 Friend Poll 进行应答;

4、接收到 LPN 的 Friend Poll 应答后,Friend 节点回复 Friend Update,正式建立友谊;

BLE Mesh (8) —— Friendship

2.2、关键细节分析

2.2.1、Friend Request

上述流程,对于期望对整个过程大致了解的情况来说,已经够了,接下来看看 Friendship 建立中更细节的部分;

首先是 LPN 来说,他会空中发起 Friend Request 请求,如果不建立友谊,单单一个 LPN 是没有意义的,所以急切的建立友谊对它来说十分有意义;

前面的章节说过,Friend Request 请求是一个 Control message,展开这个 Control message 的包体看到的是这样一个结构:

BLE Mesh (8) —— Friendship

接下来每个字段分析:

1、Criteria 字段:1个字节,Friend node 应该支持的标准,用于建立友谊的时候的交互

他包含的内容如下:

BLE Mesh (8) —— Friendship

Criteria 字段包含了:

1、RSSIFactor:由 LPN 指定的 RSSI 计算因子,为 Friend node 提供基于 RSSI 的 Friend Offer Delay 的计算输入;

2、ReceiveWindowFactor:由 LPN 指定的 Receive Window 计算因子,为 Friend node 提供基于 Receive Window 的 Friend Offer Delay 的计算输入;

3、MinQueueSizeLog:期望的 Friend Queue 中能够存储的最少的消息数量;

RSSIFactor 和 ReceiveWindowFactor 用于 Friend node 计算 Friend Offer Delay ,所以这里有必要介绍一下他的原理;

在建立友谊的时候呢,最终决定和哪个建立起友谊的,是 LPN,也就是当 LPN 发起 Friend Request 请求,Friend 回复(可能多个 Friend node)Friend Offer 消息,即,Friend 给了 Offer,那么 LPN 到底要不要接受,或者接受哪个 Friend 和他建立友谊呢?这个是 LPN 说了算,他会精打细算后,和他最想要的那个 Friend 建立友谊,并向其发送 Friend Poll ;那么这个精打细算的准则是什么?由两个因素构成:

1、Receive Window

2、RSSI

有些 LPN 希望 Friend node 有一个很小的 Receive Window,这样交互起来,更快(几下发完),能够使得 LPN 更省电;

有些 LPN 希望 RSSI 信号更好的进行交互,更加可靠;

所以,RSSIFactor 和 ReceiveWindowFactor 用于表征了一个 LPN 希望 RSSI 和 Receive Window 哪个更被本 LPN 看重!也算是一个权重值:

BLE Mesh (8) —— Friendship

接下来解释下 Friend Offer Delay 的定义:

当 Friend 收到 Friend Request 请求后,和发送 Friend Offer 之间的时间间隔称之为 Friend Offer Delay ;

当 Friend 接收到 Friend Request 请求后,便知道了 LPN 的 RSSIFactor 和 ReceiveWindowFactor 期望权重,然后会使用本地 Friend 实际支持的 Receive Window 和接收到 LPN 的 Friend Request 请求的 RSSI 值来计算这个 Friend Offer Delay 公式如下:

 

Local Delay = ReceiveWindowFactor * ReceiveWindow - RSSIFactor * RSSI

在计算完这个 Friend Offer Delay 后,延时 Friend Offer Delay 时间,给 LPN 发送 Friend Offer 消息;

 

2.2.2、Friend Offer

这次轮到 Friend 发起消息了,前面说了,LPN 可能看重 Receive Window 和 RSSI 的值,那么 Friend 只能老老实实告诉 LPN 它能够支持的 Receive Window 和 它上次收到 LPN 的 Friend Request 的包的 RSSI 值,与此同时, Friend 还需要给出自己还有多少可以用于缓存消息能力以及他支持的的订阅消息的能力,所以 Friend Offer 的包组成为:

BLE Mesh (8) —— Friendship

 

2.2.3、Friend Poll

好了,当接 LPN 收到 Friend Offer 后,它便会选择和哪个 Friend 建立友谊,选择好后,向它发送 Friend Poll 消息:

BLE Mesh (8) —— Friendship

可以看到,有一个 FSN 的字段,这个字段用于在真正 Poll 消息的时候的重传机制,在建立 Friendship 的流程的回复包中,这个字段强制为 0

 

2.2.4、Friend Update

最后 Friend 发送 Friend Update,来告知此次建立成功

BLE Mesh (8) —— Friendship

 

2.2.5、建立过程图示

BLE Mesh (8) —— Friendship

这个例子的解说如下:

A、首先 LPN ,也就是最左边的那个玩意,希望建立一个 Friendship 来搞事情,所以他向空中发送 Friend Request;

B、当前 mesh 网络中,有 3 个 Friend,分别是 Friend 1、Friend 2、Friend 3

C、Friend 1、Friend 2、Friend 3 都收到了 LPN 的 Friend Request,开始根据自身情况计算 Delay,并回复 Friend Offer

D、LPN 收到了 3 个 Offer 后,自己选,选择了 Friend 2,并发送 Friend Poll

E、对端回复 Friend Update 正式建立友谊

 

3、建立 Friendship 后

LPN 和 Friend 建立友谊后,Friend node 方面会初始化一个 Friend 订阅列表,并且将其初始化为 0,同时开始为刚刚建立好友谊的 LPN 存储消息(在 Friend Queue);

在建立友谊之初,Friend A 收到来自 LPN 的 Friend Request 的时候,Friend Request 中带了一个 PreviousAddress 字段,这个 PreviousAddress 字段代表了上次与此 LPN 建立友谊的那个 Friend 地址(可能是 Friend A,也可能是其他的 Friend X);

在与 Friend A 建立友谊了后,如果 Friend A 发现这个 LPN 之前发送 Friend Request 的时候的那个 PreviousAddress 字段不是自己,那么这个 Friend A 就要做一些清理工作:给之前和这个 LPN 建立 Friendship 的那个 Friend X 发送消息,让他死心;

同样,同图解来说明问题:

BLE Mesh (8) —— Friendship

这个例子的解说如下:

A、首先 LPN ,已经和 Friend 1 完成了友谊的建立;

B、LPN 会定期的 Poll 消息,Friend 1 回复 Friend Update;

C、Friend 1 断电了;

D、LPN 去 Poll 消息,一直没得到应答,此刻,LPN 认为与 Friend 1 之间的友谊断开了(的确是断开了);

E、那么为了活下去,LPN 迫不及待找来了 Friend 2,并与 Friend 2 建立了新的友谊;

F、但是在与 Friend 2 建立友谊的时候,Friend Request 中的 PreviousAddress 字段,却是 Friend 1 的单播地址;

G、Friend 2 知道这个 LPN 之前与 Friend 1 有过瓜葛,显然不能就此作罢,便一直向单播地址为 Friend 1 的节点发送 Friend Clear 消息

H、一直到 Friend 1 醒来,发现了有人(Friend 2)通过 Friend Clear 告诉他  “你之前的 LPN 已经属于我了”

I、Friend 1 也无奈,回复 Friend 2 一个 Friend Clear Confirm 告诉 Friend 2,“我知道了,LPN 送给你把”,我不和他友谊了

J、谁知 Friend 2 耳朵不好使,没听到 Friend Clear Confirm 消息,继续发 Friend Clear 给 Friend 1 说:“你的 LPN 是我的啦,你的 LPN 是我的啦”

K、Friend 1 通过 Friend Clear 对 Friend 2 大声的说:“知道了”

L、Friend 2 听到了 Friend 1 气愤的回复(Friend Clear Confirm 消息),便收敛了,不在发送 Friend Clear 消息

 

4、Friend-LPN 消息交互

当 Friend-LPN 建立完成友谊后,便可以进行正常数据交互了;

1、对 LPN 端,可以休息了,定期起来 Poll 一下消息,看看有没有人给他发消息;

2、对 Friend 端,不准休息,一直将发送给他的友谊的 LPN 缓存消息到 Friend Queue,等待 LNP 来 Poll 消息

4.1、Poll 消息

当 LPN 醒来后,便开始使用 Friend Poll 包向 Friend 来 Poll 消息;

Friend Poll 包中包含一个 1 bit 的 FSN 字段:

BLE Mesh (8) —— Friendship

这个 FSN 字段用于重传,即,如果 Friend 收到和上一个 Friend Poll 消息一样的 FSN 的话,那么便重传上一个消息,否则发送下一条消息;

而且在 Friend Poll 消息中,TTL 都应该被设置成为 0;

消息在 Friend 中的组织是以 FIFO 的形式,即,总是先发送最早接收到的消息;

Friend 收到 Friend Poll 消息后,需要在最小的 ReceiveDelay 之后,最大的 ReceiveDelay + ReceiveWindow 之前进行消息的发送:即

[ ReceiveDelayReceiveDelay + ReceiveWindow ]

如果在 PollTimeout 的定时器到期的时候,Friend 还没有收到任何来自其 LPN 的任何消息:

Friend Poll 

Friend Subscription List Add

Friend Subscription List Remove

那么 Friend node 将会认为,友谊终止,同时丢弃所有为该 LPN 缓存的所有消息;

有一个默认的规则,就是,当 Friend Poll 后,除非收到对方发送的 Friend Update 中的 MD 字段(More data)为 0,否则,需要一直 Poll 消息,MD 也就是指明了,Friend node 当前的 Friend Queue 中还缓存着对这个 LPN 的消息;

 

4.2、LPN 接收消息例子

当 LPN 周期性唤醒后,向 Friend Poll 消息,消息可能是分段的(Segment)也可能是不分段的(Unsegment):

BLE Mesh (8) —— Friendship

上面的例子中,进行分解:

1、首先,Node A 发送分段的消息给 LPN(3段消息0,1,2),SegMsg 0/2 没被收到,SegMsg 1/2 也没被收到,SegMsg 2/2 被 Friend Node 收到了,由于是分段的消息,需要被 ACK,所以 Friend node  ACK 了,其中 OBO =1 代表为 LPN 缓存;

2、此刻 LPN 来 Poll 消息,因为分段消息只收到一段,所以 Friend node 并没有发送给 LPN,直接回复了 Friend Update,关闭此次 Poll;

3、Friend node 收到了 SegMsg 0/2,并没有直接 ACK(因为有 Timer),只是把消息缓存了,然后对应的 BlockAck 标记起来;

3、Friend node 收到了来自 Node B 发送给 LPN 的未分段消息 UnsegMsg,把它缓存下来,并不予应答;

4、Node A 发送分段的消息 SegMsg 1/2 ,Friend 又没收到;

5、此刻 Friend 的 ACK Timer 到期,回复给 Node A 他已经接收到的情况为 ACK(0,2) 同时 OBO = 1

6、LPN 醒来,开始 Poll 消息,因为分段的消息并未收完,所以暂时不会 Poll 到分段的消息,但是未分段的消息 UnsegMsg 是已经缓存了的,所以回复给 LPN UnsegMsg;然后 LPN 再次 Poll,此刻 Friend 已经没有消息给 LPN 了,所以回复 Friend Update,同时 MD(More Data)为 0;

7、由于 Node A 收到了 Friend 的 ACK(0,2),知道对方还差 SegMsg 1/2 ,所以,便针对性的再次发送 SegMsg 1/2;

8、这次 Friend 终于接收到了 SegMsg1/2 ,回复 ACK(0,1,2) 同时 OBO = 1;此刻所有的分段包都收到了,而且 Node A 也知道了

9、当 LPN 再次苏醒的时候去 Poll 消息,Friend 便开始给 LPN 传输消息,传输消息的顺序和 Friend node 收到 SegMsg 的顺序一致,即先发 SegMsg 2/2、在发 SegMsg 0/2、最后发 SegMsg 1/2;交互中,为了使得每次 LPN 都收到的消息可靠,全靠 Poll 的 Control 包 FSN 字段进行翻转;同时,由于分段的包有 3 包,根据 Spec 的规则,一次要 Poll 到没有缓存了为止(MD = 0),所以此刻 LPN 不会进入休眠;

10、当 Friend 全部发完了后,LPN 在次 Poll ,发现 Friend 回复了,Friend Update (MD=0)代表已经没有包了;此次交互完成!

 

4.3、LPN 发送消息例子

LPN 可以接收消息,当然也可以发布消息,打个比方:

BLE Mesh (8) —— Friendship

1、LPN 对 Node A 发布未分段的消息 SegMsg 0/2,SegMsg 1/2,SegMsg 2/2,发完,赶紧睡下去了;

2、Node A 只接收到了 SegMsg 0/2,SegMsg 2/2,没有收到 SegMsg 1/2,他 ACK(0,2) 给 LPN,当然,消息会被 Friend node 缓存;

3、LPN 醒了,首先问 Friend node(Poll 消息)有没有消息,当然,Friend 立马将之前 Node A 发的 ACK(0,2) 发给了 LPN,然后 LPN 继续 Poll,没有消息了, Friend 答复 Friend Update(MD=0)

4、LPN 根据 ACK(0,2),知道 Node A 收到了 0 和 2,所以立马发一个 SegMsg 1/2 ,然后睡下去;

5、LPN 睡下去的时候,Node B 又给他发来 UnsegMsg,被 Friend 缓存,同时 Node A 收到了 LPN 的 SegMsg 1/2 ,回复了 ACK(0,1,2) 表示都收到了,同样被 Friend 缓存;

6、此刻,LPN 醒了,照例找 Friend Poll 消息,由于 UnsegMsg 是先进的,所以先 Poll 到了 UnsegMsg,然后继续 Poll,接着 Poll 到了 ACK(0,1,2) ,由此知道了 Node A 已经接收完了所有分段消息,然后继续尝试 Poll,此刻已经没有缓存的消息了,所以 Friend 回复了 Friend Update(MD=0)

 

5、Friend-LPN 管理

5.1、Friend Subscription List Add

在建立完 Friend-LPN 之间的友谊后,Friend 便可以持续为 LPN 缓存消息了;

LPN 随时也可以发送 Friend Subscription List Add 消息,来为 Friend node 添加更多的 group/virtual 地址订阅:

BLE Mesh (8) —— Friendship

其中的 TransactionNumber 用于区分每个单独的事务

AddressList 是需要添加到订阅消息列表的 group 或者 virtual 地址

注意:这是一个 Control message,如果是 Unsegment message 的话,一次不能添加超过 5 个地址

TTL 字段被设置成为 0

 

5.2、Friend Subscription List Remove

LPN 可以发送 Friend Subscription List Remove 消息,来告诉 Friend node 从订阅列表中,取消指定 group 或者 virtual 地址;

BLE Mesh (8) —— Friendship

说明与 5.1 章节一样,不在多说;

 

5.3、Friend Subscription List Confirm

用户 Friend 在收到 Friend Subscription List Add 和 Friend Subscription List Remove 后,进行应答;

BLE Mesh (8) —— Friendship

 

相关文章: