藍牙BLE GATT完全分析和運用

http://blog.csdn.net/yueqian_scut/article/details/50752314

很多人都做過藍牙開發,很多人也能夠通過仿照GATT例程的方式添加一個屬性服務,但是很多人都未必能夠清晰地理解BLE的屬性profile,也很容易被屬性Attribute和特性characteristic所混淆。本文結合BLE的服務發現協議標準和DA14580平臺、CC2541平臺的應用實踐來深入分析GATT,讓大家能夠自如地構建一個BLE的屬性數據庫

更多藍牙設備開發的經驗原創總結敬請關注微信公衆號:嵌入式企鵝圈。 

一、 BLE GATT(Generic Attribute Profile)規範

1.   GATT定義

GATT是低功耗藍牙屬性應用規範,應用於主機和從設備之間的數據傳輸。其與GAP並列爲BLE兩大profile。

Attribute是屬性的意思。何爲屬性?在各藍牙單芯片平臺的SDK實際使用中,屬性是指一條帶有標籤的、可以被尋址的數據。在藍牙實際的規範中,尋址即用handle句柄來表示。每個屬性都對應一個唯一的handle。


2.   對屬性協議需求的思考

藍牙是無線通信,BLE利用屬性協議進行傳輸,其如此重要,如果我們不理解其需求,那麼我們也很難從真正去理解其規範。儘管在實際的藍牙單芯片SDK中很容易通過模仿的方法進行應用,但是如果想深入地理解其爲什麼要設計呢?

1)連接的參數是一個設備的固有參數,一般會作爲一個服務來提供,如GAP服務;而假設這個設備是一個溫度採集器,那麼這個溫度採集明顯跟設備的參數不屬於一類,因此可以再作爲一個服務。所以屬性協議應該支持多個服務。如何來區分這些不同的服務?這即對應藍牙標準規範規定的UUID。我們可以認爲不同的UUID對應不同的確定的服務。

2)連接的參數可以有多個,如Connection Interval、Slave Latency等等,我們如何區分這是一個服務,又如何區分服務包含了這些特性參數。我們可以認爲一個服務包含了多個特性(參數)。在藍牙標準裏面,同樣是用不同的UUID來區分服務類型、特性類型等等。

3)對於每個特性characteristic,要讓對方獲取這個特性,就必須要分別告訴對方這個特性的長度是多少,值是多少,而不能只給數值。除此之外,特性還可能有描述值(說明特性名稱或者作用等)、特性單位等(國際單位,如米是公里/每小時還是米/秒)。後面這兩個是非必選的。

4)屬性還應該有一個訪問控制,如可讀可寫還是讀寫、或者是通知notify/indicate等等,這是數據通信必須具有的權限控制,不管是服務還是特性,它都具有訪問控制屬性。


3.   屬性和屬性類型

屬性由屬性句柄、屬性類型、屬性值組成。如下圖:

1)  屬性句柄在實際的運用中可以認爲是屬性在屬性數組中的下標。我們都知道在實際的編程中,下標並不需要專門存儲,而只是通過元素的結構體來進行索引即可。因此可以認爲屬性句柄是一個無形的東西,它只能被所在的設備程序所認識,而不能用於無線傳輸。

2)  屬性類型是真實存在的,其和屬性值都會被實際存儲。屬性類型是由藍牙標準組織所規範,其一般通過128位的UUID來表徵一個具體的屬性。由於BLE的GATT可以認爲是藍牙標準規範的精簡版,所以BLE被允許只傳輸前面2字節(16位)的UUID,所有的BLE的UUID的基數都是一樣的,如下,只有前面兩字節不同。

利用2字節(16位)也可以定義65536種屬性了。事實上,藍牙標準組織對這些UUID進行了分類。如下:

屬性類型即是0x2800~0x28ff,在實際的應用中,屬性類型主要包括:我們主要使用服務和特性定義兩種,其他兩個很少用到。

3)  藍牙標準不僅通過UUID來進行屬性分類,而且還用UUID來確定各種具體的服務和特性。所以我們會看到UUID可能會出現在屬性的屬性類型和屬性值兩個地方。

4)  藍牙標準組織規定兩個ATT_DECL_PRIMARY_SERVICE服務之間的特性都隸屬於第一個服務。這樣可以理解在藍牙服務發現協議中先通過UUID找到目標服務,然後通過ATT_DECL_PRIMARY_SERVICE這個屬性類型找到下一個服務,接着即可以在這兩個服務中進行特性的遍歷,遍歷的結果即是目標服務的所有特性。


4.   屬性值

屬性值的長度可以最長到512字節,但對於某些屬性,其長度是固定的。對於藍牙標準裏面規定的UUID所對應的屬性(包括服務、特性定義、特性值、特性描述等等),服務、特性定義的長度是確定的,而特性值則是不固定長度的。

所以,對於不同的屬性,其屬性值是不一樣的。也即對於以上五類(通用服務、單位、屬性類型、特性描述和區分特性類型)等屬性,其屬性值的規範是不一樣,具體到不同的特性類型,其屬性值也是不同的。


1)通用服務類通過唯一的UUID(0x1800~0x26ff)來標識一種明確的服務。好比,0x180f代表電池電量服務。

2)計量單位類通過唯一的UUID來標識一種單位。

3)區分屬性類型類通過唯一的UUID來標識該屬性是首要服務定義、次要服務、包含服務還是特性定義等。其好比程序中的變量的類型,是整型、字節型、還是確定的結構體。

