BLE GATTS_READ_EVT - diferenciate via handle

jtantera
Posts: 6
Joined: Thu Mar 03, 2022 3:22 pm

BLE GATTS_READ_EVT - diferenciate via handle

Postby jtantera » Thu Nov 23, 2023 4:36 pm

Hi to all.
I am making a bluetooth BLE aplication and i want to create serveral characteristics under the same service, some of those are for Notify, some are for Read and some for Write.
I had made the Notify ones and they work as i want. I have a function that its called via a timer that indicates when the data is ready and that function sends the notify data.
The problem its when i want to read or write... since there are several characteristics and i am trying to diferenciate from the handler. I cant find how to make this. I dont know what to compare... what to write inside the "if" statment.
I had started from the "gatt_server_service_table" example.
I have asked google and chatGPT but no success.

Can you help me?

Search for "-----------------------------> HERE IS THE PROBLEM <----------------------------------" in the codebox

Full Database Description
  1. /* Full Database Description - Used to add attributes into the database */
  2. static const esp_gatts_attr_db_t gatt_db[HRS_IDX_NB] =
  3. {
  4.     // Service Declaration
  5.     [IDX_SVC]        =
  6.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ,
  7.       sizeof(uint16_t), sizeof(GATTS_SERVICE_UUID_TEST), (uint8_t *)&GATTS_SERVICE_UUID_TEST}},
  8.  
  9.     /* Characteristic Declaration */
  10.     [IDX_CHAR_A]     =
  11.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
  12.       CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_write_notify}},
  13.  
  14.     /* Characteristic Value */
  15.     [IDX_CHAR_VAL_A] =
  16.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID_TEST_A, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  17.       GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(char_value), (uint8_t *)char_value}},
  18.  
  19.     /* Client Characteristic Configuration Descriptor */
  20.     [IDX_CHAR_CFG_A]  =
  21.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  22.       sizeof(uint16_t), sizeof(heart_measurement_ccc), (uint8_t *)heart_measurement_ccc}},
  23.  
  24.     /* Characteristic Declaration */
  25.     [IDX_CHAR_B]      =
  26.     {{ESP_GATT_RSP_BY_APP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
  27.       CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read}},
  28.  
  29.     /* Characteristic Value */
  30.     [IDX_CHAR_VAL_B]  =
  31.     {{ESP_GATT_RSP_BY_APP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID_TEST_B, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  32.       GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(char_value), (uint8_t *)char_value}},
  33.  
  34.     /* Descripción para Característica B */
  35.     [IDX_CHAR_DESCR_B] =
  36.     {{ESP_GATT_RSP_BY_APP}, {ESP_UUID_LEN_16, (uint8_t *)&descr_uuid, ESP_GATT_PERM_READ,
  37.       strlen(CHAR_DESCRIP_B), strlen(CHAR_DESCRIP_B), (uint8_t *)CHAR_DESCRIP_B}},
  38.  
  39.     /* Characteristic Declaration */
  40.     [IDX_CHAR_C]      =
  41.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
  42.       CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_write}},
  43.  
  44.     /* Characteristic Value */
  45.     [IDX_CHAR_VAL_C]  =
  46.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID_TEST_C, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  47.       GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(char_value), (uint8_t *)char_value}},
  48.      
  49.     /* Descripción para Característica C */
  50.     [IDX_CHAR_DESCR_C] =
  51.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&descr_uuid, ESP_GATT_PERM_READ,
  52.       strlen(CHAR_DESCRIP_C), strlen(CHAR_DESCRIP_C), (uint8_t *)CHAR_DESCRIP_C}},
  53.  
  54.     /* Agregado por Jose */
  55.     /* Characteristic Declaration */
  56.     [IDX_CHAR_D]     =
  57.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
  58.       CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}},
  59.  
  60.     /* Characteristic Value */
  61.     [IDX_CHAR_VAL_D] =
  62.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID_TEST_D, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  63.       GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(char_value), (uint8_t *)char_value}},
  64.  
  65.     /* Client Characteristic Configuration Descriptor */
  66.     [IDX_CHAR_CFG_D]  =
  67.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  68.       sizeof(uint16_t), sizeof(heart_measurement_ccc), (uint8_t *)heart_measurement_ccc}},
  69.  
  70.     /* Descripción para Característica E */
  71.     [IDX_CHAR_DESCR_D] =
  72.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&descr_uuid, ESP_GATT_PERM_READ,
  73.       strlen(CHAR_DESCRIP_D), strlen(CHAR_DESCRIP_D), (uint8_t *)CHAR_DESCRIP_D}},
  74.  
  75.     /* Characteristic Declaration */
  76.     [IDX_CHAR_E]     =
  77.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
  78.       CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}},
  79.  
  80.     /* Characteristic Value */
  81.     [IDX_CHAR_VAL_E] =
  82.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID_TEST_E, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  83.       GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(char_value), (uint8_t *)char_value}},
  84.  
  85.     /* Client Characteristic Configuration Descriptor */
  86.     [IDX_CHAR_CFG_E]  =
  87.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  88.       sizeof(uint16_t), sizeof(heart_measurement_ccc), (uint8_t *)heart_measurement_ccc}},
  89.  
  90.     /* Descripción para Característica E */
  91.     [IDX_CHAR_DESCR_E] =
  92.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&descr_uuid, ESP_GATT_PERM_READ,
  93.       strlen(CHAR_DESCRIP_E), strlen(CHAR_DESCRIP_E), (uint8_t *)CHAR_DESCRIP_E}},
  94.  
  95.  
  96.     //CARACTERISTICAS DE ESCRITURA
  97.     /* Characteristic Declaration */
  98.     [IDX_CHAR_0]     =
  99.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
  100.       CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}},
  101.  
  102.     /* Characteristic Value */
  103.     [IDX_CHAR_VAL_0] =
  104.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID_TEST_0, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  105.       GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(char_value), (uint8_t *)char_value}},
  106.  
  107.     /* Client Characteristic Configuration Descriptor */
  108.     [IDX_CHAR_CFG_0]  =
  109.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  110.       sizeof(uint16_t), sizeof(heart_measurement_ccc), (uint8_t *)heart_measurement_ccc}},
  111.  
  112.     /* Descripción para Característica E */
  113.     [IDX_CHAR_DESCR_0] =
  114.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&descr_uuid, ESP_GATT_PERM_READ,
  115.       strlen(CHAR_DESCRIP_0), strlen(CHAR_DESCRIP_0), (uint8_t *)CHAR_DESCRIP_0}},
  116.    
  117.     [IDX_CHAR_1]     =
  118.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
  119.       CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}},
  120.  
  121.     /* Characteristic Value */
  122.     [IDX_CHAR_VAL_1] =
  123.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID_TEST_1, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  124.       GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(char_value), (uint8_t *)char_value}},
  125.  
  126.     /* Client Characteristic Configuration Descriptor */
  127.     [IDX_CHAR_CFG_1]  =
  128.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  129.       sizeof(uint16_t), sizeof(heart_measurement_ccc), (uint8_t *)heart_measurement_ccc}},
  130.  
  131.     /* Descripción para Característica E */
  132.     [IDX_CHAR_DESCR_1] =
  133.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&descr_uuid, ESP_GATT_PERM_READ,
  134.       strlen(CHAR_DESCRIP_1), strlen(CHAR_DESCRIP_1), (uint8_t *)CHAR_DESCRIP_1}},
  135.    
  136.     [IDX_CHAR_2]     =
  137.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
  138.       CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}},
  139.  
  140.     /* Characteristic Value */
  141.     [IDX_CHAR_VAL_2] =
  142.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID_TEST_2, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  143.       GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(char_value), (uint8_t *)char_value}},
  144.  
  145.     /* Client Characteristic Configuration Descriptor */
  146.     [IDX_CHAR_CFG_2]  =
  147.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  148.       sizeof(uint16_t), sizeof(heart_measurement_ccc), (uint8_t *)heart_measurement_ccc}},
  149.  
  150.     /* Descripción para Característica E */
  151.     [IDX_CHAR_DESCR_2] =
  152.     {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&descr_uuid, ESP_GATT_PERM_READ,
  153.       strlen(CHAR_DESCRIP_2), strlen(CHAR_DESCRIP_2), (uint8_t *)CHAR_DESCRIP_2}},
  154. };

  1. static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
  2. {
  3.     switch (event) {
  4.         case ESP_GATTS_REG_EVT:{
  5.             esp_err_t set_dev_name_ret = esp_ble_gap_set_device_name(SAMPLE_DEVICE_NAME);
  6.             if (set_dev_name_ret){
  7.                 ESP_LOGE(GATTS_TABLE_TAG, "set device name failed, error code = %x", set_dev_name_ret);
  8.             }
  9.     #ifdef CONFIG_SET_RAW_ADV_DATA
  10.             esp_err_t raw_adv_ret = esp_ble_gap_config_adv_data_raw(raw_adv_data, sizeof(raw_adv_data));
  11.             if (raw_adv_ret){
  12.                 ESP_LOGE(GATTS_TABLE_TAG, "config raw adv data failed, error code = %x ", raw_adv_ret);
  13.             }
  14.             adv_config_done |= ADV_CONFIG_FLAG;
  15.             esp_err_t raw_scan_ret = esp_ble_gap_config_scan_rsp_data_raw(raw_scan_rsp_data, sizeof(raw_scan_rsp_data));
  16.             if (raw_scan_ret){
  17.                 ESP_LOGE(GATTS_TABLE_TAG, "config raw scan rsp data failed, error code = %x", raw_scan_ret);
  18.             }
  19.             adv_config_done |= SCAN_RSP_CONFIG_FLAG;
  20.     #else
  21.             //config adv data
  22.             esp_err_t ret = esp_ble_gap_config_adv_data(&adv_data);
  23.             if (ret){
  24.                 ESP_LOGE(GATTS_TABLE_TAG, "config adv data failed, error code = %x", ret);
  25.             }
  26.             adv_config_done |= ADV_CONFIG_FLAG;
  27.             //config scan response data
  28.             ret = esp_ble_gap_config_adv_data(&scan_rsp_data);
  29.             if (ret){
  30.                 ESP_LOGE(GATTS_TABLE_TAG, "config scan response data failed, error code = %x", ret);
  31.             }
  32.             adv_config_done |= SCAN_RSP_CONFIG_FLAG;
  33.     #endif
  34.             esp_err_t create_attr_ret = esp_ble_gatts_create_attr_tab(gatt_db, gatts_if, HRS_IDX_NB, SVC_INST_ID);
  35.             if (create_attr_ret){
  36.                 ESP_LOGE(GATTS_TABLE_TAG, "create attr table failed, error code = %x", create_attr_ret);
  37.             }
  38.         }
  39.             break;
  40.         case ESP_GATTS_READ_EVT:
  41.             ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_READ_EVT");
  42.             esp_gatt_rsp_t rsp;
  43.             memset(&rsp, 0, sizeof(esp_gatt_rsp_t));
  44.             rsp.attr_value.handle = param->read.handle;
  45.  
  46.             if (-----------------------------> HERE IS THE PROBLEM <----------------------------------){
  47.                 if ( getWifiConnStatus() != WIFI_STATUS_OFF ) {
  48.                     rsp.attr_value.len = 6;
  49.                     uint64_t productUID = getUniqueID();                                    //TODO Modificar esto para que lea el UID desde la memoria y no desde la MAC, por si mañana cambia
  50.                     //ESP_LOGI(GATTS_TABLE_TAG, "MAC = %lld", productUID);
  51.                     for (uint8_t i = 0 ; i < 6 ; i++){
  52.                         rsp.attr_value.value[i] = ((uint8_t)(productUID>>(8*i)) & 0xFF);
  53.                         //ESP_LOGI(GATTS_TABLE_TAG, "Byte = %d", rsp.attr_value.value[i]);
  54.                     }
  55.                 }
  56.             }
  57.            
  58.             esp_ble_gatts_send_response(gatts_if, param->read.conn_id, param->read.trans_id,
  59.                                         ESP_GATT_OK, &rsp);
  60.             break;
  61.         case ESP_GATTS_WRITE_EVT:
  62.             if (!param->write.is_prep){
  63.                 // the data length of gattc write  must be less than GATTS_DEMO_CHAR_VAL_LEN_MAX.
  64.                 ESP_LOGI(GATTS_TABLE_TAG, "GATT_WRITE_EVT, handle = %d, value len = %d, value :", param->write.handle, param->write.len);
  65.                 esp_log_buffer_hex(GATTS_TABLE_TAG, param->write.value, param->write.len);
  66.  
  67.                 //Habilitacion de notificaciones de caracteristicas
  68.                 if (heart_rate_handle_table[IDX_CHAR_CFG_A] == param->write.handle && param->write.len == 2){
  69.                     uint16_t descr_value = param->write.value[1]<<8 | param->write.value[0];
  70.                     if (descr_value == 0x0001){
  71.                         ESP_LOGI(GATTS_TABLE_TAG, "notify enable");
  72.                         heart_rate_profile_tab[PROFILE_APP_IDX].conn_id = param->write.conn_id;
  73.  
  74.                     }else if (descr_value == 0x0002){
  75.                         ESP_LOGI(GATTS_TABLE_TAG, "indicate enable");
  76.                         uint8_t indicate_data[15];
  77.                         for (int i = 0; i < sizeof(indicate_data); ++i)
  78.                         {
  79.                             indicate_data[i] = i % 0xff;
  80.                         }
  81.                         //the size of indicate_data[] need less than MTU size
  82.                         esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, heart_rate_handle_table[IDX_CHAR_VAL_A],
  83.                                             sizeof(indicate_data), indicate_data, true);
  84.                     }
  85.                     else if (descr_value == 0x0000){
  86.                         ESP_LOGI(GATTS_TABLE_TAG, "notify/indicate disable ");
  87.                         //setBTMotorSpeedNotifStatus(NOTIF_DISABLED);
  88.  
  89.                     }else{
  90.                         ESP_LOGE(GATTS_TABLE_TAG, "unknown descr value");
  91.                         esp_log_buffer_hex(GATTS_TABLE_TAG, param->write.value, param->write.len);
  92.                     }
  93.  
  94.                 }
  95.  
  96.                 //Velocidad del Motor
  97.                 if (heart_rate_handle_table[IDX_CHAR_CFG_D] == param->write.handle && param->write.len == 2){
  98.                     uint16_t descr_value = param->write.value[1]<<8 | param->write.value[0];
  99.                     if (descr_value == 0x0001){
  100.                         ESP_LOGI(GATTS_TABLE_TAG, "notify enable");
  101.                         heart_rate_profile_tab[PROFILE_APP_IDX].conn_id = param->write.conn_id;
  102.                         setBTMotorSpeedNotifStatus(NOTIF_ENABLED);          //Agregado por Jose
  103.  
  104.                     }else if (descr_value == 0x0002){
  105.                         ESP_LOGI(GATTS_TABLE_TAG, "indicate enable");
  106.                         uint8_t indicate_data[15];
  107.                         for (int i = 0; i < sizeof(indicate_data); ++i)
  108.                         {
  109.                             indicate_data[i] = i % 0xff;
  110.                         }
  111.                         //the size of indicate_data[] need less than MTU size
  112.                         esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, heart_rate_handle_table[IDX_CHAR_VAL_A],
  113.                                             sizeof(indicate_data), indicate_data, true);
  114.                     }
  115.                     else if (descr_value == 0x0000){
  116.                         ESP_LOGI(GATTS_TABLE_TAG, "notify/indicate disable ");
  117.                         xTimerStop(notify_timer_handle, 0);
  118.                         setBTMotorSpeedNotifStatus(NOTIF_DISABLED);          //Agregado por Jose
  119.  
  120.                     }else{
  121.                         ESP_LOGE(GATTS_TABLE_TAG, "unknown descr value");
  122.                         esp_log_buffer_hex(GATTS_TABLE_TAG, param->write.value, param->write.len);
  123.                     }
  124.  
  125.                 }
  126.                
  127.                 //Potencia del Motor
  128.                 if (heart_rate_handle_table[IDX_CHAR_CFG_E] == param->write.handle && param->write.len == 2){
  129.                     uint16_t descr_value = param->write.value[1]<<8 | param->write.value[0];
  130.                     if (descr_value == 0x0001){
  131.                         ESP_LOGI(GATTS_TABLE_TAG, "notify enable");
  132.                         heart_rate_profile_tab[PROFILE_APP_IDX].conn_id = param->write.conn_id;
  133.                         setBTMotorPowerNotifStatus(NOTIF_ENABLED);          //Agregado por Jose
  134.  
  135.                     }else if (descr_value == 0x0002){
  136.                         ESP_LOGI(GATTS_TABLE_TAG, "indicate enable");
  137.                         uint8_t indicate_data[15];
  138.                         for (int i = 0; i < sizeof(indicate_data); ++i)
  139.                         {
  140.                             indicate_data[i] = i % 0xff;
  141.                         }
  142.                         //the size of indicate_data[] need less than MTU size
  143.                         esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, heart_rate_handle_table[IDX_CHAR_VAL_A],
  144.                                             sizeof(indicate_data), indicate_data, true);
  145.                     }
  146.                     else if (descr_value == 0x0000){
  147.                         ESP_LOGI(GATTS_TABLE_TAG, "notify/indicate disable ");
  148.                         xTimerStop(notify_timer_handle, 0);
  149.                         setBTMotorPowerNotifStatus(NOTIF_DISABLED);          //Agregado por Jose
  150.  
  151.                     }else{
  152.                         ESP_LOGE(GATTS_TABLE_TAG, "unknown descr value");
  153.                         esp_log_buffer_hex(GATTS_TABLE_TAG, param->write.value, param->write.len);
  154.                     }
  155.  
  156.                 }
  157.                
  158.                 /* send response when param->write.need_rsp is true*/
  159.                 if (param->write.need_rsp){
  160.                     esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL);
  161.                 }
  162.             }else{
  163.                 /* handle prepare write */
  164.                 example_prepare_write_event_env(gatts_if, &prepare_write_env, param);
  165.             }
  166.             break;
  167.         case ESP_GATTS_EXEC_WRITE_EVT:
  168.             // the length of gattc prepare write data must be less than GATTS_DEMO_CHAR_VAL_LEN_MAX.
  169.             ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_EXEC_WRITE_EVT");
  170.             example_exec_write_event_env(&prepare_write_env, param);
  171.             break;
  172.         case ESP_GATTS_MTU_EVT:
  173.             ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_MTU_EVT, MTU %d", param->mtu.mtu);
  174.             break;
  175.         case ESP_GATTS_CONF_EVT:
  176.             //ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_CONF_EVT, status = %d, attr_handle %d", param->conf.status, param->conf.handle);
  177.             break;
  178.         case ESP_GATTS_START_EVT:
  179.             ESP_LOGI(GATTS_TABLE_TAG, "SERVICE_START_EVT, status %d, service_handle %d", param->start.status, param->start.service_handle);
  180.             break;
  181.         case ESP_GATTS_CONNECT_EVT:
  182.             ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_CONNECT_EVT, conn_id = %d", param->connect.conn_id);
  183.            
  184.             //Agregada por Jose
  185.             setBTStatus(BT_CONNECTED);
  186.  
  187.             esp_log_buffer_hex(GATTS_TABLE_TAG, param->connect.remote_bda, 6);
  188.             esp_ble_conn_update_params_t conn_params = {0};
  189.             memcpy(conn_params.bda, param->connect.remote_bda, sizeof(esp_bd_addr_t));
  190.             /* For the iOS system, please refer to Apple official documents about the BLE connection parameters restrictions. */
  191.             conn_params.latency = 0;
  192.             conn_params.max_int = 0x20;    // max_int = 0x20*1.25ms = 40ms
  193.             conn_params.min_int = 0x10;    // min_int = 0x10*1.25ms = 20ms
  194.             conn_params.timeout = 400;    // timeout = 400*10ms = 4000ms
  195.             //start sent the update connection parameters to the peer device.
  196.             esp_ble_gap_update_conn_params(&conn_params);
  197.             break;
  198.         case ESP_GATTS_DISCONNECT_EVT:
  199.             ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_DISCONNECT_EVT, reason = 0x%x", param->disconnect.reason);
  200.            
  201.             setBTStatus(BT_DISCONNECTED);       //Agregada por Jose
  202.            
  203.             esp_ble_gap_start_advertising(&adv_params);
  204.             break;
  205.         case ESP_GATTS_CREAT_ATTR_TAB_EVT:{
  206.             if (param->add_attr_tab.status != ESP_GATT_OK){
  207.                 ESP_LOGE(GATTS_TABLE_TAG, "create attribute table failed, error code=0x%x", param->add_attr_tab.status);
  208.             }
  209.             else if (param->add_attr_tab.num_handle != HRS_IDX_NB){
  210.                 ESP_LOGE(GATTS_TABLE_TAG, "create attribute table abnormally, num_handle (%d) \
  211.                         doesn't equal to HRS_IDX_NB(%d)", param->add_attr_tab.num_handle, HRS_IDX_NB);
  212.             }
  213.             else {
  214.                 ESP_LOGI(GATTS_TABLE_TAG, "create attribute table successfully, the number handle = %d\n",param->add_attr_tab.num_handle);
  215.                 memcpy(heart_rate_handle_table, param->add_attr_tab.handles, sizeof(heart_rate_handle_table));
  216.                 esp_ble_gatts_start_service(heart_rate_handle_table[IDX_SVC]);
  217.             }
  218.             break;
  219.         }
  220.         case ESP_GATTS_STOP_EVT:
  221.         case ESP_GATTS_OPEN_EVT:
  222.         case ESP_GATTS_CANCEL_OPEN_EVT:
  223.         case ESP_GATTS_CLOSE_EVT:
  224.         case ESP_GATTS_LISTEN_EVT:
  225.         case ESP_GATTS_CONGEST_EVT:
  226.         case ESP_GATTS_UNREG_EVT:
  227.         case ESP_GATTS_DELETE_EVT:
  228.         default:
  229.             break;
  230.     }
  231. }

MicroController
Posts: 1706
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: BLE GATTS_READ_EVT - diferenciate via handle

Postby MicroController » Fri Nov 24, 2023 12:15 pm

The example creates an 'attribute table' and then receives the ESP_GATTS_CREAT_ATTR_TAB_EVT from which it takes the handles of all attributes so that it can later reference a handle back to an attribute.

jtantera
Posts: 6
Joined: Thu Mar 03, 2022 3:22 pm

Re: BLE GATTS_READ_EVT - diferenciate via handle

Postby jtantera » Fri Nov 24, 2023 2:42 pm

MicroController wrote:
Fri Nov 24, 2023 12:15 pm
The example creates an 'attribute table' and then receives the ESP_GATTS_CREAT_ATTR_TAB_EVT from which it takes the handles of all attributes so that it can later reference a handle back to an attribute.
Sorry but i dont quite undertand. I am quite new in ESP32 and specially in Bluetooth BLE.
This line memcpy takes the handles al copys them into the heart_rate_handle_table.
Where i can connect the read event from the IDX_CHAR_B or any other one to a function that can reply the information that i want.

I dont understand quite yet all the data_base created.

Thanks for your response

MicroController
Posts: 1706
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: BLE GATTS_READ_EVT - diferenciate via handle

Postby MicroController » Sat Nov 25, 2023 11:19 am

