藍牙GATT和GAP層


一、開篇

    本篇主要介紹一下關於BLE開發過程中必須了解的兩個協議:GAP(通用訪問協議)、GATT(通用屬性協議)。兩個協議都隸屬於Host層,直接關系到應用層開發,與BLE開發人員的關系比較密切,其分別負責連接前數據廣播和連接后的數據傳輸。

 

三、試驗平台

Software Version:BLE_STACK_CC26XX_2.1.0

Hardware Version:CC2640/CC2650

IDE:IAR 7.40

四、GAP

 

    1、藍牙低能耗技術“完成”一次連接(即掃描其它設備、建立鏈路、發送數據、認證和適當地結束)只需3ms。而標准藍牙技術完成相同的連接周期需要數百毫秒。

    GAP層有4種不同類型的廣播:通用的、定向的、不可連接的以及可發現的。

    設備每次廣播時,會在3個廣播信道上發送相同的報文。這些報文被稱為一個廣播事件。除了定向報文以外,其他廣播事件均可以選擇20ms - 10.28s不等的間隔。通常,一個廣播中的設備會每一秒廣播一次。廣播事件之間的時間稱為廣播間隔。主機可以控制該間隔。但是,設備周期性的發送廣播會有一個問題:由於設備間的時鍾會不同程度的漂移,兩個設備可能在很長一段時間同時廣播而造成千擾。為防止選一情況的發生,在上一次廣播事件發生后加入隨機延時。它們發送下一個廣播事件時也很可能不再沖突。

    通用廣播:通用廣播是用途最廣的廣播方式。進行通用廣播的設備能夠被掃描設備掃描到,或者在接收到連接請求時作為從設備進入一個連接。通用廣播可以在沒有連接的情況下發出,換句話說,沒有主從設備之分。

    定向廣播:有時候,設備間需要快速建立連接。如果從設備想這么做,就需要進行廣播。定向廣播事件就是為了盡可能快的建立連接。這種報文包含兩個地址:廣播者的地址和發起者的地址。發起設備收到發紿自己的定向廣播報文后,可以立即發送連接請求作為回應。

    不可連接廣播:不想被連接的設備使用不可連接廣播事件。這種廣播的典型應用包括設備只想廣播數據,而不想被掃描或者連接。速也是唯一可用於只有發射機而沒有接收機設備的廣播類型。不可連接廣播設備不會進入連接態,因此,它只能根據主機的要求在廣播態和就緒態之間切換。

    可發現廣播:最后一種廣播事件是可發現廣播。這種廣播不能用於發起連接,但允許其他設備掃描該廣播設備。這意味着該設備可以被發現,既可以廣播數據,又可以響應掃描,但不能建立連接。這是一種適用於廣播數據的廣播形式,動態數據可以包含於廣播數據之中,而靜態數據可以包含於掃描響應數據之中。可發現廣播不會進入連接態,而只能在停止后回到就緒態。

    如上面所述,BLE設備可以進行廣播。但是,一個廣播設備必須在廣播中包含一些有用的數據。這意味着可以通過4種廣播事件中的3種進行廣播:通用廣播、不可連接廣播以及可發現廣播。進行廣播時,需要在廣播報文中給數據打上標簽。之所以要這么做,是因為並非所有設備都能理解所有可能的廣播數據。因此,需要給廣播數據打上標簽並指出其長度。每個數據片段均起始於一個長度域,用以指示后面的類型及數據域的長度;接下來是類型域,接收機可根據其內容判斷自己是否能夠理解后面的數據。事例代碼:

  1. // GAP - Advertisement data (max size = 31 bytes, though this is
  2. // best kept short to conserve power while advertisting)
  3. static uint8_t advertData[] =
  4. {
  5. // Flags; this sets the device to use limited discoverable
  6. // mode (advertises for 30 seconds at a time) instead of general
  7. // discoverable mode (advertises indefinitely)
  8. 0x02, // length of this data
  9. GAP_ADTYPE_FLAGS,
  10. DEFAULT_DISCOVERABLE_MODE | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
  11.  
  12. // service UUID, to notify central devices what services are included
  13. // in this peripheral
  14. 0x03, // length of this data
  15. GAP_ADTYPE_16BIT_MORE, // some of the UUID's, but not all
  16. #ifdef FEATURE_OAD
  17. LO_UINT16(OAD_SERVICE_UUID),
  18. HI_UINT16(OAD_SERVICE_UUID)
  19. #else
  20. LO_UINT16(SIMPLEPROFILE_SERV_UUID),
  21. HI_UINT16(SIMPLEPROFILE_SERV_UUID)
  22. #endif //!FEATURE_OAD
  23. };

 

五、GATT

    通用屬性配置文件(GATT)在屬性協議(ATT)的基礎上構建,為屬性協議傳輸和存儲數據建立了一些通用操作和框架。

