text:
/builds/idf/crosstool-NG/.build/xtensa-esp32-elf/src/gdb/gdb/thread.c:93: internal-error: thread_info* inferior_thread(): Assertion `tp' failed. (IDFGH-3361)

Development Kit:    none
Module or chip used:  ESP32-WROOM-32
IDF version: v4.2-dev-1206-g741960d5c
Build System:     idf.py
Compiler version: xtensa-esp32-elf-gcc (crosstool-NG esp-2020r1) 8.2.0
Operating System:    Linux
Using an IDE?:  No
Power Supply:    USB

Problem Description
idf.py monitor with gdb stubs doesnt work
//Detailed problem description goes here.

***ERROR*** A stack overflow in task carrier has been detected.

Backtrace:0x4008eb63:0x3ffe0340 0x4008e885:0x3ffe0360 0x4009b5a9:0x3ffe0380 0x4009cd0a:0x3ffe0400 0x4009b69c:0x3ffe0420 0x4009b652:0x00000000 |<-CORRUPTED
0x4008eb63: panic_abort at /opt/toolchains/esp32/idf/components/esp_system/panic.c:330

0x4008e885: esp_system_abort at /opt/toolchains/esp32/idf/components/esp_system/system_api.c:97

0x4009b5a9: vApplicationStackOverflowHook at /opt/toolchains/esp32/idf/components/freertos/xtensa/port.c:436

0x4009cd0a: vTaskSwitchContext at /opt/toolchains/esp32/idf/components/freertos/tasks.c:2769

0x4009b69c: _frxt_dispatch at /opt/toolchains/esp32/idf/components/freertos/xtensa/portasm.S:431

0x4009b652: _frxt_int_exit at /opt/toolchains/esp32/idf/components/freertos/xtensa/portasm.S:231

ELF file SHA256: 6a0adf99108b697c

Entering gdb stub now.
$T0b#e6GNU gdb (crosstool-NG esp-2020r1) 8.1.0.20180627-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-build_pc-linux-gnu --target=xtensa-esp32-elf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /home/aep/proj/corona/esp/counter/build/crs19.elf...done.
Remote debugging using /dev/ttyUSB0
/builds/idf/crosstool-NG/.build/xtensa-esp32-elf/src/gdb/gdb/thread.c:93: internal-error: thread_info* inferior_thread(): Assertion `tp' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Quit this debugging session? (y or n) n

Hi @aep, do you see this behavior on every crash, or only when the stack overflow is detected? I made a trivial test application which overflows the stack, but couldn't get the same behavior. Do you think you could trim your app down to something that reproduces the issue?

i'm having difficulties reproducing this as well. the root cause was a function with very large stack values calling itself.
this code wont even trigger stack smashing protection, it just resets due to watchdog
void large_stack()
{
    char something[10000];
    memset(something, 0xff, 10000);
    large_stack();
}

void app_main(void)
{
    large_stack();
}

Could you try adding CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y to your sdkconfig?
I think this issue can not be detected with stack smashing protection, because from the C compiler perspective stack smashing is not happening — the memset stays within the boundaries of the function's stack frame. The issue is that the stack frame overflows the space available on the stack. The above mentioned option is not a guaranteed way to catch such stack  overflow (it won't help if you memset only the last 1k of the array), but it still increases the chances of detecting this early.

yeah this is with

[x] FREERTOS_WATCHPOINT_END_OF_STACK
[x] COMPILER_STACK_CHECK_MODE_STRONG
[x] FREERTOS_CHECK_STACKOVERFLOW_CANARY

any idea how i could intentionally trigger a context switch? the problematic app had 10 tasks, so maybe its not reproducible because its just 1 task

authors: aep igrr


