espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.51k stars 7.26k forks source link

gattc_demo.c gives error in "GATTC_DEMO: write char failed, error status = 3" (IDFGH-2022) #2807

Closed an-erd closed 5 years ago

an-erd commented 5 years ago

Environment

Problem Description

I used the code from the IDF from esp-idf/examples/bluetooth/gatt_client/main/ and only made the following changes:

#define REMOTE_SERVICE_UUID        0x1814  // RSC (Running Speed and Cadence)
#define REMOTE_NOTIFY_CHAR_UUID    0x2a53  // RSC Measurement
static const char remote_device_name[] = "MilestonePod";

and the decision whether we found our device just to check the beginning of the string remote_device_name:

case ESP_GAP_BLE_SCAN_RESULT_EVT: {
        esp_ble_gap_cb_param_t *scan_result = (esp_ble_gap_cb_param_t *)param;
        switch (scan_result->scan_rst.search_evt) {
        case ESP_GAP_SEARCH_INQ_RES_EVT:
            esp_log_buffer_hex(GATTC_TAG, scan_result->scan_rst.bda, 6);
            ESP_LOGI(GATTC_TAG, "searched Adv Data Len %d, Scan Response Len %d", scan_result->scan_rst.adv_data_len, scan_result->scan_rst.scan_rsp_len);
            adv_name = esp_ble_resolve_adv_data(scan_result->scan_rst.ble_adv,
                                                ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len);
            ESP_LOGI(GATTC_TAG, "searched Device Name Len %d", adv_name_len);
            esp_log_buffer_char(GATTC_TAG, adv_name, adv_name_len);
            ESP_LOGI(GATTC_TAG, "\n");
            if (adv_name != NULL) {
                if (strlen(remote_device_name) <= adv_name_len && strncmp((char *)adv_name, remote_device_name, strlen(remote_device_name)) == 0) {
                    ESP_LOGI(GATTC_TAG, "searched device %s\n", remote_device_name);
                    if (connect == false) {
                        connect = true;
                        ESP_LOGI(GATTC_TAG, "connect to the remote device.");
                        esp_ble_gap_stop_scanning();
                        esp_ble_gattc_open(gl_profile_tab[PROFILE_A_APP_ID].gattc_if, scan_result->scan_rst.bda, scan_result->scan_rst.ble_addr_type, true);
                    }
                }
            }
            break;

Everything else is unchanged. Full code:

/*
   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/

/****************************************************************************
*
* This file is for gatt client. It can scan ble device, connect one device.
* Run the gatt_server demo, the client demo will automatically connect to the gatt_server demo.
* Client demo will enable gatt_server's notify after connection. Then the two devices will exchange
* data.
*
****************************************************************************/

#include "../build/include/sdkconfig.h"     // TODO: nicer way to do it?
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#include "nvs.h"
#include "nvs_flash.h"

#include "esp_bt.h"
#include "esp_gap_ble_api.h"
#include "esp_gattc_api.h"
#include "esp_gatt_defs.h"
#include "esp_bt_main.h"
#include "esp_gatt_common_api.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"

#define GATTC_TAG "GATTC_DEMO"
#define REMOTE_SERVICE_UUID        0x1814  // RSC (Running Speed and Cadence)
#define REMOTE_NOTIFY_CHAR_UUID    0x2a53  // RSC Measurement
#define PROFILE_NUM      1
#define PROFILE_A_APP_ID 0
#define INVALID_HANDLE   0

static const char remote_device_name[] = "MilestonePod";
static bool connect    = false;
static bool get_server = false;
static esp_gattc_char_elem_t *char_elem_result   = NULL;
static esp_gattc_descr_elem_t *descr_elem_result = NULL;

/* eclare static functions */
static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
static void esp_gattc_cb(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);

static esp_bt_uuid_t remote_filter_service_uuid = {
    .len = ESP_UUID_LEN_16,
    .uuid = {.uuid16 = REMOTE_SERVICE_UUID,},
};

static esp_bt_uuid_t remote_filter_char_uuid = {
    .len = ESP_UUID_LEN_16,
    .uuid = {.uuid16 = REMOTE_NOTIFY_CHAR_UUID,},
};

static esp_bt_uuid_t notify_descr_uuid = {
    .len = ESP_UUID_LEN_16,
    .uuid = {.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG,},
};

static esp_ble_scan_params_t ble_scan_params = {
    .scan_type              = BLE_SCAN_TYPE_ACTIVE,
    .own_addr_type          = BLE_ADDR_TYPE_PUBLIC,
    .scan_filter_policy     = BLE_SCAN_FILTER_ALLOW_ALL,
    .scan_interval          = 0x50,
    .scan_window            = 0x30,
    .scan_duplicate         = BLE_SCAN_DUPLICATE_ENABLE     // TODO: check, was BLE_SCAN_DUPLICATE_DISABLE
};

struct gattc_profile_inst {
    esp_gattc_cb_t gattc_cb;
    uint16_t gattc_if;
    uint16_t app_id;
    uint16_t conn_id;
    uint16_t service_start_handle;
    uint16_t service_end_handle;
    uint16_t char_handle;
    esp_bd_addr_t remote_bda;
};

/* One gatt-based profile one app_id and one gattc_if, this array will store the gattc_if returned by ESP_GATTS_REG_EVT */
static struct gattc_profile_inst gl_profile_tab[PROFILE_NUM] = {
    [PROFILE_A_APP_ID] = {
        .gattc_cb = gattc_profile_event_handler,
        .gattc_if = ESP_GATT_IF_NONE,       /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */
    },
};

static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
{
    esp_ble_gattc_cb_param_t *p_data = (esp_ble_gattc_cb_param_t *)param;

    switch (event) {
    case ESP_GATTC_REG_EVT:
        ESP_LOGI(GATTC_TAG, "REG_EVT");
        esp_err_t scan_ret = esp_ble_gap_set_scan_params(&ble_scan_params);
        if (scan_ret){
            ESP_LOGE(GATTC_TAG, "set scan params error, error code = %x", scan_ret);
        }
        break;
    case ESP_GATTC_CONNECT_EVT:{
        ESP_LOGI(GATTC_TAG, "ESP_GATTC_CONNECT_EVT conn_id %d, if %d", p_data->connect.conn_id, gattc_if);
        gl_profile_tab[PROFILE_A_APP_ID].conn_id = p_data->connect.conn_id;
        memcpy(gl_profile_tab[PROFILE_A_APP_ID].remote_bda, p_data->connect.remote_bda, sizeof(esp_bd_addr_t));
        ESP_LOGI(GATTC_TAG, "REMOTE BDA:");
        esp_log_buffer_hex(GATTC_TAG, gl_profile_tab[PROFILE_A_APP_ID].remote_bda, sizeof(esp_bd_addr_t));
        esp_err_t mtu_ret = esp_ble_gattc_send_mtu_req (gattc_if, p_data->connect.conn_id);
        if (mtu_ret){
            ESP_LOGE(GATTC_TAG, "config MTU error, error code = %x", mtu_ret);
        }
        break;
    }
    case ESP_GATTC_OPEN_EVT:
        if (param->open.status != ESP_GATT_OK){
            ESP_LOGE(GATTC_TAG, "open failed, status %d", p_data->open.status);
            break;
        }
        ESP_LOGI(GATTC_TAG, "open success");
        break;
    case ESP_GATTC_CFG_MTU_EVT:
        if (param->cfg_mtu.status != ESP_GATT_OK){
            ESP_LOGE(GATTC_TAG,"config mtu failed, error status = %x", param->cfg_mtu.status);
        }
        ESP_LOGI(GATTC_TAG, "ESP_GATTC_CFG_MTU_EVT, Status %d, MTU %d, conn_id %d", param->cfg_mtu.status, param->cfg_mtu.mtu, param->cfg_mtu.conn_id);
        esp_ble_gattc_search_service(gattc_if, param->cfg_mtu.conn_id, &remote_filter_service_uuid);
        break;
    case ESP_GATTC_SEARCH_RES_EVT: {
        ESP_LOGI(GATTC_TAG, "SEARCH RES: conn_id = %x is primary service %d", p_data->search_res.conn_id, p_data->search_res.is_primary);
        ESP_LOGI(GATTC_TAG, "start handle %d end handle %d current handle value %d", p_data->search_res.start_handle, p_data->search_res.end_handle, p_data->search_res.srvc_id.inst_id);
        if (p_data->search_res.srvc_id.uuid.len == ESP_UUID_LEN_16 && p_data->search_res.srvc_id.uuid.uuid.uuid16 == REMOTE_SERVICE_UUID) {
            ESP_LOGI(GATTC_TAG, "service found");
            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", p_data->search_res.srvc_id.uuid.uuid.uuid16);
        }
        break;
    }
    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;
        }
        if(p_data->search_cmpl.searched_service_source == ESP_GATT_SERVICE_FROM_REMOTE_DEVICE) {
            ESP_LOGI(GATTC_TAG, "Get service information from remote device");
        } else if (p_data->search_cmpl.searched_service_source == ESP_GATT_SERVICE_FROM_NVS_FLASH) {
            ESP_LOGI(GATTC_TAG, "Get service information from flash");
        } else {
            ESP_LOGI(GATTC_TAG, "unknown service source");
        }
        ESP_LOGI(GATTC_TAG, "ESP_GATTC_SEARCH_CMPL_EVT");
        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);
                    }
                }
                /* free char_elem_result */
                free(char_elem_result);
            }else{
                ESP_LOGE(GATTC_TAG, "no char found");
            }
        }
         break;
    case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
        ESP_LOGI(GATTC_TAG, "ESP_GATTC_REG_FOR_NOTIFY_EVT");
        if (p_data->reg_for_notify.status != ESP_GATT_OK){
            ESP_LOGE(GATTC_TAG, "REG FOR NOTIFY failed: error status = %d", p_data->reg_for_notify.status);
        }else{
            uint16_t count = 0;
            uint16_t notify_en = 1;
            esp_gatt_status_t ret_status = esp_ble_gattc_get_attr_count( gattc_if,
                                                                         gl_profile_tab[PROFILE_A_APP_ID].conn_id,
                                                                         ESP_GATT_DB_DESCRIPTOR,
                                                                         gl_profile_tab[PROFILE_A_APP_ID].service_start_handle,
                                                                         gl_profile_tab[PROFILE_A_APP_ID].service_end_handle,
                                                                         gl_profile_tab[PROFILE_A_APP_ID].char_handle,
                                                                         &count);
            if (ret_status != ESP_GATT_OK){
                ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_attr_count error");
            }
            if (count > 0){
                descr_elem_result = malloc(sizeof(esp_gattc_descr_elem_t) * count);
                if (!descr_elem_result){
                    ESP_LOGE(GATTC_TAG, "malloc error, gattc no mem");
                }else{
                    ret_status = esp_ble_gattc_get_descr_by_char_handle( gattc_if,
                                                                         gl_profile_tab[PROFILE_A_APP_ID].conn_id,
                                                                         p_data->reg_for_notify.handle,
                                                                         notify_descr_uuid,
                                                                         descr_elem_result,
                                                                         &count);
                    if (ret_status != ESP_GATT_OK){
                        ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_descr_by_char_handle error");
                    }
                    /* Every char has only one descriptor in our 'ESP_GATTS_DEMO' demo, so we used first 'descr_elem_result' */
                    if (count > 0 && descr_elem_result[0].uuid.len == ESP_UUID_LEN_16 && descr_elem_result[0].uuid.uuid.uuid16 == ESP_GATT_UUID_CHAR_CLIENT_CONFIG){
                        ret_status = esp_ble_gattc_write_char_descr( gattc_if,
                                                                     gl_profile_tab[PROFILE_A_APP_ID].conn_id,
                                                                     descr_elem_result[0].handle,
                                                                     sizeof(notify_en),
                                                                     (uint8_t *)&notify_en,
                                                                     ESP_GATT_WRITE_TYPE_RSP,
                                                                     ESP_GATT_AUTH_REQ_NONE);
                    }

                    if (ret_status != ESP_GATT_OK){
                        ESP_LOGE(GATTC_TAG, "esp_ble_gattc_write_char_descr error");
                    }

                    /* free descr_elem_result */
                    free(descr_elem_result);
                }
            }
            else{
                ESP_LOGE(GATTC_TAG, "decsr not found");
            }

        }
        break;
    }
    case ESP_GATTC_NOTIFY_EVT:
        if (p_data->notify.is_notify){
            ESP_LOGI(GATTC_TAG, "ESP_GATTC_NOTIFY_EVT, receive notify value:");
        }else{
            ESP_LOGI(GATTC_TAG, "ESP_GATTC_NOTIFY_EVT, receive indicate value:");
        }
        esp_log_buffer_hex(GATTC_TAG, p_data->notify.value, p_data->notify.value_len);
        break;
    case ESP_GATTC_WRITE_DESCR_EVT:
        if (p_data->write.status != ESP_GATT_OK){
            ESP_LOGE(GATTC_TAG, "write descr failed, error status = %x", p_data->write.status);
            break;
        }
        ESP_LOGI(GATTC_TAG, "write descr success ");
        uint8_t write_char_data[35];
        for (int i = 0; i < sizeof(write_char_data); ++i)
        {
            write_char_data[i] = i % 256;
        }
        esp_ble_gattc_write_char( gattc_if,
                                  gl_profile_tab[PROFILE_A_APP_ID].conn_id,
                                  gl_profile_tab[PROFILE_A_APP_ID].char_handle,
                                  sizeof(write_char_data),
                                  write_char_data,
                                  ESP_GATT_WRITE_TYPE_RSP,
                                  ESP_GATT_AUTH_REQ_NONE);
        break;
    case ESP_GATTC_SRVC_CHG_EVT: {
        esp_bd_addr_t bda;
        memcpy(bda, p_data->srvc_chg.remote_bda, sizeof(esp_bd_addr_t));
        ESP_LOGI(GATTC_TAG, "ESP_GATTC_SRVC_CHG_EVT, bd_addr:");
        esp_log_buffer_hex(GATTC_TAG, bda, sizeof(esp_bd_addr_t));
        break;
    }
    case ESP_GATTC_WRITE_CHAR_EVT:
        if (p_data->write.status != ESP_GATT_OK){
            ESP_LOGE(GATTC_TAG, "write char failed, error status = %x", p_data->write.status);
            break;
        }
        ESP_LOGI(GATTC_TAG, "write char success ");
        break;
    case ESP_GATTC_DISCONNECT_EVT:
        connect = false;
        get_server = false;
        ESP_LOGI(GATTC_TAG, "ESP_GATTC_DISCONNECT_EVT, reason = %d", p_data->disconnect.reason);
        break;
    default:
        break;
    }
}