1)GATT定義了兩個角色:服務器和客戶端。

    GATT的角色並不一定與特定的GAP角色有關聯,但可能由更高層級的配置文件指定。GATT和ATT不是傳輸專用,也可以用於BR/EDR和低耗能。但是,由於GATT和ATT用作發現服務,故必須在低耗能技術中實施。GATT服務器存儲通過屬性協議傳輸的數據,並接受GATT客戶端發出的屬性協議請求、指令及確認。GATT服務器發送請求回復,而如果在配置時GATT服務器發生特定事件,則會向GATT客戶端異步發送指示和通知。GATT還指定GATT服務器中所載的數據格式。

    屬性在當經由屬性協議傳輸時,會被格式化為相關的服務和特性。服務可能包括許多特征。特征包括單一值和許多描述特征值的描述符。

憑借經定義的服務、特征和特征描述符架構,並非配置文件特定的GATT客戶端仍然可以遍歷GATT服務器,並向用戶顯示特征值。特征描述符可用於顯示特征值的描述符,從而可讓用戶了解該值。

2)GATT配置文件層級

    GATT配置文件規格規定了交換配置文件數據的架構。此架構定義了配置文件所用的基本元素,例如服務和特征。

該層級的最高層是配置文件(profile)。配置文件由實現用例所需的一個或多個服務組成。服務由特征或有關其它服務的引用組成。每一個特征包括一個值,還可能包括有關該值的可選信息。服務、特征以及特征的組件(即特征值和特征描述符)構成了配置文件數據,並全部存儲在服務器的屬性中。

    英文原版(摘自Core_V4.1 vol 1:6.5,p226):The top level of the hierarchy is a profile. A profile is composed of oneor more services necessary to fulfill a use case. A service is composed of characteristicsor references to other services. Each characteristic contains a value and maycontain optional information about the value. Theservice and characteristic and the components of the characteristic (i.e.,value and descriptors) contain the profile data and are all stored in Attributes on theserver.

0

 

3)服務

    服務是數據和完成設備或設備的某些部分的特定功能或特征的相關行為的集合。服務可能涉及其它主要或次要服務和/或構成該服務的特征集合。

服務分為兩種類型:主要服務和次要服務。主要服務提供設備的主要功能。次要服務提供設備的輔助功能,引用自該設備至少一項主要服務。

為了令早前的客戶端保持向后兼容性,服務定義的其后修訂僅可增加新引用的服務或可選特征。服務定義的其后修訂也不得改變該服務定義先前修訂的特征。

服務可能用於一個或多個配置文件,以實現特定用例。

4)特征

    特征,連同屬性和有關如何訪問該值的配置信息以及有關如何顯示或表述該值的信息,是用於服務的值。特征定義包含特征聲明、特征屬性和值。它還可能包含描述該值或允許服務器配置有關特征值的描述符。

