diff --git a/components/log/include/esp_log.h b/components/log/include/esp_log.h index 6fda8d605..6a9550046 100644 --- a/components/log/include/esp_log.h +++ b/components/log/include/esp_log.h @@ -95,6 +95,29 @@ uint32_t esp_log_early_timestamp(void); */ void esp_log_write(esp_log_level_t level, const char* tag, const char* format, ...) __attribute__ ((format (printf, 3, 4))); +/** + * @brief Log a buffer of hex bytes at Info level + * + * @param tag description tag + * + * @param buffer Pointer to the buffer array + * + * @param buff_len length of buffer + * + */ +void esp_log_buffer_hex(const char *tag, const char *buffer, uint16_t buff_len); + +/** + * @brief Log a buffer of characters at Info level. Buffer should contain only printable characters. + * + * @param tag description tag + * + * @param buffer Pointer to the buffer array + * + * @param buff_len length of buffer + * + */ +void esp_log_buffer_char(const char *tag, const char *buffer, uint16_t buff_len); #if CONFIG_LOG_COLORS #define LOG_COLOR_BLACK "30" diff --git a/components/log/log.c b/components/log/log.c index 3826e173b..26d58b228 100644 --- a/components/log/log.c +++ b/components/log/log.c @@ -54,6 +54,8 @@ #include #include "esp_log.h" +//print number of bytes per line for esp_log_buffer_char and esp_log_buffer_hex +#define BYTES_PER_LINE 16 #ifndef BOOTLOADER_BUILD @@ -316,3 +318,31 @@ uint32_t IRAM_ATTR esp_log_timestamp() uint32_t esp_log_timestamp() __attribute__((alias("esp_log_early_timestamp"))); #endif //BOOTLOADER_BUILD + +void esp_log_buffer_hex(const char *tag, const char *buffer, uint16_t buff_len) +{ + char temp_buffer[3*BYTES_PER_LINE + 1]= {0}; + int line_len = 0; + for (int i = 0; i < buff_len; i++) { + line_len += sprintf(temp_buffer+line_len, "%02x ", buffer[i]); + if (((i + 1) % BYTES_PER_LINE == 0) || (i == buff_len - 1)) { + ESP_LOGI(tag, "%s", temp_buffer); + line_len = 0; + temp_buffer[0] = 0; + } + } +} + +void esp_log_buffer_char(const char *tag, const char *buffer, uint16_t buff_len) +{ + char temp_buffer[2*BYTES_PER_LINE + 1] = {0}; + int line_len = 0; + for (int i = 0; i < buff_len; i++) { + line_len += sprintf(temp_buffer+line_len, "%c ", buffer[i]); + if (((i + 1) % BYTES_PER_LINE == 0) || (i == buff_len - 1)) { + ESP_LOGI(tag, "%s", temp_buffer); + line_len = 0; + temp_buffer[0] = 0; + } + } +} diff --git a/docs/api-reference/system/log.rst b/docs/api-reference/system/log.rst index 8aadeac09..4ea0335e9 100644 --- a/docs/api-reference/system/log.rst +++ b/docs/api-reference/system/log.rst @@ -55,7 +55,10 @@ Functions .. doxygenfunction:: esp_log_level_set .. doxygenfunction:: esp_log_set_vprintf .. doxygenfunction:: esp_log_timestamp +.. doxygenfunction:: esp_log_early_timestamp .. doxygenfunction:: esp_log_write +.. doxygenfunction:: esp_log_buffer_hex +.. doxygenfunction:: esp_log_buffer_char diff --git a/examples/bluetooth/gatt_server/main/gatts_demo.c b/examples/bluetooth/gatt_server/main/gatts_demo.c index f36206b79..8bcbde7a0 100644 --- a/examples/bluetooth/gatt_server/main/gatts_demo.c +++ b/examples/bluetooth/gatt_server/main/gatts_demo.c @@ -53,6 +53,8 @@ static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_i #define GATTS_DEMO_CHAR_VAL_LEN_MAX 0x40 +#define PREPARE_BUF_MAX_SIZE 1024 + uint8_t char1_str[] = {0x11,0x22,0x33}; esp_attr_value_t gatts_demo_char1_val = { @@ -139,6 +141,17 @@ static struct gatts_profile_inst gl_profile_tab[PROFILE_NUM] = { }, }; +typedef struct { + uint8_t *prepare_buf; + int prepare_len; +} prepare_type_env_t; + +static prepare_type_env_t a_prepare_write_env; +static prepare_type_env_t b_prepare_write_env; + +void example_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param); +void example_exec_write_event_env(prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param); + static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { switch (event) { @@ -170,6 +183,63 @@ static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param } } +void example_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param){ + esp_gatt_status_t status = ESP_GATT_OK; + if (param->write.need_rsp){ + if (param->write.is_prep){ + if (prepare_write_env->prepare_buf == NULL) { + prepare_write_env->prepare_buf = (uint8_t *)malloc(PREPARE_BUF_MAX_SIZE*sizeof(uint8_t)); + prepare_write_env->prepare_len = 0; + if (prepare_write_env->prepare_buf == NULL) { + LOG_ERROR("Gatt_server prep no mem\n"); + status = ESP_GATT_NO_RESOURCES; + } + } else { + if(param->write.offset > PREPARE_BUF_MAX_SIZE) { + status = ESP_GATT_INVALID_OFFSET; + } else if ((param->write.offset + param->write.len) > PREPARE_BUF_MAX_SIZE) { + status = ESP_GATT_INVALID_ATTR_LEN; + } + } + + esp_gatt_rsp_t *gatt_rsp = (esp_gatt_rsp_t *)malloc(sizeof(esp_gatt_rsp_t)); + gatt_rsp->attr_value.len = param->write.len; + gatt_rsp->attr_value.handle = param->write.handle; + gatt_rsp->attr_value.offset = param->write.offset; + gatt_rsp->attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE; + memcpy(gatt_rsp->attr_value.value, param->write.value, param->write.len); + esp_err_t response_err = esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, status, gatt_rsp); + if (response_err != ESP_OK){ + LOG_ERROR("Send response error\n"); + } + free(gatt_rsp); + if (status != ESP_GATT_OK){ + return; + } + memcpy(prepare_write_env->prepare_buf + param->write.offset, + param->write.value, + param->write.len); + prepare_write_env->prepare_len += param->write.len; + + }else{ + esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, status, NULL); + } + } +} + +void example_exec_write_event_env(prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param){ + if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC){ + esp_log_buffer_hex(GATTS_TAG, (char *)prepare_write_env->prepare_buf, prepare_write_env->prepare_len); + }else{ + ESP_LOGI(GATTS_TAG,"ESP_GATT_PREP_WRITE_CANCEL"); + } + if (prepare_write_env->prepare_buf) { + free(prepare_write_env->prepare_buf); + prepare_write_env->prepare_buf = NULL; + } + prepare_write_env->prepare_len = 0; +} + 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: @@ -205,10 +275,14 @@ static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_i 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_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL); + example_write_event_env(gatts_if, &a_prepare_write_env, param); break; } case ESP_GATTS_EXEC_WRITE_EVT: + ESP_LOGI(GATTS_TAG,"ESP_GATTS_EXEC_WRITE_EVT"); + esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL); + example_exec_write_event_env(&a_prepare_write_env, param); + break; case ESP_GATTS_MTU_EVT: case ESP_GATTS_CONF_EVT: case ESP_GATTS_UNREG_EVT: @@ -308,10 +382,14 @@ static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_i 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_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL); + example_write_event_env(gatts_if, &b_prepare_write_env, param); break; } case ESP_GATTS_EXEC_WRITE_EVT: + ESP_LOGI(GATTS_TAG,"ESP_GATTS_EXEC_WRITE_EVT"); + esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL); + example_exec_write_event_env(&b_prepare_write_env, param); + break; case ESP_GATTS_MTU_EVT: case ESP_GATTS_CONF_EVT: case ESP_GATTS_UNREG_EVT: