Bluetooth profile: ATT/GATT(襄坤在线)
藍牙4.0版本推出了低功耗規范,引入了兩個核心協議:ATT(Attribute Protocol)和GATT(Generic Attribute Protocol).這兩個協議主要目標是BLE,但是也可以運行在傳統藍牙上(BR/EDR).
Overview
ATT是wire application protocol(無線應用層連接協議?),GATT基于ATT協議。所有的BLE profile一定基于GATT。也就是所有的BLE服務都使用ATT作為應用協議。
鎖定BLE使用這兩個協議的好處是:
- 1.開發和實現新的BLE profile更加容易,因為不需要從頭實現wire protocol。
- 2.ATT針對BLE 設備進行了特別的優化:使用盡可能少的字節,因此可能在存儲中使用定長結構來生成PDU。
- 3.ATT/GATT的簡單意味著固件可能提供某種程度的協議支持,省去了微處理器軟件的麻煩。
- 4.對于軟件實現的協議棧來說,ATT/GATT在協議棧里實現,省去了應用的麻煩。
- 5.即使有的場景下,ATT/GATT不夠理想。也可以在L2CAP連接上實現平行于ATTchannel的協議。
ATT: Attribute Protocol
ATT協議的唯一基礎是屬性。每個屬性由三個元素構成:
1,一個16bit handle;
2,一個UUID來定義屬性的類型;
3,確定長度的屬性值
在ATT中,屬性值可以是任意長度的byte數組。屬性值的實際意義依賴于UUID,而且ATT并不會檢查屬性值長度是否與給定的UUID定義一致。
Handle是用來唯一識別屬性的數字,因為在一個BLE 設備中可能存在多個屬性具有相同的UUID。
ATT協議本身沒有定義任何UUID。這部分工作留給了GATT和上層協議。
ATT server存儲屬性。ATT client什么也不存儲,它使用ATT協議來讀寫server端的屬性。
和屬性相關的還有讀寫權限。讀寫權限存在屬性值里,由高層協議確定。ATT本身不會關心,也不會試圖解釋屬性值來確定權限。這部分工作也留給了GATT和上層協議。
ATT有一些良好的特征,比如通過UUID來搜索屬性,通過handle區間范圍來獲取所有區間內的屬性,因此client不需要提前獲得handle的值,也不需要高層協議硬編碼這些值。
但是在特定的設備上handle的取值最好保持不變,這樣的話client能夠緩沖信息。在第一個discovery以后,client能夠使用緩沖信息,這樣能夠減少傳輸的包數量,也能夠節約能量。如果服務端的屬性布局已經發生了變換,高層協議應該能夠”暗示”client,比如固件升級。
大多數情況下ATT協議都是純C/S架構,client發起請求,server響應。但是服務端也有通知的能力,在服務端屬性發生變化時,server能夠通知client,這樣避免了client不停的poll。
ATT協議不會顯式發送屬性值的長度,只能從PDU長度里面獲得。因此client最好能夠知道某種UUID類型所代表的屬性的精確結構。
不發送屬性值長度,是為了減少發送的字節,因為LE的MTU只有23bytes。
23bytes的MTU對于較長的屬性值來說是個麻煩。因此不得采用“read long”,”write long“這樣的操作。
ATT是如此通用,意味著高層協議有太多工作要做。過度的自由也會帶來問題,比如:如果一個設備提供多個服務怎么辦?對每一個設備只有一個ATT handle空間,多個服務不得不共享同一份空間。
幸運地是,我們還有GATT,它為我們提供了屬性用法,并解除了這些限制。
GATT:Generic Attribute Profile
GATT是所有LE頂層協議的基礎。它定義了怎么把一堆ATT屬性分組成為有意義的服務。
?
GATT services
GATT service的基礎是UUID值為0x2800的屬性。所有跟在這個屬性后面的屬性都屬于這個屬性定義的服務,直到另一個0x2800屬性出現。
比如說,一個設備里面的三個屬性布局如下:?
?
| 0x0100 | 0x2800 | Service A definition |
| ... | ... | Service details |
| 0x0150 | 0x2800 | Service B definition |
| ... | ... | Service details |
| 0x0300 | 0x2800 | Service C definition |
| ... | ... | Service details |
?
?
每一個屬性不知道它自己屬于哪個服務,GATT需要根據0x2800屬性作為標記來識別出哪個屬性屬于哪個服務。
按照這個定義,handle值就有意義了。在上面的例子中,屬于service B的屬性handle必須位于0x0151和0x02ff之間。
UUID 0x2800定義了primary服務,
也可以使用0x2801來定義secondary服務。
Secondary服務表示包含于primary服務。
然后我們怎么能知道一個服務是溫度計,智能鑰匙或者GPS?答案是通過讀取屬性值。服務屬值包含了一個UUID,通過這個UUID區分服務。
因此,每個屬性定義事實上包含了兩個UUID,0x2800或者0x2801作為屬性UUID,另外一個屬性值里面存儲的UUID。后面這個UUID是服務ID。
舉個例子:?
?
| 0x0100 | 0x2800 | Thermometer service definition | UUID 0x1816 |
| ... | ... | Service details | ... |
| 0x0150 | 0x2800 | Service B definition | 0x18xx |
| ... | ... | Service details | ... |
| 0x0300 | 0x2800 | Service C definition | 0x18xx |
| ... | ... | Service details | ... |
?
在圖中,?thermometer service的UUID是0x1816。
是不是感覺怪怪的?兩個UUID定義一個服務?這是GATT/ATT分層方式導致的后果。
UUID0x2800被GATT用來尋找服務定義邊界。一旦找到了邊界,屬性值,也就是第二個UUID用來指定服務。這樣client能夠找到所有的服務而不需要知道服務的具體定義。
GATT service characteristics
每一個服務有幾個特征。特征存儲了有用的值以及權限。
比如,一個溫度計可能有只讀的溫度特征,也可能有可讀寫的時間戳。
?
| 0x0100 | 0x2800 | Thermometer service definition | UUID 0x1816 |
| 0x0101 | 0x2803 | Characteristic: temperature | UUID 0x2A2B Value handle: 0x0102 |
| 0x0102 | 0x2A2B | Temperature value | 20 degrees |
| 0x0110 | 0x2803 | Characteristic: date/time | UUID 0x2A08 Value handle: 0x0111 |
| 0x0111 | 0x2A08 | Date/Time | 1/1/1980 12:00 |
?
?
每一個服務可能有幾個特征,這些特征也是通過路碑屬性來發現的。
主特征的UUID是0x2803,然后主特征的屬性值用來定義特征。比如圖中 0x2803用來找到特征,0x2A2B用來找到特征包含的信息。
每一個特征至少包含兩個屬性,主屬性0x2803和真正的值屬性。主屬性知道屬性值的handle和UUID。這能夠進行一定程度的交叉檢測。
特征值的真正格式是由UUID決定的。因此,如果客戶端知道如何解釋UUID為 0x2A08的特征值,就能夠從包含這個特征任何服務里面讀取日期和時間。當然如果客戶端不知道如何解釋這個UUID的話,也可以選擇忽略。
Characteristic descriptors
?? 除了特征值,我們也可以為每個特征增加更多的屬性。在GATT語法里,這個額外的屬性成為描述符。
???????? 舉個例子子,我們也許需要指定溫度的計量單位。?
?
| 0x0100 | 0x2800 | Thermometer service definition | UUID 0x1816 |
| 0x0101 | 0x2803 | Characteristic: temperature | UUID 0x2A2B Value handle: 0x0102 |
| 0x0102 | 0x2A2B | Temperature value | 20 degrees |
| 0x0104 | 0x2A1F | Descriptor: unit | Celsius |
| 0x0110 | 0x2803 | Characteristic: date/time | UUID 0x2A08 Value handle: 0x0111 |
| 0x0111 | 0x2A08 | Date/Time | 1/1/1980 12:00 |
?
?
GATT知道handle 0x0104是特征0x0101的描述符,因為:
1, 他不是特征的值,因為特征值的handle應該是0x0102
2, 他的handle落在了0x0103-0x010f之間,因此也不屬于下一個特征。
?
描述符值的意義依賴于屬性UUID。例子中,描述符的UUID是0x2A1F,客戶端如果不能識別這個UUId,他可以選擇忽略。這樣可以實現向下兼容。
每個服務可能定義自己的描述符,但是GATT已經定義了能夠覆蓋大多數情況的標準描述符,比如:
數值格式和表示;
人類可讀的描述;
合理范圍擴展屬性等等。其中特別重要的描述符是client characteristic configuration。
Client Characteristic Configurationdescriptor
Client Characteristic Configurationdescriptor的UUID是0x2902,具有一個16bit的可讀寫值,作為一個bitmap來使用。
這個屬性被server用來存儲和代表每個已經綁定的client的獨立實例,每個client只能看到它自己的拷貝。
前兩個bit被GATT用來定義通知和暗示。其他bit暫時未使用。
通過設置CCC,client能夠讓server在特征發生改變時得到通知。比如包含了CCC的屬性布局如下:?
?
| 0x0100 | 0x2800 | Thermometer service definition | UUID 0x1816 |
| 0x0101 | 0x2803 | Characteristic: temperature | UUID 0x2A2B Value handle: 0x0102 |
| 0x0102 | 0x2A2B | Temperature value | 20 degrees |
| 0x0104 | 0x2A1F | Descriptor: unit | Celsius |
| 0x0105 | 0x2902 | Client characteristic configuration descriptor | 0x0000 |
| 0x0110 | 0x2803 | Characteristic: date/time | UUID 0x2A08 Value handle: 0x0111 |
| 0x0111 | 0x2A08 | Date/Time | 1/1/1980 12:00 |
?
Servicediscovery in Low Energy
因為GATT中所有的服務細節通過ATT來描述,所以不需要像BR/EDR那樣設置專門的服務發現協議。ATT負責一切:發現服務,查找特征,讀寫值等等。
GATT andvanilla Bluetooth
GATT也可以工作在傳統藍牙上面,但是規范規定傳統藍牙仍然使用SDP發送服務,即使通過GATT來進行實際數據交換。
這樣的好處是在雙模設備上不用設置標識來識別LE-only服務。如果一個服務只能通過GATT發現,就是LE-only。如果能夠通過GATT和SDP發現,就是雙模。
???????? 如果一個profile通過GATT來進行數據交換,并且是雙模的,它必須首先發布SDP record。然后這個服務通過SDP來發現,然后通過GATT來查找特征。
???????? 當然,現在沒有雙模的profile。以前的profile是BR/EDR only,并且沒有適配到GATT;LE-only只有LE。
???????? 如果想要測試GATT而沒有LE硬件,可以修改藍牙協議棧來使BR/EDR可以進行GATT discovery。這是規范不運行的,但是開發者可以。
Notificationsversus connections
??????? 通知和暗示使得server可以發送消息給client。這樣客戶端不需要pollserver來獲取新的數據。
另外,典型的GATT server是“小的“外設,像非常需要節能的傳感器之類。因此,外設的LE 設備不能發起連接。那么通知怎么發送呢?
在BLE協議棧,如果server有數據發送,它就進入廣播模式,并且發送一些信號。每個profile定義了廣播時長和頻率。時長和頻率應該根據使用場景進行了節能和及時性的權衡。
處于中心模式的設備隨時處于監聽模式。當它監聽到廣播后,如果發現廣播設備是認識的(配對過或者白名單中的),就會向外設發起連接。
連接建立以后,GATT通信能夠進行,通知得以發送。所以典型的序列是:1,server發送廣播 2,client連接 3server通知
如果沒有更多的數據發送,server和client就會超時斷開。最佳超時時間依賴于用例;如果服務不會頻繁發送通知并且沒有實時性要求的話,可以立馬斷開。因為BLE重連是非常快的。
典型的GATT server是外設設備,但是不是必須的。也可以外設做client,center做server。在這種場景下,client想要讀寫數據的時候,需要先進入廣播模式。
總結
以上是生活随笔為你收集整理的Bluetooth profile: ATT/GATT(襄坤在线)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BLE 配对后通信其中一方LTK丢失情况
- 下一篇: 通用属性配置文件(Generic Att