協議棧代碼實現如下:

 

  1. /*********************************************************************
  2. * Profile Attributes - variables
  3. */
  4. // Simple Profile Service attribute
  5. static CONST gattAttrType_t simpleProfileService = { ATT_BT_UUID_SIZE, simpleProfileServUUID };
  6. // Simple Profile Characteristic 1 Properties
  7. static uint8 simpleProfileChar1Props = GATT_PROP_READ | GATT_PROP_WRITE;
  8. // Characteristic 1 Value
  9. static uint8 simpleProfileChar1 = 0;
  10. // Simple Profile Characteristic 1 User Description
  11. static uint8 simpleProfileChar1UserDesp[17] = "Characteristic 1";
  12.  
  13.  
  14. /*********************************************************************
  15. * Profile Attributes - Table
  16. */
  17. static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] =
  18. {
  19. // Simple Profile Service
  20. {
  21. { ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */
  22. GATT_PERMIT_READ, /* permissions */
  23. 0, /* handle */
  24. (uint8 *)&simpleProfileService /* pValue */
  25. },
  26. // Characteristic 1 Declaration
  27. {
  28. { ATT_BT_UUID_SIZE, characterUUID },
  29. GATT_PERMIT_READ,
  30. 0,
  31. &simpleProfileChar1Props
  32. },
  33. // Characteristic Value 1
  34. {
  35. { ATT_BT_UUID_SIZE, simpleProfilechar1UUID },
  36. GATT_PERMIT_READ | GATT_PERMIT_WRITE,
  37. 0,
  38. &simpleProfileChar1
  39. },
  40. // Characteristic 1 User Description
  41. {
  42. { ATT_BT_UUID_SIZE, charUserDescUUID },
  43. GATT_PERMIT_READ,
  44. 0,
  45. simpleProfileChar1UserDesp
  46. },

5)關於句柄handle 和UUID

    Handle即是地址(記住它,類比於C語言的指針操作)

    屬性句柄:一台設備可以有許多的屬性,例如溫度傳感器可能包含溫度屬性、設備名稱屬性和電池電量屬性。表面看來,通過屬性類型似乎足以判別某種屬性。比如使用溫度屬性來獲取溫度,通過設備名稱屬性來獲取設備名等。但是,如果設備包含了兩種溫度屬性,比如一個室內溫度傳感器加上室外溫度傳感器,情況會變得怎樣。這時你便無法直接讀取溫度傳感器,而必須讀取第一個或第二個溫度屬性。考慮到可能有任意多個溫度傳感器,問題將變得更加復雜。為了解決這個同題,我們使用了一個16位的地址,也就是屬性句柄。有效的句柄范圍從0x0001--xFFFF。0x0000為無效句柄,不能用於尋址屬性。可以根據在軟硬件或嵌入式方面的背景,把句柄(Handle)相應地想象為內存地址、端口號、屬性值對應的硬件寄存器地址。

    屬性類型:可以被公開的數據有許許多多的類型:溫度、壓強、體積、距離、功率、時間、充電狀態、開關狀態、狀態機的狀態等。所公開的數據的種類稱作屬性類型。為了區分如此多的數據類型,一串128位的數字被用來標識屬性的類型。這個唯一標識碼就叫做通用唯一識別碼(UUID),128位的UUID相當長,設備間為了識別數據的類型需要發送長達16個字節的數據。為了提高傳輸效率,藍牙技術聯盟( SIG)定義了一種稱為“藍牙UUID基數”的128位通用唯一識別碼,結合一個較短的16位數使用。二者仍然遵循通用唯一識別碼的分配規則,只不過在設備間傳輸常用的UUID時,只發送較短的16位版本,接收方收到后補上藍牙的UUID基數即可。

藍牙UUID基數如下:

00000000—0000—1000—8000—00805F9B34FB

例如要發送的16位識別碼位0X2A01,完整的128位UUID便是:

00002A01—0000—1000—8000—00805F9B34FB

    由上所述,所以在協議棧代碼中經常見到的都是16位的UUID而不常見128位的UUID的原因所在,下面是官方demo的UUID,供參考。

  1. // Simple Profile Service UUID
  2. #define SIMPLEPROFILE_SERV_UUID 0xFFF0
  3.  
  4. // Key Pressed UUID
  5. #define SIMPLEPROFILE_CHAR1_UUID 0xFFF1
  6. #define SIMPLEPROFILE_CHAR2_UUID 0xFFF2
  7. #define SIMPLEPROFILE_CHAR3_UUID 0xFFF3
  8. #define SIMPLEPROFILE_CHAR4_UUID 0xFFF4
  9. #define SIMPLEPROFILE_CHAR5_UUID 0xFFF5

談到16位的UUID,通常不直接使用數值,而是冠以一個名稱並加上書名號(這些UUID可以在gatt_profile_uuid.h中查看到)

0x1800 - 0x26FF用作服務類通用唯一識別碼

0x2700 - 0x27FF用於標識計量單位

0x2800 - 0x28FF用於區分屬性類型

0x2900 - 0x29FF用作特性描述

0x2A00- 0x7FFF用於區分特性類型

UUID,就是用來唯一識別一個特征值的ID。

handle,就是對應的attribute的一個句柄。

具體細節詳見:Generic Attribute Profile (GATT)

摘抄一部分源碼供參考:

  1. /**
  2. * GATT Service UUIDs
  3. */
  4. #define IMMEDIATE_ALERT_SERV_UUID 0x1802 // Immediate Alert
  5. #define LINK_LOSS_SERV_UUID 0x1803 // Link Loss
  6. #define TX_PWR_LEVEL_SERV_UUID 0x1804 // Tx Power
  7. #define CURRENT_TIME_SERV_UUID 0x1805 // Current Time Service
  8. #define REF_TIME_UPDATE_SERV_UUID 0x1806 // Reference Time Update Service
  9.  
  10. /**
  11. * GATT Characteristic UUIDs
  12. */
  13. #define ALERT_LEVEL_UUID 0x2A06 // Alert Level
  14. #define TX_PWR_LEVEL_UUID 0x2A07 // Tx Power Level
  15. #define DATE_TIME_UUID 0x2A08 // Date Time
  16. #define DAY_OF_WEEK_UUID 0x2A09 // Day of Week
  17. #define DAY_DATE_TIME_UUID 0x2A0A // Day Date Time
  18. #define EXACT_TIME_256_UUID 0x2A0C // Exact Time 256
  19.  
  20. /**
  21. * GATT Unit UUIDs
  22. */
  23. #define GATT_UNITLESS_UUID 0x2700 // <Symbol>, <Expressed in terms of SI base units>
  24. #define GATT_UNIT_LENGTH_METER_UUID 0x2701 // m, m
  25. #define GATT_UNIT_MASS_KGRAM_UUID 0x2702 // kg, kg

    所有對特征值的操作,都是通過對UUID 的搜索得到對應的handle之后,通過handle來操作特征值的。對於藍牙通信來說,其都是通過一個個不同的UUID來標識區分不同的服務,區分不同的特性,甚至服務和特性之間的類別。

 

 

六、總結

    不知道寫什么了,就這樣吧,后續想到了寫吧,學習BLE也不久,路還很長。路漫漫其修遠兮,吾將上下而求索~~~

    PS:該死的房價。。。。啊啊啊啊啊啊。。。。

    參考:1)藍牙技術聯盟官方網站

               2)Bluetooth開發者門戶

               3)Bluetooth Spec Core_V4.1

 

 

注:本文轉載自https://blog.csdn.net/qq_21842557/article/details/50771077,真心是一篇好文章!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM