A: What is GATT? B: Let me show you

  • 導(dǎo)語(yǔ)
    該篇文章,主要講述BLE中的GATT profile。

1、什么是GATT

GATTgeneric attribute的簡(jiǎn)稱,顧名思義,其描述的是BLE的屬性應(yīng)用規(guī)范。所謂的屬性,我們可以理解為數(shù)據(jù)庫(kù)中的一張表,是一個(gè)可以被查找的數(shù)據(jù);在BLE中,我們使用handle句柄來進(jìn)行尋址,handle句柄值是唯一的。

在實(shí)際應(yīng)用場(chǎng)景中,需要多個(gè)service來支持 ,每個(gè)service下面同時(shí)有多個(gè)特性(character),每個(gè)特性要有較為詳細(xì)的描述,如這個(gè)特性的值和一些簡(jiǎn)單的說明等。無論是服務(wù)、特性,都要進(jìn)行區(qū)分,BLE中使用UUID進(jìn)行了區(qū)分。除此之外,作為數(shù)據(jù),我們肯定是要對(duì)其進(jìn)行訪問的,這就要提供相應(yīng)的訪問權(quán)限,如可讀、可寫等。

屬性
屬性由屬性句柄、屬性類型、屬性值等組成。
屬性句柄就是我們來進(jìn)行數(shù)據(jù)查找的依據(jù);
屬性類型使用UUID來進(jìn)行區(qū)分,SIG對(duì)屬性類型進(jìn)行了分類:
0x1800 ~ 0x26FF 用作服務(wù)類通用唯一識(shí)別碼
0x2700 ~ 0x27FF 用于標(biāo)識(shí)計(jì)量單位
0x2800 ~ 0x28FF 用于區(qū)分屬性類型
0x2900 ~ 0x29FF 用作特性描述
0x2A00 ~ 0x2AFF 用于區(qū)分特性類型

特性
在BLE規(guī)范中,特性一般包括聲明、數(shù)值和描述三個(gè)部分,其中前兩者是強(qiáng)制實(shí)現(xiàn)的。

2、GATT能干啥


簡(jiǎn)單來講,BLE利用GATT來進(jìn)行數(shù)據(jù)的傳輸。


3、 怎么來分析GATT

GATT中的service or characteristic,本質(zhì)上都是attribute,為了使用的方便,BLE對(duì)這些又進(jìn)行了邏輯上的抽象。

以電池服務(wù)為例:
一個(gè)電池服務(wù)(service)包含一個(gè)電池電量特性(characteristic),其一般包含以下幾個(gè)屬性:primary service 電池服務(wù)、當(dāng)前電量的特性定義、當(dāng)前電量的特性值。由于用戶通常會(huì)希望能夠進(jìn)行低電量提醒,所以在設(shè)計(jì)的時(shí)候,這個(gè)電量特性值不僅是可讀的,而且是可以通知的。

Android Bluetooth GATT attribute type

以下是battery service在Android中的實(shí)現(xiàn)。

/*******************************************************************************
**
** Function         Battery_Instantiate
**
** Description      Instantiate a Battery service
**
*******************************************************************************/
UINT16 Battery_Instantiate (UINT8 app_id, tBA_REG_INFO *p_reg_info)
{
    tBT_UUID            uuid = {LEN_UUID_16, {UUID_SERVCLASS_BATTERY}};
    UINT16              srvc_hdl;
    tGATT_STATUS        status = GATT_ERROR;
    tBA_INST            *p_inst;
    tGATT_CHAR_PROP     prop = GATT_CHAR_PROP_BIT_READ;

    if (battery_cb.inst_id == BA_MAX_INT_NUM)
    {
        GATT_TRACE_ERROR("MAX battery service has been reached");
        return 0;
    }

    p_inst = &battery_cb.battery_inst[battery_cb.inst_id];

    srvc_hdl = GATTS_CreateService (srvc_eng_cb.gatt_if ,
                                            &uuid,
                                            battery_cb.inst_id ,
                                            BA_MAX_ATTR_NUM,
                                            p_reg_info->is_pri);

    if (srvc_hdl == 0)
    {
        GATT_TRACE_ERROR("Can not create service, Battery_Instantiate() failed!");
        return 0;
    }

    battery_cb.inst_id ++;

    p_inst->app_id  =   app_id;
    p_inst->p_cback =   p_reg_info->p_cback;

    /* add battery level
    */
    uuid.uu.uuid16 = GATT_UUID_BATTERY_LEVEL;

    if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY)
        prop |= GATT_CHAR_PROP_BIT_NOTIFY;

    if ((p_inst->ba_level_hdl  = GATTS_AddCharacteristic(srvc_hdl,
                                                &uuid,
                                                BATTER_LEVEL_PERM,
                                                prop)) == 0)
    {
        GATT_TRACE_ERROR("Can not add Battery Level, Battery_Instantiate() failed!");
        status = GATT_ERROR;
    }
    else
    {
        if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY)
        {
            uuid.uu.uuid16 = GATT_UUID_CHAR_CLIENT_CONFIG;
            p_inst->clt_cfg_hdl  = GATTS_AddCharDescriptor(srvc_hdl,
                                                           (GATT_PERM_READ|GATT_PERM_WRITE),
                                                           &uuid);
            if (p_inst->clt_cfg_hdl == 0)
            {
                GATT_TRACE_ERROR("Add battery level client notification FAILED!");
            }
        }
        /* need presentation format descriptor? */
        if (p_reg_info->ba_level_descr & BA_LEVEL_PRE_FMT)
        {
            uuid.uu.uuid16 = GATT_UUID_CHAR_PRESENT_FORMAT;
            if ( (p_inst->pres_fmt_hdl = GATTS_AddCharDescriptor(srvc_hdl,
                                                                 GATT_PERM_READ,
                                                                 &uuid))
                                       == 0)
            {
                GATT_TRACE_ERROR("Add battery level presentation format descriptor FAILED!");
            }

        }
        /* need presentation format descriptor? */
        if (p_reg_info->ba_level_descr & BA_LEVEL_RPT_REF)
        {
            uuid.uu.uuid16 = GATT_UUID_RPT_REF_DESCR;
            if ( (p_inst->rpt_ref_hdl = GATTS_AddCharDescriptor(srvc_hdl,
                                                                GATT_PERM_READ,
                                                                &uuid))
                                       == 0)
            {
                GATT_TRACE_ERROR("Add battery level report reference descriptor FAILED!");
            }

        }
        /* start service
        */
        status = GATTS_StartService (srvc_eng_cb.gatt_if, srvc_hdl, p_reg_info->transport);
    }

    if (status != GATT_SUCCESS)
    {
        battery_cb.inst_id --;
        uuid.uu.uuid16 = UUID_SERVCLASS_BATTERY;
        GATTS_DeleteService(srvc_eng_cb.gatt_if, &uuid, battery_cb.inst_id);
        srvc_hdl = 0;
    }

    return srvc_hdl;
}

  • 總結(jié)
    本篇文章旨在簡(jiǎn)明的講述GATT是什么,能干什么,怎么去使用GATT,讀者有什么疑惑,可以一起討論。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容