1. 程式人生 > >認識BLE 5協議棧 —— 屬性協議層

認識BLE 5協議棧 —— 屬性協議層

轉自  http://www.sunyouqun.com/2017/04/understand-ble-5-stack-attribute-protocol-layer/


 

屬性協議(Attribute Protocol)簡稱ATT。

ATT層定義了屬性實體的概念,包括UUID、控制代碼和屬性值等,也規定了屬性的讀、寫、通知等操作方法和細節,這些與屬性操作相關的內容稱為屬性協議。ATT層規定了ATT_MTU值,如果屬性值很長,超過了ATT_MTU限制,將使用特殊的讀寫方法進行操作。

基於ATT層,可以構建出通用屬性操作規範。

1. 屬性

在藍芽協議中, 屬性是指一個數據實體,它包含識別符號,控制代碼,資料內容,訪問許可權,安全問題等。

屬性協議規定了屬性的發現和讀寫訪問的方法。

1.1 型別

屬性型別由一個UUID(Universally Unique Identifier)表示。UUID是指從時間尺度和空間尺度都具有唯一性的一串128-bit的數字,該數字串在全球範圍內不會重複,並且在未來也不會出現重複。

一個典型的16位元組UUID格式為XXXX-XX-XX-XX-XXXXXX。

藍芽協議設定了一個藍芽基礎UUID: 00000000 – 0000 – 1000 – 8000 – 00805F9B34FB。

利用該基礎UUID,可以使用16-bit或32-bit的UUID來代替128-bit的UUID,當傳遞到對端裝置,再還原成128-bit的UUID。

假如16-bit的UUID為YYYY,則還原後的128-bit的UUID為:0000YYYY – 0000 – 1000 – 8000 – 00805F9B34FB。

假如32-bit的UUID為YYYYYYYY,則還原後的128-bit的UUID為:YYYYYYYY – 0000 – 1000 – 8000 – 00805F9B34FB。

ATT層支援使用16-bit和128-bit兩種UUID,32-bit的UUID在使用前必須轉換成128-bit。

1.2 控制代碼

屬性控制代碼猶如指向屬性實體的指標,對端裝置通過控制代碼來訪問該屬性。

屬性控制代碼是一個2位元組數,有效範圍為0x0001-0xFFFF。

屬性控制代碼為有序排列,後面的控制代碼值會大於前面的控制代碼,通常下一個屬性的控制代碼值是上一個屬性的控制代碼加1。

1.3 分組

多個屬性可以合成一組,一組屬性包含的引數為:開始控制代碼、結束控制代碼。

1.4 值

屬性值可以是一個數字或一個字串。屬性值的長度資訊不包含在PDU中,所以需要從PDU的長度間接推算出屬性值的長度資訊。

屬性值通常在一個PDU中傳送,如果屬性值太長,也可以分成多個PDU進行傳送。

1.5 許可權

屬性的讀寫許可權由ATT層之上的協議層規定,有效的讀寫許可權包括:可讀、可寫、讀寫。

在讀寫屬性之前,客戶端裝置還需要具有足夠的安全許可權,包括:

  • 加密許可權:需要加密、無需加密
  • 認證許可權:需要認證、無需認證
  • 授權許可權:需要授權、無需授權

如果許可權不足,將觸發錯誤處理機制。

1.6 控制點屬性

控制點屬性是一類特殊屬性,它不可讀,只能寫。

1.7 協議方法

對屬性的操作稱為協議方法,包括:命令(Command),請求(Request),響應(Response),通知(Notification),指示(Indication)和確認(Confirmation),某些屬性PDU還涉及授權簽名方法。

1.8 交換MTU Size

ATT_MTU表示ATT層間傳輸的資料包的最大長度。兩端裝置可以通過Exchange MTU Request/Response進行交換MTU。

1.9 長包屬性

對於讀屬性的資料包,最大長度為(ATT_MTU-1)個位元組。其中減去的1表示1位元組的操作碼。