4)特性描述類除了描述特性的名稱、作用之外,還有一個非常重要的配置作用。例如如果提供的特性服務需要主動告知對方,那麼對方就必須在連接時進行訂閱配置。這樣在該特性的數據值發生變更時能夠主動地進行notify或者indicate。

5)區分特性類型用於用戶定義不同的特性,用於區分該設備裏面所有的特性。


5.   特性

把特性理解爲一個程序中的一個變量是最好理解的。變量有變量類型和值,變量類型有int整型、字節型等等(其實就是變量的存儲長度),值即具體的數值。相應地,而特性則有值和存儲值的長度的概念。如同變量的聲明和定義,特性characteristic也有聲明和定義(賦值)的概念。

一般地,在藍牙標準裏面,特性一般包括三個要素:聲明、數值和描述。前兩者都是必須的。作爲通信交互,一個特性必須要告訴對方聲明(存儲長度和訪問控制)、定義(具體賦值)。在某些特性(如notify或者indicate)裏面,特性還需要告知對方附加的配置屬性(提供訂閱等)。

特性聲明必須作爲服務屬性之後的第一條屬性,而數值必須緊隨其後。

1)  特性聲明

性質爲一個8位字段,指示訪問控制權限,包括讀、寫、notify或者indicate等。對於特性聲明而言,其一般是隻讀的(這裏只針對聲明這條屬性本身,而不是針對對應的特性數值)。數值句柄即用於直接尋址接下來的特性數值。其對於通信的對方是很有好處的,因爲對方只需要記錄該句柄即可在後續的訪問中直接尋址,否則每次通信都要遍歷。在實際的編程應用中,我們往往在初始化時填入0,代表由底層邏輯來自動更新該handle。而屬性UUID和接下來的特性數值屬性的區分特性類型值是一致的。

2)特性數值

特性數值也是一個屬性,其屬性類型填入特性聲明的屬性UUID。屬性值要填入特性數值的訪問權限、長度和數值。

3)特性描述

      其可以是字符串表示的特性名稱,或者是notify/indicate要求的配置等等。


二、對屬性協議重要的理解原則

1)無論是服務還是特性,它們都是一條條屬性;特性的各個要素也是一條條屬性。只不過,不同的服務是獨立的;而一個服務如果有多個特性,那麼不同的特性也是獨立的;一個特性包含的多條屬性則是關聯的。

2)對於藍牙通信來說,其都是通過一個個不同的UUID來標識區分不同的服務,區分不同的特性,甚至服務/特性之間的類別。

3)對於各個藍牙單芯片SDK平臺,其上層應用對於屬性協議的支持並不一致,它們只需要保證底層的藍牙數據格式一致即可。


三、屬性協議範例說明

例如一個電池服務包括一個特性(電池電量),那麼其至少包括以下屬性:首要服務定義(電池服務)、當前電量的特性定義(定義值長度)、當前電量的特性值。如果希望電池電量在低於某個水平時主動告知對方,那麼這個電量特性值不僅應該是可讀的,還應該是能夠notify的。由於有主動告知,因此該特性還需要包括配置要素,用於對方來訂閱。

1.對於電池服務這個屬性,其屬性類型是ATT_DECL_PRIMARY_SERVICE(0x2800),屬性值是訪問可讀和藍牙標準組織規定的0x180f(位於0x1800到0x26ff之間);

2.電池當前電量的特性定義這個屬性,其屬性類型是ATT_DECL_CHARACTERISTIC(0x2803),屬性值是可讀、特性值句柄和特性值的UUID(0x2A19)。

3.對於當前電量的特性值這個屬性,其屬性類型是0x2A19(0x2A00~0x7fff之間,區分特性類型),其用於區分多種不同的特性(如一個溫度採集器可能要採集多個溫度,這裏就要用戶通過不同的UUID來區分不同的特性了),屬性值即訪問控制(可讀/indicate)、長度(1字節)、數值。

4.配置屬性,用於notify的訂閱配置。其屬性類型是0x2902,屬性值是可讀/可寫(要能寫入訂閱方的handle)、長度(2個字節)、handle值。

      根據以上分析,我們來重構這個藍牙的數據底層數據庫。

四、DA14580平臺SDK屬性結構定義

1.單個屬性定義

對於不同的屬性,其length長度由value的類型來決定。例如服務的屬性值對應的結構就是uint16_t;而特性聲明的屬性值對應的結構就是:

 

2.電池電量服務定義

五、CC254X平臺SDK屬性結構定義

1.單個屬性定義

同樣的,屬性值pValue的數據結構由其對應的UUID來決定。例如服務屬性的pValue對應的結構是gattAttrType_t(包括長度2和具體的服務UUID)。而特性聲明的pValue對應的結構是一個字節的訪問權限控制。特性數值的pValue對應的結構則是直接的變量定義,其可能是一個字節或者是字節數組,其長度由底層通過判斷數組來決定。

2.電池電量服務定義

 

六、參考文獻

1.   BLE標準core_V4.0,英文規格書

2.   低功耗藍牙開發權威指南,藍牙標準起草人撰寫,中譯本。

如需要這兩本電子書請關注微信公衆號:嵌入式企鵝圈 之後發消息獲取。​

做藍牙開發的童鞋們記得點贊啊,網上幾乎沒有類似這樣對底層協議結構進行分析的文章,最多就是寫寫屬性、服務、特性之類的定義,看了過眼就忘。這篇文章應該可以好好收藏,不記得的時候就翻出來看看:-)

更多嵌入式Linux和物聯網原創技術總結敬請關注微信公衆號:嵌入式企鵝圈


發佈了30 篇原創文章 · 獲贊 54 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章