Creating our own READ,write event in BLE ESP 32 ESP IDF

Manveen
Posts: 5
Joined: Wed Jun 13, 2018 10:11 am

Creating our own READ,write event in BLE ESP 32 ESP IDF

Postby Manveen » Wed Jun 13, 2018 12:01 pm

How do we manually create read /write event to send or receive data ?
I have been using the example code for GATT client given here

https://github.com/espressif/esp-idf/bl ... ttc_demo.c

I tried to use esp_ble_gattc_write_char() in app main directly after registering all the App Profile ID but it shows that all the param meters of esp_ble_gattc_write_char() are not present

So how can we manually trigger the read and write event ??


here is my code if any one wants

Code: Select all

/*
   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 <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" //used for logging 

#define REMOTE_SERVICE_UUID        0x00FF   //The service that we want the characteristics from has an UUID of 0x00FF
#define REMOTE_NOTIFY_CHAR_UUID    0xFF01   // the characteristic we are interested in has an UUID of 0xFF01:

//custom uuid i tried but they did not work
// 6 bit uuid also doenst work
//#define REMOTE_SERVICE_UUID   8e575d17-0bc3-45f1-9839-d494ae954eea
//#define REMOTE_NOTIFY_CHAR_UUID   8bf4e50f-b3ed-47e2-b776-faca59c0ab62


#define PROFILE_NUM      1 //this is an application profile
#define PROFILE_A_APP_ID 0 // this is the id of that app profile // The Application Profile are stored in the gl_profile_tab array,
#define INVALID_HANDLE   0 //char_handle: the characteristic handle, this parameter valid when the type is ESP_GATT_DB_DESCRIPTOR. 
						   //If the type isn’t ESP_GATT_DB_DESCRIPTOR, this parameter should be ignore.

static const char remote_device_name[] = "ESP_GATTS_DEMO"; // this is the device we want to connect to 
//static const char remote_device_name[] = "Manveenmob"; // this is the device we want to connect to 

//static bool connect    = false;
static bool connect    = false;  // this means that the client is now not connected to anything
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;
uint8_t devicenumber = 1;

/* eclare static functions */
static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param); // basically isr function to a gap event  used in line 451
static void esp_gattc_cb(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param); // basically isr function to a gap event used in line 451  
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 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,
//	.own_addr_type          = BLE_ADDR_TYPE_RANDOM,
/*	doesnt work  shows error  BT_HCI: btu_
	hcif_hdl_command_complete opcode 0x200c status 0xc
	maybe i have to generate a random address then it will resolve this issue
	
	esp_err_t esp_ble_gap_set_rand_addr(esp_bd_addr_t rand_addr)
This function set the random address for the application.
	
	*/

    .scan_filter_policy     = BLE_SCAN_FILTER_ALLOW_ALL,
    .scan_interval          = 0x50,
    .scan_window            = 0x30,
   // .scan_duplicate         = BLE_SCAN_DUPLICATE_DISABLE
	.scan_duplicate         = BLE_SCAN_DUPLICATE_ENABLE // filters out duplicates
};

struct gattc_profile_inst {
    esp_gattc_cb_t gattc_cb; //GATT client callback function
    uint16_t gattc_if; //GATT client interface number for this profile
    uint16_t app_id; // Application Profile ID number
    uint16_t conn_id; // Connection ID
    uint16_t service_start_handle; //Service start handle
    uint16_t service_end_handle; //Service end handle
    uint16_t char_handle; //Char handle
    esp_bd_addr_t remote_bda; //Remote device address connected to this client.
};