jtantera wrote:
Fri Nov 24, 2023 2:42 pm
Where i can connect the read event from the IDX_CHAR_B or any other one to a function that can reply the information that i want.
Yeah, the example doesn't make it very clear.
The trick is that you define your GATT database, i.e. a list/array of all the BLE attributes you want to provide. Then you pass this list of N attributes (N=HRS_IDX_NB in this case) to esp_ble_gatts_create_attr_tab(...) and in response you get the ESP_GATTS_CREAT_ATTR_TAB_EVT event which contains a list of N handles. In this handle list, the i-th entry corresponds to the i-th attribute from the list you passed to esp_ble_gatts_create_attr_tab(...).

So you could do:

Code: Select all

static const uint32_t ATTRIBUTE_COUNT = sizeof(gatt_db)/sizeof(*gatt_db); // # of attribute entries in the gatt_db
static uint16_t handle_list[ATTRIBUTE_COUNT]; // <- to be filled by handling ESP_GATTS_CREAT_ATTR_TAB_EVT 

const esp_gatts_attr_db_t* get_attribute_by_handle(const uint16_t handle) {
  for(int i = 0; i < ATTRIBUTE_COUNT; ++i ) {
    if(handle_list[i] == handle) {
	  return &(gatt_db[i]);
    }
  }
  return NULL; // handle not found?!
}
or like the example does it:

