BLE 5協議棧-屬性協議層(ATT)
文章轉載自:http://www.sunyouqun.com/2017/04/page/2/
屬性協議(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之上的協議層有較大聯系。
(完)
BLE 5協議棧-屬性協議層(ATT)