text:
[TW#12271] BLE indicate/notification issue

Hi, is there a sample to show how to send and receive indicate/noitification between two ESP32 devices? I can send notification between ESP32 (sender) and iPhone (receiver). But I cannot receive notification between two ESP32.

@Nicholas3388
If you want receive notify or indicate from server:

register for notification.
write char description.

In step 1, call esp_ble_gattc_register_for_notify(gattc_if, server_bda, srvc_id, char_id)
/**
 * @brief           This function is called to register for notification of a service.
 *
 * @param[in]       gattc_if: Gatt client access interface.
 * @param[in]       server_bda : target GATT server.
 * @param[in]       srvc_id : pointer to GATT service ID.
 * @param[in]       char_id : pointer to GATT characteristic ID.
 *
 * @return
 *                  - ESP_OK: registration succeeds
 *                  - other: failed
 *
 */
esp_gatt_status_t esp_ble_gattc_register_for_notify (esp_gatt_if_t gattc_if,
                                                    esp_bd_addr_t server_bda,
                                                    esp_gatt_srvc_id_t *srvc_id,
                                                    esp_gatt_id_t *char_id);

after invoke this API, the event  ESP_GATTC_REG_FOR_NOTIFY_EVT will come.
In step 2, write char descr, if the char prem is notify, write value 0x1, if the char prem is indicate, write value 0x2.
    case ESP_GATTC_REG_FOR_NOTIFY_EVT:
        esp_ble_gattc_write_char_descr(......)
        break;

/**
 * @brief           This function is called to write characteristic descriptor value.
 *
 * @param[in]       gattc_if: Gatt client access interface.
 * @param[in]       conn_id : connection ID
 * @param[in]       srvc_id : service ID.
 * @param[in]       char_id : characteristic ID.
 * @param[in]       descr_id : characteristic descriptor ID to write.
 * @param[in]       value_len: length of the value to be written.
 * @param[in]       value : the value to be written.
 * @param[in]       write_type : the type of attribute write operation.
 * @param[in]       auth_req : authentication request.
 *
 * @return
 *                  - ESP_OK: success
 *                  - other: failed
 *
 */
esp_err_t esp_ble_gattc_write_char_descr (esp_gatt_if_t gattc_if,
                                        uint16_t conn_id,
                                        esp_gatt_srvc_id_t *srvc_id,
                                        esp_gatt_id_t *char_id,
                                        esp_gatt_id_t *descr_id,
                                        uint16_t value_len,
                                        uint8_t *value,
                                		esp_gatt_write_type_t write_type,
                                        esp_gatt_auth_req_t auth_req);

OK, you can receive notify or indicate now!

@xiewenxiang Hi, thanks for you code. I follow your steps, on the client I register notify for char, say 0xFF01, and then write char descriptor (0x2902). For server, I use the esp-idf gatts_demo.
The server calls esp_ble_gatts_add_char to add char  0xFF01 (read|write|notify), and then calls esp_ble_gatts_add_char_descr to add the descriptor 0x2902. When char and desc is added, I create a task to send notification as following:
static void led_task(void *arg) {   while (1) {     vTaskDelay(3000 / portTICK_RATE_MS);     esp_ble_gatts_send_indicate(client_if, client_conn, char_handle, notif_len, value, false);   } }
The char_handle is the handle for char 0xFF01. Is there anything wrong with my steps?  The ESP32 client  cannot receive notification from the ESP32 server.

@Nicholas3388
Hi, Nicholas, I'd like to confirm the procedure for your operation:

server: create service 、start service and start adv
client connected to server
client discover service  esp_ble_gattc_search_service(gattc_if, conn_id, NULL) , in this step, If there is only one service on the server, Event case ESP_GATTC_SEARCH_RES_EVT: will come three times, the last one is the real service.
client discover char esp_ble_gattc_get_characteristic(gatt_if, conn_id, &srvc_id, NULL) , in this step, event case ESP_GATTC_GET_CHAR_EVT: will come, you can find the descripton of this char, and find next char

    case ESP_GATTC_GET_CHAR_EVT:
        if (p_data->get_char.status != ESP_GATT_OK) {
            break;
        }
        char_id.inst_id = p_data->get_char.char_id.inst_id;
        char_id.uuid.len = p_data->get_char.char_id.uuid.len;
        if (char_id.uuid.len == ESP_UUID_LEN_16) {
            char_id.uuid.uuid.uuid16 = p_data->get_char.char_id.uuid.uuid.uuid16;
        } else if (char_id.uuid.len == ESP_UUID_LEN_32) {
            char_id.uuid.uuid.uuid32 = p_data->get_char.char_id.uuid.uuid.uuid32;
        } else if (char_id.uuid.len == ESP_UUID_LEN_128) {
            for (int i = 0; i < 16; i++) {
                char_id.uuid.uuid.uuid128[i] = p_data->get_char.char_id.uuid.uuid.uuid128[i];
            }
        }
        //TODO:
        esp_ble_gattc_get_descriptor(gatt_if, conn_id, &srvc_id, &char_id, NULL);
        break;
    case ESP_GATTC_GET_DESCR_EVT:
        if (p_data->get_descr.status != ESP_GATT_OK) {
            esp_ble_gattc_get_characteristic(gatt_if, conn_id, &srvc_id, &char_id);
            break;
        }
        descr_id.inst_id = p_data->get_descr.descr_id.inst_id;
        descr_id.uuid.len = p_data->get_descr.descr_id.uuid.len;

        if (descr_id.uuid.len == ESP_UUID_LEN_16) {
            descr_id.uuid.uuid.uuid16 = p_data->get_descr.descr_id.uuid.uuid.uuid16;
        } else if (descr_id.uuid.len == ESP_UUID_LEN_32) {
            descr_id.uuid.uuid.uuid32 = p_data->get_descr.descr_id.uuid.uuid.uuid32;
        } else if (descr_id.uuid.len == ESP_UUID_LEN_128) {
            for (int i = 0; i < 16; i++) {
                descr_id.uuid.uuid.uuid128[i] = p_data->get_descr.descr_id.uuid.uuid.uuid128[i];
            }
        }
        //TODO:
        esp_ble_gattc_get_descriptor(gatt_if, conn_id, &srvc_id, &char_id, &descr_id);
        break;

Make sure that the parameters are correct
esp_ble_gattc_register_for_notify(gattc_if, server_bda, srvc_id, char_id) esp_ble_gattc_write_char_descr(...)

If possible, please provide your code. Thanks

@xiewenxiang  Hi, the following code is client:
`#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#include "controller.h"
#include "bt.h"
#include "bt_trace.h"
#include "bt_types.h"
#include "btm_api.h"
#include "bta_api.h"
#include "bta_gatt_api.h"
#include "esp_gap_ble_api.h"
#include "esp_gattc_api.h"
#include "esp_gatt_defs.h"
#include "esp_bt_main.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#define BT_BD_ADDR_STR         "%02x:%02x:%02x:%02x:%02x:%02x"
#define BT_BD_ADDR_HEX(addr)   addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]
#define TEST_SRV_UUID			0x00FF
#define TEST_CHAR_UUID			0xFF01
#define LED_GPIO				2
static esp_gatt_if_t client_if;
static uint16_t client_conn = 0;
esp_gatt_status_t status = ESP_GATT_ERROR;
bool connet = false;
uint16_t simpleClient_id = 0xEE;
const char device_name[] = "ESP32";
static char tar_dev_mac[6] = {0xff, 0xb5, 0x30, 0x4e, 0x0a, 0xcb};
static esp_bd_addr_t server_dba;
static bool is_led_on = false;
static esp_ble_scan_params_t ble_scan_params = {
.scan_type              = BLE_SCAN_TYPE_ACTIVE,
.own_addr_type          = ESP_PUBLIC_ADDR,
.scan_filter_policy     = BLE_SCAN_FILTER_ALLOW_ALL,
.scan_interval          = 0x50,
.scan_window            = 0x30
};
static esp_gatt_srvc_id_t test_service_id = {
.id = {
.uuid = {
.len = ESP_UUID_LEN_16,
.uuid = {.uuid16 = TEST_SRV_UUID,},
},
.inst_id = 0,
},
.is_primary = true,
};
static esp_gatt_id_t test_char_id = {
.uuid = {
.len = ESP_UUID_LEN_16,
.uuid = {.uuid16 = TEST_CHAR_UUID,},
},
.inst_id = 0,
};
static esp_gatt_id_t notify_descr_id = {
.uuid = {
.len = ESP_UUID_LEN_16,
.uuid = {.uuid16 = GATT_UUID_CHAR_CLIENT_CONFIG,},
},
.inst_id = 0,
};
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 get_characteristic_property(uint32_t flag)
{
int i;
ESP_LOGI(TAG, "=======================================");
for (i = 0; i < 8; i ++) {
switch (flag & (2 << i))
{
case ESP_GATT_CHAR_PROP_BIT_BROADCAST:
ESP_LOGI(TAG, "==> CHAR PROP ESP_GATT_CHAR_PROP_BIT_BROADCAST");
break;
case ESP_GATT_CHAR_PROP_BIT_READ:
ESP_LOGI(TAG, "==> CHAR PROP ESP_GATT_CHAR_PROP_BIT_READ");
break;
case ESP_GATT_CHAR_PROP_BIT_WRITE_NR:
ESP_LOGI(TAG, "==> CHAR PROP ESP_GATT_CHAR_PROP_BIT_WRITE_NR");
break;
case ESP_GATT_CHAR_PROP_BIT_WRITE:
ESP_LOGI(TAG, "==> CHAR PROP ESP_GATT_CHAR_PROP_BIT_WRITE");
break;
case ESP_GATT_CHAR_PROP_BIT_NOTIFY:
ESP_LOGI(TAG, "==> CHAR PROP ESP_GATT_CHAR_PROP_BIT_NOTIFY");
break;
case ESP_GATT_CHAR_PROP_BIT_INDICATE:
ESP_LOGI(TAG, "==> CHAR PROP ESP_GATT_CHAR_PROP_BIT_INDICATE");
break;
case ESP_GATT_CHAR_PROP_BIT_AUTH:
ESP_LOGI(TAG, "==> CHAR PROP ESP_GATT_CHAR_PROP_BIT_AUTH");
break;
case ESP_GATT_CHAR_PROP_BIT_EXT_PROP:
ESP_LOGI(TAG, "==> CHAR PROP ESP_GATT_CHAR_PROP_BIT_EXT_PROP");
break;
default:
break;
}
}
ESP_LOGI(TAG, "=======================================");
}
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 = 10;
esp_ble_gap_start_scanning(duration);
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:
switch (scan_result->scan_rst.dev_type) {
case ESP_BT_DEVICE_TYPE_BREDR:
ESP_LOGI(TAG, "==> Connected Device type BREDR");
break;
case ESP_BT_DEVICE_TYPE_BLE:
ESP_LOGI(TAG, "==> Connected Device type BLE");
break;
case ESP_BT_DEVICE_TYPE_DUMO:
ESP_LOGI(TAG, "==> Connected Device type DUMO");
break;
default:
break;
}
LOG_INFO("BDA %x,%x,%x,%x,%x,%x:",scan_result->scan_rst.bda[0],
scan_result->scan_rst.bda[1],scan_result->scan_rst.bda[2],
scan_result->scan_rst.bda[3],scan_result->scan_rst.bda[4],
scan_result->scan_rst.bda[5]);
for (int i = 0; i < 6; i++) {
server_dba[i]=scan_result->scan_rst.bda[i];
}
adv_name = esp_ble_resolve_adv_data(scan_result->scan_rst.ble_adv,
ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len);
LOG_INFO("adv_name_len=%x\n", adv_name_len);
/for (int j = 0; j < adv_name_len; j++) {
LOG_INFO("a%d %x %c = d%d %x %c",j, adv_name[j], adv_name[j],j, device_name[j], device_name[j]);
}/
		if (strncmp((char *)adv_name, device_name,adv_name_len) == 0 && connet == false) {
			connet = true;
			ESP_LOGI(TAG, "==> address type: %d, dev name: %s", scan_result->scan_rst.ble_addr_type, adv_name);
            LOG_INFO("Connect to the remote device.");
            esp_ble_gap_stop_scanning();
            esp_ble_gattc_open(client_if, scan_result->scan_rst.bda, true);
			memcpy(tar_dev_mac, scan_result->scan_rst.bda, 6);
		}
        break;
    case ESP_GAP_SEARCH_INQ_CMPL_EVT:
		//esp_ble_gap_cb_param_t *scan_result = (esp_ble_gap_cb_param_t *)param;
		switch (scan_result->scan_rst.ble_evt_type) {
			 case ESP_BLE_EVT_CONN_ADV:
				 ESP_LOGI(TAG, "==> CONN_ADV");
				 ESP_LOGI(TAG, "BDA %x,%x,%x,%x,%x,%x:",scan_result->scan_rst.bda[0],
							 scan_result->scan_rst.bda[1],scan_result->scan_rst.bda[2],
											 scan_result->scan_rst.bda[3],scan_result->scan_rst.bda[4],
											 scan_result->scan_rst.bda[5]);
				 ESP_LOGI(TAG, "==> RSSI: %d", scan_result->scan_rst.rssi);
				 ESP_LOGI(TAG, "==> address type: %d", scan_result->scan_rst.ble_addr_type);
				 break;
			 case ESP_BLE_EVT_CONN_DIR_ADV:
				 ESP_LOGI(TAG, "==> CONN_DIR_ADV");
				 break;
			 case ESP_BLE_EVT_DISC_ADV:
				 ESP_LOGI(TAG, "==> DISC_ADV");
				 break;
			 case ESP_BLE_EVT_NON_CONN_ADV:
				 ESP_LOGI(TAG, "==> NON_CONN_ADV");
				 break;
			 case ESP_BLE_EVT_SCAN_RSP:
				 ESP_LOGI(TAG, "==> receive scan response");
				 LOG_INFO("BDA %x,%x,%x,%x,%x,%x:",scan_result->scan_rst.bda[0],
							 scan_result->scan_rst.bda[1],scan_result->scan_rst.bda[2],
											 scan_result->scan_rst.bda[3],scan_result->scan_rst.bda[4],
											 scan_result->scan_rst.bda[5]);
				 break;
		}
        break;
    default:
        break;
    }
    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)
{
uint16_t conn_id = 0;
esp_ble_gattc_cb_param_t *p_data = (esp_ble_gattc_cb_param_t *)param;
LOG_INFO("esp_gattc_cb, event = %x", event);
switch (event) {
case ESP_GATTC_REG_EVT:
    status = p_data->reg.status;
    LOG_INFO("ESP_GATTC_REG_EVT status = %x, client_if = %x", status, gattc_if);
if (status == ESP_GATT_OK) {
	client_if = gattc_if;
} else {
	LOG_INFO("ESP_GATTC_REG failed!");
}
    break;
case ESP_GATTC_OPEN_EVT:
    conn_id = p_data->open.conn_id;
    LOG_INFO("ESP_GATTC_OPEN_EVT conn_id %d, if %d, status %d", conn_id, gattc_if, p_data->open.status);
	if (p_data->open.status != 0) {
		LOG_INFO("==> open GATTC error, closed");
		esp_ble_gattc_close(gattc_if, conn_id);
		esp_ble_gattc_open(gattc_if, (uint8_t *)tar_dev_mac, true);
		break;
	}
    esp_ble_gattc_search_service(gattc_if, conn_id, NULL);
	client_conn = conn_id;
    break;
case ESP_GATTC_CLOSE_EVT:
	LOG_INFO("==> GATTC closed");
	esp_ble_gattc_open(client_if, (uint8_t *)tar_dev_mac, true);
	client_conn = 0;
break;
case ESP_GATTC_READ_CHAR_EVT: {
    // esp_gatt_srvc_id_t *srvc_id = &p_data->read.srvc_id;
    esp_gatt_id_t *char_id = &p_data->read.char_id;
    conn_id = p_data->open.conn_id;
    LOG_INFO("READ CHAR: open.conn_id = %x search_res.conn_id = %x  read.conn_id = %x", conn_id,p_data->search_res.conn_id,p_data->read.conn_id);
    LOG_INFO("READ CHAR: read.status = %x inst_id = %x", p_data->read.status, char_id->inst_id);
    if (p_data->read.status==0) {
		if (char_id->uuid.len == ESP_UUID_LEN_16) {
			LOG_INFO("Char UUID16: %x", char_id->uuid.uuid.uuid16);
		} else if (char_id->uuid.len == ESP_UUID_LEN_32) {
			LOG_INFO("Char UUID32: %x", char_id->uuid.uuid.uuid32);
		} else if (char_id->uuid.len == ESP_UUID_LEN_128) {
			LOG_INFO("Char UUID128: %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x", char_id->uuid.uuid.uuid128[0],
					 char_id->uuid.uuid.uuid128[1], char_id->uuid.uuid.uuid128[2], char_id->uuid.uuid.uuid128[3],
					 char_id->uuid.uuid.uuid128[4], char_id->uuid.uuid.uuid128[5], char_id->uuid.uuid.uuid128[6],
					 char_id->uuid.uuid.uuid128[7], char_id->uuid.uuid.uuid128[8], char_id->uuid.uuid.uuid128[9],
					 char_id->uuid.uuid.uuid128[10], char_id->uuid.uuid.uuid128[11], char_id->uuid.uuid.uuid128[12],
					 char_id->uuid.uuid.uuid128[13], char_id->uuid.uuid.uuid128[14], char_id->uuid.uuid.uuid128[15]);
		} else {
			LOG_ERROR("Char UNKNOWN LEN %d\n", char_id->uuid.len);
		}
        for (int i = 0; i < p_data->read.value_len; i++) {
            LOG_INFO("%x:", p_data->read.value[i]);
        }
    }
    break;
}
case ESP_GATTC_WRITE_CHAR_EVT: {
    // esp_gatt_srvc_id_t *srvc_id = &p_data->write.srvc_id;
    esp_gatt_id_t *char_id = &p_data->write.char_id;
    esp_gatt_id_t *descr_id = &p_data->write.descr_id;
    conn_id = p_data->open.conn_id;
    LOG_INFO("WRITE CHAR: open.conn_id = %x search_res.conn_id = %x  write.conn_id = %x", conn_id,p_data->search_res.conn_id,p_data->write.conn_id);
    LOG_INFO("WRITE CHAR: write.status = %x inst_id = %x", p_data->write.status, char_id->inst_id);
    if (p_data->write.status==0) {
		if (char_id->uuid.len == ESP_UUID_LEN_16) {
			LOG_INFO("Char UUID16: %x", char_id->uuid.uuid.uuid16);
		} else if (char_id->uuid.len == ESP_UUID_LEN_32) {
			LOG_INFO("Char UUID32: %x", char_id->uuid.uuid.uuid32);
		} else if (char_id->uuid.len == ESP_UUID_LEN_128) {
			LOG_INFO("Char UUID128: %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x", char_id->uuid.uuid.uuid128[0],
					 char_id->uuid.uuid.uuid128[1], char_id->uuid.uuid.uuid128[2], char_id->uuid.uuid.uuid128[3],
					 char_id->uuid.uuid.uuid128[4], char_id->uuid.uuid.uuid128[5], char_id->uuid.uuid.uuid128[6],
					 char_id->uuid.uuid.uuid128[7], char_id->uuid.uuid.uuid128[8], char_id->uuid.uuid.uuid128[9],
					 char_id->uuid.uuid.uuid128[10], char_id->uuid.uuid.uuid128[11], char_id->uuid.uuid.uuid128[12],
					 char_id->uuid.uuid.uuid128[13], char_id->uuid.uuid.uuid128[14], char_id->uuid.uuid.uuid128[15]);
		} else {
			LOG_ERROR("Char UNKNOWN LEN %d", char_id->uuid.len);
		}
		if (descr_id->uuid.len == ESP_UUID_LEN_16) {
			LOG_INFO("Decr UUID16: %x", descr_id->uuid.uuid.uuid16);
		} else if (descr_id->uuid.len == ESP_UUID_LEN_32) {
			LOG_INFO("Decr UUID32: %x", descr_id->uuid.uuid.uuid32);
		} else if (descr_id->uuid.len == ESP_UUID_LEN_128) {
			LOG_INFO("Decr UUID128: %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x", descr_id->uuid.uuid.uuid128[0],
					 descr_id->uuid.uuid.uuid128[1], descr_id->uuid.uuid.uuid128[2], descr_id->uuid.uuid.uuid128[3],
					 descr_id->uuid.uuid.uuid128[4], descr_id->uuid.uuid.uuid128[5], descr_id->uuid.uuid.uuid128[6],
					 descr_id->uuid.uuid.uuid128[7], descr_id->uuid.uuid.uuid128[8], descr_id->uuid.uuid.uuid128[9],
					 descr_id->uuid.uuid.uuid128[10], descr_id->uuid.uuid.uuid128[11], descr_id->uuid.uuid.uuid128[12],
					 descr_id->uuid.uuid.uuid128[13], descr_id->uuid.uuid.uuid128[14], descr_id->uuid.uuid.uuid128[15]);
		} else {
			LOG_ERROR("Decr UNKNOWN LEN %d", descr_id->uuid.len);
		}
    }
    break;
}
case ESP_GATTC_SEARCH_RES_EVT: {
    esp_gatt_srvc_id_t *srvc_id = &p_data->search_res.srvc_id;
    conn_id = p_data->open.conn_id;
    LOG_INFO("SEARCH RES: open.conn_id = %x search_res.conn_id = %x", conn_id,p_data->search_res.conn_id);
    if (srvc_id->id.uuid.len == ESP_UUID_LEN_16) {
        LOG_INFO("UUID16: %x", srvc_id->id.uuid.uuid.uuid16);
    } else if (srvc_id->id.uuid.len == ESP_UUID_LEN_32) {
        LOG_INFO("UUID32: %x", srvc_id->id.uuid.uuid.uuid32);
    } else if (srvc_id->id.uuid.len == ESP_UUID_LEN_128) {
        LOG_INFO("UUID128: %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x", srvc_id->id.uuid.uuid.uuid128[0],
                 srvc_id->id.uuid.uuid.uuid128[1], srvc_id->id.uuid.uuid.uuid128[2], srvc_id->id.uuid.uuid.uuid128[3],
                 srvc_id->id.uuid.uuid.uuid128[4], srvc_id->id.uuid.uuid.uuid128[5], srvc_id->id.uuid.uuid.uuid128[6],
                 srvc_id->id.uuid.uuid.uuid128[7], srvc_id->id.uuid.uuid.uuid128[8], srvc_id->id.uuid.uuid.uuid128[9],
                 srvc_id->id.uuid.uuid.uuid128[10], srvc_id->id.uuid.uuid.uuid128[11], srvc_id->id.uuid.uuid.uuid128[12],
                 srvc_id->id.uuid.uuid.uuid128[13], srvc_id->id.uuid.uuid.uuid128[14], srvc_id->id.uuid.uuid.uuid128[15]);
    } else {
        LOG_ERROR("UNKNOWN LEN %d", srvc_id->id.uuid.len);
    }
	esp_ble_gattc_get_characteristic(gattc_if, p_data->search_res.conn_id, srvc_id, NULL);
    break;
}
case ESP_GATTC_WRITE_DESCR_EVT: {
    esp_gatt_srvc_id_t *srvc_id = &p_data->write.srvc_id;
    esp_gatt_id_t *char_id = &p_data->write.char_id;
    esp_gatt_id_t *descr_id = &p_data->write.descr_id;
    conn_id = p_data->open.conn_id;
    LOG_INFO("WRITE DESCR: open.conn_id = %x search_res.conn_id = %x  write.conn_id = %x", conn_id,p_data->search_res.conn_id,p_data->write.conn_id);
    LOG_INFO("WRITE DESCR: write.status = %x inst_id = %x open.gatt_if = %x", p_data->write.status, char_id->inst_id,gattc_if);
    if (p_data->write.status==0) {
		if (char_id->uuid.len == ESP_UUID_LEN_16) {
			LOG_INFO("Char UUID16: %x", char_id->uuid.uuid.uuid16);
		} else if (char_id->uuid.len == ESP_UUID_LEN_32) {
			LOG_INFO("Char UUID32: %x", char_id->uuid.uuid.uuid32);
		} else if (char_id->uuid.len == ESP_UUID_LEN_128) {
			LOG_INFO("Char UUID128: %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x", char_id->uuid.uuid.uuid128[0],
					 char_id->uuid.uuid.uuid128[1], char_id->uuid.uuid.uuid128[2], char_id->uuid.uuid.uuid128[3],
					 char_id->uuid.uuid.uuid128[4], char_id->uuid.uuid.uuid128[5], char_id->uuid.uuid.uuid128[6],
					 char_id->uuid.uuid.uuid128[7], char_id->uuid.uuid.uuid128[8], char_id->uuid.uuid.uuid128[9],
					 char_id->uuid.uuid.uuid128[10], char_id->uuid.uuid.uuid128[11], char_id->uuid.uuid.uuid128[12],
					 char_id->uuid.uuid.uuid128[13], char_id->uuid.uuid.uuid128[14], char_id->uuid.uuid.uuid128[15]);
		} else {
			LOG_ERROR("Char UNKNOWN LEN %d", char_id->uuid.len);
		}
		if (descr_id->uuid.len == ESP_UUID_LEN_16) {
			LOG_INFO("Decr UUID16: %x", descr_id->uuid.uuid.uuid16);
		} else if (descr_id->uuid.len == ESP_UUID_LEN_32) {
			LOG_INFO("Decr UUID32: %x", descr_id->uuid.uuid.uuid32);
		} else if (descr_id->uuid.len == ESP_UUID_LEN_128) {
			LOG_INFO("Decr UUID128: %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x", descr_id->uuid.uuid.uuid128[0],
					 descr_id->uuid.uuid.uuid128[1], descr_id->uuid.uuid.uuid128[2], descr_id->uuid.uuid.uuid128[3],
					 descr_id->uuid.uuid.uuid128[4], descr_id->uuid.uuid.uuid128[5], descr_id->uuid.uuid.uuid128[6],
					 descr_id->uuid.uuid.uuid128[7], descr_id->uuid.uuid.uuid128[8], descr_id->uuid.uuid.uuid128[9],
					 descr_id->uuid.uuid.uuid128[10], descr_id->uuid.uuid.uuid128[11], descr_id->uuid.uuid.uuid128[12],
					 descr_id->uuid.uuid.uuid128[13], descr_id->uuid.uuid.uuid128[14], descr_id->uuid.uuid.uuid128[15]);
		} else {
			LOG_ERROR("Decr UNKNOWN LEN %d", descr_id->uuid.len);
		}
		if (srvc_id->id.uuid.len == ESP_UUID_LEN_16) {
			LOG_INFO("SRVC UUID16: %x", srvc_id->id.uuid.uuid.uuid16);
		} else if (srvc_id->id.uuid.len == ESP_UUID_LEN_32) {
			LOG_INFO("SRVC UUID32: %x", srvc_id->id.uuid.uuid.uuid32);
		} else if (srvc_id->id.uuid.len == ESP_UUID_LEN_128) {
			LOG_INFO("SRVC UUID128: %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x", srvc_id->id.uuid.uuid.uuid128[0],
					 srvc_id->id.uuid.uuid.uuid128[1], srvc_id->id.uuid.uuid.uuid128[2], srvc_id->id.uuid.uuid.uuid128[3],
					 srvc_id->id.uuid.uuid.uuid128[4], srvc_id->id.uuid.uuid.uuid128[5], srvc_id->id.uuid.uuid.uuid128[6],
					 srvc_id->id.uuid.uuid.uuid128[7], srvc_id->id.uuid.uuid.uuid128[8], srvc_id->id.uuid.uuid.uuid128[9],
					 srvc_id->id.uuid.uuid.uuid128[10], srvc_id->id.uuid.uuid.uuid128[11], srvc_id->id.uuid.uuid.uuid128[12],
					 srvc_id->id.uuid.uuid.uuid128[13], srvc_id->id.uuid.uuid.uuid128[14], srvc_id->id.uuid.uuid.uuid128[15]);
		} else {
			LOG_ERROR("SRVC UNKNOWN LEN %d", srvc_id->id.uuid.len);
		}
        LOG_INFO("WRITE DESCR: gattc_if = %x",gattc_if);
        LOG_INFO("remote_bda %x,%x,%x,%x,%x,%x:",p_data->open.remote_bda[0],
        		p_data->open.remote_bda[1],p_data->open.remote_bda[2],
				p_data->open.remote_bda[3],p_data->open.remote_bda[4],
				p_data->open.remote_bda[5]);
        LOG_INFO("server_dba %x,%x,%x,%x,%x,%x:",server_dba[0],
        		server_dba[1],server_dba[2],
				server_dba[3],server_dba[4],
				server_dba[5]);
    }
    break;
}
case ESP_GATTC_NOTIFY_EVT: {
    // esp_gatt_srvc_id_t *srvc_id = &p_data->read.srvc_id;
    esp_gatt_id_t *char_id = &p_data->notify.char_id;
    conn_id = p_data->open.conn_id;
    LOG_INFO("NOTIFY: open.conn_id = %x search_res.conn_id = %x  notify.conn_id = %x", conn_id,p_data->search_res.conn_id,p_data->notify.conn_id);
    LOG_INFO("NOTIFY: notify.is_notify = %x inst_id = %x", p_data->notify.is_notify, char_id->inst_id);
    if (p_data->notify.is_notify==1) {
		if (char_id->uuid.len == ESP_UUID_LEN_16) {
			LOG_INFO("Char UUID16: %x", char_id->uuid.uuid.uuid16);
		} else if (char_id->uuid.len == ESP_UUID_LEN_32) {
			LOG_INFO("Char UUID32: %x", char_id->uuid.uuid.uuid32);
		} else if (char_id->uuid.len == ESP_UUID_LEN_128) {
			LOG_INFO("Char UUID128: %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x", char_id->uuid.uuid.uuid128[0],
					 char_id->uuid.uuid.uuid128[1], char_id->uuid.uuid.uuid128[2], char_id->uuid.uuid.uuid128[3],
					 char_id->uuid.uuid.uuid128[4], char_id->uuid.uuid.uuid128[5], char_id->uuid.uuid.uuid128[6],
					 char_id->uuid.uuid.uuid128[7], char_id->uuid.uuid.uuid128[8], char_id->uuid.uuid.uuid128[9],
					 char_id->uuid.uuid.uuid128[10], char_id->uuid.uuid.uuid128[11], char_id->uuid.uuid.uuid128[12],
					 char_id->uuid.uuid.uuid128[13], char_id->uuid.uuid.uuid128[14], char_id->uuid.uuid.uuid128[15]);
		} else {
			LOG_ERROR("Char UNKNOWN LEN %d\n", char_id->uuid.len);
		}
        for (int i = 0; i < p_data->notify.value_len; i++) {
            LOG_INFO("NOTIFY: V%d %x:", i, p_data->notify.value[i]);
        }

		if (is_led_on) {
			gpio_set_level(LED_GPIO, 1);
		} else {
			gpio_set_level(LED_GPIO, 0);
		}
    }
    break;
}
case ESP_GATTC_GET_CHAR_EVT: {
    esp_gatt_srvc_id_t *srvc_id = &p_data->get_char.srvc_id;
    esp_gatt_id_t *char_id = &p_data->get_char.char_id;
    conn_id = p_data->open.conn_id;
    LOG_INFO("GET CHAR: open.conn_id = %x search_res.conn_id = %x  get_char.conn_id = %x", conn_id,p_data->search_res.conn_id,p_data->get_char.conn_id);
    LOG_INFO("GET CHAR: get_char.char_prop = %x get_char.status = %x inst_id = %x open.gatt_if = %x", p_data->get_char.char_prop, p_data->get_char.status, char_id->inst_id,gattc_if);
    LOG_INFO("remote_bda %x,%x,%x,%x,%x,%x:",p_data->open.remote_bda[0],
    		p_data->open.remote_bda[1],p_data->open.remote_bda[2],
			p_data->open.remote_bda[3],p_data->open.remote_bda[4],
			p_data->open.remote_bda[5]);
    if (p_data->get_char.status==0) {
		// print characteristic property
		get_characteristic_property(p_data->get_char.char_prop);

		if (char_id->uuid.len == ESP_UUID_LEN_16) {
			LOG_INFO("UUID16: %x", char_id->uuid.uuid.uuid16);
			if (char_id->uuid.uuid.uuid16 == TEST_CHAR_UUID) {
				ESP_LOGI(TAG, "register notify\n");
				esp_ble_gattc_register_for_notify(gattc_if, p_data->open.remote_bda, &test_service_id, &test_char_id);
			}
		} else if (char_id->uuid.len == ESP_UUID_LEN_32) {
			LOG_INFO("UUID32: %x", char_id->uuid.uuid.uuid32);
		} else if (char_id->uuid.len == ESP_UUID_LEN_128) {
			LOG_INFO("UUID128: %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x", char_id->uuid.uuid.uuid128[0],
					 char_id->uuid.uuid.uuid128[1], char_id->uuid.uuid.uuid128[2], char_id->uuid.uuid.uuid128[3],
					 char_id->uuid.uuid.uuid128[4], char_id->uuid.uuid.uuid128[5], char_id->uuid.uuid.uuid128[6],
					 char_id->uuid.uuid.uuid128[7], char_id->uuid.uuid.uuid128[8], char_id->uuid.uuid.uuid128[9],
					 char_id->uuid.uuid.uuid128[10], char_id->uuid.uuid.uuid128[11], char_id->uuid.uuid.uuid128[12],
					 char_id->uuid.uuid.uuid128[13], char_id->uuid.uuid.uuid128[14], char_id->uuid.uuid.uuid128[15]);

			esp_ble_gattc_get_descriptor(gattc_if, conn_id, srvc_id, char_id, NULL);
			esp_ble_gattc_get_characteristic(gattc_if, conn_id, srvc_id, char_id);
		} else {
			LOG_ERROR("UNKNOWN LEN %d", char_id->uuid.len);
		}
    } else {
		ESP_LOGE(TAG, "get characteristic failed");
	}
    break;
}
case ESP_GATTC_GET_DESCR_EVT: {
    //esp_gatt_srvc_id_t *srvc_id = &p_data->get_descr.srvc_id;
    esp_gatt_id_t *char_id = &p_data->get_descr.char_id;
    esp_gatt_id_t *descr_id = &p_data->get_descr.descr_id;
    conn_id = p_data->open.conn_id;
    LOG_INFO("GET DESCR: open.conn_id = %x search_res.conn_id = %x  get_descr.conn_id = %x", conn_id,p_data->search_res.conn_id,p_data->get_descr.conn_id);
    LOG_INFO("GET DESCR: get_descr.status = %x inst_id = %x open.gatt_if = %x", p_data->get_descr.status, char_id->inst_id,gattc_if);
    //uint8_t value[2];
    //value[0]=0x01;
    //value[1]=0x00;
    if (p_data->get_descr.status==0) {
		if (char_id->uuid.len == ESP_UUID_LEN_16) {
			LOG_INFO("Char UUID16: %x", char_id->uuid.uuid.uuid16);
		} else if (char_id->uuid.len == ESP_UUID_LEN_32) {
			LOG_INFO("Char UUID32: %x", char_id->uuid.uuid.uuid32);
		} else if (char_id->uuid.len == ESP_UUID_LEN_128) {
			LOG_INFO("Char UUID128: %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x", char_id->uuid.uuid.uuid128[0],
					 char_id->uuid.uuid.uuid128[1], char_id->uuid.uuid.uuid128[2], char_id->uuid.uuid.uuid128[3],
					 char_id->uuid.uuid.uuid128[4], char_id->uuid.uuid.uuid128[5], char_id->uuid.uuid.uuid128[6],
					 char_id->uuid.uuid.uuid128[7], char_id->uuid.uuid.uuid128[8], char_id->uuid.uuid.uuid128[9],
					 char_id->uuid.uuid.uuid128[10], char_id->uuid.uuid.uuid128[11], char_id->uuid.uuid.uuid128[12],
					 char_id->uuid.uuid.uuid128[13], char_id->uuid.uuid.uuid128[14], char_id->uuid.uuid.uuid128[15]);
		} else {
			LOG_ERROR("Char UNKNOWN LEN %d", char_id->uuid.len);
		}
		if (descr_id->uuid.len == ESP_UUID_LEN_16) {
			LOG_INFO("Decr UUID16: %x", descr_id->uuid.uuid.uuid16);
		} else if (descr_id->uuid.len == ESP_UUID_LEN_32) {
			LOG_INFO("Decr UUID32: %x", descr_id->uuid.uuid.uuid32);
		} else if (descr_id->uuid.len == ESP_UUID_LEN_128) {
			LOG_INFO("Decr UUID128: %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x", descr_id->uuid.uuid.uuid128[0],
					 descr_id->uuid.uuid.uuid128[1], descr_id->uuid.uuid.uuid128[2], descr_id->uuid.uuid.uuid128[3],
					 descr_id->uuid.uuid.uuid128[4], descr_id->uuid.uuid.uuid128[5], descr_id->uuid.uuid.uuid128[6],
					 descr_id->uuid.uuid.uuid128[7], descr_id->uuid.uuid.uuid128[8], descr_id->uuid.uuid.uuid128[9],
					 descr_id->uuid.uuid.uuid128[10], descr_id->uuid.uuid.uuid128[11], descr_id->uuid.uuid.uuid128[12],
					 descr_id->uuid.uuid.uuid128[13], descr_id->uuid.uuid.uuid128[14], descr_id->uuid.uuid.uuid128[15]);
		} else {
			LOG_ERROR("Decr UNKNOWN LEN %d", descr_id->uuid.len);
		}
		/*esp_ble_gattc_write_char_descr (
			gattc_if,
			conn_id,
			srvc_id,
			char_id,
			descr_id,
			2,
			&value[0],
			ESP_GATT_WRITE_TYPE_NO_RSP,
			ESP_GATT_AUTH_REQ_NONE);*/
    }
    break;
}
case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
    LOG_INFO("NOTIFY_EVT: open.conn_id = %x ", p_data->open.conn_id);
    LOG_INFO("NOTIFY_EVT: reg_for_notify.status = %x ", p_data->reg_for_notify.status);
    esp_gatt_id_t *char_id = &p_data->reg_for_notify.char_id;
    if (p_data->reg_for_notify.status==0) {
		if (char_id->uuid.len == ESP_UUID_LEN_16) {
			LOG_INFO("UUID16: %x", char_id->uuid.uuid.uuid16);
		} else if (char_id->uuid.len == ESP_UUID_LEN_32) {
			LOG_INFO("UUID32: %x", char_id->uuid.uuid.uuid32);
		} else if (char_id->uuid.len == ESP_UUID_LEN_128) {
			LOG_INFO("UUID128: %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x", char_id->uuid.uuid.uuid128[0],
					 char_id->uuid.uuid.uuid128[1], char_id->uuid.uuid.uuid128[2], char_id->uuid.uuid.uuid128[3],
					 char_id->uuid.uuid.uuid128[4], char_id->uuid.uuid.uuid128[5], char_id->uuid.uuid.uuid128[6],
					 char_id->uuid.uuid.uuid128[7], char_id->uuid.uuid.uuid128[8], char_id->uuid.uuid.uuid128[9],
					 char_id->uuid.uuid.uuid128[10], char_id->uuid.uuid.uuid128[11], char_id->uuid.uuid.uuid128[12],
					 char_id->uuid.uuid.uuid128[13], char_id->uuid.uuid.uuid128[14], char_id->uuid.uuid.uuid128[15]);
		} else {
			LOG_ERROR("UNKNOWN LEN %d", char_id->uuid.len);
		}

		// enable gatt server notification
		uint8_t notify_en = 1;
		esp_err_t err = esp_ble_gattc_write_char_descr(
            gattc_if,
            conn_id,
            &test_service_id,
            &test_char_id,
            &notify_descr_id,
            1,
            &notify_en,
            ESP_GATT_WRITE_TYPE_RSP,
            ESP_GATT_AUTH_REQ_NONE);
		if (err != 0) {
			ESP_LOGE(TAG, "write char desc failed");
		} else {
			ESP_LOGI(TAG, "==> write char desc OK");
		}
    } else {
		ESP_LOGE(TAG, "notify register failed");
	}
    break;
}
case ESP_GATTC_SEARCH_CMPL_EVT:
    conn_id = p_data->search_cmpl.conn_id;
    LOG_INFO("SEARCH_CMPL: conn_id = %x, status %d", conn_id, p_data->search_cmpl.status);
	esp_ble_gap_cb_param_t *scan_result = (esp_ble_gap_cb_param_t *)param;
	switch (scan_result->scan_rst.ble_evt_type) {
		case ESP_BLE_EVT_CONN_ADV:
			ESP_LOGI(TAG, "==> CONN_ADV");
			ESP_LOGI(TAG, "BDA %x,%x,%x,%x,%x,%x:",scan_result->scan_rst.bda[0],
							 scan_result->scan_rst.bda[1],scan_result->scan_rst.bda[2],
											 scan_result->scan_rst.bda[3],scan_result->scan_rst.bda[4],
											 scan_result->scan_rst.bda[5]);
			ESP_LOGI(TAG, "==> RSSI: %d", scan_result->scan_rst.rssi);
			ESP_LOGI(TAG, "==> address type: %d", scan_result->scan_rst.ble_addr_type);
			/*esp_ble_gap_stop_scanning();
			esp_err_t err = esp_ble_gattc_open(client_if, scan_result->scan_rst.bda, true);
			ESP_LOGI(TAG, "==> esp_ble_gattc_open %d", err);*/
			break;
		case ESP_BLE_EVT_CONN_DIR_ADV:
			ESP_LOGI(TAG, "==> CONN_DIR_ADV");
			break;
		case ESP_BLE_EVT_DISC_ADV:
			ESP_LOGI(TAG, "==> DISC_ADV");
			break;
		case ESP_BLE_EVT_NON_CONN_ADV:
			ESP_LOGI(TAG, "==> NON_CONN_ADV");
			break;
		case ESP_BLE_EVT_SCAN_RSP:
			ESP_LOGI(TAG, "==> receive scan response");
			LOG_INFO("BDA %x,%x,%x,%x,%x,%x:",scan_result->scan_rst.bda[0],
							 scan_result->scan_rst.bda[1],scan_result->scan_rst.bda[2],
											 scan_result->scan_rst.bda[3],scan_result->scan_rst.bda[4],
											 scan_result->scan_rst.bda[5]);
			break;
	}
	//esp_ble_gattc_get_characteristic(gattc_if, conn_id, &p_data->search_res.srvc_id, NULL);
    break;
default:
    break;
}

}
void ble_client_appRegister(void)
{
LOG_INFO("register callback");
//register the scan callback function to the Generic Access Profile (GAP) module
if ((status = esp_ble_gap_register_callback(esp_gap_cb)) != ESP_OK) {
    LOG_ERROR("gap register error, error code = %x", status);
    return;
}

//register the callback function to the Generic Attribute Profile (GATT) Client (GATTC) module
if ((status = esp_ble_gattc_register_callback(esp_gattc_cb)) != ESP_OK) {
    LOG_ERROR("gattc register error, error code = %x", status);
    return;
}
esp_ble_gattc_app_register(simpleClient_id);
esp_ble_gap_set_scan_params(&ble_scan_params);

}
void gattc_client_test(void)
{
esp_bluedroid_init();
esp_bluedroid_enable();
ble_client_appRegister();
}
void app_main()
{
gpio_pad_select_gpio(LED_GPIO);
/* Set the GPIO as a push/pull output */
gpio_set_direction(LED_GPIO, GPIO_MODE_OUTPUT);
gpio_set_level(LED_GPIO, 0);
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
esp_err_t ret = esp_bt_controller_init(&bt_cfg);

if (ret) {
    ESP_LOGE(TAG, "%s initialize controller failed\n", __func__);
    return;
}

esp_bt_controller_enable(ESP_BT_MODE_BTDM);
gattc_client_test();

}`

The following is the server code:
`#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "bt.h"
#include "bta_api.h"
#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
#include "esp_bt_defs.h"
#include "esp_bt_main.h"
#include "esp_bt_main.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#define GATTS_TAG "GATTS_DEMO"
///Declare the static function
static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);
static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);
static bool task_run = false;
static esp_gatt_if_t client_if;
static uint16_t client_conn = 0;
static uint16_t ccc_handle = 0;
static uint16_t notif_test_v = 1;
#define GATTS_SERVICE_UUID_TEST_A   0x00FF
#define GATTS_CHAR_UUID_TEST_A      0xFF01
#define GATTS_DESCR_UUID_TEST_A     0x3333
#define GATTS_NUM_HANDLE_TEST_A     4
#define GATTS_SERVICE_UUID_TEST_B   0x00EE
#define GATTS_CHAR_UUID_TEST_B      0xEE01
#define GATTS_DESCR_UUID_TEST_B     0x2222
#define GATTS_NUM_HANDLE_TEST_B     4
#define TEST_DEVICE_NAME            "ESP32"
#define TEST_MANUFACTURER_DATA_LEN  17
#define GATTS_DEMO_CHAR_VAL_LEN_MAX 0x40
#define LED_GPIO					2
uint8_t char1_str[] = {0x11,0x22,0x33};
esp_attr_value_t gatts_demo_char1_val =
{
.attr_max_len = GATTS_DEMO_CHAR_VAL_LEN_MAX,
.attr_len     = sizeof(char1_str),
.attr_value   = char1_str,
};
static uint8_t test_service_uuid128[32] = {
/* LSB <--------------------------------------------------------------------------------> MSB */
//first uuid, 16bit, [12],[13] is the value
0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xAB, 0xCD, 0x00, 0x00,
//second uuid, 32bit, [12], [13], [14], [15] is the value
0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xAB, 0xCD, 0xAB, 0xCD,
};
//static uint8_t test_manufacturer[TEST_MANUFACTURER_DATA_LEN] =  {0x12, 0x23, 0x45, 0x56};
static esp_ble_adv_data_t test_adv_data = {
.set_scan_rsp = false,
.include_name = true,
.include_txpower = true,
.min_interval = 0x20,
.max_interval = 0x40,
.appearance = 0x00,
.manufacturer_len = 0, //TEST_MANUFACTURER_DATA_LEN,
.p_manufacturer_data =  NULL, //&test_manufacturer[0],
.service_data_len = 0,
.p_service_data = NULL,
.service_uuid_len = 32,
.p_service_uuid = test_service_uuid128,
.flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
};
static esp_ble_adv_params_t test_adv_params = {
.adv_int_min        = 0x20,
.adv_int_max        = 0x40,
.adv_type           = ADV_TYPE_SCAN_IND,
.own_addr_type      = BLE_ADDR_TYPE_PUBLIC,
//.peer_addr            =
//.peer_addr_type       =
.channel_map        = ADV_CHNL_ALL,
.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
};
#define PROFILE_NUM 2
#define PROFILE_A_APP_ID 0
#define PROFILE_B_APP_ID 1
struct gatts_profile_inst {
esp_gatts_cb_t gatts_cb;
uint16_t gatts_if;
uint16_t app_id;
uint16_t conn_id;
uint16_t service_handle;
esp_gatt_srvc_id_t service_id;
uint16_t char_handle;
esp_bt_uuid_t char_uuid;
esp_gatt_perm_t perm;
esp_gatt_char_prop_t property;
uint16_t descr_handle;
esp_bt_uuid_t descr_uuid;
};
/* One gatt-based profile one app_id and one gatts_if, this array will store the gatts_if returned by ESP_GATTS_REG_EVT /
static struct gatts_profile_inst gl_profile_tab[PROFILE_NUM] = {
[PROFILE_A_APP_ID] = {
.gatts_cb = gatts_profile_a_event_handler,
.gatts_if = ESP_GATT_IF_NONE,       / Not get the gatt_if, so initial is ESP_GATT_IF_NONE /
},
[PROFILE_B_APP_ID] = {
.gatts_cb = gatts_profile_b_event_handler,                   / This demo does not implement, similar as profile A /
.gatts_if = ESP_GATT_IF_NONE,       / Not get the gatt_if, so initial is ESP_GATT_IF_NONE */
},
};
static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
esp_ble_gap_cb_param_t *scan_result = (esp_ble_gap_cb_param_t *)param;
switch (scan_result->scan_rst.ble_evt_type) {
case ESP_BLE_EVT_CONN_ADV:
ESP_LOGI(TAG, "==> CONN_ADV");
LOG_INFO("BDA %x,%x,%x,%x,%x,%x:",scan_result->scan_rst.bda[0],
scan_result->scan_rst.bda[1],scan_result->scan_rst.bda[2],
scan_result->scan_rst.bda[3],scan_result->scan_rst.bda[4],
scan_result->scan_rst.bda[5]);
break;
case ESP_BLE_EVT_CONN_DIR_ADV:
ESP_LOGI(TAG, "==> CONN_DIR_ADV");
break;
case ESP_BLE_EVT_DISC_ADV:
ESP_LOGI(TAG, "==> DISC_ADV");
break;
case ESP_BLE_EVT_NON_CONN_ADV:
ESP_LOGI(TAG, "==> NON_CONN_ADV");
break;
case ESP_BLE_EVT_SCAN_RSP:
ESP_LOGI(TAG, "==> receive scan response");
LOG_INFO("BDA %x,%x,%x,%x,%x,%x:",scan_result->scan_rst.bda[0],
scan_result->scan_rst.bda[1],scan_result->scan_rst.bda[2],
scan_result->scan_rst.bda[3],scan_result->scan_rst.bda[4],
scan_result->scan_rst.bda[5]);
break;
}
switch (event) {
case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
esp_ble_gap_start_advertising(&test_adv_params);
break;
case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT:
esp_ble_gap_start_advertising(&test_adv_params);
break;
case ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT:
esp_ble_gap_start_advertising(&test_adv_params);
break;
case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
//advertising start complete event to indicate advertising start successfully or failed
if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS) {
ESP_LOGE(GATTS_TAG, "Advertising start failed\n");
}
break;
default:
break;
}
}
static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) {
switch (event) {
case ESP_GATTS_REG_EVT:
ESP_LOGI(GATTS_TAG, "REGISTER_APP_EVT, status %d, app_id %d\n", param->reg.status, param->reg.app_id);
gl_profile_tab[PROFILE_A_APP_ID].service_id.is_primary = true;
gl_profile_tab[PROFILE_A_APP_ID].service_id.id.inst_id = 0x00;
gl_profile_tab[PROFILE_A_APP_ID].service_id.id.uuid.len = ESP_UUID_LEN_16;
gl_profile_tab[PROFILE_A_APP_ID].service_id.id.uuid.uuid.uuid16 = GATTS_SERVICE_UUID_TEST_A;
esp_ble_gap_set_device_name(TEST_DEVICE_NAME);
#ifdef CONFIG_SET_RAW_ADV_DATA
esp_ble_gap_config_adv_data_raw(raw_adv_data, sizeof(raw_adv_data));
esp_ble_gap_config_scan_rsp_data_raw(raw_scan_rsp_data, sizeof(raw_scan_rsp_data));
#else
esp_ble_gap_config_adv_data(&test_adv_data);
#endif
esp_ble_gatts_create_service(gatts_if, &gl_profile_tab[PROFILE_A_APP_ID].service_id, GATTS_NUM_HANDLE_TEST_A);
break;
case ESP_GATTS_READ_EVT: {
ESP_LOGI(GATTS_TAG, "GATT_READ_EVT, conn_id %d, trans_id %d, handle %d\n", param->read.conn_id, param->read.trans_id, param->read.handle);
esp_gatt_rsp_t rsp;
memset(&rsp, 0, sizeof(esp_gatt_rsp_t));
rsp.attr_value.handle = param->read.handle;
rsp.attr_value.len = 4;
rsp.attr_value.value[0] = 0xde;
rsp.attr_value.value[1] = 0xed;
rsp.attr_value.value[2] = 0xbe;
rsp.attr_value.value[3] = 0xef;
esp_ble_gatts_send_response(gatts_if, param->read.conn_id, param->read.trans_id, ESP_GATT_OK, &rsp);
break;
}
case ESP_GATTS_WRITE_EVT: {
ESP_LOGI(GATTS_TAG, "GATT_WRITE_EVT, conn_id %d, trans_id %d, handle %d\n", param->write.conn_id, param->write.trans_id, param->write.handle);
ESP_LOGI(GATTS_TAG, "GATT_WRITE_EVT, value len %d, value %08x\n", param->write.len, *(uint32_t *)param->write.value);
esp_gatt_rsp_t rsp;
memset(&rsp, 0, sizeof(esp_gatt_rsp_t));
rsp.attr_value.handle = param->read.handle;
rsp.attr_value.len = 4;
rsp.attr_value.value[0] = 0xde;
rsp.attr_value.value[1] = 0xed;
rsp.attr_value.value[2] = 0xbe;
rsp.attr_value.value[3] = 0xef;
esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, &rsp);
uint32_t val = *(uint32_t *)param->write.value;
if (val == 0x0) {
ESP_LOGI(GATTS_TAG, "GATT write 0");
task_run = false;
} else if (val == 0x1) {
ESP_LOGI(GATTS_TAG, "GATT write 1");
task_run = true;
const uint8_t v = 0x1;
esp_ble_gatts_set_attr_value(0x002B, 1, &v);
} else {
ESP_LOGE(GATTS_TAG, "Unknown notify value");
}
    break;
}
case ESP_GATTS_EXEC_WRITE_EVT:
case ESP_GATTS_MTU_EVT:
case ESP_GATTS_CONF_EVT:
case ESP_GATTS_UNREG_EVT:
    break;
case ESP_GATTS_CREATE_EVT:
    ESP_LOGI(GATTS_TAG, "CREATE_SERVICE_EVT, status %d,  service_handle %d\n", param->create.status, param->create.service_handle);
    gl_profile_tab[PROFILE_A_APP_ID].service_handle = param->create.service_handle;
    gl_profile_tab[PROFILE_A_APP_ID].char_uuid.len = ESP_UUID_LEN_16;
    gl_profile_tab[PROFILE_A_APP_ID].char_uuid.uuid.uuid16 = GATTS_CHAR_UUID_TEST_A;
	//gl_profile_tab[PROFILE_A_APP_ID].descr_uuid.uuid.uuid16 = GATTS_DESCR_UUID_TEST_A;
    esp_ble_gatts_start_service(gl_profile_tab[PROFILE_A_APP_ID].service_handle);

    esp_ble_gatts_add_char(gl_profile_tab[PROFILE_A_APP_ID].service_handle, &gl_profile_tab[PROFILE_A_APP_ID].char_uuid,
                           ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
                           ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY,
                           &gatts_demo_char1_val, NULL);
    break;
case ESP_GATTS_ADD_INCL_SRVC_EVT:
    break;
case ESP_GATTS_ADD_CHAR_EVT: {
    uint16_t length = 0;
    const uint8_t *prf_char;

    ESP_LOGI(GATTS_TAG, "ADD_CHAR_EVT, status %d,  attr_handle %d, service_handle %d\n",
            param->add_char.status, param->add_char.attr_handle, param->add_char.service_handle);
    gl_profile_tab[PROFILE_A_APP_ID].char_handle = param->add_char.attr_handle;
    gl_profile_tab[PROFILE_A_APP_ID].descr_uuid.len = ESP_UUID_LEN_16;
    gl_profile_tab[PROFILE_A_APP_ID].descr_uuid.uuid.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG;
    esp_ble_gatts_get_attr_value(param->add_char.attr_handle,  &length, &prf_char);

    ESP_LOGI(GATTS_TAG, "the gatts demo char length = %x\n", length);
    for(int i = 0; i < length; i++){
        ESP_LOGI(GATTS_TAG, "prf_char[%x] =%x\n",i,prf_char[i]);
    }

	if (param->add_char.char_uuid.uuid.uuid16 == GATTS_CHAR_UUID_TEST_A) {
		ccc_handle = param->add_char.attr_handle;
		ESP_LOGI(GATTS_TAG, "get target char handle=%d", ccc_handle);
	}

    esp_ble_gatts_add_char_descr(gl_profile_tab[PROFILE_A_APP_ID].service_handle, &gl_profile_tab[PROFILE_A_APP_ID].descr_uuid,
                                 ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, NULL, NULL);
    break;
}
case ESP_GATTS_ADD_CHAR_DESCR_EVT: {
    ESP_LOGI(GATTS_TAG, "ADD_DESCR_EVT, status %d, attr_handle %d, service_handle %d, desc UUID %04x, desc handle %d\n",
             param->add_char.status, param->add_char.attr_handle, param->add_char.service_handle, param->add_char_descr.char_uuid.uuid.uuid16, param->add_char_descr.attr_handle);
    break;
}
case ESP_GATTS_DELETE_EVT:
    break;
case ESP_GATTS_START_EVT:
    ESP_LOGI(GATTS_TAG, "SERVICE_START_EVT, status %d, service_handle %d\n",
             param->start.status, param->start.service_handle);
    break;
case ESP_GATTS_STOP_EVT:
    break;
case ESP_GATTS_CONNECT_EVT:
    ESP_LOGI(GATTS_TAG, "CONNECT_EVT, conn_id %d, remote %02x:%02x:%02x:%02x:%02x:%02x:, is_conn %d\n",
             param->connect.conn_id,
             param->connect.remote_bda[0], param->connect.remote_bda[1], param->connect.remote_bda[2],
             param->connect.remote_bda[3], param->connect.remote_bda[4], param->connect.remote_bda[5],
             param->connect.is_connected);
    gl_profile_tab[PROFILE_A_APP_ID].conn_id = param->connect.conn_id;

	client_if = gatts_if;
	client_conn = param->connect.conn_id;

	// turn on the LED to show that connection established
	gpio_set_level(LED_GPIO, 1);
    break;
case ESP_GATTS_DISCONNECT_EVT:
    esp_ble_gap_start_advertising(&test_adv_params);
	gpio_set_level(LED_GPIO, 0);	// turn off the LED to show BLE disconnected
    break;
case ESP_GATTS_OPEN_EVT:
case ESP_GATTS_CANCEL_OPEN_EVT:
case ESP_GATTS_CLOSE_EVT:
case ESP_GATTS_LISTEN_EVT:
case ESP_GATTS_CONGEST_EVT:
default:
    break;
}

}
static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) {
switch (event) {
case ESP_GATTS_REG_EVT:
ESP_LOGI(GATTS_TAG, "REGISTER_APP_EVT, status %d, app_id %d\n", param->reg.status, param->reg.app_id);
gl_profile_tab[PROFILE_B_APP_ID].service_id.is_primary = true;
gl_profile_tab[PROFILE_B_APP_ID].service_id.id.inst_id = 0x00;
gl_profile_tab[PROFILE_B_APP_ID].service_id.id.uuid.len = ESP_UUID_LEN_16;
gl_profile_tab[PROFILE_B_APP_ID].service_id.id.uuid.uuid.uuid16 = GATTS_SERVICE_UUID_TEST_B;
    esp_ble_gatts_create_service(gatts_if, &gl_profile_tab[PROFILE_B_APP_ID].service_id, GATTS_NUM_HANDLE_TEST_B);
    break;
case ESP_GATTS_READ_EVT: {
    ESP_LOGI(GATTS_TAG, "GATT_READ_EVT, conn_id %d, trans_id %d, handle %d\n", param->read.conn_id, param->read.trans_id, param->read.handle);
    esp_gatt_rsp_t rsp;
    memset(&rsp, 0, sizeof(esp_gatt_rsp_t));
    rsp.attr_value.handle = param->read.handle;
    rsp.attr_value.len = 4;
    rsp.attr_value.value[0] = 0xde;
    rsp.attr_value.value[1] = 0xed;
    rsp.attr_value.value[2] = 0xbe;
    rsp.attr_value.value[3] = 0xef;
    esp_ble_gatts_send_response(gatts_if, param->read.conn_id, param->read.trans_id,
                                ESP_GATT_OK, &rsp);
    break;
}
case ESP_GATTS_WRITE_EVT: {
    ESP_LOGI(GATTS_TAG, "GATT_WRITE_EVT, conn_id %d, trans_id %d, handle %d\n", param->write.conn_id, param->write.trans_id, param->write.handle);
    ESP_LOGI(GATTS_TAG, "GATT_WRITE_EVT, value len %d, value %08x\n", param->write.len, *(uint32_t *)param->write.value);
	esp_gatt_rsp_t rsp;
    memset(&rsp, 0, sizeof(esp_gatt_rsp_t));
    rsp.attr_value.handle = param->read.handle;
    rsp.attr_value.len = 4;
    rsp.attr_value.value[0] = 0xde;
    rsp.attr_value.value[1] = 0xed;
    rsp.attr_value.value[2] = 0xbe;
    rsp.attr_value.value[3] = 0xef;
    esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, &rsp);
    break;
}
case ESP_GATTS_EXEC_WRITE_EVT:
case ESP_GATTS_MTU_EVT:
case ESP_GATTS_CONF_EVT:
case ESP_GATTS_UNREG_EVT:
    break;
case ESP_GATTS_CREATE_EVT:
    ESP_LOGI(GATTS_TAG, "CREATE_SERVICE_EVT, status %d,  service_handle %d\n", param->create.status, param->create.service_handle);
    gl_profile_tab[PROFILE_B_APP_ID].service_handle = param->create.service_handle;
    gl_profile_tab[PROFILE_B_APP_ID].char_uuid.len = ESP_UUID_LEN_16;
    gl_profile_tab[PROFILE_B_APP_ID].char_uuid.uuid.uuid16 = GATTS_CHAR_UUID_TEST_B;

    esp_ble_gatts_start_service(gl_profile_tab[PROFILE_B_APP_ID].service_handle);

    esp_ble_gatts_add_char(gl_profile_tab[PROFILE_B_APP_ID].service_handle, &gl_profile_tab[PROFILE_B_APP_ID].char_uuid,
                           ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
                           ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY,
                           NULL, NULL);
    break;
case ESP_GATTS_ADD_INCL_SRVC_EVT:
    break;
case ESP_GATTS_ADD_CHAR_EVT:
    ESP_LOGI(GATTS_TAG, "ADD_CHAR_EVT, status %d,  attr_handle %d, service_handle %d\n",
             param->add_char.status, param->add_char.attr_handle, param->add_char.service_handle);

    gl_profile_tab[PROFILE_B_APP_ID].char_handle = param->add_char.attr_handle;
    gl_profile_tab[PROFILE_B_APP_ID].descr_uuid.len = ESP_UUID_LEN_16;
    gl_profile_tab[PROFILE_B_APP_ID].descr_uuid.uuid.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG;
    esp_ble_gatts_add_char_descr(gl_profile_tab[PROFILE_B_APP_ID].service_handle, &gl_profile_tab[PROFILE_B_APP_ID].descr_uuid,
                                 ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
                                 NULL, NULL);
    break;
case ESP_GATTS_ADD_CHAR_DESCR_EVT:
    ESP_LOGI(GATTS_TAG, "ADD_DESCR_EVT, status %d, attr_handle %d, service_handle %d\n",
             param->add_char.status, param->add_char.attr_handle, param->add_char.service_handle);
    break;
case ESP_GATTS_DELETE_EVT:
    break;
case ESP_GATTS_START_EVT:
    ESP_LOGI(GATTS_TAG, "SERVICE_START_EVT, status %d, service_handle %d\n",
             param->start.status, param->start.service_handle);
    break;
case ESP_GATTS_STOP_EVT:
    break;
case ESP_GATTS_CONNECT_EVT:
    ESP_LOGI(GATTS_TAG, "SERVICE_START_EVT, conn_id %d, remote %02x:%02x:%02x:%02x:%02x:%02x:, is_conn %d\n",
             param->connect.conn_id,
             param->connect.remote_bda[0], param->connect.remote_bda[1], param->connect.remote_bda[2],
             param->connect.remote_bda[3], param->connect.remote_bda[4], param->connect.remote_bda[5],
             param->connect.is_connected);
    gl_profile_tab[PROFILE_B_APP_ID].conn_id = param->connect.conn_id;
    break;
case ESP_GATTS_DISCONNECT_EVT:
case ESP_GATTS_OPEN_EVT:
case ESP_GATTS_CANCEL_OPEN_EVT:
case ESP_GATTS_CLOSE_EVT:
case ESP_GATTS_LISTEN_EVT:
case ESP_GATTS_CONGEST_EVT:
default:
    break;
}

}
static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t param)
{
/ If event is register event, store the gatts_if for each profile */
if (event == ESP_GATTS_REG_EVT) {
if (param->reg.status == ESP_GATT_OK) {
gl_profile_tab[param->reg.app_id].gatts_if = gatts_if;
} else {
ESP_LOGI(GATTS_TAG, "Reg app failed, app_id %04x, status %d\n",
param->reg.app_id,
param->reg.status);
return;
}
}
/* If the gatts_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 (gatts_if == ESP_GATT_IF_NONE || /* ESP_GATT_IF_NONE, not specify a certain gatt_if, need to call every profile cb function */
                gatts_if == gl_profile_tab[idx].gatts_if) {
            if (gl_profile_tab[idx].gatts_cb) {
                gl_profile_tab[idx].gatts_cb(event, gatts_if, param);
            }
        }
    }
} while (0);

}
static void led_task(void *arg)
{
while (1) {
vTaskDelay(3000 / portTICK_RATE_MS);
//ESP_LOGI(TAG, "led_task is running");
if (task_run) {
ESP_LOGI(GATTS_TAG, "send notify handle=%d", ccc_handle);
uint16_t notif_len = 2;
uint8_t val2[2] = {0x11, 0x22};
esp_ble_gatts_send_indicate(client_if, client_conn, ccc_handle, notif_len, val2, false);
//esp_ble_gatts_set_attr_value(ccc_handle, sizeof(notif_test_v), (uint8_t *)&notif_test_v);
if (notif_test_v == 1) {
notif_test_v = 0;
} else {
notif_test_v = 1;
}
}
}
vTaskDelete(NULL);
}
void app_main()
{
esp_err_t ret;
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
ret = esp_bt_controller_init(&bt_cfg);

ret = esp_bt_controller_enable(ESP_BT_MODE_BTDM);
if (ret) {
    ESP_LOGE(GATTS_TAG, "%s enable controller failed\n", __func__);
    return;
}
ret = esp_bluedroid_init();
if (ret) {
    ESP_LOGE(GATTS_TAG, "%s init bluetooth failed\n", __func__);
    return;
}
ret = esp_bluedroid_enable();
if (ret) {
    ESP_LOGE(GATTS_TAG, "%s enable bluetooth failed\n", __func__);
    return;
}

gpio_pad_select_gpio(LED_GPIO);
/* Set the GPIO as a push/pull output */
gpio_set_direction(LED_GPIO, GPIO_MODE_OUTPUT);
gpio_set_level(LED_GPIO, 0);

esp_ble_gatts_register_callback(gatts_event_handler);
esp_ble_gap_register_callback(gap_event_handler);
esp_ble_gatts_app_register(PROFILE_A_APP_ID);
esp_ble_gatts_app_register(PROFILE_B_APP_ID);

xTaskCreate(&led_task, "led_task", 2048, NULL, 6, NULL);

return;

}
`

@Nicholas3388
Hi, Nicholas, The following code is untested：

connected
service search
get char by test_service_id
if (char_prop & 0x30) == 0x0, get next char
if (char_prop & 0x30) != 0x0, get the char descr
register notification for this char
write this char descr

static uint16_t write_desc_value = 0;

static void esp_gattc_cb(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,esp_ble_gattc_cb_param_t *param)
{
    uint16_t conn_id = 0;
    esp_ble_gattc_cb_param_t *p_data = (esp_ble_gattc_cb_param_t *) param;

    switch (event) {
    case ESP_GATTC_OPEN_EVT:
        client_conn = p_data->open.conn_id;
        at_memcpy(server_dba, p_data->open.remote_bda, sizeof(esp_bd_addr_t));
        esp_ble_gattc_search_service(gattc_if, client_conn, NULL);
        break;
    case ESP_GATTC_SEARCH_RES_EVT:
        test_service_id.is_primary = p_data->search_res.srvc_id.is_primary;
        test_service_id.id.inst_id = p_data->search_res.srvc_id.id.inst_id;
        test_service_id.id.uuid.len = p_data->search_res.srvc_id.id.uuid.len;
        if (test_service_id.id.uuid.len == ESP_UUID_LEN_16) {
            test_service_id.id.uuid.uuid.uuid16 = p_data->search_res.srvc_id.id.uuid.uuid.uuid16;
        } else if (test_service_id.id.uuid.len == ESP_UUID_LEN_32) {
            test_service_id.id.uuid.uuid.uuid32 = p_data->search_res.srvc_id.id.uuid.uuid.uuid32;
        } else if (test_service_id.id.uuid.len == ESP_UUID_LEN_128) {
            for (int i = 0; i < 16; i++) {
                test_service_id.id.uuid.uuid.uuid128[i] = p_data->search_res.srvc_id.id.uuid.uuid.uuid128[i];
            }
        }
        break;
    case ESP_GATTC_SEARCH_CMPL_EVT:
        esp_ble_gattc_get_characteristic(gattc_if, p_data->search_res.conn_id,&test_service_id, NULL);
        break;
    case ESP_GATTC_GET_CHAR_EVT:
        if (p_data->get_char.status != ESP_GATT_OK) {
            break;
        }
        test_char_id.inst_id = p_data->get_char.char_id.inst_id;
        test_char_id.uuid.len = p_data->get_char.char_id.uuid.len;
        pGattc_char_node->char_prop = p_data->get_char.char_prop;
        if (test_char_id.uuid.len == ESP_UUID_LEN_16) {
            test_char_id.uuid.uuid.uuid16 = p_data->get_char.char_id.uuid.uuid.uuid16;
        } else if (test_char_id.uuid.len == ESP_UUID_LEN_32) {
            test_char_id.uuid.uuid.uuid32 = p_data->get_char.char_id.uuid.uuid.uuid32;
        } else if (test_char_id.uuid.len == ESP_UUID_LEN_128) {
            for (int i = 0; i < 16; i++) {
                test_char_id.uuid.uuid.uuid128[i] = p_data->get_char.char_id.uuid.uuid.uuid128[i];
            }
        }
        if(((p_data->get_char.char_prop)&0x10)||((p_data->get_char.char_prop)&0x20)){
            if(((p_data->get_char.char_prop)&0x10)){
                write_desc_value = 0x1;
            }else if(((p_data->get_char.char_prop)&0x20)){
                write_desc_value = 0x2;
            }
            esp_ble_gattc_get_descriptor(gattc_if, client_conn, &test_service_id, &test_char_id, NULL);
        }else{
            esp_ble_gattc_get_characteristic(gattc_if, client_conn, &test_service_id, &test_char_id);
        }
        break;
    case ESP_GATTC_GET_DESCR_EVT:
        if (p_data->get_descr.status != ESP_GATT_OK) {
            break;
        }
        notify_descr_id.inst_id = p_data->get_descr.descr_id.inst_id;
        notify_descr_id.uuid.len = p_data->get_descr.descr_id.uuid.len;

        if (notify_descr_id.uuid.len == ESP_UUID_LEN_16) {
            notify_descr_id.uuid.uuid.uuid16 = p_data->get_descr.descr_id.uuid.uuid.uuid16;
        } else if (notify_descr_id.uuid.len == ESP_UUID_LEN_32) {
            notify_descr_id.uuid.uuid.uuid32 = p_data->get_descr.descr_id.uuid.uuid.uuid32;
        } else if (notify_descr_id.uuid.len == ESP_UUID_LEN_128) {
            for (int i = 0; i < 16; i++) {
                notify_descr_id.uuid.uuid.uuid128[i] = p_data->get_descr.descr_id.uuid.uuid.uuid128[i];
            }
        }
        esp_ble_gattc_register_for_notify(gattc_if, server_dba,&test_service_id, &test_char_id);

        break;
    case ESP_GATTC_REG_FOR_NOTIFY_EVT:
        esp_ble_gattc_write_char_descr(
                gattc_if,
                client_conn,
                &test_service_id,
                &test_char_id,
                &notify_descr_id,
                sizeof(write_desc_value),
                (uint8_t *) &write_desc_value,
                ESP_GATT_WRITE_TYPE_NO_RSP,
                ESP_GATT_AUTH_REQ_NONE);

        esp_ble_gattc_get_characteristic(gattc_if, client_conn, &test_service_id, &test_char_id);
        break;
    case ESP_GATTC_WRITE_DESCR_EVT:
        break;
    case ESP_GATTC_NOTIFY_EVT:
        break;
    case ESP_BLE_EVT_CONN_DIR_ADV:
        break;
    default:
        break;
}

@Nicholas3388
Hi, Nicholas, can you receive indicate/noitification now?

@xiewenxiang  Hi, thanks for you code. Unfortunately, I still cannot receive notification now. I think my code is almost the same with your untested code. The character property is set as ESP_GATT_CHAR_PROP_BIT_NOTIFY on server, and on client  I can search the character whose property is accurately notify. But the client cannot receive notification, when the server called  esp_ble_gatts_send_indicate
By the way, in your code is it necessary to call  esp_ble_gattc_get_characteristic after esp_ble_gattc_write_char_descr?

@Nicholas3388
I don't find register for notification in your client code；
/**
 * @brief           This function is called to register for notification of a service.
 *
 * @param[in]       gattc_if: Gatt client access interface.
 * @param[in]       server_bda : target GATT server.
 * @param[in]       srvc_id : pointer to GATT service ID.
 * @param[in]       char_id : pointer to GATT characteristic ID.
 *
 * @return
 *                  - ESP_OK: registration succeeds
 *                  - other: failed
 *
 */
esp_gatt_status_t esp_ble_gattc_register_for_notify (esp_gatt_if_t gattc_if,
                                                    esp_bd_addr_t server_bda,
                                                    esp_gatt_srvc_id_t *srvc_id,
                                                    esp_gatt_id_t *char_id);

Hi,
I also met up with this issue. It seems that the esp_gattc_write_char_descriptor can not write the descriptor correctly. Because when I tried to write the descriptor, after I registered the notification, the BT will dump out "NO pending cmd" for this function. However, I can write the characteristic successfully. Any suggestions?
Thanks.
kaikai

@wolfking0815  There is no problem with writing characteristic. But I still cannot receive notifications between two ESP32 devices

I am having this issue as welll... Has anyone had luck with this? I can register for Notifications from an smartphone, but not from a ESP32 acting as a GATT client.

@Nicholas3388 ， @Weijian-Espressif will reply you and provide a demo.

@Nicholas3388 I  provide you a demo. you can test it.
gatts_demo.c.zip
gattc_demo.c.zip
The client demo automatically connect the server demo, the clinet would enable the notify of server demo after connection is established. then the server demo would send some  notify value to the client . The client will send back the value to the server after receiving the notify value.
if any question, let me know.

@Weijian-Espressif @TianHao-Espressif  Thanks. It works for me

source: gharchive/issue

authors: Nicholas3388 TianHao-Espressif Weijian-Espressif danicampora wolfking0815 xiewenxiang

repo: espressif/esp-idf

license_type: permissive

license_source: github-api


text:
fix(esp_ringbuf): Fixed no split buffer in case of wrap around with dummy data (IDFGH-14146)

Description
Fixed no split buffer in case of wrap around with dummy data. This is a corner case of the issue #14568.
I added an additional check and exit condition to prvGetItemDefault. The reason for this is to avoid moving the read pointer in prvCheckItemAvail.
Related
Fixes #14568
Testing
A new unit test was added to cover this scenario (test_ringbuf_common.c: TEST_CASE("Test no-split buffers always receive items in order (with dummy)", "[esp_ringbuf][linux]").

Checklist
Before submitting a Pull Request, please ensure the following:

[ ] 🚨 This PR does not introduce breaking changes.
[ ] All CI checks (GH Actions) pass.
[ ] Documentation is updated as needed.
[ ] Tests are updated or added as necessary.
[ ] Code is well-commented, especially in complex areas.
[ ] Git history is clean — commits are squashed to the minimum necessary.

 Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.You have signed the CLA already but the status is still pending? Let us recheck it.

Hi @upolc-lg,
Thank you for providing the fix. However, I debugged the issue further and it turns out that the problem lies in the prvSendItemDoneNoSplit() function. I do not see a need for an additional check in prvCheckItemAvail() or the functions dealing with allow-split buffers which do not support acquiring space on a buffer before writing to it.
So, we would not merge this fix and instead create a new one which fixes your problem. Thanks.

source: gharchive/pull-request

authors: CLAassistant sudeep-mohanty upolc-lg


text:
Error

When I run ESPRainmaker it shows 4 error as the follows
Type 'ConnectViewController' does not conform to protocol 'ESPDeviceConnectionDelegate'
Type 'ProvisionLandingViewController' does not conform to protocol 'ESPDeviceConnectionDelegate'
Type 'ScannerViewController' does not conform to protocol 'ESPDeviceConnectionDelegate'
Command CompileSwift failed with a nonzero exit code
Can you please walk me through these error correction

@Vishnu2201 You need to edit your PodFile to use older version of the ESPProvision library.
pod 'ESPProvision', '2.0.9'
Do pod clean and pod install and rebuild the app.

Am getting a single error now as
Command PhaseScriptExecution failed with a nonzero exit code

@Vishnu2201 You need to instal SwiftFormat using brew install swiftformat.

Thankyou its working

repo: espressif/esp-rainmaker-ios


text:
I am using time cluster to update time from router(server) to end device(client)   (TZ-486)

Answers checklist.

[X] I have read the documentation ESP Zigbee SDK Programming Guide and the issue is not addressed there.
[X] I have updated my IDF branch (master or release) and ESP Zigbee libs (esp-zboss-lib and esp-zigbee-lib) to the latest version and checked that the issue is present there.
[X] I have searched the issue tracker for a similar issue and not found a similar issue.

IDF version.
v5.1
esp-zigbee-lib version.
v1.0.6
esp-zboss-lib version.
v1.0.6
Espressif SoC revision.
ESP32C6
What is the expected behavior?
To read and write particular attribute with write access.
What is the actual behavior?
I am unable to read/write attribute from router(server) to End device(client) .
I am using time , occupancy and temperature cluster.
Also, can I report from client to server?
Steps to reproduce.

Step
Step
Step
...

More Information.
No response

It's not a bug

Subscribe on core actions
esp_zb_core_action_handler_register(zb_action_handler);
Handle read attribute callback

static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message)
{
    ESP_LOGW(TAG, "Receive Zigbee action(0x%x) callback", callback_id);
    esp_err_t ret = ESP_OK;
    switch (callback_id) {
    case ESP_ZB_CORE_CMD_READ_ATTR_RESP_CB_ID:
        ret = zb_read_attr_resp_handler((esp_zb_zcl_cmd_read_attr_resp_message_t *)message);
        break;
    default:
        ESP_LOGE(TAG, "No handler for action(0x%x)", callback_id);
        break;
    }
    return ret;
}

write needed behavior

static esp_err_t zb_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_resp_message_t *message)
{
    ESP_RETURN_ON_FALSE(message, ESP_FAIL, TAG, "Empty message");
    ESP_RETURN_ON_FALSE(message->info.status == ESP_ZB_ZCL_STATUS_SUCCESS, ESP_ERR_INVALID_ARG, TAG, "Received message: error status(%d)", message->info.status);

    esp_zb_zcl_read_attr_resp_variable_t *variable = message->variables;
    ESP_LOGI(TAG, "Read attribute response: status(%d), cluster(0x%x), attribute(0x%x), type(0x%x), value(%d)",
            message->info.status,
            message->info.cluster,
            variable->attribute.id,
            variable->attribute.data.type,
            variable->attribute.data.value ? *(uint8_t *)variable->attribute.data.value : 0);

    if (message->info.dst_endpoint == ENDPOINT)
    {
        switch (message->info.cluster)
        {
        case ESP_ZB_ZCL_CLUSTER_ID_TIME:
            switch(variable->attribute.id)
            {
                case ESP_ZB_ZCL_ATTR_TIME_LOCAL_TIME_ID:
                    time_t t = *(uint32_t*) variable->attribute.data.value + 946684800;
                    //TODO
                    break;
                default:
                    ESP_LOGE(TAG, "Message data: cluster(0x%x), attribute(0x%x)  ", message->info.cluster, variable->attribute.id);
            }
            break;
        default:
            ESP_LOGE(TAG, "Message data: cluster(0x%x), attribute(0x%x)  ", message->info.cluster, variable->attribute.id);
        }
    }
    return ESP_OK;
}

Call this method after network steering on end device
void read_server_time()
{
    uint16_t attributes[] =
    {
        ESP_ZB_ZCL_ATTR_TIME_LOCAL_TIME_ID
    };

    esp_zb_zcl_read_attr_cmd_t read_req;
    read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
    read_req.attr_field = attributes;
    read_req.attr_number = sizeof(attributes) / sizeof(uint16_t);
    read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TIME;
    read_req.zcl_basic_cmd.dst_endpoint = ENDPOINT;
    read_req.zcl_basic_cmd.src_endpoint = ENDPOINT;
    read_req.zcl_basic_cmd.dst_addr_u.addr_short = 0x0000;  //coordinator
    ESP_LOGI(TIME_TAG, "Request read time attr");
    esp_zb_zcl_read_attr_cmd_req(&read_req);
}

@omtrivedi-bacancy,
Do you have some updates for this issue? If not, please consider closing it.

authors: grebenyuk51 omtrivedi-bacancy xieqinan

repo: espressif/esp-zigbee-sdk


text:
Npk mksquashfs options contain uid, gid, and all-root

The combination of the three mksquashfs flags  uid, gid, and all-root do not make sense. Currently the file in the squashfs   images are assigned to uid, gid because the cli arg is after all-root. Probably the all-root flag needs to be removed.

I removed the unnecessary --all-root flag in #317.

authors: flxo inorick

repo: esrlabs/northstar


text:
Handle exception when message has wrong schema

The python-streaming-data-types module changed to throw exceptions if the schema is wrong, this change allows us to support it.

Codecov Report

Merging #62 (7770d19) into master (a16973f) will decrease coverage by 0.63%.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##           master      #62      +/-   ##
==========================================
- Coverage   93.99%   93.36%   -0.64%
==========================================
  Files          11       11
  Lines         433      437       +4
  Branches       58       59       +1
==========================================
+ Hits          407      408       +1
- Misses         20       22       +2
- Partials        6        7       +1

Impacted Files
Coverage Δ

forwarder/parse_config_update.py
87.50% <100.00%> (-3.68%)
:arrow_down:

Codecov Report

Merging #62 (7770d19) into master (a16973f) will decrease coverage by 0.63%.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##           master      #62      +/-   ##
==========================================
- Coverage   93.99%   93.36%   -0.64%
==========================================
  Files          11       11
  Lines         433      437       +4
  Branches       58       59       +1
==========================================
+ Hits          407      408       +1
- Misses         20       22       +2
- Partials        6        7       +1

Impacted Files
Coverage Δ

forwarder/parse_config_update.py
87.50% <100.00%> (-3.68%)
:arrow_down:

authors: codecov-io mattclarke

repo: ess-dmsc/forwarder


text:
Bower package

It'd be great if you could create a bower package for this so people don't have to manually copy it over into their browser projects.

@alevicki while this may be a helpful addition, Finance.js is already happily available on bower.js, as is any other git repo, or script.
# Git endpoint
$ bower install git://github.com/user/package.git
# URL
$ bower install http://example.com/script.js

Additionally, someone has already added it to bower. Try using bower install financejs --save.

Please use bower install financejs to install the library.

authors: alevicki essamjoubori unr

license: mit

license_source: bigquery


text:
typed messages

I don't know how yet, but it should be.

probably via flow typeof

ok, too hard now

repo: este/este


text:
Upgrade to React 15

[ ] waiting for React Native

If you don't need React Native, you can upgrade to React 15 now.

React Native just got released https://github.com/facebook/react-native/releases I'm going to take a stab at upgrading to it but I have very little experience with react native for now. I'll post back.

Still not resolved since React Native use peer dependency to React 0.14

React Native 0.25 should work https://twitter.com/matzatorski/status/722708472769482756

Ok I see what's going on, I falsely assumed they had the same release cycle as react:

Version
RC release
Stable release

0.24.0
week of Apr 4
Apr 18

0.25.0
week of Apr 18
May 2

0.26.0
week of May 2
May 16

...
...
...

So we can currently use 0.25.0 RC which has a peer dependency on React 0.15 with a view to switching to the final version on May 2nd.
I'll try and find some time to sit down with this today.

Let's wait for React Native 0.25.
TODO: Use the same React import with PropTypes in native.

Btw, React 15 has several issues where 0.14 just works. Este is edge still conservative, so let's patiently wait.

So React Native 0.25.1 has a warning for using React from react-native but we have to wait for 0.26 which comes with React 15.2

More patient waiting =) the release cycle is quite quick anyway so that's only 2 or 3 weeks away.
All the React Native stuff seems to be working fine on a fresh install with 0.14, no more of those firebase errors or anything so that's all good.

