从零开始学ESP32:(三)ESP32的蓝牙GATT服务测试

从零开始学ESP32:个人笔记记录:

芯片型号: ESP32
网络环境支持:LWIP
IDF.PY-SDK: ESP-IDF v4.3
芯片功能: 支持STA/AP网络共存模式:

参考工程:esp-idf/examples/bluetooth/bluedroid/ble/gatt_server

蓝牙初始化:主要测试接口,要注意的是我将ESP32的代码重新编排了

TEST_DEVICE_NAME 蓝牙设备名称


#define TEST_DEVICE_NAME            "ESP_GATTS_DEMO" 

/****************************************************************************
 * 函数名称:BLE_bleDeviceMain
 * 输入值:  
 * 输出值:
 * 返回值:
 * 其他:
 * 说明: 蓝牙设备处理 
 *      
 * */
void BLE_bleDeviceMain(void)
{
    esp_err_t ret = 0;
    esp_err_t local_mtu_ret = 0;
    ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) 
    {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK( ret );
    ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT)); 
    esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
    for( int i = 0; i < 9 ; i++)
    {
        switch ( i )
        {
            case 0: ret = esp_bt_controller_init(&bt_cfg);                      break;
            case 1: ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);            break;
            case 2: ret = esp_bluedroid_init();                                 break;
            case 3: ret = esp_bluedroid_enable();                               break;
            case 4: ret = esp_ble_gatts_register_callback(gatts_event_handler); break;
            case 5: ret = esp_ble_gap_register_callback(gap_event_handler);     break;
            case 6: ret = esp_ble_gatts_app_register(PROFILE_A_APP_ID);         break;
            #ifdef  POR_FILE_B
            case 7: ret = esp_ble_gatts_app_register(PROFILE_B_APP_ID);         break;
            #endif 
            case 8: local_mtu_ret = esp_ble_gatt_set_local_mtu(500);            break;
            default: break;
        }

        if( ret || local_mtu_ret )
        {
            DEV_PRINTF("number = %d errot local_mtu_ret = %x %s\n", i ,  local_mtu_ret  , esp_err_to_name(ret) );
            DEV_PRINTF("BEL DEVICE INIT FAILED ");
            return ; 
        }
    }
    return;
}

讲解这个代码: 里面ESP32默认开启的是两条服务配置,
也就是PORFILE_A和 PORFILE_B 服务。
在这里插入图片描述

在注册进去的时候,例程里面提供了两个事件回调函数结构:

在这里插入图片描述
下面分别介绍gatts_profile_a_event_handler 和 gatts_profile_b_event_handler回调函数:
由于ESP32蓝牙这块的代码写实在是有点难以言喻,按照事件重新编排,但是其实本质上是没有变化的

gatts_profile_a_event_handler 回调函数的讲解
学习主要是学习几个事件:
ESP_GATTS_REG_EVT 在注册时候回出现注册回调
ESP_GATTS_READ_EVT
ESP_GATTS_WRITE_EVT 作为服务端的写事件,居然是接收手机APP发送过来的数据
ESP_GATTS_CONNECT_EVT 当前用户连接进来就会回调产生事件
ESP_GATTS_DISCONNECT_EVT 断开事件