對於寫屬性的資料包,最大長度為(ATT_MTU-3)個位元組。其中減去的3表示1位元組的操作碼和2位元組的屬性控制代碼。

如果資料包超過這個長度,則稱為長包屬性。

讀長包屬性,需要使用Read Blob Request,寫長包屬性,需要使用Prepare Write Request和Execute Write Request。

如果使用普通Read操作讀長包屬性,僅能讀取前(ATT_MTU – 1)個位元組,使用普通Write操作寫長包屬性,僅能寫前(ATT_MTU-3)個位元組。

無論普通屬性還是長包屬性,屬性值的最大長度均為512位元組。

1.10 原子操作

一個請求或一個命令,稱為一個原子操作。一個原子操作結束後,才能進行新的原子操作。

讀寫長包屬性無法在一個原子操作內完成。

2. 屬性PDU

2.1 屬性角色

在ATT層協議框架內,擁有一組屬性的裝置稱為服務端(Server),讀寫該屬性值的裝置稱為客戶端(Client)。

2.2 分類

屬性PDU有六類:

屬性PDU 方向 觸發響應
Command Client -> Server
Request Client -> Server Response
Response Server -> Client
Notification Server -> Client
Indication Server -> Client Confirmation
Confirmation Client -> Server

屬性PDU格式如下:

欄位 Opcode Parameter Authentication Signature
長度 1 octet 0 – (ATT_MTU-X) octets 0 or 12 octets

其中Opcode的第0-5位表示該屬性的具體型別,第6位表示命令標誌位,如果該位為1,表示該操作碼對應一個命令,最後1位表示認證簽名(Authentication Signature)標誌位,如果該位為1,表示該PDU的最後一個欄位中包含12位元組的認證簽名。

Parameter欄位中包含了引數,其長度為0支ATT_MTU-x,如果認證簽名位為1,則此處x等於13,否則等於1。

只有寫命令才需要認證簽名,其他命令不需要。此外,如果鏈路已經進行加密,則屬性PDU中也無需額外新增認證簽名。

2.3 操作順序

對於Request和Indication屬性,需要接收端返回響應。在發出Request和Indication後,收到響應之前,不能發出新的Request和Indication。

對於其他無需響應的屬性,則可以在自由傳送,但是不保證接收端一定能夠收到和執行。

可以在Request和Response之間,或Indication和Confirmation之間傳送其他無需響應的屬性。

2.4 事務

一個Request-Response對,或Indication-Confirmation對,稱為一個事務。

對於客戶端裝置而言,發出Request或收到Indication表示事務的開始,收到Response或返回Confirmation表示事務的結束。

對於服務端裝置而言,發出Indication或收到Confirmation表示事務的開始,收到Confirmation或返回Response表示事務的結束。

3. 屬性協議PDU

屬性協議規定了多種Request-Response對,請求屬性由客戶端裝置發出,響應屬性由服務端裝置發出。

3.1 錯誤處理

Opcode PDU
0x01 Error Response

如果屬性PDU的操作碼無效,或屬性控制代碼無效,將返回錯誤響應PDU。在PDU的Parameter欄位中,包含了錯誤編碼。

3.2 交換MTU

Opcode PDU
0x02 Exchange MTU Request
0x03 Exchange MTU Response

客戶端裝置向服務端裝置傳送交換MTU請求,提供客戶端裝置的MTU值。服務端裝置獲知客戶端的MTU值,並返回自己的MTU值。兩端裝置都將設定較小的MTU值作為新的MTU值。

如果兩端裝置沒有交換MTU,則使用預設的MTU值(BLE下為23)處理屬性事務。

3.3 查詢資訊

PDU Opcode
0x04 Find Information Request
0x05 Find Information Response
0x06 Find By Type Value Request
0x07 Find By Type Value Response

查詢資訊請求,包含兩個引數:起始屬性控制代碼和結束屬性控制代碼,用於獲取服務端裝置屬性控制代碼處於該引數區間內的屬性。

查詢資訊響應,包含指定控制代碼區間內的屬性UUID。如果區間內有多個屬性,則返回多個響應。