Building anything for release mode is still not working for iOS ... Aka if there is ever a plan to release an Este app on the App Store.

Sure there is. But I do not plan to release anything in next few weeks so I don't have any incentive to fix it now. Can you update your pull request please?

Done :-)

authors: hairychris justinr1234 steida


text:
Publish on crates.io

Hi, is it possible to update crates.io to the newest version?
Crates.io still lists 1.2 as the latest

@SWvheerden Hi, yup we are planning on fixing that this weekend (if not tonight)! There was a hiccup with the chrono library that was just resolved.

@here done

authors: SWvheerden bconn98 estk


text:
Adding path->Document transformer + AnnotationDatasetCreator

WIP

Nice, I will merge

repo: etalab-ia/ocr-xtract

license: MIT


text:
Implement GPU events II [16]

Following the work of #183, move event queue behaviour to device side for large-step (mindelay/2) periods, allowing desynchronized simulation time across cells.

Add infrastructure for per-cell simulation time and time step.
Implement device-side per-cell event queues.
Implement cell_group plumbing and device-side delivery.

Implementation plan.
The goal is to have event queuing and sampler data delivery performed on the cell_group side, and event delivery and probe data capture performed on the lowered cell side. Probe data vs. sampler delivery will be handled in another ticket, but the implementation of this work should anticipate this future work.
There are four proposed components of the implementation:

