天天看點

CC2640R2F BLE5.0 藍牙協定棧通用屬性配置檔案(GATT)通用屬性配置檔案(GATT)

CC2640R2F BLE5.0 藍牙協定棧通用屬性配置檔案(GATT)通用屬性配置檔案(GATT)
CC2640R2F BLE5.0 藍牙協定棧通用屬性配置檔案(GATT)通用屬性配置檔案(GATT)
CC2640R2F BLE5.0 藍牙協定棧通用屬性配置檔案(GATT)通用屬性配置檔案(GATT)

通用屬性配置檔案(GATT)

正如GAP層負責連接配接相關的功能,GATT主要是負責在兩個已經連接配接的裝置互動資料,GAP層把BLE裝置區分為主機Master(Central)和從機Slave(Perpherial),在GATT層則區分為Server和Client。用戶端讀取和寫入存儲在服務端的特征值(Characteristics )。

Server

該裝置包含由GATT用戶端讀取或寫入的characteristic。

Client

從GATT伺服器讀取或寫入資料的藍牙裝置。

CC2640R2F BLE5.0 藍牙協定棧通用屬性配置檔案(GATT)通用屬性配置檔案(GATT)
注意:對于GATT分層的Server/Client角色和GAP分層的Master(Central)/Slave(Perpherial)并沒有直接關系。如上圖,手機作為Central/Client,CC2640R2開發闆作為 Peripheral/Server。

GATT的Profile、Service、Characteristics、Attributes

對于GATT層的Profile、Service、Characteristics、Attributes概念,我們一定要深入了解,因為一旦建立連接配接後,不管是嵌入式端還是應用端進行資料互動的都是這些概念。為了幫助了解,我們抽象以下包含關系:

CC2640R2F BLE5.0 藍牙協定棧通用屬性配置檔案(GATT)通用屬性配置檔案(GATT)

一個或者多個Characteristic組成一個Service,一個多個Service組成Profile,Characteristic又由多個Attributes組成,每個Attribute由包含 Handle、Type、Permissions三個屬性。

以下我們着重了解Characteristic,也是我們資料互動的最終實體,每個特征包含以下4個Attributes。

  • Characteristic Value(特征值)

    用于characteristic的值

  • Characteristic Declaration(特征聲明)

    存儲特征值的屬性,位置和類型的描述符

  • Client Characteristic Configuration(用戶端特征配置)

    允許GATT伺服器配置要通知的特性(異步發送消息)或訓示的配置(與确認異步發送消息)

  • Characteristic User Description(特征使用者描述)

    描述特征的ASCII字元串

    這些屬性存儲在屬性表中的GATT伺服器中。除了該值之外,以下屬性與每個屬性相關聯。

以上的每個Attributes 又由以下元素組成。

  • Handle(句柄)

    表中屬性的索引(每個屬性都有一個唯一的句柄)

  • Type(類型)

    訓示屬性資料表示什麼(稱為UUID [通用唯一辨別符],其中一些是藍牙SIG定義的,一些是自定義的)

  • Permissions(權限)

    強制GATT用戶端裝置如何以及如何通路屬性的值

GATT用戶端抽象層

下圖所示,在GATT用戶端應用程式大部分是直接使用GATT的API(少部分直接使用ATT層API),沒有profile檔案,因為GATT客戶是得到資料,不需要建立屬性表和配置檔案。

CC2640R2F BLE5.0 藍牙協定棧通用屬性配置檔案(GATT)通用屬性配置檔案(GATT)

GATT服務端抽象層

如圖所示,在GATT服務端,GATT層的大部分功能由獨立的profiles處理,然後可以看見perfiles又使用GAttservApp子產品(一個可配置的子產品,用于儲存和管理屬性表,詳見BLE Stack API Reference)處理。

CC2640R2F BLE5.0 藍牙協定棧通用屬性配置檔案(GATT)通用屬性配置檔案(GATT)

是以在建立GATT服務端的時候首先需要配置profiles檔案,profiles檔案調用GattServAppApp子產品并使用其API與GATT層接口。在這種情況下應用程式不需要直接調用GATT層API,應用程式和Profiles檔案接口。

GATT Services 和 Profile

在概述部分講過,GATT service是characteristic的集合,多個service可以組合在一起形成一個profile,許多profile僅實作一個service,是以profile和service可以互換。

在simple_peripheral示例應用程式項目中定義了四個GATT服務。

  • GAP GATT服務(GGS)

    此服務包含裝置和通路資訊,例如裝置名稱,供應商辨別和産品辨別。

    為此服務定義了以下特征:

    裝置名稱

    表現(Appearance)

    外圍首選連接配接參數

  • 通用屬性服務

    該服務包含有關GATT伺服器的資訊,是藍牙低功耗協定棧的一部分,每個GATT伺服器裝置都需要根據藍牙5.0版本核心規範。

  • 裝置資訊服務

    此服務公開了有關裝置的資訊,如硬體,軟體版本,固件版本,規範資訊,合規性資訊和制造商名稱。裝置資訊服務是藍牙低功耗協定棧的一部分,由應用程式配置。

  • simple_gatt_profile服務

    此服務是用于測試和示範的示例配置檔案。完整的源代碼在simple_gatt_profile.c和simple_gatt_profile.h檔案中提供。

// Initialize GATT attributes
	  GGS_AddService(GATT_ALL_SERVICES);           // GAP GATT Service
	  GATTServApp_AddService(GATT_ALL_SERVICES);   // GATT Service
	  DevInfo_AddService();                        // Device Information Service
	  SimpleProfile_AddService(GATT_ALL_SERVICES); // Simple GATT Profile      

下圖顯示了simple_peripheral項目中的屬性表,這些屬性的設定都是通過上面4個服務函數。可以逐一打開檢視修改。

CC2640R2F BLE5.0 藍牙協定棧通用屬性配置檔案(GATT)通用屬性配置檔案(GATT)

使用BTool擷取的簡單GATT配置檔案特性表。紅色表示Profile聲明,黃色表示字元聲明,White表示與特定聲明相關的屬性。

simple_gatt_profile包含以下特性:

  • SIMPLEPROFILE_CHAR1

    可以從GATT用戶端裝置讀取或寫入的1位元組值

  • SIMPLEPROFILE_CHAR2

    可以從GATT用戶端裝置讀取但不能寫入的1位元組值

  • SIMPLEPROFILE_CHAR3

    可以從GATT用戶端裝置寫入但不能讀取的1位元組值

  • SIMPLEPROFILE_CHAR4

    不能從GATT用戶端裝置直接讀取或寫入的1位元組值(該值是通知屬性)

  • SIMPLEPROFILE_CHAR5

    可從GATT用戶端裝置讀取(但不寫入)的5位元組值

0x001C是simple_gatt_profile服務聲明。

此聲明的UUID為0x2800(藍牙定義 GATT_PRIMARY_SERVICE_UUID)。該聲明的值是simple_gatt_profile(自定義)的UUID。

0x001D是SimpleProfileChar1特征聲明。

