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 *)¬ify_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:
*/