Code: Select all

if(handle_list[MY_ATTRIBUTE_X_INDEX] == handle) {
  // Handle attribute X...
} else
if(handle_list[MY_ATTRIBUTE_Y_INDEX] == handle) {
  // Handle attribute Y...
} ...

jtantera
Posts: 6
Joined: Thu Mar 03, 2022 3:22 pm

Re: BLE GATTS_READ_EVT - diferenciate via handle

Postby jtantera » Mon Nov 27, 2023 2:17 pm

I think that I understand you.
You propose to create this function

Code: Select all

const esp_gatts_attr_db_t* get_attribute_by_handle(const uint16_t handle)
This function returns the index in the table acording to the handle passed.

You propoouse tu fill the static uint16_t handle_list[ATTRIBUTE_COUNT] during the ESP_GATTS_CREAT_ATTR_TAB_EVT

Something like this?

Code: Select all

memcpy(handle_list, param->add_attr_tab.handles, sizeof(handle_list));
Then when the event ESP_GATTS_READ_EVT its triggered, I can select the handler using the index return of

Code: Select all

get_attribute_by_handle(param->read.handle)
.

I understand right?



I can't find this in the example, i asume that its an example made by you
MicroController wrote:
Sat Nov 25, 2023 11:19 am
or like the example does it:

Code: Select all

if(handle_list[MY_ATTRIBUTE_X_INDEX] == handle) {
  // Handle attribute X...
} else
if(handle_list[MY_ATTRIBUTE_Y_INDEX] == handle) {
  // Handle attribute Y...
} ...

MicroController
Posts: 1706
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: BLE GATTS_READ_EVT - diferenciate via handle

Postby MicroController » Tue Nov 28, 2023 8:03 am

jtantera wrote:
Mon Nov 27, 2023 2:17 pm
I understand right?
Yes :)
I can't find this in the example, i asume that its an example made by you
MicroController wrote:
Sat Nov 25, 2023 11:19 am
or like the example does it:

Code: Select all

if(handle_list[MY_ATTRIBUTE_X_INDEX] == handle) {
  // Handle attribute X...
} else
if(handle_list[MY_ATTRIBUTE_Y_INDEX] == handle) {
  // Handle attribute Y...
} ...
It's just my attempt to more clearly show the logic in the example(s), i.e.

Code: Select all

//Habilitacion de notificaciones de caracteristicas
if (heart_rate_handle_table[IDX_CHAR_CFG_A] == param->write.handle && param->write.len == 2){
...

jtantera
Posts: 6
Joined: Thu Mar 03, 2022 3:22 pm

Re: BLE GATTS_READ_EVT - diferenciate via handle

Postby jtantera » Tue Nov 28, 2023 8:48 am

Thank you VERY MUCH!
I will try to implement this and let you know how it works.

Again thanks for your time! :D

jtantera
Posts: 6
Joined: Thu Mar 03, 2022 3:22 pm

Re: BLE GATTS_READ_EVT - diferenciate via handle

Postby jtantera » Tue Nov 28, 2023 10:55 am

So, i implemented some code and star testing it.

Here is how my DB was configured:
  1. /* Full Database Description - Used to add attributes into the database */
  2. static const esp_gatts_attr_db_t gatt_db[HRS_IDX_NB] =
  3. {
  4.  // Service Declaration
  5.  [IDX_SVC]        =
  6.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ,
  7.    sizeof(uint16_t), sizeof(GATTS_SERVICE_UUID_TEST), (uint8_t *)&GATTS_SERVICE_UUID_TEST}},
  8.  
  9.  /* Characteristic Declaration */
  10.  [IDX_CHAR_A]     =
  11.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
  12.    CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_write_notify}},
  13.  
  14. /* Characteristic Value */
  15.  [IDX_CHAR_VAL_A] =
  16.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID_TEST_A, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  17.    GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(char_value), (uint8_t *)char_value}},
  18.  
  19.  /* Client Characteristic Configuration Descriptor */
  20.  [IDX_CHAR_CFG_A]  =
  21.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  22.    sizeof(uint16_t), sizeof(heart_measurement_ccc), (uint8_t *)heart_measurement_ccc}},
  23.  
  24.  /* Characteristic Declaration */
  25.  [IDX_CHAR_B]      =
  26.  {{ESP_GATT_RSP_BY_APP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
  27.    CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read}},
  28.  
  29. /* Characteristic Value */
  30.  [IDX_CHAR_VAL_B]  =
  31.  {{ESP_GATT_RSP_BY_APP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID_TEST_B, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  32.   GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(char_value), (uint8_t *)char_value}},
  33.  
  34.  /* Descripción para Característica B */
  35.  [IDX_CHAR_DESCR_B] =
  36.  {{ESP_GATT_RSP_BY_APP}, {ESP_UUID_LEN_16, (uint8_t *)&descr_uuid, ESP_GATT_PERM_READ,
  37.    strlen(CHAR_DESCRIP_B), strlen(CHAR_DESCRIP_B), (uint8_t *)CHAR_DESCRIP_B}},
  38.  
  39.  /* Client Characteristic Configuration Descriptor */
  40.  [IDX_CHAR_CFG_B]  =
  41.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  42.    sizeof(uint16_t), sizeof(heart_measurement_ccc), (uint8_t *)heart_measurement_ccc}},
  43.  
  44.  /* Characteristic Declaration */
  45.  [IDX_CHAR_C]      =
  46.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
  47.    CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_write}},
  48.  
  49.  /* Characteristic Value */
  50.  [IDX_CHAR_VAL_C]  =
  51.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID_TEST_C, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  52.       GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(char_value), (uint8_t *)char_value}},
  53.      
  54.  /* Descripción para Característica C */
  55.  [IDX_CHAR_DESCR_C] =
  56.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&descr_uuid, ESP_GATT_PERM_READ,
  57.    strlen(CHAR_DESCRIP_C), strlen(CHAR_DESCRIP_C), (uint8_t *)CHAR_DESCRIP_C}},
  58.    
  59.  /* Client Characteristic Configuration Descriptor */
  60.  [IDX_CHAR_CFG_C]  =
  61.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  62.    sizeof(uint16_t), sizeof(heart_measurement_ccc), (uint8_t *)heart_measurement_ccc}},
  63.  
  64.  
  65.  /* Characteristic Declaration */
  66.  [IDX_CHAR_D]     =
  67.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
  68.    CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}},
  69.  
  70.  /* Characteristic Value */
  71.  [IDX_CHAR_VAL_D] =
  72.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID_TEST_D, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  73.    GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(char_value), (uint8_t *)char_value}},
  74.  
  75.  /* Client Characteristic Configuration Descriptor */
  76.  [IDX_CHAR_CFG_D]  =
  77.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  78.    sizeof(uint16_t), sizeof(heart_measurement_ccc), (uint8_t *)heart_measurement_ccc}},
  79.  
  80.  /* Descripción para Característica E */
  81.  [IDX_CHAR_DESCR_D] =
  82.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&descr_uuid, ESP_GATT_PERM_READ,
  83.    strlen(CHAR_DESCRIP_D), strlen(CHAR_DESCRIP_D), (uint8_t *)CHAR_DESCRIP_D}},
  84.  
  85.  /* Characteristic Declaration */
  86.  [IDX_CHAR_E]     =
  87.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
  88.    CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}},
  89.  
  90.  /* Characteristic Value */
  91.  [IDX_CHAR_VAL_E] =
  92.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID_TEST_E, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  93.    GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(char_value), (uint8_t *)char_value}},
  94.  
  95.  /* Client Characteristic Configuration Descriptor */
  96.  [IDX_CHAR_CFG_E]  =
  97.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  98.    sizeof(uint16_t), sizeof(heart_measurement_ccc), (uint8_t *)heart_measurement_ccc}},
  99.  
  100.  /* Descripción para Característica E */
  101.  [IDX_CHAR_DESCR_E] =
  102.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&descr_uuid, ESP_GATT_PERM_READ,
  103.   strlen(CHAR_DESCRIP_E), strlen(CHAR_DESCRIP_E), (uint8_t *)CHAR_DESCRIP_E}},
  104.  
  105.  
  106.  //CARACTERISTICAS DE ESCRITURA
  107.  /* Characteristic Declaration */
  108.  [IDX_CHAR_0]     =
  109.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
  110.    CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}},
  111.  
  112.  /* Characteristic Value */
  113.  [IDX_CHAR_VAL_0] =
  114.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID_TEST_0, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  115.   GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(char_value), (uint8_t *)char_value}},
  116.  
  117.  /* Client Characteristic Configuration Descriptor */
  118.  [IDX_CHAR_CFG_0]  =
  119.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  120.   sizeof(uint16_t), sizeof(heart_measurement_ccc), (uint8_t *)heart_measurement_ccc}},
  121.  
  122.  /* Descripción para Característica E */
  123.  [IDX_CHAR_DESCR_0] =
  124.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&descr_uuid, ESP_GATT_PERM_READ,
  125.    strlen(CHAR_DESCRIP_0), strlen(CHAR_DESCRIP_0), (uint8_t *)CHAR_DESCRIP_0}},
  126.    
  127.  [IDX_CHAR_1]     =
  128.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
  129.    CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}},
  130.  
  131.  /* Characteristic Value */
  132.  [IDX_CHAR_VAL_1] =
  133.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID_TEST_1, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  134.    GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(char_value), (uint8_t *)char_value}},
  135.  
  136.  /* Client Characteristic Configuration Descriptor */
  137.  [IDX_CHAR_CFG_1]  =
  138.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  139.    sizeof(uint16_t), sizeof(heart_measurement_ccc), (uint8_t *)heart_measurement_ccc}},
  140.  
  141.  /* Descripción para Característica E */
  142.  [IDX_CHAR_DESCR_1] =
  143.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&descr_uuid, ESP_GATT_PERM_READ,
  144.   strlen(CHAR_DESCRIP_1), strlen(CHAR_DESCRIP_1), (uint8_t *)CHAR_DESCRIP_1}},
  145.    
  146.  [IDX_CHAR_2]     =
  147.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
  148.   CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}},
  149.  
  150.  /* Characteristic Value */
  151.  [IDX_CHAR_VAL_2] =
  152.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID_TEST_2, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  153.    GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(char_value), (uint8_t *)char_value}},
  154.  
  155.  /* Client Characteristic Configuration Descriptor */
  156.  [IDX_CHAR_CFG_2]  =
  157.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
  158.    sizeof(uint16_t), sizeof(heart_measurement_ccc), (uint8_t *)heart_measurement_ccc}},
  159.  
  160.  /* Descripción para Característica E */
  161.  [IDX_CHAR_DESCR_2] =
  162.  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&descr_uuid, ESP_GATT_PERM_READ,
  163.   strlen(CHAR_DESCRIP_2), strlen(CHAR_DESCRIP_2), (uint8_t *)CHAR_DESCRIP_2}},
  164. };