該聲明可以被認為是指向SimpleProfileChar1值的指針。該聲明的UUID為0x2803(藍牙定義GATT_CHARACTER_UUID)。下面解釋characteristic聲明值的含義(MSB到LSB):

  • 位元組0是藍牙核心規範版本5.0中定義的SimpleProfileChar1的屬性 (以下是某些相關屬性)。

    0x02:允許讀取特征值

    0x04:允許寫入特征值(無響應)

    0x08:允許寫入特征值(帶響應)

    0x10:允許通知特征值(無确認)

    0x20:允許通知特征值(帶确認)

    characteristic1 0x0A的意義是該特性可讀可寫(0x02|0x08)

  • 位元組1-2:SimpleProfileChar1的值的句柄(句柄0x001E)
  • 位元組3-4:SimpleProfileChar1值的UUID(自定義0xFFF1)
  • 0x001E是SimpleProfileChar1特征值

    該值的UUID為0xFFF1(自定義)。該值是characteristic的實際有效載荷資料。如其SimpleProfileChar1聲明(句柄0x01D)所示,該值是可讀寫的。

  • 0x001F是SimpleProfileChar1特征使用者描述

    該描述的UUID為0x2901(藍牙定義)。該描述的值是描述特征的使用者可讀字元串。

  • 0x0020 - 0x002C

    剩下的四個特征描述具有和simpleProfileChar1相同結構的屬性。唯一不同的屬性是處理0x0028時,描述如下。

    0x0028是SimpleProfileChar4用戶端特征配置。此配置的UUID為0x2902(藍牙定義)。通過寫入此屬性,GATT伺服器可以将SimpleProfileChar4配置為通知(寫入0x0001)或訓示(寫入0x0002)。将0x0000寫入此屬性将禁用通知和訓示。

GATT安全

如GATT 服務端抽象所述,GATT伺服器可以為每個特性獨立定義權限。伺服器可能允許任何用戶端通路某些characteristic,同時将通路其他characteristic僅限于認證或授權的用戶端。這些權限通常被定義為更進階别的配置檔案規範的一部分。對于自定義配置檔案,使用者可以選擇他們認為合适的權限。有關GATT安全性的更多資訊,請參閱藍牙核心規範版本5.0的安全注意事項部分([第3卷,第G部分,第8部分])。

認證(Authentication)

在用戶端通過認證配對方法之前,無法通路需要身份驗證的特性。此驗證在堆棧内執行,無需應用程式處理。唯一的要求是使GATT服務端正确注冊該特性。

例如,simple_gatt_profile的characteristic5設定需要認證的讀取。

//characteristic 5 
{ 
   {  ATT_BT_UUID_SIZE , simpleProfilechar5UUID  },
   GATT_PERMIT_AUTHEN_READ ,
   0 ,
   simpleProfileChar5 
},      

當未經身份驗證的用戶端嘗試讀取此值時,GATT伺服器将自動拒絕它,而不調用simpleProfile_ReadAttrCB()。隻有當認證成功之後,讀寫的請求才會轉發到profiles的讀寫回調,請參閱一下代碼,該代碼在simple_gatt_profile.c中simpleProfile_ReadAttrCB()函數裡面。

case SIMPLEPROFILE_CHAR1_UUID:
  case SIMPLEPROFILE_CHAR2_UUID:
  case SIMPLEPROFILE_CHAR4_UUID:
    *pLen = 1;
    pValue[0] = *pAttr->pValue;
    break;

  case SIMPLEPROFILE_CHAR5_UUID:
    *pLen = SIMPLEPROFILE_CHAR5_LEN;
    VOID memcpy( pValue, pAttr->pValue, SIMPLEPROFILE_CHAR5_LEN );
    break;
    
  default:
    // Should never get here! (characteristics 3 和 4沒有讀權限)
    *pLen = 0;
    status = ATT_ERR_ATTR_NOT_FOUND;
    break;      

授權(Authorization)

授權是發生在認證之後對一些文檔的通路權限更改删除,需要授權。授權是BLE已經實作的一個安全層。由于應用程式需要定義自己的授權要求,是以協定棧将這些特性的讀/寫請求轉發到配置檔案的應用程式層。

要從profile檔案注冊GATT伺服器的授權資訊,它必須使用堆棧定義一個授權回調。如下面僞代碼(例程中沒有使用授權)。

  1. 注冊授權回調
CONST  gattServiceCBs_t  simpleProfileCBs  = { 
	   simpleProfile_ReadAttrCB ,      //讀回調函數指針
	   simpleProfile_WriteAttrCB ,     //寫回調函數指針
	   simpleProfile_authorizationCB   //授權回調函數指針
	};      
  1. 實作授權回調代碼