/* 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. If callback report gattc_if/gatts_if as this macro, 
																means this event is not correspond to any app  */
    },
};

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: // sets scan parameters
			 ESP_LOGI(GATTC_TAG, "REG_EVT"); // logs 
			 esp_err_t scan_ret = esp_ble_gap_set_scan_params(&ble_scan_params); // checks wether the scan parameters have been set or not
			 if (scan_ret)
			 {// if scan parameter are not set then
              ESP_LOGE(GATTC_TAG, "set scan params error, error code = %x", scan_ret);
			 }
        break;
		case ESP_GATTC_CONNECT_EVT: //this wasnt triggered connection wasnt opened
			{  //After opening the connection, an ESP_GATTC_CONNECT_EVT event is triggered:
			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:    //The connection opening also triggers an ESP_GATTC_OPEN_EVT, 
								//which is used to check that the opening of the connection was done successfully,
								//otherwise print an error and exit.
			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: // when mtu is exchanged
        if (param->cfg_mtu.status != ESP_GATT_OK) // when there is a problem in exchange
		{
            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);
        //The MTU configuration event is also used to start discovering the services available in the server that the client just connected to.
		esp_ble_gattc_search_service(gattc_if, param->cfg_mtu.conn_id, &remote_filter_service_uuid);
        //To discover the services, the function esp_ble_gattc_search_service() is used.
		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.start_handle, p_data->search_res.srvc_id.inst_id);
        
		 // this is used to look for the service
		 
		 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: // when search event is complete 
        if (p_data->search_cmpl.status != ESP_GATT_OK)
		{ // if searching for devices has failed
            ESP_LOGE(GATTC_TAG, "search service failed, error status = %x", p_data->search_cmpl.status);
            break;
        }
        
		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) // this is a function created to 
{
    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
			
				ESP_LOGI(GATTC_TAG, "Started scaning");
				//uint32_t duration = 15;
				uint32_t duration = 5;
				
				esp_ble_gap_start_scanning(duration); // couldnt start the scan 
			
        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:  
	     {  // after scaning this event is called 
			esp_ble_gap_cb_param_t *scan_result = (esp_ble_gap_cb_param_t *)param; // it copies all the parameters to a new param meter called scan result
			ESP_LOGI(GATTC_TAG, "ESP_GAP_BLE_SCAN_RESULT_EVT is trigerd ");
			// switch inside a switch
			
			switch (scan_result->scan_rst.search_evt) //checks what search event has given output
													/*
												ESP_GAP_SEARCH_INQ_RES_EVT             = 0,      !< Inquiry result for a peer device. 
												ESP_GAP_SEARCH_INQ_CMPL_EVT            = 1,      !< Inquiry complete.
												ESP_GAP_SEARCH_DISC_RES_EVT            = 2,      !< Discovery result for a peer device. 
												ESP_GAP_SEARCH_DISC_BLE_RES_EVT        = 3,      !< Discovery result for BLE GATT based service on a peer device. 
												ESP_GAP_SEARCH_DISC_CMPL_EVT           = 4,      !< Discovery complete. 
												ESP_GAP_SEARCH_DI_DISC_CMPL_EVT        = 5,     !< Discovery complete. 
												ESP_GAP_SEARCH_SEARCH_CANCEL_CMPL_EVT  = 6,      < Search cancelled 
			*/
			{
				case ESP_GAP_SEARCH_INQ_RES_EVT:  //ESP_GAP_SEARCH_INQ_RES_EVT event, which is called every time a new device is found.
					//Every time we receive a result from the ESP_GAP_SEARCH_INQ_RES_EVT event, the code first prints the address of the remote device:
					
					 esp_log_buffer_hex(GATTC_TAG, scan_result->scan_rst.bda, 6); // prints the device address
					 //The client then prints the advertised data length and the scan response length
					 
					 ESP_LOGI(GATTC_TAG, "scanned device number = %d",devicenumber);
					 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);
					 devicenumber++;
					
					/*In order to get the device name, we use the esp_ble_resolve_adv_data() function, 
					which takes the advertised data stored in scan_result->scan_rst.ble_adv, the type of advertising data 
					and the length, in order to extract the value from the advertising packet frame.
					Then the device name is printed.
					*/
					
					// this is used to print the device name
					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)
					{ // this line is used to check create a connection
						if (strlen(remote_device_name) == adv_name_len && strncmp((char *)adv_name, remote_device_name, adv_name_len) == 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: // this is the last event trigered this event is trigered when there is no connection formed
					 ESP_LOGI(GATTC_TAG, "esp gap search inq cmpl evnt all the devices have been searched .. what happens after this ? where and how to connect");
					 uint32_t duration = 15;
				//uint32_t duration = 5;
				
				esp_ble_gap_start_scanning(duration); // couldnt start the scan 
				break;
				default:
				break;
			}
    break;
    }

    case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:   // stopped scanning
		 
		//this event was not trigerd
		 
		 ESP_LOGI(GATTC_TAG, "Stop scan event");
        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:    // advertising has completed
        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:   // updates the parameter
         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;
    }
}
						// this is event 				this is interface		these are parameters
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) 
		{ // checks the status
            gl_profile_tab[param->reg.app_id].gattc_if = gattc_if;  // if status is ok then create a gl profile tab
        } else {
            ESP_LOGI(GATTC_TAG, "reg app failed, app_id %04x, status %d",
                    param->reg.app_id,
                    param->reg.status);    //logs that registration failed
            return;
        }
    }

    /* If the gattc_if equal to profile A, call profile A cb handler,
     * so here call each profile's callback */
	 //Finally, the callback function invokes the corresponding event handler for each profile in the gl_profile_tab table.
    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);// runs one time  this is done to remove  int idx from memory
}

void app_main()
{
    // Initialize NVS.
    esp_err_t ret = nvs_flash_init();
	//esp_bd_addr_t rand_addr;
	//esp_err_t  randaddrret =   esp_ble_gap_set_rand_addr(rand_addr);
/*	if (ret) {   
        ESP_LOGE(GATTC_TAG, "didnt work");
        return;  
    }*/
	
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES) {  // if there is no free space then
        ESP_ERROR_CHECK(nvs_flash_erase());  // perform an error check by erasing the whole memory
        ret = nvs_flash_init();  // again put ret as nvs flash initialization
    }
    ESP_ERROR_CHECK( ret );  //performs a function

    ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));

    esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();// bt_cfg is a configurations data type which has default settings
    ret = esp_bt_controller_init(&bt_cfg);   //Initialize BT controller to allocate task and other resource. and it returns esp ok if succesfull
    if (ret) {   // here ret is not esp_ok  // esp ok has 0 value so if ret has any value this means an error has occoured
        ESP_LOGE(GATTC_TAG, "%s initialize controller failed: %s\n", __func__, esp_err_to_name(ret));
        return;  // this function creates a log for this
    }

    ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);  // now we have started bt controller   in ble mode
    if (ret) {
        ESP_LOGE(GATTC_TAG, "%s enable controller failed: %s\n", __func__, esp_err_to_name(ret));
        return; // this creates a log that enable controller failed
    }

    ret = esp_bluedroid_init(); // now we have to initialize the bt controller 
    if (ret) {
        ESP_LOGE(GATTC_TAG, "%s init bluetooth failed: %s\n", __func__, esp_err_to_name(ret));
        return;
    }

    ret = esp_bluedroid_enable(); // enable the bt 
    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); // This function is called to occur gap event, such as scan result.
    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;
    }
	/*
	The GAP and GATT event handlers are the functions used to catch 
	the events generated by the BLE stack and execute functions 
	to configure parameters of the application.
	*/	
//The functions esp_gap_cb() and esp_gattc_cb() handle all the events generated by the BLE stack.
    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);
    }
	
	//vTaskDelay(10000 / portTICK_PERIOD_MS);
	
	gattc_profile_event_handler(ESP_GATTC_WRITE_DESCR_EVT,gattc_if,*param);
	
	
}



 // tutorial 
 //https://github.com/espressif/esp-idf/blob/64b56be/examples/bluetooth/gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md

 /*
 /// Ble scan parameters
typedef struct {
    esp_ble_scan_type_t     scan_type;               !< Scan type  
    esp_ble_addr_type_t     own_addr_type;           !< Owner address type  
    esp_ble_scan_filter_t   scan_filter_policy;      !< Scan filter policy  
    uint16_t                scan_interval;           !< Scan interval. This is defined as the time interval from when the Controller started its last LE scan until it begins the subsequent LE scan.  
    //Range: 0x0004 to 0x4000 
    //Default: 0x0010 (10 ms)
    //Time = N * 0.625 msec
    //Time Range: 2.5 msec to 10.24	seconds
    uint16_t                scan_window;             !< Scan window. The duration of the LE scan. LE_Scan_Window shall be less than or equal to LE_Scan_Interval 
    //Range: 0x0004 to 0x4000                                                   	 //Default: 0x0010 (10 ms)
    //Time = N * 0.625 msec
    //Time Range: 2.5 msec to 10240 msec
} esp_ble_scan_params_t;
 
 An it is initialized as:

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
};




A service is defined using the esp_gatt_srvc_id_t structure as:

@brief Gatt id, include uuid and instance id
 
typedef struct {
    esp_bt_uuid_t   uuid;                  < UUID 
    uint8_t         inst_id;                < Instance id
} __attribute__((packed)) esp_gatt_id_t;
 
 ESP_GAP_SEARCH_INQ_CMPL_EVT, which is triggered when the duration of the scanning is
 completed and can be used to restart the scanning procedure:
 
 */

chegewara
Posts: 2362
Joined: Wed Jun 14, 2017 9:00 pm

Re: Creating our own READ,write event in BLE ESP 32 ESP IDF

Postby chegewara » Tue Jun 19, 2018 1:41 am

Why you are trying to write to characteristic on write to descriptor event ESP_GATTC_WRITE_DESCR_EVT:

Code: Select all

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;

Manveen
Posts: 5
Joined: Wed Jun 13, 2018 10:11 am

Re: Creating our own READ,write event in BLE ESP 32 ESP IDF

Postby Manveen » Tue Jun 19, 2018 4:19 am

This is the example code provided by expressif themselves. I am just trying to modify it so that I can perform the required operation. thats why I have not changed any other line of code. I will just add my code on top of it.

lx393ale
Posts: 15
Joined: Fri Jan 10, 2020 12:41 pm

Re: Creating our own READ,write event in BLE ESP 32 ESP IDF

Postby lx393ale » Fri Jan 10, 2020 1:05 pm

Hi Manveen!
I'm in the same situation, can you help me to find the right way pls?
I didn't found an example to exchange data with the two esp example client and server.

Thank you in advance

playground
Posts: 6
Joined: Mon Jan 25, 2021 3:54 am

Re: Creating our own READ,write event in BLE ESP 32 ESP IDF

Postby playground » Thu Mar 04, 2021 10:41 pm

I'm trying to do the same thing too. I want to manually trigger events from client to server. For example, ESP32-A as the server and ESP32-B as the client. Would like to push a button on ESP32-B to send the event to ESP32-A to turn on/off LED.

Does anyone have any examples?

SIDHAR
Posts: 2
Joined: Mon Sep 20, 2021 7:48 am

Re: Creating our own READ,write event in BLE ESP 32 ESP IDF

Postby SIDHAR » Mon Sep 20, 2021 7:59 am

yes i want a examples of same concept?

elDi@mond
Posts: 19
Joined: Fri Feb 04, 2022 10:42 am

Re: Creating our own READ,write event in BLE ESP 32 ESP IDF

Postby elDi@mond » Fri Feb 04, 2022 2:40 pm

topic bump
i wanna to know any way to write characteristics form any place of my code

oguzhantokuc
Posts: 2
Joined: Wed Feb 16, 2022 11:37 am

Re: Creating our own READ,write event in BLE ESP 32 ESP IDF

Postby oguzhantokuc » Thu Feb 17, 2022 11:36 am

Topic UPP!! I am in the same situation!!

lessoo
Posts: 1
Joined: Tue Nov 29, 2022 3:39 pm

Re: Creating our own READ,write event in BLE ESP 32 ESP IDF

Postby lessoo » Tue Nov 29, 2022 4:43 pm

I know this is old, but I have searched the same some time ago when I started my own project. Funny enough, I stumbled upon this thread after finding my solution. So for anyone after me I will leave something behind.

TLDR; save important parts from the cb-function in global variables to use from within the main

FIRST OF ALL: the example code of the original post is already quite old. Yet, at the current moment, my explanation should work for the current example and the old example.

1. We need to have discovered our services, characteristics and descriptors

2. The event ESP_GATTC_WRITE_CHAR_EVT is triggered upon calling the function 'esp_ble_gattc_write_char'. The same goes for the read event and function. (I have once called the read-function from within the read-event and created an infinite loop)

3. Of all the necessary variables for the 'esp_ble_gattc_write_char' call, the 'gattc_if' and 'conn_id' are usable within the main() with 'gl_profile_tab[PROFILE_A_APP_ID]'. The 'value_len' and 'value' are yours to specify obviously. The 'write_type' and 'auth_req' are specified by predefined macros you can look up. So the only remaining problem is the 'handle' (the characteristic handle).

The handle you are looking for is found and allocated in

Code: Select all

                    /*  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);
                    }
To be more specific, in the call of 'esp_ble_gattc_get_char_by_uuid', the handle(s) is/are saved in 'char_elem_result[ ].char_handle'. The array index in the example is 0, as there is only one result. The handle is saved then in 'gl_profile_tab[PROFILE_A_APP_ID].char_handle', because the 'char_elem_result' is freed right after. So you can create a global variable of type uint16_t and save the char_handle in that variable right after it is saved in the profile_tab or use it from the profile_tab (depends on the type of example-code. I have used my own structs with UUIDs and handles for my characteristics)

With this you have everything to call the read/write functions. These functions trigger their events and the result of the read call will be found in the read event. The size that was read is in 'p_data->read.value_len' and the value in 'p_data->read.value'. The only important thing left is to make sure that the read/write call is made after the successful setup of the connection and the service and characteristic have been found.

I know this is not the cleanest of methods, but it enables one to read and write from and to characteristics from within the main(). The same should roughly work for descriptors. I hope this helps someone, even though this thread is already quite old.

Who is online

Users browsing this forum: No registered users and 101 guests