四、BLE(中)


1.1       GATT Manager

GATT MGR模塊管理所有的GATT服務,同時也是連接GATT模塊與GATT ServiceS模塊的橋梁。

1.1.1    主要功能模塊

先來看一張該模塊的API關系圖,sink_gatt_manager.c里面定義的接口主要供ApplicationLayer調用和回調,如用戶(BLE Server)調用sinkGattManagerStartAdvertising()開始進行廣播,用戶(BLE Client)調用sinkGattManagerStartConnection()開始進行BLE連接。該該部分同時負責接收和處理來自ApplicationLayer的消息——GATT_MANAGER_DISCONNECT_IND,GATT_MANAGER_REGISTER_WITH_GATT_CFM等GATT_MANAGER_XXX系列消息。這些消息主要用來處理注冊連接確認,斷開連接請求等事件。

 

       Gatt_nanager_handler.c主要定義和實現了內部回調函數gattManagerMessageHandler(),該接口主要接收來自GATT模塊的GATT_XXX系列消息,以及GATT MGR內部的消息GATT_MANAGER_INTERNAL_MSG_XXX。處理這些消息的函數接口主要分布在gatt_manager_server.c和gatt_manager_client.c兩個函數內部。

       根據BLE工作的角色不同,BLE分別定義了兩套接口,分別完成客戶和服務的角色的任務。

         作為BLE客戶主要完成的任務有:

1.連接到服務器。這里包括主導發起連接至服務器,以及接收到服務器連接請求的確認。即:GattManagerConnectToRemoteServer()用來主動發起連接請求,在接收到GATT_CONNECT_CFM消息后,調用gattManagerClientRemoteServerConnected ()接口用於確認連接,完成連接的三次握手過程。

2. GATT支持notification和indication操作,因此客戶端需要有着兩種請求操作對應的接口。gattManagerClientRemoteServerNotification()和gattManagerClientRemoteServerIndication()就是為了實現這兩種操作巍峨設計的。

3. 獲取服務器的服務。根據GATT標准,獲取服務的服務主要有:獲取服務器主要GATT服務,獲取某個GATT服務的所有特征值定義,獲取某個GATT服務的特征值描述符,讀/寫某個特征值等。

         作為BLE服務器主要完成的任務有:

1.廣播,以及處理客戶端的連接請求。gattManagerServerAdvertising()開啟廣播,GattManagerWaitForRemoteClient()等待遠程客戶發起連接,gattManagerServerConnectInd()處理連接請求。gattManagerServerRemoteClientConnected()處理連接請求確認(三次握手最后一次)消息。

2.注冊GATT service。GattManagerRegisterServer()向GATT MGR模塊注冊一個GATT service。

3.處理來自客戶端的GATT操作,如access,indication,notification等。其中indication,notification操作都是由服務器主動對客戶端發起的操作,因此客戶端和服務器端處理的消息剛好是互為匹配的,即服務器處理的消息有(GATT_ACCESS_IND, GATT_NOTIFICATION_CFM, GATT_INDICATION_CFM),客戶端對應的處理消息有(ATT_ACCESS_RSP, GATT_NOTIFICATION_IND, GATT_INDICATION_IND)。

1.1.2    GATT數據庫

作為GATT的服務器,通常需要存儲比較多的數據來支撐多個不同的GATT服務,因此在GATT服務器端,建立一個數據庫是必要的。在CSR的BlueCore和CSRμEnergy軟件開發工具包(SDK)中使用了一種特殊的數據庫目標語言。該數據庫通過GATT數據庫生成器(CSR提供的gattdbgen.exe)自動生成。這就允許應用程序開發者以一種簡單易讀,便於維護的方式來創建一個數據庫,避免采用諸如SDP這種用復雜的二進制形式表示方式。

數據庫的生成

GATT數據庫生成器輸入一個用jeason語言描述的GATT服務文件foobar.db,輸出一個foobar.c和foobar.h文件,這兩個文件可以作為ADK工程的一部分進行編譯和鏈接。可見數據庫的生產是在整個工程編譯前,准確的說是在預編譯階段就已經完成了。顯然這樣生產的數據是一個准常量的數據庫,不能往里面新增記錄,即不能動態的添加GATT服務,所有的服務必須在編譯前就已經確定好。

例如,在ADK的sink例程中,sink_gatt_db.db作為數據庫生成器的輸入文件,輸出sink_gatt_db.c和sink_gatt_db.h。

其中xxx_db.c文件有const uint16 gattDatabase[] = {}存儲數據庫記錄。並提供兩個接口工外部操作數據庫,這兩個接口分別為:

uint16 *GattGetDatabase(uint16 *len);  /*獲取數據庫存儲區首地址*/

uint16 GattGetDatabaseSize(void);      /*獲取數據庫大小*/

在xxx_db.h文件中,除了GattGetDatabase()和GattGetDatabaseSize()接口的聲明外,還有數據庫中所有ATT記錄的句柄(UUID)的宏定義,通常以HANDLE_GAIA_XXX的形式定義。通過該宏,可以快速索引某條ATT記錄。

BLE在初始化GATT Manager模塊時,對GATT database進行了初始化:

initialiseGattWithServers()->

GattManagerRegisterConstDB(&gattDatabase[0], GattGetDatabaseSize());

 

例如某個gaia_db.db內容為:

primary_service {

    uuid : 0x01

    name : "GAIA_SERVICE",

    characteristic {

        uuid        : 0x02,

        name        : "GAIA_COMMAND_ENDPOINT",

        flags       : [ FLAG_IRQ, FLAG_DYNLEN, FLAG_ENCR_W ],

        properties  : [ write ],

        value       : 0x0

    }

},

則其生成的gaia_db.c文件如下:

/* Static GATT database */

const uint16 gattDatabase[] = {

    /* 0001: Primary Service 0001 */

    0x0002, 0x0100,

    /* 0002: Characteristic Declaration 0002 */

    0x3005, 0x0803, 0x0002, 0x0000,

    /* 0003: . */

    0xdd01, 0x0000,

};

 

uint16 *GattGetDatabase(uint16 *len)

{

    uint16 *rc = PanicUnlessMalloc(sizeof(gattDatabase));

    *len = sizeof(gattDatabase);

    memmove(rc, gattDatabase, sizeof(gattDatabase));

    return rc;

}

 

uint16 GattGetDatabaseSize(void)

{

    return sizeof(gattDatabase);

}

其生成的gaia_db.h文件如下:

#define HANDLE_GAIA_SERVICE             (0x0001)

#define HANDLE_GAIA_SERVICE_END         (0xffff)

#define HANDLE_GAIA_COMMAND_ENDPOINT    (0x0003)

 

uint16 *GattGetDatabase(uint16 *len);

uint16 GattGetDatabaseSize(void);

 

數據庫維護

         GATT數據庫的數據單元是ATT記錄,通過某條ATT記錄的句柄(handler)可以快速和唯一地訪問該條記錄,例如,如果希望訪問電池服務的電量特征值,該條特征值定義封裝在一條句柄為0x0003的ATT記錄中,通過句柄0x0003找到該條ATT記錄,ATT.value即對應着電池電量值。


免責聲明!

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



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