static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
    uint8_t *adv_name = NULL;
    uint8_t adv_name_len = 0;
    switch (event) {
    case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: {
        //the unit of the duration is second
        uint32_t duration = 30;
        esp_ble_gap_start_scanning(duration);
        break;
    }
    case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:
        //scan start complete event to indicate scan start successfully or failed
        if (param->scan_start_cmpl.status != ESP_BT_STATUS_SUCCESS) {
            ESP_LOGE(GATTC_TAG, "scan start failed, error status = %x", param->scan_start_cmpl.status);
            break;
        }
        ESP_LOGI(GATTC_TAG, "scan start success");

        break;
    case ESP_GAP_BLE_SCAN_RESULT_EVT: {
        esp_ble_gap_cb_param_t *scan_result = (esp_ble_gap_cb_param_t *)param;
        switch (scan_result->scan_rst.search_evt) {
        case ESP_GAP_SEARCH_INQ_RES_EVT:
            esp_log_buffer_hex(GATTC_TAG, scan_result->scan_rst.bda, 6);
            ESP_LOGI(GATTC_TAG, "searched Adv Data Len %d, Scan Response Len %d", scan_result->scan_rst.adv_data_len, scan_result->scan_rst.scan_rsp_len);
            adv_name = esp_ble_resolve_adv_data(scan_result->scan_rst.ble_adv,
                                                ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len);
            ESP_LOGI(GATTC_TAG, "searched Device Name Len %d", adv_name_len);
            esp_log_buffer_char(GATTC_TAG, adv_name, adv_name_len);
            ESP_LOGI(GATTC_TAG, "\n");
            if (adv_name != NULL) {
                // TODO: better control of device we're searching for
                if (strlen(remote_device_name) <= adv_name_len && strncmp((char *)adv_name, remote_device_name, strlen(remote_device_name)) == 0) {
                    ESP_LOGI(GATTC_TAG, "searched device %s\n", remote_device_name);
                    if (connect == false) {
                        connect = true;
                        ESP_LOGI(GATTC_TAG, "connect to the remote device.");
                        esp_ble_gap_stop_scanning();
                        esp_ble_gattc_open(gl_profile_tab[PROFILE_A_APP_ID].gattc_if, scan_result->scan_rst.bda, scan_result->scan_rst.ble_addr_type, true);
                    }
                }
            }
            break;
        case ESP_GAP_SEARCH_INQ_CMPL_EVT:
            break;
        default:
            break;
        }
        break;
    }

    case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:
        if (param->scan_stop_cmpl.status != ESP_BT_STATUS_SUCCESS){
            ESP_LOGE(GATTC_TAG, "scan stop failed, error status = %x", param->scan_stop_cmpl.status);
            break;
        }
        ESP_LOGI(GATTC_TAG, "stop scan successfully");
        break;

    case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
        if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS){
            ESP_LOGE(GATTC_TAG, "adv stop failed, error status = %x", param->adv_stop_cmpl.status);
            break;
        }
        ESP_LOGI(GATTC_TAG, "stop adv successfully");
        break;
    case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT:
         ESP_LOGI(GATTC_TAG, "update connection params status = %d, min_int = %d, max_int = %d,conn_int = %d,latency = %d, timeout = %d",
                  param->update_conn_params.status,
                  param->update_conn_params.min_int,
                  param->update_conn_params.max_int,
                  param->update_conn_params.conn_int,
                  param->update_conn_params.latency,
                  param->update_conn_params.timeout);
        break;
    default:
        break;
    }
}

static void esp_gattc_cb(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
{
    /* If event is register event, store the gattc_if for each profile */
    if (event == ESP_GATTC_REG_EVT) {
        if (param->reg.status == ESP_GATT_OK) {
            gl_profile_tab[param->reg.app_id].gattc_if = gattc_if;
        } else {
            ESP_LOGI(GATTC_TAG, "reg app failed, app_id %04x, status %d",
                    param->reg.app_id,
                    param->reg.status);
            return;
        }
    }

    /* If the gattc_if equal to profile A, call profile A cb handler,
     * so here call each profile's callback */
    do {
        int idx;
        for (idx = 0; idx < PROFILE_NUM; idx++) {
            if (gattc_if == ESP_GATT_IF_NONE || /* ESP_GATT_IF_NONE, not specify a certain gatt_if, need to call every profile cb function */
                    gattc_if == gl_profile_tab[idx].gattc_if) {
                if (gl_profile_tab[idx].gattc_cb) {
                    gl_profile_tab[idx].gattc_cb(event, gattc_if, param);
                }
            }
        }
    } while (0);
}

void app_main()
{
    // Initialize NVS.
    esp_err_t 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_log_level_set("*", ESP_LOG_INFO);
    esp_log_level_set("*ble*", ESP_LOG_VERBOSE);
    esp_log_level_set("*GATTC*", ESP_LOG_VERBOSE);

    esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
    ret = esp_bt_controller_init(&bt_cfg);
    if (ret) {
        ESP_LOGE(GATTC_TAG, "%s initialize controller failed: %s\n", __func__, esp_err_to_name(ret));
        return;
    }

    ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
    if (ret) {
        ESP_LOGE(GATTC_TAG, "%s enable controller failed: %s\n", __func__, esp_err_to_name(ret));
        return;
    }

    ret = esp_bluedroid_init();
    if (ret) {
        ESP_LOGE(GATTC_TAG, "%s init bluetooth failed: %s\n", __func__, esp_err_to_name(ret));
        return;
    }

    ret = esp_bluedroid_enable();
    if (ret) {
        ESP_LOGE(GATTC_TAG, "%s enable bluetooth failed: %s\n", __func__, esp_err_to_name(ret));
        return;
    }

    //register the  callback function to the gap module
    ret = esp_ble_gap_register_callback(esp_gap_cb);
    if (ret){
        ESP_LOGE(GATTC_TAG, "%s gap register failed, error code = %x\n", __func__, ret);
        return;
    }

    //register the callback function to the gattc module
    ret = esp_ble_gattc_register_callback(esp_gattc_cb);
    if(ret){
        ESP_LOGE(GATTC_TAG, "%s gattc register failed, error code = %x\n", __func__, ret);
        return;
    }

    ret = esp_ble_gattc_app_register(PROFILE_A_APP_ID);
    if (ret){
        ESP_LOGE(GATTC_TAG, "%s gattc app register failed, error code = %x\n", __func__, ret);
    }
    esp_err_t local_mtu_ret = esp_ble_gatt_set_local_mtu(500);
    if (local_mtu_ret){
        ESP_LOGE(GATTC_TAG, "set local  MTU failed, error code = %x", local_mtu_ret);
    }

}

The device I want to connect to is a fitness tracker, providing the Running Speed and Cadence service (UUID 0x1814), and the characteristic (UUID 0x2a53). The device is alive, provides the services (can be checked with an app lika a BLE scanner), and I have an old running code version on one ESP32 device running.

Log file is as follows:

rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:5832
load:0x40078000,len:9176
load:0x40080000,len:6008
0x40080000: _WindowOverflow4 at C:/msys32/home/AKAEM/esp/esp-idf/components/freertos/xtensa_vectors.S:1685

entry 0x4008032c
0x4008032c: _KernelExceptionVector at ??:?

I (28) boot: ESP-IDF v3.1.1 2nd stage bootloader
I (28) boot: compile time 20:56:11
I (28) boot: Enabling RNG early entropy source...
I (33) boot: SPI Speed      : 40MHz
I (37) boot: SPI Mode       : DIO
I (41) boot: SPI Flash Size : 16MB
I (45) boot: Partition Table:
I (49) boot: ## Label            Usage          Type ST Offset   Length
I (56) boot:  0 nvs              WiFi data        01 02 00009000 00006000
I (63) boot:  1 phy_init         RF data          01 01 0000f000 00001000
I (71) boot:  2 factory          factory app      00 00 00010000 00100000
I (78) boot: End of partition table
I (83) esp_image: segment 0: paddr=0x00010020 vaddr=0x3f400020 size=0x22a14 (141844) map
I (141) esp_image: segment 1: paddr=0x00032a3c vaddr=0x3ff80000 size=0x00000 (     0) load
I (142) esp_image: segment 2: paddr=0x00032a44 vaddr=0x3ff80000 size=0x00000 (     0) load
I (148) esp_image: segment 3: paddr=0x00032a4c vaddr=0x3ffbdb60 size=0x02c8c ( 11404) load
I (161) esp_image: segment 4: paddr=0x000356e0 vaddr=0x3ffc07ec size=0x00000 (     0) load
I (166) esp_image: segment 5: paddr=0x000356e8 vaddr=0x40080000 size=0x00400 (  1024) load
0x40080000: _WindowOverflow4 at C:/msys32/home/AKAEM/esp/esp-idf/components/freertos/xtensa_vectors.S:1685

I (175) esp_image: segment 6: paddr=0x00035af0 vaddr=0x40080400 size=0x0a520 ( 42272) load
I (201) esp_image: segment 7: paddr=0x00040018 vaddr=0x400d0018 size=0x647ec (411628) map
0x400d0018: _stext at ??:?

I (346) esp_image: segment 8: paddr=0x000a480c vaddr=0x4008a920 size=0x07194 ( 29076) load
0x4008a920: ram_set_chan_cal_interp at ??:?

I (358) esp_image: segment 9: paddr=0x000ab9a8 vaddr=0x400c0000 size=0x00000 (     0) load
I (358) esp_image: segment 10: paddr=0x000ab9b0 vaddr=0x50000000 size=0x00000 (     0) load
I (365) esp_image: segment 11: paddr=0x000ab9b8 vaddr=0x50000000 size=0x00000 (     0) load
I (384) boot: Loaded app from partition at offset 0x10000
I (384) boot: Disabling RNG early entropy source...
I (386) cpu_start: Pro cpu up.
I (389) cpu_start: Starting app cpu, entry point is 0x40081050
0x40081050: call_start_cpu1 at C:/msys32/home/AKAEM/esp/esp-idf/components/esp32/cpu_start.c:245

I (0) cpu_start: App cpu up.
D (400) memory_layout: Checking 11 reserved memory ranges:
D (405) memory_layout: Reserved memory range 0x3ffae000 - 0x3ffae6e0
D (411) memory_layout: Reserved memory range 0x3ffae6e0 - 0x3ffaff10
D (418) memory_layout: Reserved memory range 0x3ffb0000 - 0x3ffb6388
D (424) memory_layout: Reserved memory range 0x3ffb8000 - 0x3ffb9a20
D (431) memory_layout: Reserved memory range 0x3ffbdb28 - 0x3ffbdb5c
D (437) memory_layout: Reserved memory range 0x3ffbdb60 - 0x3ffc7598
D (443) memory_layout: Reserved memory range 0x3ffe0000 - 0x3ffe0440
D (450) memory_layout: Reserved memory range 0x3ffe3f20 - 0x3ffe4350
D (456) memory_layout: Reserved memory range 0x40070000 - 0x40078000
D (463) memory_layout: Reserved memory range 0x40078000 - 0x40080000
0x40080000: _WindowOverflow4 at C:/msys32/home/AKAEM/esp/esp-idf/components/freertos/xtensa_vectors.S:1685

D (469) memory_layout: Reserved memory range 0x40080000 - 0x40091ab4
0x40080000: _WindowOverflow4 at C:/msys32/home/AKAEM/esp/esp-idf/components/freertos/xtensa_vectors.S:1685

D (476) memory_layout: Building list of available memory regions:
D (482) memory_layout: Available memory region 0x3ffaff10 - 0x3ffb0000
D (488) memory_layout: Available memory region 0x3ffb6388 - 0x3ffb8000
D (495) memory_layout: Available memory region 0x3ffb9a20 - 0x3ffbdb28
D (501) memory_layout: Available memory region 0x3ffbdb5c - 0x3ffbdb60
D (508) memory_layout: Available memory region 0x3ffc7598 - 0x3ffc8000
D (515) memory_layout: Available memory region 0x3ffc8000 - 0x3ffca000
D (521) memory_layout: Available memory region 0x3ffca000 - 0x3ffcc000
D (528) memory_layout: Available memory region 0x3ffcc000 - 0x3ffce000
D (534) memory_layout: Available memory region 0x3ffce000 - 0x3ffd0000
D (541) memory_layout: Available memory region 0x3ffd0000 - 0x3ffd2000
D (548) memory_layout: Available memory region 0x3ffd2000 - 0x3ffd4000
D (554) memory_layout: Available memory region 0x3ffd4000 - 0x3ffd6000
D (561) memory_layout: Available memory region 0x3ffd6000 - 0x3ffd8000
D (567) memory_layout: Available memory region 0x3ffd8000 - 0x3ffda000
D (574) memory_layout: Available memory region 0x3ffda000 - 0x3ffdc000
D (581) memory_layout: Available memory region 0x3ffdc000 - 0x3ffde000
D (587) memory_layout: Available memory region 0x3ffde000 - 0x3ffe0000
D (594) memory_layout: Available memory region 0x3ffe0440 - 0x3ffe3f20
D (600) memory_layout: Available memory region 0x3ffe4350 - 0x3ffe8000
D (607) memory_layout: Available memory region 0x3ffe8000 - 0x3fff0000
D (614) memory_layout: Available memory region 0x3fff0000 - 0x3fff8000
D (620) memory_layout: Available memory region 0x3fff8000 - 0x3fffc000
D (627) memory_layout: Available memory region 0x3fffc000 - 0x40000000
D (633) memory_layout: Available memory region 0x40091ab4 - 0x40092000
D (640) memory_layout: Available memory region 0x40092000 - 0x40094000
D (647) memory_layout: Available memory region 0x40094000 - 0x40096000
D (653) memory_layout: Available memory region 0x40096000 - 0x40098000
D (660) memory_layout: Available memory region 0x40098000 - 0x4009a000
D (666) memory_layout: Available memory region 0x4009a000 - 0x4009c000
D (673) memory_layout: Available memory region 0x4009c000 - 0x4009e000
D (680) memory_layout: Available memory region 0x4009e000 - 0x400a0000
I (686) heap_init: Initializing. RAM available for dynamic allocation:
D (693) heap_init: New heap initialised at 0x3ffaff10
I (699) heap_init: At 3FFAFF10 len 000000F0 (0 KiB): DRAM
D (705) heap_init: New heap initialised at 0x3ffb6388
I (710) heap_init: At 3FFB6388 len 00001C78 (7 KiB): DRAM
D (716) heap_init: New heap initialised at 0x3ffb9a20
I (721) heap_init: At 3FFB9A20 len 00004108 (16 KiB): DRAM
I (727) heap_init: At 3FFBDB5C len 00000004 (0 KiB): DRAM
D (733) heap_init: New heap initialised at 0x3ffc7598
I (738) heap_init: At 3FFC7598 len 00018A68 (98 KiB): DRAM
I (744) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (751) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
D (757) heap_init: New heap initialised at 0x40091ab4
I (762) heap_init: At 40091AB4 len 0000E54C (57 KiB): IRAM
I (769) cpu_start: Pro cpu start user code
D (781) clk: RTC_SLOW_CLK calibration value: 3264499
D (119) intr_alloc: Connected src 46 to int 2 (cpu 0)
D (120) intr_alloc: Connected src 57 to int 3 (cpu 0)
D (120) stack_chk: Intialize random stack guard
D (125) intr_alloc: Connected src 24 to int 9 (cpu 0)
I (130) cpu_start: Starting scheduler on PRO CPU.
D (0) intr_alloc: Connected src 25 to int 2 (cpu 1)
I (0) cpu_start: Starting scheduler on APP CPU.
D (145) heap_init: New heap initialised at 0x3ffe0440
D (155) heap_init: New heap initialised at 0x3ffe4350
D (165) intr_alloc: Connected src 16 to int 12 (cpu 0)
D (165) nvs: nvs_flash_init_custom partition=nvs start=9 count=6
D (245) BTDM_INIT: Release DRAM [0x3ffb2730] - [0x3ffb6388]
I (245) BTDM_INIT: BT controller compile version [6a842ec]
I (245) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
I (335) phy: phy_version: 4000, b6198fa, Sep  3 2018, 15:11:06, 0, 0
I (675) GATTC_DEMO: REG_EVT
I (675) GATTC_DEMO: scan start success
I (1195) GATTC_DEMO: 60 80 4a ac 1f cd
I (1195) GATTC_DEMO: searched Adv Data Len 14, Scan Response Len 0
I (1195) GATTC_DEMO: searched Device Name Len 0
I (1195) GATTC_DEMO:

I (1205) GATTC_DEMO: 4e 5e b5 99 3c fb
I (1205) GATTC_DEMO: searched Adv Data Len 14, Scan Response Len 0
I (1215) GATTC_DEMO: searched Device Name Len 0
I (1215) GATTC_DEMO:

I (1655) GATTC_DEMO: 50 33 8b 1c ef f6
I (1655) GATTC_DEMO: searched Adv Data Len 30, Scan Response Len 26
I (1655) GATTC_DEMO: searched Device Name Len 15
I (1655) GATTC_DEMO: MilestonePod F6
I (1665) GATTC_DEMO:

I (1665) GATTC_DEMO: searched device MilestonePod

I (1675) GATTC_DEMO: connect to the remote device.
I (1685) GATTC_DEMO: stop scan successfully
I (2735) GATTC_DEMO: ESP_GATTC_CONNECT_EVT conn_id 0, if 1
I (2735) GATTC_DEMO: REMOTE BDA:
I (2735) GATTC_DEMO: 50 33 8b 1c ef f6
I (2735) GATTC_DEMO: open success
I (3935) GATTC_DEMO: ESP_GATTC_CFG_MTU_EVT, Status 0, MTU 23, conn_id 0
I (3935) GATTC_DEMO: SEARCH RES: conn_id = 0 is primary service 1
I (3935) GATTC_DEMO: start handle 16 end handle 29 current handle value 16
I (3945) GATTC_DEMO: service found
I (3945) GATTC_DEMO: UUID16: 1814
I (3955) GATTC_DEMO: Get service information from remote device
I (3965) GATTC_DEMO: ESP_GATTC_SEARCH_CMPL_EVT
I (3965) GATTC_DEMO: ESP_GATTC_REG_FOR_NOTIFY_EVT
I (3995) GATTC_DEMO: write descr success
E (4055) GATTC_DEMO: write char failed, error status = 3
I (7795) GATTC_DEMO: update connection params status = 0, min_int = 16, max_int = 32,conn_int = 32,latency = 0, timeout = 600

Here it stops with the line

E (4055) GATTC_DEMO: write char failed, error status = 3

The last line appears with a little delay of 3-5 seconds, no lines in the next minutes.

Expected behaviour:

register notify and get notifications with updated values, at least not receiving this error.

dhrishi commented 5 years ago

@an-erd In this case, the above error can be returned when write is not permitted on the characteristic. Can you please check if write permissions (in addition to write Property) are given to characteristic RSC Measurement on the BLE peripheral you are using?

I replaced the existing gattc_demo.c with the one above with the following change to send appropriate values: uint8_t write_char_data[4] = {0x00, 0x01, 0x02, 0x00};

On the BLE peripheral app I could see the write request was received "Speed 2.00 m/s Cadence: RPM and Status: Walking" and it was successful. On the ESP32 console: "I (2043) GATTC_DEMO: write char success"

Now, If I remove write permissions to characteristic RSC measurement in the peripheral app I get the following error on the ESP32 console: "E (2443) GATTC_DEMO: write char failed, error status = 3"

an-erd commented 5 years ago

@dhrishi Good point. I've a log from an old test with Arduino. The both characteristics I'm interested in are 0x2a53 (RSC) and 0xff00 (custom data). In the old log there's only notify available for them, see first line.

[D][BLERemoteCharacteristic.cpp:442] registerForNotify(): >> registerForNotify(): Characteristic: uuid: 00002a53-0000-1000-8000-00805f9b34fb, handle: 18 0x12, props: broadcast: 0, read: 0, write_nr: 0, write: 0, notify: 1, indicate: 0, auth: 0
[D][BLERemoteCharacteristic.cpp:327] getDescriptor(): >> getDescriptor: uuid: 00002902-0000-1000-8000-00805f9b34fb
[V][BLEUtils.cpp:950] gattClientEventTypeToString(): Unknown GATT Client event type: 38
[D][BLERemoteCharacteristic.cpp:331] getDescriptor(): << getDescriptor: found
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[D][BLERemoteDescriptor.cpp:135] writeValue(): >> writeValue: handle: 19, uuid: 00002902-0000-1000-8000-00805f9b34fb
[V][BLEUtils.cpp:950] gattClientEventTypeToString(): Unknown GATT Client event type: 38
[D][BLERemoteDescriptor.cpp:154] writeValue(): << writeValue
[V][BLEUtils.cpp:1282] dumpGattClientEvent(): GATT Event: Unknown
[V][BLEUtils.cpp:950] gattClientEventTypeToString(): Unknown GATT Client event type: 38
[D][BLEClient.cpp:162] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[D][BLERemoteCharacteristic.cpp:482] registerForNotify(): << registerForNotify()
[W][disPOD.ino:602] my_gattc_event_handler(): custom gattc event handler, event: 38
[D][BLERemoteCharacteristic.cpp:327] getDescriptor(): >> getDescriptor: uuid: 00002902-0000-1000-8000-00805f9b34fb
[V][BLEUtils.cpp:950] gattClientEventTypeToString(): Unknown GATT Client event type: 9
[D][BLERemoteCharacteristic.cpp:331] getDescriptor(): << getDescriptor: found
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[D][BLERemoteDescriptor.cpp:135] writeValue(): >> writeValue: handle: 19, uuid: 00002902-0000-1000-8000-00805f9b34fb
[V][BLEUtils.cpp:950] gattClientEventTypeToString(): Unknown GATT Client event type: 9
[D][BLERemoteDescriptor.cpp:154] writeValue(): << writeValue
[V][BLEUtils.cpp:1282] dumpGattClientEvent(): GATT Event: Unknown
[D][BLERemoteCharacteristic.cpp:442] registerForNotify(): >> registerForNotify(): Characteristic: uuid: 0000ff00-0000-1000-8000-00805f9b34fb, handle: 28 0x1c, props: broadcast: 0, read: 0, write_nr: 0, write: 0, notify: 1, indicate: 0, auth: 0
[V][BLEUtils.cpp:950] gattClientEventTypeToString(): Unknown GATT Client event type: 9
[D][BLERemoteCharacteristic.cpp:327] getDescriptor(): >> getDescriptor: uuid: 00002902-0000-1000-8000-00805f9b34fb
[D][BLEClient.cpp:162] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[D][BLERemoteCharacteristic.cpp:331] getDescriptor(): << getDescriptor: found
[W][disPOD.ino:602] my_gattc_event_handler(): custom gattc event handler, event: 9
[D][BLERemoteDescriptor.cpp:135] writeValue(): >> writeValue: handle: 29, uuid: 00002902-0000-1000-8000-00805f9b34fb
[V][BLEUtils.cpp:950] gattClientEventTypeToString(): Unknown GATT Client event type: 38
[D][BLERemoteDescriptor.cpp:154] writeValue(): << writeValue
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[V][BLEUtils.cpp:950] gattClientEventTypeToString(): Unknown GATT Client event type: 38
[V][BLEUtils.cpp:1282] dumpGattClientEvent(): GATT Event: Unknown
[V][BLEUtils.cpp:950] gattClientEventTypeToString(): Unknown GATT Client event type: 38
[D][BLEClient.cpp:162] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[D][BLERemoteCharacteristic.cpp:482] registerForNotify(): << registerForNotify()
[W][disPOD.ino:602] my_gattc_event_handler(): custom gattc event handler, event: 38
[D][BLERemoteCharacteristic.cpp:327] getDescriptor(): >> getDescriptor: uuid: 00002902-0000-1000-8000-00805f9b34fb
[V][BLEUtils.cpp:950] gattClientEventTypeToString(): Unknown GATT Client event type: 9
[D][BLERemoteCharacteristic.cpp:331] getDescriptor(): << getDescriptor: found
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[D][BLERemoteDescriptor.cpp:135] writeValue(): >> writeValue: handle: 29, uuid: 00002902-0000-1000-8000-00805f9b34fb
[V][BLEUtils.cpp:950] gattClientEventTypeToString(): Unknown GATT Client event type: 9
[D][BLERemoteDescriptor.cpp:154] writeValue(): << writeValue
[V][BLEUtils.cpp:1282] dumpGattClientEvent(): GATT Event: Unknown
[V][BLEUtils.cpp:950] gattClientEventTypeToString(): Unknown GATT Client event type: 9
[D][BLEClient.cpp:162] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[W][disPOD.ino:602] my_gattc_event_handler(): custom gattc event handler, event: 9
[V][BLEUtils.cpp:950] gattClientEventTypeToString(): Unknown GATT Client event type: 9
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[V][BLEUtils.cpp:950] gattClientEventTypeToString(): Unknown GATT Client event type: 9
[V][BLEUtils.cpp:1282] dumpGattClientEvent(): GATT Event: Unknown
[V][BLEUtils.cpp:950] gattClientEventTypeToString(): Unknown GATT Client event type: 9
[D][BLEClient.cpp:162] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[W][disPOD.ino:602] my_gattc_event_handler(): custom gattc event handler, event: 9
Preparation done, waiting for NOTIFY

Actually, I don't want to write to the device, but only receive the RSC and custom values from the device.

Why does this "write char failed" occur? I see its called in gattc_profile_event_handler() with ESP_GATTC_WRITE_DESCR_EVT, but I don't yet understand why this is called at all?

dhrishi commented 5 years ago

@an-erd It is called because under ESP_GATTC_WRITE_DESCR_EVT (where it receives the result for enabling notify) it writes to that characteristic, see API esp_ble_gattc_write_char() in there. If you don't want to write to that characteristic, you can simply remove this call. You have already subscribed to notifications through the call esp_ble_gattc_write_char_descr()

This may be present in the example just to demonstrate the API for writing to a characteristic.

an-erd commented 5 years ago

Ok, to summarize:

@dhrishi Thanks!

monikharajs commented 4 years ago

GATTC_DEMO: write char failed, error status : d

What is the reason for this??

monikharajs commented 4 years ago

write char failed,error status d @dhrishi What is the reason for this??

prasad-alatkar commented 4 years ago

Hi @monikharajs the error status translates to ESP_GATT_INVALID_ATTR_LEN , Can you please let me know the changes you have made to gattc_demo?

monikharajs commented 4 years ago

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; } if(p_data->search_cmpl.searched_service_source == ESP_GATT_SERVICE_FROM_REMOTE_DEVICE) { ESP_LOGI(GATTC_TAG, "Get service information from remote device"); } else if (p_data->search_cmpl.searched_service_source == ESP_GATT_SERVICE_FROM_NVS_FLASH) { ESP_LOGI(GATTC_TAG, "Get service information from flash"); } else { ESP_LOGI(GATTC_TAG, "unknown service source"); } ESP_LOGI(GATTC_TAG, "ESP_GATTC_SEARCH_CMPL_EVT"); 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){
            printf("cunt %d\n",count);
            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{
                printf("Count before gattc no mem %d",count);
                printf("Gattc MEMMM\n");
                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){
                    printf("Get char by uuid not success\n");
                    ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_char_by_uuid error");
                }
                else
                {
                    printf("Get char by uuid success\n");
                }
                printf("Count before if %d\n",count);
                /*  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)){
                    printf("Before Write\n");
                    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);
                    esp_err_t write_status= esp_ble_gattc_write_char(gattc_if,
                                                    gl_profile_tab[PROFILE_A_APP_ID].conn_id,
                                                    gl_profile_tab[PROFILE_A_APP_ID].char_handle,
                                                    sizeof(write_char_data), write_char_data,
                                                    ESP_GATT_WRITE_TYPE_RSP,
                                                    ESP_GATT_AUTH_REQ_NONE);
                    if(write_status==ESP_OK)
                    {
                        printf("Write success %s\n",write_char_data);
                    }
                    else
                    {
                        printf("Write Not OKkk\n");
                    }
                }
                else
                {
                    printf("Not going to write\n");
                }
            }
            /* free char_elem_result */
            free(char_elem_result);
        }else{
            ESP_LOGE(GATTC_TAG, "no char found");
        }
    }
     break;
case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
    ESP_LOGI(GATTC_TAG, "ESP_GATTC_REG_FOR_NOTIFY_EVT");
    if (p_data->reg_for_notify.status != ESP_GATT_OK){
        ESP_LOGE(GATTC_TAG, "REG FOR NOTIFY failed: error status = %d", p_data->reg_for_notify.status);
    }else{
        uint16_t count = 0;
        uint16_t notify_en = 1;
        esp_gatt_status_t ret_status = esp_ble_gattc_get_attr_count( gattc_if,
                                                                     gl_profile_tab[PROFILE_A_APP_ID].conn_id,
                                                                     ESP_GATT_DB_DESCRIPTOR,
                                                                     gl_profile_tab[PROFILE_A_APP_ID].service_start_handle,
                                                                     gl_profile_tab[PROFILE_A_APP_ID].service_end_handle,
                                                                     gl_profile_tab[PROFILE_A_APP_ID].char_handle,
                                                                     &count);
        if (ret_status != ESP_GATT_OK){
            ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_attr_count error");
        }
        /*if (count > 0){
            descr_elem_result = malloc(sizeof(esp_gattc_descr_elem_t) * count);
            if (!descr_elem_result){
                ESP_LOGE(GATTC_TAG, "malloc error, gattc no mem");
            }else{
                ret_status = esp_ble_gattc_get_descr_by_char_handle( gattc_if,
                                                                     gl_profile_tab[PROFILE_A_APP_ID].conn_id,
                                                                     p_data->reg_for_notify.handle,
                                                                     notify_descr_uuid,
                                                                     descr_elem_result,
                                                                     &count);
                if (ret_status != ESP_GATT_OK){
                    ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_descr_by_char_handle error");
                }
                 Every char has only one descriptor in our 'ESP_GATTS_DEMO' demo, so we used first 'descr_elem_result'
                if (count > 0 && descr_elem_result[0].uuid.len == ESP_UUID_LEN_16 && descr_elem_result[0].uuid.uuid.uuid16 == ESP_GATT_UUID_CHAR_CLIENT_CONFIG){
                    ret_status = esp_ble_gattc_write_char_descr( gattc_if,
                                                                 gl_profile_tab[PROFILE_A_APP_ID].conn_id,
                                                                 descr_elem_result[0].handle,
                                                                 sizeof(notify_en),
                                                                 (uint8_t *)&notify_en,
                                                                 ESP_GATT_WRITE_TYPE_RSP,
                                                                 ESP_GATT_AUTH_REQ_NONE);
                }

                if (ret_status != ESP_GATT_OK){
                    ESP_LOGE(GATTC_TAG, "esp_ble_gattc_write_char_descr error");
                }

                 free descr_elem_result
                free(descr_elem_result);
            }
        }
        else{
            ESP_LOGE(GATTC_TAG, "decsr not found");
        }

/ } break; } case ESP_GATTC_NOTIFY_EVT: if (p_data->notify.is_notify){ ESP_LOGI(GATTC_TAG, "ESP_GATTC_NOTIFY_EVT, receive notify value:"); }else{ ESP_LOGI(GATTC_TAG, "ESP_GATTC_NOTIFY_EVT, receive indicate value:"); } esp_log_buffer_hex(GATTC_TAG, p_data->notify.value, p_data->notify.value_len); break; case ESP_GATTC_WRITE_DESCR_EVT: if (p_data->write.status != ESP_GATT_OK){ ESP_LOGE(GATTC_TAG, "write descr failed, error status = %x", p_data->write.status); break; } ESP_LOGI(GATTC_TAG, "write descr success "); / uint8_t write_char_data[35]; for (int i = 0; i < sizeof(write_char_data); ++i) { write_char_data[i] = i % 256; }*/ esp_ble_gattc_write_char( gattc_if, gl_profile_tab[PROFILE_A_APP_ID].conn_id, gl_profile_tab[PROFILE_A_APP_ID].char_handle, sizeof(write_char_data), write_char_data, ESP_GATT_WRITE_TYPE_RSP, ESP_GATT_AUTH_REQ_NONE); printf("success dcsr\n"); break; case ESP_GATTC_SRVC_CHG_EVT: { esp_bd_addr_t bda; memcpy(bda, p_data->srvc_chg.remote_bda, sizeof(esp_bd_addr_t)); ESP_LOGI(GATTC_TAG, "ESP_GATTC_SRVC_CHG_EVT, bd_addr:"); esp_log_buffer_hex(GATTC_TAG, bda, sizeof(esp_bd_addr_t)); break; } case ESP_GATTC_WRITE_CHAR_EVT: printf("in case\n"); if (p_data->write.status != ESP_GATT_OK){ printf("Write not success in case\n"); ESP_LOGE(GATTC_TAG, "write char failed, error status = %x", p_data->write.status); break; } printf("success in case\n"); ESP_LOGI(GATTC_TAG, "write char success ");

    break;
case ESP_GATTC_DISCONNECT_EVT:
    printf("ESP_GATTC_DISCONNECT EVENT\n");
    connect = false;
    get_server = false;
    ESP_LOGI(GATTC_TAG, "ESP_GATTC_DISCONNECT_EVT, reason = %d", p_data->disconnect.reason);
    break;
default:
    printf("Default\n");
    break;
}

} i used gatt_client example , just declared write char data as global unsigned char write_char_data[100] = {"hii" };