Here its the implementation of the ESP_GATTS_READ_EVT
  1. case ESP_GATTS_READ_EVT:
  2.     ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_READ_EVT");
  3.     esp_gatt_rsp_t rsp;
  4.     memset(&rsp, 0, sizeof(esp_gatt_rsp_t));
  5.     rsp.attr_value.handle = param->read.handle;
  6.  
  7.     ESP_LOGI(GATTS_TABLE_TAG, "param->read.handle = %d", param->read.handle);
  8.     ESP_LOGI(GATTS_TABLE_TAG, "heart_rate_handle_table[IDX_CHAR_CFG_A] = %d", heart_rate_handle_table[IDX_CHAR_CFG_A]);
  9.     ESP_LOGI(GATTS_TABLE_TAG, "heart_rate_handle_table[IDX_CHAR_CFG_B] = %d", heart_rate_handle_table[IDX_CHAR_CFG_B]);
  10.     ESP_LOGI(GATTS_TABLE_TAG, "heart_rate_handle_table[IDX_CHAR_CFG_C] = %d", heart_rate_handle_table[IDX_CHAR_CFG_C]);
  11.     ESP_LOGI(GATTS_TABLE_TAG, "heart_rate_handle_table[IDX_CHAR_CFG_D] = %d", heart_rate_handle_table[IDX_CHAR_CFG_D]);
  12.     ESP_LOGI(GATTS_TABLE_TAG, "heart_rate_handle_table[IDX_CHAR_CFG_E] = %d", heart_rate_handle_table[IDX_CHAR_CFG_E]);
  13.     ESP_LOGI(GATTS_TABLE_TAG, "heart_rate_handle_table[IDX_CHAR_CFG_0] = %d", heart_rate_handle_table[IDX_CHAR_CFG_0]);
  14.     ESP_LOGI(GATTS_TABLE_TAG, "heart_rate_handle_table[IDX_CHAR_CFG_1] = %d", heart_rate_handle_table[IDX_CHAR_CFG_1]);
  15.     ESP_LOGI(GATTS_TABLE_TAG, "heart_rate_handle_table[IDX_CHAR_CFG_2] = %d", heart_rate_handle_table[IDX_CHAR_CFG_2]);
  16.  
  17.     if (heart_rate_handle_table[IDX_CHAR_CFG_A] == param->read.handle){
  18.         ESP_LOGI(GATTS_TABLE_TAG, "Read event IDX_CHAR_CFG_A");
  19.     } else if (heart_rate_handle_table[IDX_CHAR_CFG_B] == param->read.handle) {
  20.         ESP_LOGI(GATTS_TABLE_TAG, "Read event IDX_CHAR_CFG_B");
  21.     } else if (heart_rate_handle_table[IDX_CHAR_CFG_C] == param->read.handle) {
  22.         ESP_LOGI(GATTS_TABLE_TAG, "Read event IDX_CHAR_CFG_C");
  23.     }
  24.            
  25.     esp_ble_gatts_send_response(gatts_if, param->read.conn_id, param->read.trans_id,
  26.                             ESP_GATT_OK, &rsp);
  27.         break;
