Bluetooth Mesh Provisioning
Provisioning是將未配網設備加入到mesh網中的過程,該過程是通過provisioner來實現的。Provisioner向未配網設備提供provisioning 數據,其中包括network-key、當前網絡的IV_Index,還有設備每一個element對應的unicast地址。
provisioner可以是手機或者其他智能設備,一個mesh網中只需要一個provisioner角色,但是亦可以允許多個provisioner實現,多個provisioner共存時的數據共享可以被特定實現。
provisioning過程,首先需要在未配網設備和provisioner節點間建立一個provisioning-bearer。未配網設備向provisioner廣播自己的UUID以及其他必要信息。provisioner連續掃描消息,收到未配網設備的消息時,選擇與某一個對應的設備建立provisioning-bearer。
Provisioning-bearer建立后,provisioner與為配網設備間使用Elliptic Curve Diffie-Hellman (ECDH)協議加密。
Provision協議使用分層的結構,如上圖所示。設備的provision過程是通過發送provisioning-PDU實現的。provisioning-PDU通過generic provision layer層發往未配網設備。該層定義了provisioning-PDU是如何傳輸、分段重組的,傳輸包通過provisioning-bearer發送。provisioning-bearer定義了連接對話是如何建立的,即generic provision layer的傳輸包是怎樣被傳送到設備的。最后,在provision結構的最下層就是bearers。
Provisioning bearer layer
provisioning bearer layer實現了在provision過程中provisioning PDUs的傳輸。mesh協議中定義了兩種provisioning bearers
- PB_ADV
- PB_GATT
未配網設備可以支持PB_ADV或是PB_GATT,建議在未配網設備同時實現兩種bearer。provisioner至少支持一種,強烈建議provisioner支持PB-ADV。
PB-ADV
PB-ADV是一個provisioning bearer,是用來在advertising channel上使用Generic Provision PDUs來進行provision的。provision機制是基於對話(session)的。一個未配網設備一次只能支持一個對話(session),而對於provisioner則無此限制。
PB-ADV用來傳輸Generic Provisioning PDUs,PB-ADV bearer最大的傳輸單元(Maximum Transmission Unit, MTU)是24個字節。
支持PB-ADV的設備應該以占空比100%的頻率掃描消息,以免丟失Generic Provision PDUs。
PB-ADV PDU 消息包的格式如下:
Feild | Size | Description |
---|---|---|
Length | 1 | length of the pb-adv PDU |
AD type | 1 | PB_ADV |
contents | 可變 | PDB-ADV PDU |
其中PB-ADV PDU格式如下:
Field | Size | Description |
---|---|---|
LInk ID | 4 | 一個link的標識符 |
Transaction Number | 1 | The number for identifying a transaction |
Generic Provisioning PDU | 1-24 | Generic Provisioning PDU being transferred |
LinkID 用來表示兩個設備之間的一個連接。
Transaction Number 包含一個1-byte的值,用來表示每個Generic Provisioning PDU, 如果Generic Provisioning PDU經過了分段,則每個分片的Transaction Number 都是相同的。而且當Generic Provisioning PDU重發時,該值也是不變的。
在實現時還需要遵循以下幾條規則:
- 當PB-ADV PDU包含Provisioning Bearer Control PDU時, Transaction Number應該設置為0.
- 當一個Provisioner通過一個打開的provision link,首次發送Provisioning PDU時,Transaction Number 的值應該從0x00開始,每發送一個Provisioning PDU該值累加。當到達0x7F時,返回的0.
- 當未配網設備通過一個打開的provisin link首次發送PDU時,Transaction Number的值應該從0x80開始,每發送一個provisioning PDU累加1.當到達0xFF時,返回到0x80.
- 當一個設備收到provisioning PDU時,將會根據收到包的Transaction Number值來設置該值。
- 當一個設備發送Transaction響應PDU時, Transaction Number 值應該設置為其響應的那條消息的 Transaction Number 值。
PB-GATT
PB_GATT是通過Proxy PDU來provision的bearer,PB-GATT是用來支持那些不支持PB-ADV的provisioner的而實現的bearer.
關於GATT不太理解,后續在做整理。
Generic Provisioning PDU
Generic Provisioning PDU包含兩部分,一部是Generic Provisioning Control(GPC)field, 緊接着是Generic Provisioning Payload。
Generic ProvisionIng Control field的最低兩位包含一個Generic Provisioning Control Format (GPCF)field,該值決定了PDU的類型。
Value | Description |
---|---|
0b00 | Transaction Start |
0b01 | Transaction Acknowledgement |
0b10 | Trabsaction Continue |
0b11 | Transaction Bearer Control |
Generic Provisioning PDU
Transaction Start PDU
Transaction Start PDU 用來開始一段分段消息傳輸,其格式如下:
Transaction Acknowledgment PDU
Transaction Acknowledgment PDU用來響應一個Provisioning PDU
該PDU只包含一個字節,如下所示:
此時Generic Provisioning Payload的長度是0.
Transaction Continuation PDU
Transaction Continuation PDU用來傳輸后續的provisioning PDU,其結構如下所示:
SegmentIndex是分段消息的index(從0開始)
GPCF為0b10
Generic Provisioning Payload 包含Provisioning PDU分段索引為SegmentIndex的內容。
Provisioning Bearer Control
Provisioning Bearer Control PDU用來管理bearer上的額對話(session),其格式如下:
Link Open Message
該消息用於打開一個連接,該消息需要使用Link-ACK-message來響應。
一個設備一次只能處理一個連接,當一個連接處於活動狀態時,會忽略其他的Link-Open-message.
Link_Open_message消息的參數是需要建立連接的設備的UUID,如下所示:
Link ACK message
該消息用來響應Link-Open-message,沒有參數,只有一個字節,如下所示:
Link Close message
該消息同來關閉一個連接,由於該消息是沒有響應的,因此發送端需要重復發送該消息至少三次,連接兩端都可以發送該消息,並處理該消息。
該消息的參數域描述關閉連接的原因,其結構如下:
| Field | Size | Description |
| - | - |
| Reason | 1 | The reason for closing the link |
其值為:
Value | Reason | Notes |
---|---|---|
0x00 | success | provisioning successful |
0x01 | Timeout | provisioning transaction timed out |
0x02 | Fail | The provisioning failed |
0x03 - 0xFF | Unrecognized | 未定義 |
Link Establishment procedure
Link Establishment procedure 用於建立一個對話(session), 一個對話用Link ID 標識,在連接過程中該值不會變化。LinkID需要隨機生成,以避免多個對話間沖突。
連接建立時,未配網設備使用UUID標識,Provisioner掃描未配網設備的廣播,然后provisioner發起Link-Open-message來建立連接。Link-Open-message中包含了未配網設備的UUID。在PB-ADV上的PB-ADV PDU包含了連接的Link ID.
對於一個沒有配網並且已經收到了Provisioning Invite PDU的設備,當其周到一盒Link Open messsage時,會響應該消息返回一個帶有相同LinkID的Link ACK message.
連接可以在任何時候通過發送Link Close message來關閉,連接的兩端都可以發送該消息。
連接建立的流程可以用下圖表示:
Generic Provisioning behavior
每個Generic Provisioning PDU發送時,要與上一個PDU有一個20~50毫秒的隨機延時。
每個Provisioning PDU都應該作為一個獨立的消息包,每個消息包由一個或多個分段組成。
Provisioning PDU被分段的數量,取決於該PDU的大小,segment Index可以是0~63之間的數。segment 0 應該使用Transaction Start PDU來發送。其他的分段應該使用Transaction Continue PDU來發送。每個分段都被放入Generic Provisioning Payload中。
每個bearer都有一個MTU最大值限制,每個Generic ProvisionIng PDU都應該是最長的MTU長度,最后一個分段除外。
發送端需要順序發送每個分段,如果發送端沒有收到回應,那么發送端會重發整個PDU的所有消息。
若果發送端收到了Transaction Acknowledgement message,則表示傳輸成功。
如果發送端在發送第一條消息后30秒內,沒有收到Transaction Acknowledgement message,則發送端會取消傳輸,終止provision過程,關閉link。
接收端會根據Transaction Start PDU中的內容,判斷分段的個數。
在PB-ADV bearer中,當接收端收到了所有的分段,它會計算收到Provisioning PDU的FCS,如果該值符合Transaction Start PDU中的FCS值,那么接收端就會在一個20~50毫秒的人隨機延時之后,發送一個Transaction Acknowledgement PDU。