按型別值查詢請求,是在查詢資訊請求的基礎上,加上了屬性型別和屬性值兩個引數,這樣能夠更加精確的找到目標屬性。

按型別值查詢響應,包含了滿足條件的屬性控制代碼列表。

3.4 讀屬性

Opcode PDU
0x08 Read By Type Request
0x09 Read By Type Response
0x0A Read Request
0x0B Read Response
0x0C Read Blob Request
0x0D Read Blob Response
0x0E Read Multiple Request
0x0F Read Multiple Response
0x10 Read by Group Type Request
0x11 Read by Group Type Response

按型別讀請求,包含三個引數:起始屬性控制代碼、結束屬性控制代碼和屬性型別。

按型別讀響應,包含了滿足條件的屬性的“控制代碼-值”對的列表。

讀請求,包含一個引數:屬性控制代碼。

讀響應,返回滿足條件的屬性值。

讀片段(blob)請求,用於讀取一個長包屬性的值,它包含兩個引數:屬性控制代碼和偏移量。以不同的偏移量作為引數,多次執行該請求可以讀取長包屬性的完整值。

讀片段響應,包含了長包屬性值的指定偏移量片段。

讀多次請求,用於讀取多個給定控制代碼的屬性值,它包含一個引數:控制代碼列表。

讀多次響應,包含了多個指定控制代碼的屬性值。

按組型別讀請求,用於讀取指定組型別的屬性值,組型別是由ATT層之上的協議層設定的。它包含三個引數:起始屬性控制代碼、結束屬性控制代碼和屬性組型別。

按組型別讀響應,包含了滿足條件的屬性值列表。

3.5 寫屬性

Opcode PDU
0x12 Write Request
0x13 Write Response
0x14 Write Command
0x15 Signed Write Command

寫請求,將待寫數值寫入指定的屬性值,包含兩個引數:屬性控制代碼和數值。

寫響應,表示寫請求執行成功,不含任何引數。

寫命令,將待寫數值寫入指定的屬性值,包含兩個引數:屬性控制代碼和數值。它不會觸發一個寫響應。

簽名的寫命令,與上面的寫命令類似,指示包含了額外的引數:認證簽名。典型應用是寫控制點屬性。

3.6 佇列寫屬性

佇列寫是指利用一個先進先出的佇列,快取多個屬性值的寫操作,然後在一個原子操作中完成所有的值寫入操作。

佇列寫專門用於長包屬性的寫操作,現將一個長資料分成多個部分並記錄偏移量,然後通過佇列快取,等資料傳送完畢,再按照收到的順序,一次性將整個長資料寫入屬性值。

Opcode PDU
0x16 Prepare Write Request
0x17 Prepare Write Response
0x18 Execute Write Request
0x19 Execute Write Response

準備寫請求,用於傳送一個長資料片段,它包含三個引數:屬性控制代碼、偏移量和待寫入資料。

準備寫響應,收到準備寫請求以後,快取收到的資料。

執行寫請求,對前面快取的資料執行寫操作,它包含一個引數:標誌位。如果標誌位為1,則執行寫操作,如果為0,則取消前面的快取資料。

執行寫響應,根據執行寫請求的標誌位,執行或取消寫操作。

3.7 通知屬性

Opcode PDU
0x1B Handle Value Notification
0x1D Handle Value Indication
0x1E Handle Value Confirmation

傳送數值通知,它包含兩個引數:屬性控制代碼和屬性值。它不需要客戶端收到後返回響應。

傳送數值指示,它包含兩個引數:屬性控制代碼和屬性值。它需要客戶端收到後返回確認。

傳送數值確認,它不包含引數,客戶端發出該確認訊息表示收到了數值指示。

4. 許可權

通知和指示與讀寫操作類似,也可以設定安全許可權。

每個屬性可以設定單獨的許可權。

許可權不足將阻止操作,並觸發錯誤響應。

許可權問題與ATT之上的協議層有較大聯絡。