And here its the terminal LOG:
Image


I am using the app nRF Connect for Android to reand and write the values on the ESP32.
Image

The problem is when I use the A characteristic the event and handler works fine. But if i use the B characteristic the number of handler its wrong. I change the comparison of IDX_CHAR_CFG_B with other values to check but clearly there are several things that I don't quite understand about how the BT database works.

Can you tell me where I am missing?

I bought a course on UDEMY to try to understand it better but it's pretty bad and doesn't explain how things work.
Can you recommend a course or book to understand better this topic?

Again, thanks

MicroController
Posts: 1706
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: BLE GATTS_READ_EVT - diferenciate via handle

Postby MicroController » Tue Nov 28, 2023 2:00 pm

The characteristics in your service each are composed of three attributes, one for the characteristic declaration (e.g. at IDX_CHAR_A), one for the characteristic's value (e.g. IDX_CHAR_VAL_A) and one for the cccd (e.g. IDX_CHAR_CFG_A).
Commonly, the declaration is constant and the cccd should be handled by Bluedroid internally. So 1) you can leave them set to ESP_GATT_AUTO_RSP, and 2) you only care about accesses to the value attribute. If you want to handle these value accesses yourself, you should set the attribute to ESP_GATT_RSP_BY_APP instead of ESP_GATT_AUTO_RSP, and of course react to the handles of the value attribute(s) (e.g. IDX_CHAR_VAL_A), but not the other attributes (e.g. IDX_CHAR_CFG_A, IDX_CHAR_A) which are set to ESP_GATT_AUTO_RSP.

jtantera
Posts: 6
Joined: Thu Mar 03, 2022 3:22 pm

Re: BLE GATTS_READ_EVT - diferenciate via handle

Postby jtantera » Tue Nov 28, 2023 3:52 pm

What you just told me, make me realize that i was clicking the wrong button on the "nRF Connect" app.
Now its replying like it should.

Anyways, for all the only read characteristics i will leave ESP_GATT_RSP_BY_APP configuration, meanwhile all the notification characteristics i will leave the ESP_GATT_AUTO_RSP configuration.

Thanks again for your help.

Who is online

Users browsing this forum: No registered users and 102 guests