static void  gatts_profile_a_event_handler( esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param )
{
    switch ( event )
    {
        case ESP_GATTS_REG_EVT:             gatt_a_registerEventHandler( event , gatts_if ,  param ); break; // 注册
        case ESP_GATTS_READ_EVT:            gatt_a_readPackEventHandler( event , gatts_if ,  param ); break; //读
        case ESP_GATTS_WRITE_EVT:           gatt_a_writePackEventHandler(event , gatts_if ,  param ); break; //写
        case ESP_GATTS_EXEC_WRITE_EVT:      gatt_a_execPackWriteHandler( event , gatts_if ,  param ); break;
        case ESP_GATTS_MTU_EVT:             DEV_PRINTF("ESP_GATTS_MTU_EVT, MTU %d", param->mtu.mtu);  break;
        case ESP_GATTS_CREATE_EVT:          gatt_a_createPackEventHandler(event , gatts_if ,  param); break;
        case ESP_GATTS_ADD_CHAR_EVT:        gatt_a_addCharPackEventHandler(event , gatts_if , param); break;
        case ESP_GATTS_ADD_CHAR_DESCR_EVT:  gatt_a_addCharDescrEventHandler(event, gatts_if , param); break;
        case ESP_GATTS_CONNECT_EVT:         gatt_a_connectEventHandler( event , gatts_if ,  param );  break; //连接事件
        case ESP_GATTS_DISCONNECT_EVT:      gatt_a_disconnectEventHandler( event, gatts_if, param );  break; //断开连接
        case ESP_GATTS_CONF_EVT:            gatt_a_configEventHandler(  event , gatts_if ,  param );  break;  
        case ESP_GATTS_START_EVT:           DEV_PRINTF("SERVICE_START_EVT, status %d, service_handle %d\n",
                                            param->start.status, param->start.service_handle);        break;
        case ESP_GATTS_UNREG_EVT:           break;
        case ESP_GATTS_ADD_INCL_SRVC_EVT:   break;
        case ESP_GATTS_DELETE_EVT:          break;
        case ESP_GATTS_STOP_EVT:            break;
        case ESP_GATTS_OPEN_EVT:            break;
        case ESP_GATTS_CANCEL_OPEN_EVT:     break;
        case ESP_GATTS_CLOSE_EVT:           break;
        case ESP_GATTS_LISTEN_EVT:          break;
        case ESP_GATTS_CONGEST_EVT:         break;
        default: DEV_PRINTF("none event "); break;
    }
    return ;
}

*******主要可以看看 事件的回调和产生************

/****************************************************************************
 * 函数名称
 * 
 * 
 * GATT B 系列事件 ESP_GATTS_WRITE_EVT
 * */
void gatt_b_writePackEventHandler( esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param )
{
    char buff[100] = { 0 };   
    // DEV_PRINTF ("GATT_WRITE_EVT, conn_id %d, trans_id %d, handle %d\n", param->write.conn_id, param->write.trans_id, param->write.handle);
    if (!param->write.is_prep)
    {
        memcpy( buff ,param->write.value, param->write.len  );
        buff[  param->write.len ] = '\0'; 
        /********   param->write.value 就是我们接收到APP 的信息 **************/
        DEV_PRINTF("value = %s  len %d, value :", buff ,  param->write.len );  
  
        if (gl_profile_tab[PROFILE_B_APP_ID].descr_handle == param->write.handle && param->write.len == 2) 
        {
            uint16_t descr_value= param->write.value[1]<<8 | param->write.value[0];
            if (descr_value == 0x0001)
            {
                if (b_property & ESP_GATT_CHAR_PROP_BIT_NOTIFY)
                {
                    DEV_PRINTF("notify enable");
                    uint8_t notify_data[15];
                    for (int i = 0; i < sizeof(notify_data); ++i)
                    {
                        notify_data[i] = i%0xff;
                    }
                    //the size of notify_data[] need less than MTU size
                    esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, gl_profile_tab[PROFILE_B_APP_ID].char_handle,
                                            sizeof(notify_data), notify_data, false);
                }
            }else if (descr_value == 0x0002)
            {
                if (b_property & ESP_GATT_CHAR_PROP_BIT_INDICATE)
                {
                    DEV_PRINTF("indicate enable");
                    uint8_t indicate_data[15];
                    for (int i = 0; i < sizeof(indicate_data); ++i)
                    {
                        indicate_data[i] = i%0xff;
                    }
                    esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, gl_profile_tab[PROFILE_B_APP_ID].char_handle,
                                            sizeof(indicate_data), indicate_data, true);
                }
            }
            else if (descr_value == 0x0000){
                DEV_PRINTF("notify/indicate disable ");
            }else{
                DEV_PRINTF("unknown value");
            }

        }
    }
    example_write_event_env(gatts_if, &b_prepare_write_env, param);
}

有关APP得测试:
IOS : NRF CONNECT
ANDROID : NRF CONNECT
下面是测试图片:

进行一次连接和断开操作,发现都存在事件回调
在这里插入图片描述
下面是收到APP的数据
在这里插入图片描述


IOS系统的NRF CONECT 软件操作:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


ANDROID系统的NRF CONECT 软件操作:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
关注微信公众号 一起学习 ( 技术Code城 )

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值