static  bStatus_t  simpleProfile_authorizationCB ( uint16  connHandle , gattAttribute_t  * pAttr , uint8  opcode  )
	{ 
	   //這隻是一個示例實作,正常的用例将需要
	   更複雜的邏輯來确定裝置是否被授權
	
	   if (clientIsAuthorized )
	      return SUCCESS ; 
	   else
	      return ATT_ERR_INSUFFICIENT_AUTHOR ; 
	}      

授權回調在協定棧上下文中執行,是以在這個函數中不應該執行太複雜的處理。具體實作由開發人員決定;上述回調應該被視為一個shell。如果用戶端有權通路該特征傳回SUCCESS,如果沒有傳回ATT_ERR_INSUFFICIENT_AUTHOR,授權需要事先通過連接配接進行身份驗證,否則ATT_ERR_INSUFFICIENT_AUTHEN将作為錯誤響應發送。

如果需要授權的特性并注冊了授權回調,但沒有定義應用級授權回調,那麼協定棧将傳回ATT_ERR_UNLIKELY。因為這個錯誤并不明确,是以TI建議使用授權回調。

直接使用GATT層

上面用戶端抽象說過,應用程式也可以直接使用GATT層API,本節就介紹如何在應用程式中使用GATT層,GATT層的功能在庫中實作,但頭檔案功能可在gatt.h中找到。BLE Stack API Reference中有完整的API參考。作為GATT用戶端(在simple_central項目中)使用GATT層的一般過程如下:

CC2640R2F BLE5.0 藍牙協定棧通用屬性配置檔案(GATT)通用屬性配置檔案(GATT)

圖中可以看出,GATT用戶端發送指令之後,通過ICALL給協定棧發送ATT指令,然後協定棧處理之後傳回響應,再由ICALL以ATT事件通知應用程式,應用程式得到ATT事件之後異步處理。注意:除了收到對自己的指令的響應外,GATT用戶端還可以從GATT伺服器接收異步資料作為訓示或通知。使用GATT_RegisterForInd(selfEntity)注冊接收這些ATT通知和訓示。這些通知和訓示也作為ATT事件(ATT_HANDLE_VALUE_NOTI& ATT_HANDLE_VALUE_INDG)發送到應用程式。這些事件必須按照GATT Services和Profile中的說明進行處理。

GAP GATT 服務(GGS)

在前面GATT服務和簡介中說過,GGS服務包含裝置和通路資訊,例如裝置名稱,Appearance,外圍首選連接配接參數。GGS的目的是在裝置發現和連接配接啟動過程中進行輔助。有關GGS的更多資訊,請參閱藍牙核心規範版本5.0的“GAT service”和“Characteristics for GATT Server”部分([Vol 3],C部分,第12節)。

  1. 包含标題
#include  “gapgattserver.h”      
  1. 初始化GGS參數
// GAP GATT Attributes 
static  uint8_t  attDeviceName [ GAP_DEVICE_NAME_LEN ]  =  “This is a text” ;	
GGS_SetParameter (GGS_DEVICE_NAME_ATT , GAP_DEVICE_NAME_LEN , attDeviceName );      
  1. 使用GGS初始化應用程式回調(可選)。當GGS中的任何特征發生變化時,都會通知應用程式。
GGS_RegisterAppCB (&appGGSCBs );      
  1. 将GGS添加到GATT伺服器。
bStatus_t  GGS_AddService (GATT_ALL_SERVICES );      

經過上面4個步驟的配置,就成功設定了GGS的參數,在central裝置連接配接外圍裝置的時候就能擷取這些參數,使用我們公司提供的XXX.apk可以在手機界面直接檢視我們設定的參數值。

加入我們

文章所有代碼、工具、文檔開源。加入我們QQ群 591679055擷取更多支援,共同研究CC2640R2F&BLE5.0。

CC2640R2F BLE5.0 藍牙協定棧通用屬性配置檔案(GATT)通用屬性配置檔案(GATT)

© Copyright 2017, 成都樂控暢聯科技有限公司.

繼續閱讀