output: mac in fun..ea:46:5f:da:d6:74 I (15569) SEC_GATTC_DEMO: searched Adv Data Len 16, Scan Response Len 0 I (15579) SEC_GATTC_DEMO: searched Device Name Len 7 I (15589) SEC_GATTC_DEMO: DfuTarg I (15589) SEC_GATTC_DEMO:

I (15589) SEC_GATTC_DEMO: searched device DfuTarg

I (15599) TW_MQTT: Queue empty I (15599) SEC_GATTC_DEMO: connect to the remote device. connected deviceI (15609) SEC_GATTC_DEMO: 03 9f d7 d0 5d 12 mac in fun..ea:46:5f:da:d6:74 I (15619) SEC_GATTC_DEMO: searched Adv Data Len 31, Scan Response Len 0 I (15619) SEC_GATTC_DEMO: searched Device Name Len 0 I (15629) SEC_GATTC_DEMO:

not compare I (15629) SEC_GATTC_DEMO: stop scan successfully E (15639) BT_BTM: BTM_BleScan scan not active

W (15649) BT_APPL: bta_dm_ble_scan stop scan failed, status=0x6

E (15649) SEC_GATTC_DEMO: scan stop failed, error status = 1 I (15669) SEC_GATTC_DEMO: ESP_GATTC_CONNECT_EVT conn_id 0, if 4 I (15669) SEC_GATTC_DEMO: REMOTE BDA: I (15669) SEC_GATTC_DEMO: ea 46 5f da d6 74 I (15669) SEC_GATTC_DEMO: open success I (15699) TW_MQTT: Queue empty I (15779) SEC_GATTC_DEMO: update connection params status = 0, min_int = 12, max_int = 12,conn_int = 12,latency = 0, timeout = 600 I (15799) TW_MQTT: Queue empty I (15899) TW_MQTT: Queue empty I (15999) TW_MQTT: Queue empty I (16099) TW_MQTT: Queue empty I (16139) SEC_GATTC_DEMO: ESP_GATTC_CFG_MTU_EVT, Status 0, MTU 247, conn_id 0 I (16149) SEC_GATTC_DEMO: SEARCH RES: conn_id = 0 is primary service 1 I (16149) SEC_GATTC_DEMO: start handle 11 end handle 65535 current handle value 11 I (16159) SEC_GATTC_DEMO: service found I (16159) SEC_GATTC_DEMO: UUID16: fe59 I (16169) SEC_GATTC_DEMO: Get service information from remote device I (16169) SEC_GATTC_DEMO: ESP_GATTC_SEARCH_CMPL_EVT cunt 2 Count before gattc no mem 2Gattc MEMMM Get char by uuid success Count before if 1 Before Write Write success jkasdkljdfjfdadnfkfihorkfjfgfGFGhyuytat I (16189) SEC_GATTC_DEMO: ESP_GATTC_REG_FOR_NOTIFY_EVT I (16199) TW_MQTT: Queue empty in case Write not success in case E (16239) SEC_GATTC_DEMO: write char failed, error status = 13