Implement explicit event binning.
This is required for the split in event handling responsibility between the cell_group and the lowered cell. This also addresses the problem of events modifying the time for other events on different cells in the same group. The structure for performing the binning was added in PR #204.

Refactor interface between cell_group and lowered cell for asyncronous cell state.
While leaving the underlying behaviour and semantics intact, modify the API presented to cell_group by the lowered cell implementation to allow for the fact that outside of a large-step integration period, the time associated with the state of each cell in the cell group might differ.
This API change will also implement the division in responsibility for event handling outlined above.

Push time and integration step period state to mechanisms.
Modify the mechanism API and modcc-generated instances to use a vector of time and dt (or rather, of current time and integration step stop time). These vectors will have one element per cell in the cell group.
Use this desynchronized state to perform per-cell time-stepping and event delivery. Integration across a step or large-step will be over the half-open time interval; events at the end point of the interval will effect the discontinuous state changes in the following integration step.

Move event delivery state to the back-end.
Perform event delivery as the first item of work in nrn_state mechanism integration. For the GPU back-end in particular, this will involve the use and implementation of a GPU-specific event list data structure.

This constitutes PR #281 up for review on the devel/async-integration branch.

PR #281 merged into devel/async-integration branch; merge of most recent master into that branch is PR #284.

repo: eth-cscs/nestmc-proto


