日韩一区二区三区精品,欧美疯狂xxxxbbbb牲交,热99re久久免费视精品频,人妻互换 综合,欧美激情肉欲高潮视频

ESP32學(xué)習(xí)筆記(33)——BLE GATT客戶端發(fā)現(xiàn)服務(wù)和讀寫特征值

發(fā)布者:平和心態(tài)最新更新時(shí)間:2025-02-27 來源: jianshu關(guān)鍵字:ESP32  BLE  客戶端 手機(jī)看文章 掃描二維碼
隨時(shí)隨地手機(jī)看文章

一、背景

1.1 GATT協(xié)議

GATT(Generic Attributes Profile)的縮寫,中文是通用屬性協(xié)議,是已連接的低功耗藍(lán)牙設(shè)備之間進(jìn)行通信的協(xié)議。

一旦兩個(gè)設(shè)備建立起了連接,GATT 就開始起作用了,這也意味著,你必需完成前面的GAP協(xié)議。

GATT使用了 ATT(Attribute Protocol)協(xié)議,ATT 協(xié)議把 Service,Characteristic 對應(yīng)的數(shù)據(jù)保存在一個(gè)查找表中,查找表使用 16bit ID 作為每一項(xiàng)的索引。

GATT定義的多層數(shù)據(jù)結(jié)構(gòu)簡要概括起來就是 服務(wù)(Service) 可以包含多個(gè) 特征(Characteristic),每個(gè)特征包含 屬性(Properties) 和 值(Value),還可以包含多個(gè) 描述(Descriptor)。

1.2 屬性協(xié)議(ATT)

屬性協(xié)議層 負(fù)責(zé)數(shù)據(jù)檢索,允許一個(gè)設(shè)備暴露一些數(shù)據(jù)塊給其他設(shè)備,其他設(shè)備稱之為“屬性”。

在ATT環(huán)境中,展示屬性的設(shè)備稱之為服務(wù)器,與它配對的設(shè)備稱之為客戶端。鏈路層的主機(jī)從機(jī)和這里的服務(wù)器、客服端是兩種概念,主設(shè)備既可以是服務(wù)器,也可以是客戶端。從設(shè)備毅然。

1.3 GATT通信中角色

從GATT的角度來看,處于連接狀態(tài)時(shí)的兩個(gè)設(shè)備,它們各自充當(dāng)兩種角色中的一種:
服務(wù)端(Server)
包含被GATT客戶端讀取或?qū)懭氲奶卣鲾?shù)據(jù)的設(shè)備。
客戶端(Client)
從GATT服務(wù)器中讀取數(shù)據(jù)或向GATT服務(wù)器寫入數(shù)據(jù)的設(shè)備。

外圍設(shè)備(從機(jī))作為 GATT 服務(wù)端(Server),它維持了 ATT 的查找表以及 service 和 characteristic 的定義;

客戶端和服務(wù)器的GATT角色獨(dú)立于外圍設(shè)備和中央設(shè)備的GAP角色。外圍設(shè)備可以是GATT客戶端或GATT服務(wù)器,中心可以是GATT客戶端或GATT服務(wù)器。

image


1.4 Bluedroid主機(jī)架構(gòu)

在 ESP-IDF 中,使用經(jīng)過大量修改后的 BLUEDROID 作為藍(lán)牙主機(jī) (Classic BT + BLE)。BLUEDROID 擁有較為完善的功能,?持常用的規(guī)范和架構(gòu)設(shè)計(jì),同時(shí)也較為復(fù)雜。經(jīng)過大量修改后,BLUEDROID 保留了大多數(shù) BTA 層以下的代碼,幾乎完全刪去了 BTIF 層的代碼,使用了較為精簡的 BTC 層作為內(nèi)置規(guī)范及 Misc 控制層。修改后的 BLUEDROID 及其與控制器之間的關(guān)系如下圖:

二、API說明

以下 GATT 接口位于 bt/host/bluedroid/api/include/api/esp_gattc_api.h

2.1 esp_ble_gattc_search_service

2.2 esp_ble_gattc_get_char_by_uuid

2.3 esp_ble_gattc_get_descr_by_char_handle

2.4 esp_ble_gattc_get_attr_count

2.5 esp_ble_gattc_write_char

2.6 esp_ble_gattc_write_char_descr