i am able to pair with device when i tried to send a char getting error like this

monikharajs commented 4 years ago

@prasad-alatkar sir, The above code is the changes I have made in gattc example Can you please able to find the solution?

Thank you in advance

dhrishi commented 4 years ago

@monikharajs Can you please provide the code change from the existing example in a better form (the diff or may be the entire file)

EDIT: Also, for a different error, please file a new issue going forward.

chegewara commented 4 years ago

This can be issue with peer device. Check if characteristic you are trying write to is allowing to write, maybe requires permission (pairing/bonding)?

FJTBC commented 4 years ago

@dhrishi W (11091) BT_APPL: bta_gattc_conn_cback() - cif=3 connected=0 conn_id=3 reason=0x0008 E (11091) GATTC_DEMO: write char failed, error status = 85 I (11091) GATTC_DEMO: ESP_GATTC_DISCONNECT_EVT, reason = 8

...
ESP_GATT_CONN_TIMEOUT = 0x08,                   /*!< Connection timeout  */ 
...

...
ESP_GATT_ERROR = 0x85,
...

what is the reason for this?

chegewara commented 4 years ago

Because its bluedroid port im guessing this is accurate answer: https://github.com/qiu-yongheng/GAIAControl/blob/master/blelibrary/src/main/java/com/qualcomm/libraries/ble/ErrorStatus.java#L131

Its just generic GATT error.

rocajira commented 4 years ago

Esto puede ser un problema con el dispositivo de igual. Verifique si la característica a la que está intentando escribir le permite escribir, ¿tal vez requiere permiso (emparejamiento / vinculación)?

Como hago para hacer emparejamiento y vinculacion?