text:
lmql script not passing args to model invocation

Model args are not processed correctly when invoked like eg:
lmql.model("/home/me/models/phi-1_5", cuda=True, trust_remote_code=True, dtype='float16')

Reproduction:
Fire up an lmql server:
$ lmql serve-model "distilgpt2" --cuda

Try to swap out models with one that needs --trust_remote_code
import lmql

@lmql.query
def load_big(prompt):
    '''
sample(temperature=1.2)
"""
    {prompt}[X]
"""
from
    lmql.model("/home/me/models/phi-1_5", cuda=True, trust_remote_code=True, dtype='float16')  # <<<<<<<<<< These args
where
    len(TOKENS(X)) > 10 and len(TOKENS(X)) < 30
'''

print(load_big('Hi there'))

The server throws an error:
  File "/home/me/lib/transformers-phi/src/transformers/models/auto/auto_factory.py", line 531, in from_pretrained
    config, kwargs = AutoConfig.from_pretrained(
  File "/home/me/lib/transformers-phi/src/transformers/models/auto/configuration_auto.py", line 1043, in from_pretrained
    trust_remote_code = resolve_trust_remote_code(
  File "/home/me/lib/transformers-phi/src/transformers/dynamic_module_utils.py", line 608, in resolve_trust_remote_code
    raise ValueError(
ValueError: The repository for /home/me/models/phi-1_5 contains custom code which must be executed to correctlyload the model. You can inspect the repository content at https://hf.co//home/me/models/phi-1_5.
Please pass the argument `trust_remote_code=True` to allow custom code to be run.

I would personally prefer more control in my hands, and less opinions baked in (eg per my suggestion to have a server library, where I just have to feed in a function with a specific signature, and the server code stands it up on some port. Or I feed in a custom module.py)
So for instance, if I want to swap in/out models, maybe I need a 4bit of a large model, but a float16 of a smaller one, or some models only play nicely if in bfloat16, not float16 (falcon comes to mind, although Mistral's made it irrelevant now.) Then there's trust_remote_code, and flash_attention_2 that not all models support yet. And I'm sure other models will hvae their own custom flags.
The alternative is, I guess, to launch different model config sets on different ports, but then you absolutely need the ability to unload models, from the client. This also means now that unload logic must be handled by the client, but, that may not be so bad.

I am working on enabling this soon, it requires some more changes with respect to stopping generation early though, so it will not be immediately available.
One thing that may be interesting here, is lmql.serve, which is a way to indeed configure the model in the same process that it will actually run in. See this snippet for an example. When launching an inference endpoint via lmql.serve, the parameters you provide will be passed through all the way to the from_pretrained (HF) or Llama(...) (llama.cpp) calls.
Still, I do want to enable this more generally. To host multiple model configurations in parallel, I would indeed advise to use multiple lmql serve-model/lmql.serve processes that serve differently configured models on different ports/endpoints.

authors: freckletonj lbeurerkellner

repo: eth-sri/lmql


text:
Unable to run program using Python and remote server url

I am using Text Generation Inference (TGI) and OVH cloud server to run a GPU instance. In the server, I used the following code to run the lmql api. The model I am using for this purpose is team-lucid/mptk-1b available in the Hugging Face website.
 lmql serve-model team-lucid/mptk-1b --cuda --port 8081

Following is the code I used on my local machine. I took the code from their GitHub page itself. I ran it in a virtual environment with lmql installed.
import lmql

lmql.model("gpt2", endpoint="15.204.216.218:8081")

@lmql.query
def chain_of_thought(question):
    '''lmql
    # Q&A prompt template
    "Q: {question}\n"
    "A: Let's think step by step.\n"
    "[REASONING]"
    "Thus, the answer is:[ANSWER]."

    # return just the ANSWER to the caller
    return ANSWER
    '''

print(chain_of_thought("Today is the 12th of June, what day was it 1 week ago?"))

I am getting the following error.
Exception has occurred: MaximumRetriesExceeded
Maximum retries exceeded (21) with error <class 'TypeError'>: expected str, bytes or os.PathLike object, not NoneType
  File "C:\Users\bhasamrita\Documents\GitLab Projects\AchnetLLM\notebooks\lmql_experimentation\lmql_example.py", line 18, in <module>
    print(chain_of_thought("Today is the 12th of June, what day was it 1 week ago?"))
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lmql.runtime.bopenai.batched_openai.MaximumRetriesExceeded: Maximum retries exceeded (21) with error <class 'TypeError'>: expected str, bytes or os.PathLike object, not NoneType

The following is a part of the error information displayed on the terminal.
Retrying... (attempt: 19)
  warnings.warn(f"OpenAI API: Underlying stream of OpenAI complete() call failed with error\n\n{attempt.error} ({type(attempt.error)})\n\nRetrying... (attempt: {self.retries})",
OpenAIAPIWarning: Enable tracemalloc to get the object allocation traceback
c:\Users\bhasamrita\Documents\GitLab Projects\AchnetLLM\venv\Lib\site-packages\lmql\runtime\bopenai\batched_openai.py:507: OpenAIAPIWarning: OpenAI API: Underlying stream of OpenAI complete() call failed with error

expected str, bytes or os.PathLike object, not NoneType (<class 'TypeError'>)

Retrying... (attempt: 20)
  warnings.warn(f"OpenAI API: Underlying stream of OpenAI complete() call failed with error\n\n{attempt.error} ({type(attempt.error)})\n\nRetrying... (attempt: {self.retries})",
OpenAIAPIWarning: Enable tracemalloc to get the object allocation traceback

Any suggestions on how to solve this issue?

You have to pass the lmql.model("gpt2", endpoint="15.204.216.218:8081") to the query.
Write
model = lmql.model("gpt2", endpoint="15.204.216.218:8081")

and then
@lmql.query(model=model)
def ...

With the current code, LMQL does not use that it should use your custom model and endpoint for the provided query, and falls back to OpenAI as the default backend.

I hope this solved the issue you were facing. Closing this for now, but feel free to re-open if follow-up questions arise.

authors: bhasamritasarmah lbeurerkellner


text:
Support for arrow function entrypoint in eval()

We can't have an expression body because it throws a compile error, like
String main() => 'Hello World!';

It only accepts a block body, like
String main() {
  return 'Hello World!';
}

Code
import 'package:dart_eval/dart_eval.dart';

void main() {
  print(
    eval('''
      String main() => 'Hello World!';
    ''')
  );
}

Error

Click to expand
Unhandled exception:
CompileError: Unknown statement type FunctionDeclarationStatementImpl at unknown (file package:default/main.dart)
#0      Compiler.compileSources
package:dart_eval/…/compiler/compiler.dart:344
#1      Compiler.compile
package:dart_eval/…/compiler/compiler.dart:131
#2      eval
package:dart_eval/…/eval/eval.dart:35
#3      main
test\temp.dart:5
#4      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:297:19)

#5      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)
Exited (255)

Expression body should be supported since version 0.4.6, what version are you using?
This might also just be because you are using the eval() method, can you try using compiler.compile() -> Runtime.ofProgram() -> executeLib() instead? (described more in the readme)

Fixed in https://github.com/ethanblake4/dart_eval/commit/4e7d946bb1ebfcb621bc8eae64240283b9a5b9ec and https://github.com/ethanblake4/dart_eval/commit/36e0af75501bceaf159c0f6e1377e8d4b3066126, will be in next release


text:
EIP-2681: Limit account nonce to 2^64-1 - Create Test Cases

(closes #401 )
What was wrong?
The Non-Legacy tests were not implemented.
These tests include ones for exceptional halting of CREATE opcode when the nonce is high
Related to Issue #401
How was it fixed?
Added the High Nonce tests out of tests/fixtures/BlockchainTests/GeneralStateTests/
Cute Animal Picture

Codecov Report

Merging #454 (5230bfb) into master (0e3c03b) will increase coverage by 0.08%.
The diff coverage is n/a.

@@            Coverage Diff             @@
##           master     #454      +/-   ##
==========================================
+ Coverage   79.36%   79.45%   +0.08%
==========================================
  Files         187      187
  Lines        9864     9864
==========================================
+ Hits         7829     7837       +8
+ Misses       2035     2027       -8

Flag
Coverage Δ

unittests
79.45% <ø> (+0.08%)
:arrow_up:

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files
Coverage Δ

...ethereum/spurious_dragon/vm/instructions/system.py
95.54% <0.00%> (+0.99%)
:arrow_up:

...hereum/tangerine_whistle/vm/instructions/system.py
98.98% <0.00%> (+1.01%)
:arrow_up:

src/ethereum/homestead/vm/instructions/system.py
97.29% <0.00%> (+1.08%)
:arrow_up:

src/ethereum/frontier/vm/instructions/system.py
98.64% <0.00%> (+1.35%)
:arrow_up:

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0e3c03b...5230bfb. Read the comment docs.

@voith @SamWilsn Thanks for the feedback.
After considering the points that you raised, I did a detailed analysis of the GeneralStateTests cases within the legacy and non-legacy tests. I also looked at the keys that they use.
Here are the important points

A small number of test case names do in fact have regex meta-charactes in their names Eg:- mem64kb_singleByte+32. So we will have to do an re.escape after all :)
Occasionally, the keys in the new test case have larger numbers between the letters d g v and not just a single digit as I previously thought. Example:- sstore_combinations_initial21_2_d452g0v0_Berlin inside sstore_combinations_initial21_2.json

I say we just keep it simple and handle it all with the same regex f"{re.escape(test_name)}.*{re.escape(network)}" i.e starts with test_name and ends with network without worrying about what occurs in the middle. This handles old and new test cases in one go.
I have already tested this and it picks up exactly all the tests that we've been running thus far. Let me know what you think and I'll update the PR accordingly.

Updated as described in the comment above

I think, for the time being, I'm fine with using a single function for both styles of test.

authors: SamWilsn codecov-commenter gurukamath

repo: ethereum/execution-specs


text:
[WIP] add ed25519 precompile (EIP665)

See also:

https://github.com/ethereum/EIPs/blob/master/EIPS/eip-665.md
https://github.com/ethereum/go-ethereum/pull/16453

I am stuck on getting unit tests working though (https://github.com/ethereum/pyethereum/pull/862/files#diff-a7fd7f958e91cefb06e0febd2d19dd05R1240): https://gist.github.com/oberstet/07f76327d5e339a0757be12e9b794ad3
What am I doing wrong? =(

The PR can use 2 Ed25519 implementations:

PyNaCl (if available: this is a cffi wrapped NaCl native extension running on both CPy and PyPy)
an embedded pure Python implementation

CI is green .. oh, I see;)
  # XXX: For now we're only performing minimal CI checks as most tests are
  # broken. Tests will be individually added here as they're fixed.
- make lint-minimal
 - make test-passing

and https://github.com/ethereum/pyethereum/blob/develop/ethereum/tests/test_contracts.py isn't in this list https://github.com/ethereum/pyethereum/blob/develop/Makefile#L49

repo: ethereum/pyethereum


text:
Use content_id inside OverlayService.find_nodes_close_to_content()

If I'm not misunderstanding things, we should be using content_id instead of content_key to calculate distances in https://github.com/ethereum/trin/blob/d5413c58ec55216f266dd68db0d528bb76eb5e39/trin-core/src/portalnet/overlay_service.rs#L882. Right now this throws an error since we cannot xor two vectors of different lengths (node_id and content_key)
I played around with a couple solutions, but didn't find anything suitably simple. If anybody has some ideas, lmk or feel free to take this on. Otherwise I'll pick this back up asap

It looks like you are right, and that we should be using content_id here. Those naming semantics are kind of confusing. I can take a look.

Also, if I remember correctly, we are operating under the assumption that each overlay network could use a unique distance function. In the same method, it looks like we're enforcing xor for each lookup, but it seems like this is incorrect? (Although functional for the history network which is our primary target. But it seems to me like this should be fixed now rather than later)
https://github.com/ethereum/trin/blob/d5413c58ec55216f266dd68db0d528bb76eb5e39/trin-core/src/portalnet/overlay_service.rs#L887

I agree that we should fix the distance metric now, but I think we can create a separate issue for it, so I created #218.

authors: jacobkaufmann njgheorghita

repo: ethereum/trin


text:
hardware-wallets: "Error: transaction.chainId/signature.v mismatch"

I am getting this error: Error: transaction.chainId/signature.v mismatch
From this code:

const { LedgerSigner } = require('@ethersproject/hardware-wallets')

async function main () {
  const signer = new LedgerSigner(ethers.provider)
  const usdcAddress = '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174'
  // account 3
  const account3 = 'myaddress'
  const erc20 = (await ethers.getContractAt('IERC20', usdcAddress)).connect(signer)
  const tx = await erc20.transfer(account3, ethers.utils.parseUnits('0.1', 6))
  const receipt = await tx.wait()
  if (receipt.status) {
    console.log('Successful')
  } else {
    console.log('Failed')
  }
}

The v value for the signature is 54.
I wonder if this error could be related to the chain id math change that was made in ledgerjs:  https://github.com/LedgerHQ/ledgerjs/commit/a1f21d25f3c216d4b2ec475c0802c56223e9a9e0
This code is using Hardhat connected to Polygon, which uses chainId 137.
Please help me get this fixed. Thanks!

The new @ethers-ext/signer-ledger (this package) should now work. It uses the most recent stable Ledger libraries. :)
Let me know if you have any issues with it though.
Thanks! :)

authors: mudgen ricmoo

repo: ethers-io/ext-signer-ledger


text:
update the Readme

update the Readme File with latest changes and info please

updated the read me in commit :
feature: updated README.md

authors: rudy-saal siamakhaz

repo: ethierlab/Motopya


text:
Datamap Endpoint doesn't handle multiple data subjects in a privacy declaration

Bug Description
When you push a system with multiple data subjects in a privacy declaration, that declaration doesn't show in the datamap response.
Similarly - when you have more than one privacy declaration which share the same data categories, all the privacy declarations which contain that category are removed.
Steps to Reproduce

Push the attached files to a fides server
make a GET request on /api/v1/datamap/default_organization
The request will succeed, but it will be empty. The system isn't in it.
Edit the privacy declarations so that there are unique data categories and unique data subjects in each declaration.
Push the resources again- - All the declarations should show.

Expected behavior
Data subjects is an array, the data map output should be able to show it.
Screenshots
If applicable, add screenshots to help explain your problem.
Environment

Version:
OS:
Python Version:
Docker Version:

Additional context
Add any other context about the problem here.
Archive.zip

chatted with Michael, turns out this happens via the endpoint as well as a local export, so the bug is most likely somewhere in the export.py code

authors: ThomasLaPiana mfbrown

repo: ethyca/fides