2.7 esp_ble_gattc_register_for_notify

三、發(fā)現(xiàn)服務(wù)

本篇是關(guān)于GATT客戶端發(fā)現(xiàn)服務(wù)和讀寫特征值,連接服務(wù)端的流程查看 ESP32學(xué)習(xí)筆記(32)——BLE GAP主機(jī)端連接


MTU配置事件還用于開始發(fā)現(xiàn)客戶端剛剛連接到的服務(wù)器中可用的服務(wù)。要發(fā)現(xiàn)服務(wù),可以使用esp_ble_gattc_search_service()函數(shù)。該函數(shù)的參數(shù)包括GATT接口、應(yīng)用程序配置文件連接ID和客戶端感興趣的應(yīng)用程序UUID。


我們正在尋找的服務(wù)定義為:


#define REMOTE_SERVICE_UUID        0x00FFstatic esp_bt_uuid_t remote_filter_service_uuid = {

    .len = ESP_UUID_LEN_16,

    .uuid = {.uuid16 = REMOTE_SERVICE_UUID,},};

隨后進(jìn)行查找服務(wù):


esp_ble_gattc_search_service(gattc_if, param->cfg_mtu.conn_id, &remote_filter_service_uuid);

        break;

找到的服務(wù)結(jié)果(如果有的話)將從ESP_GATTC_SEARCH_RES_EVT返回。對于找到的每個(gè)服務(wù),將觸發(fā)事件來打印所發(fā)現(xiàn)服務(wù)的信息,具體取決于UUID的大?。?p>

 case ESP_GATTC_SEARCH_RES_EVT: {

        esp_gatt_srvc_id_t *srvc_id = &p_data->search_res.srvc_id;

        conn_id = p_data->search_res.conn_id;

        if (srvc_id->id.uuid.len == ESP_UUID_LEN_16 && srvc_id->id.uuid.uuid.uuid16 == REMOTE_SERVICE_UUID) {

        get_server = true;

        gl_profile_tab[PROFILE_A_APP_ID].service_start_handle = p_data->search_res.start_handle;

        gl_profile_tab[PROFILE_A_APP_ID].service_end_handle = p_data->search_res.end_handle;

        ESP_LOGI(GATTC_TAG, 'UUID16: %x', srvc_id->id.uuid.uuid.uuid16);

        }

        break;

如果客戶端找到了它要查找的服務(wù),就將get_server標(biāo)記設(shè)置為true,并保存開始句柄值和結(jié)束句柄值,稍后將使用它們來獲得該服務(wù)的所有特征。在返回所有服務(wù)結(jié)果之后,將完成搜索并觸發(fā)ESP_GATTC_SEARCH_CMPL_EVT事件。


四、獲取特征

此示例實(shí)現(xiàn)從預(yù)定義服務(wù)獲取特征數(shù)據(jù)。我們想要獲得特征的服務(wù)UUID是0x00FF,我們感興趣的特征UUID是0xFF01:


#define REMOTE_NOTIFY_CHAR_UUID    0xFF01

使用esp_gatt_srvc_id_t結(jié)構(gòu)定義服務(wù):


/**

 * @brief Gatt id, include uuid and instance id

 */typedef struct {

    esp_bt_uuid_t   uuid;                   /*!< UUID */

    uint8_t         inst_id;                /*!< Instance id */} __attribute__((packed)) esp_gatt_id_t;

在這個(gè)例子中,我們定義了我們想要獲取特征的服務(wù):


static esp_gatt_srvc_id_t remote_service_id = {

    .id = {

        .uuid = {

            .len = ESP_UUID_LEN_16,

            .uuid = {.uuid16 = REMOTE_SERVICE_UUID,},

        },

        .inst_id = 0,

    },

    .is_primary = true,};

定義之后,我們可以使用esp_ble_gattc_get_characteristic()函數(shù)從該服務(wù)獲取特征,該函數(shù)在服務(wù)搜索完成并且找到了它正在尋找的服務(wù)之后,在ESP_GATTC_SEARCH_CMPL_EVT事件中調(diào)用。


case ESP_GATTC_SEARCH_CMPL_EVT:

    if (p_data->search_cmpl.status != ESP_GATT_OK){

        ESP_LOGE(GATTC_TAG, 'search service failed, error status = %x', p_data->search_cmpl.status);

        break;

    }

    conn_id = p_data->search_cmpl.conn_id;

    if (get_server){

        uint16_t count = 0;

        esp_gatt_status_t status = esp_ble_gattc_get_attr_count( gattc_if,

                          p_data->search_cmpl.conn_id,ESP_GATT_DB_CHARACTERISTIC,                                                                                                                                           gl_profile_tab[PROFILE_A_APP_ID].service_start_handle,                                                                                              gl_profile_tab[PROFILE_A_APP_ID].service_end_handle,        

                                                                INVALID_HANDLE,                           

                                                                     &count);

        if (status != ESP_GATT_OK){

            ESP_LOGE(GATTC_TAG, 'esp_ble_gattc_get_attr_count error');

        }


        if (count > 0){

            char_elem_result = (esp_gattc_char_elem_t*)malloc                                          (sizeof(esp_gattc_char_elem_t) * count);

            if (!char_elem_result){

                ESP_LOGE(GATTC_TAG, 'gattc no mem');

            }else{

                status = esp_ble_gattc_get_char_by_uuid( gattc_if,

                                                       p_data->search_cmpl.conn_id,                                                                      

                              gl_profile_tab[PROFILE_A_APP_ID].service_start_handle,                                                            

                              gl_profile_tab[PROFILE_A_APP_ID].service_end_handle,

                                                         remote_filter_char_uuid,

                                                         char_elem_result,

                                                         &count);

                if (status != ESP_GATT_OK){

                    ESP_LOGE(GATTC_TAG, 'esp_ble_gattc_get_char_by_uuid error');

                }


                /*  Every service have only one char in our 'ESP_GATTS_DEMO' demo,     

                    so we used first 'char_elem_result' */

                if (count > 0 && (char_elem_result[0].properties                       

                                 &ESP_GATT_CHAR_PROP_BIT_NOTIFY)){

                    gl_profile_tab[PROFILE_A_APP_ID].char_handle =  

                    char_elem_result[0].char_handle;

                    esp_ble_gattc_register_for_notify (gattc_if,   

                                   gl_profile_tab[PROFILE_A_APP_ID].remote_bda, 

                                   char_elem_result[0].char_handle);

[1] [2]
關(guān)鍵字:ESP32  BLE  客戶端 引用地址:ESP32學(xué)習(xí)筆記(33)——BLE GATT客戶端發(fā)現(xiàn)服務(wù)和讀寫特征值

上一篇:ESP32學(xué)習(xí)筆記(34)——BLE一主多從連接
下一篇:ESP32學(xué)習(xí)筆記(32)——BLE GAP主機(jī)端連接

推薦閱讀最新更新時(shí)間:2025-06-23 19:43

ESP32系列CPU支持差分升級
在 ESP32 的官方版本中,是不含差分升級源代碼的。如果需要支持,官方另外提供了一個(gè)獨(dú)立的代碼庫https://github.com/espressif/esp-bootloader-plus 支持差分升級。 在這個(gè)代碼庫中,官方只支持了 ESP32C2 和 ESP32C3 兩款 CPU。其實(shí)其他的 CPU 也是可以支持的,我在 ESP32 和 ESP32 S3 都已驗(yàn)證是 OK 的。 如果移植開發(fā)的話,需要關(guān)注以下幾點(diǎn): 將差分的源代碼庫合入 ESP32系列的軟件 SDK 開發(fā)包后,按照庫上的說明,在 idf.py menuconfig 配置后,進(jìn)行編譯。可能大概率的會(huì)出現(xiàn) bootloader 空間不足的鏈接錯(cuò)誤。這
[單片機(jī)]
ESP32學(xué)習(xí)筆記(6)——Log日志庫使用
一、printf是不可重入函數(shù) printf不能在中斷中被調(diào)用的原因是它是一個(gè)不可重入函數(shù),而在中斷中要避免調(diào)用不可重入函數(shù),首先我們先說說什么是不可重入函數(shù)。 簡單說來,區(qū)分一個(gè)函數(shù)是否可重入就是看這個(gè)函數(shù)能否在未返回的時(shí)候再次被調(diào)用。而造成一個(gè)函數(shù)不可重入的原因往往是使用了全局變量,如果一個(gè)函數(shù)未返回再執(zhí)行一次會(huì)導(dǎo)致對全局變量的操作是不安全的。就例如我們常用的printf、malloc、free都是不可重入的函數(shù),printf會(huì)引用全局變量stdout,malloc,free會(huì)引用全局的內(nèi)存分配表,在多線程的環(huán)境下,如果沒有很好的處理數(shù)據(jù)保護(hù)和互斥訪問,就會(huì)發(fā)生錯(cuò)誤。 二、ESP_LOGx日志 日志記錄庫提供了兩種設(shè)置
[單片機(jī)]
ESP32學(xué)習(xí)筆記(41)——SNTP接口使用
一、SNTP簡介 簡單網(wǎng)絡(luò)時(shí)間協(xié)議(Simple Network Time Protocol),由 NTP 改編而來,主要用來同步因特網(wǎng)中的計(jì)算機(jī)時(shí)鐘。 SNTP 協(xié)議是用來同步本地的時(shí)間到 unix 時(shí)間戳。通常嵌入式設(shè)備上電,連接 AP(access point),獲取 IP 地址后,就需要使用 SNTP 協(xié)議獲取全球時(shí)間。以便于下一步的應(yīng)用交互和使用。 SNTP 工作原理比較簡單, 通俗來說,就是設(shè)備向 SNTP server 發(fā)送一包 SNTP 請求,服務(wù)器收到請求后回復(fù)一包 SNTP reply。其中 SNTP reply 中就含有 unix 時(shí)間戳。 ESP-IDF 編程指南——SNTP 時(shí)間同步 二、API說明
[單片機(jī)]
Nordic BLE SOC讓創(chuàng)鴻新智能深紫外LED測溫消毒筆功耗更低
Nordic Semiconductor宣布總部位于深圳的物聯(lián)網(wǎng)(IoT) 解決方案供應(yīng)商創(chuàng)鴻新智能科技有限公司選擇Nordic入門級nRF52810低功耗藍(lán)牙 (Bluetooth? Low Energy /Bluetooth LE) 芯片級系統(tǒng)(SoC),為其 “深紫外 (UVC) LED測溫消毒筆” 提供核心處理能力和無線連接。 深紫外LED測溫消毒筆是一款緊湊便攜的消毒設(shè)備 (157 x 20 x 20mm,51g),內(nèi)置溫度傳感器和產(chǎn)生深紫外光的LED。其中集成的Nordic nRF52810 SoC帶有64MHz的32位Arm?Cortex?M4處理器,使得該設(shè)備能夠精確地測量各種物體表面 (例如,皮膚表面、
[測試測量]
Nordic <font color='red'>BLE</font> SOC讓創(chuàng)鴻新智能深紫外LED測溫消毒筆功耗更低
高通公司將讓更多人可以使用基于EV-DO版本A的移動(dòng)寬帶智能手機(jī)
—MSM7525芯片組將推動(dòng)全球智能手機(jī)使用門檻的降低— 圣迭戈,2007年3月27日 ——碼分多址(CDMA)和其他領(lǐng)先無線技術(shù)的開發(fā)及創(chuàng)新廠商美國高通公司(Nasdaq:QCOM)今天宣布擴(kuò)展其產(chǎn)品線以支持主流CDMA2000智能手機(jī)。高通公司的Mobile Station Modem (MSM) MSM7525支持CDMA2000 1xEV-DO版本A的終端設(shè)備,將讓更多的無線用戶可以購買配備了先進(jìn)功能但性價(jià)比高的智能手機(jī)。高通公司的MSM7525芯片組計(jì)劃在今年第三季度出樣,基于這種芯片組的手機(jī)預(yù)計(jì)在2008年底投產(chǎn)。 “高通公司有著開發(fā)并商業(yè)化先進(jìn)技術(shù)、以改變移動(dòng)用戶日常生活的悠久歷史?!备咄ü臼紫\(yùn)營官兼高通C
[新品]
小廣播
設(shè)計(jì)資源 培訓(xùn) 開發(fā)板 精華推薦

最新單片機(jī)文章

 
EEWorld訂閱號

 
EEWorld服務(wù)號

 
汽車開發(fā)圈

 
機(jī)器人開發(fā)圈

電子工程世界版權(quán)所有 京ICP證060456號 京ICP備10001474號-1 電信業(yè)務(wù)審批[2006]字第258號函 京公網(wǎng)安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved