fix(nimble): Fix issues found in review for nimble examples

This commit is contained in:
Rahul Tank
2026-07-17 12:21:28 +05:30
committed by BOT
parent 99b87ca81f
commit fa1bf5e2fc
73 changed files with 1299 additions and 635 deletions

View File

@@ -83,6 +83,7 @@ void app_main(void) {
rc = gap_init();
if (rc != 0) {
ESP_LOGE(TAG, "failed to initialize GAP service, error code: %d", rc);
nimble_port_deinit();
return;
}
#endif

View File

@@ -35,6 +35,9 @@ static void start_advertising(void) {
/* Set device name */
name = ble_svc_gap_device_name();
if (name == NULL) {
name = DEVICE_NAME;
}
adv_fields.name = (uint8_t *)name;
adv_fields.name_len = strlen(name);
adv_fields.name_is_complete = 1;

View File

@@ -87,6 +87,7 @@ void app_main(void) {
rc = gap_init();
if (rc != 0) {
ESP_LOGE(TAG, "failed to initialize GAP service, error code: %d", rc);
nimble_port_deinit();
return;
}
#endif

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -64,6 +64,9 @@ static void start_advertising(void) {
/* Set device name */
name = ble_svc_gap_device_name();
if (name == NULL) {
name = DEVICE_NAME;
}
adv_fields.name = (uint8_t *)name;
adv_fields.name_len = strlen(name);
adv_fields.name_is_complete = 1;
@@ -160,26 +163,29 @@ static int gap_event_handler(struct ble_gap_event *event, void *arg) {
print_conn_desc(&desc);
led_on();
/* Try to update connection parameters */
/* Try to update connection parameters.
* BT spec requires: supervision_timeout > (1+latency)*itvl/4
* Ensure the timeout satisfies this constraint when latency=3. */
uint16_t min_timeout = (uint16_t)(((1 + 3) * (uint32_t)desc.conn_itvl) / 4 + 1);
uint16_t supervision_timeout = (desc.supervision_timeout > min_timeout)
? desc.supervision_timeout : min_timeout;
struct ble_gap_upd_params params = {.itvl_min = desc.conn_itvl,
.itvl_max = desc.conn_itvl,
.latency = 3,
.supervision_timeout =
desc.supervision_timeout};
.supervision_timeout = supervision_timeout};
rc = ble_gap_update_params(event->connect.conn_handle, &params);
if (rc != 0) {
ESP_LOGE(
TAG,
"failed to update connection parameters, error code: %d",
rc);
return rc;
}
}
/* Connection failed, restart advertising */
else {
start_advertising();
}
return rc;
return 0;
/* Disconnect event */
case BLE_GAP_EVENT_DISCONNECT:

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -54,7 +54,7 @@ static void nimble_host_task(void *param) {
nimble_port_run();
/* Clean up at exit */
vTaskDelete(NULL);
nimble_port_freertos_deinit();
}
static void heart_rate_task(void *param) {
@@ -114,6 +114,7 @@ void app_main(void) {
rc = gap_init();
if (rc != 0) {
ESP_LOGE(TAG, "failed to initialize GAP service, error code: %d", rc);
nimble_port_deinit();
return;
}
#endif
@@ -122,6 +123,7 @@ void app_main(void) {
rc = gatt_svc_init();
if (rc != 0) {
ESP_LOGE(TAG, "failed to initialize GATT server, error code: %d", rc);
nimble_port_deinit();
return;
}
@@ -129,12 +131,7 @@ void app_main(void) {
nimble_host_config_init();
/* Start NimBLE host task thread and return */
rc = xTaskCreate(nimble_host_task, "NimBLE Host", 4 * 1024, NULL,
5, NULL);
if (rc != pdPASS) {
ESP_LOGE(TAG, "failed to create NimBLE host task");
return;
}
nimble_port_freertos_init(nimble_host_task);
rc = xTaskCreate(heart_rate_task, "Heart Rate", 4 * 1024, NULL, 5, NULL);
if (rc != pdPASS) {

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -64,6 +64,9 @@ static void start_advertising(void) {
/* Set device name */
name = ble_svc_gap_device_name();
if (name == NULL) {
name = DEVICE_NAME;
}
adv_fields.name = (uint8_t *)name;
adv_fields.name_len = strlen(name);
adv_fields.name_is_complete = 1;
@@ -159,26 +162,29 @@ static int gap_event_handler(struct ble_gap_event *event, void *arg) {
/* Print connection descriptor */
print_conn_desc(&desc);
/* Try to update connection parameters */
/* Try to update connection parameters.
* BT spec requires: supervision_timeout > (1+latency)*itvl/4
* Ensure the timeout satisfies this constraint when latency=3. */
uint16_t min_timeout = (uint16_t)(((1 + 3) * (uint32_t)desc.conn_itvl) / 4 + 1);
uint16_t supervision_timeout = (desc.supervision_timeout > min_timeout)
? desc.supervision_timeout : min_timeout;
struct ble_gap_upd_params params = {.itvl_min = desc.conn_itvl,
.itvl_max = desc.conn_itvl,
.latency = 3,
.supervision_timeout =
desc.supervision_timeout};
.supervision_timeout = supervision_timeout};
rc = ble_gap_update_params(event->connect.conn_handle, &params);
if (rc != 0) {
ESP_LOGE(
TAG,
"failed to update connection parameters, error code: %d",
rc);
return rc;
}
}
/* Connection failed, restart advertising */
else {
start_advertising();
}
return rc;
return 0;
/* Disconnect event */
case BLE_GAP_EVENT_DISCONNECT:

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -164,9 +164,11 @@ error:
/* Public functions */
void send_heart_rate_indication(void) {
if (heart_rate_ind_status && heart_rate_chr_conn_handle_inited) {
ble_gatts_indicate(heart_rate_chr_conn_handle,
heart_rate_chr_val_handle);
ESP_LOGI(TAG, "heart rate indication sent!");
int rc = ble_gatts_indicate(heart_rate_chr_conn_handle,
heart_rate_chr_val_handle);
if (rc != 0) {
ESP_LOGE(TAG, "failed to send heart rate indication, error code: %d", rc);
}
}
}
@@ -230,9 +232,13 @@ void gatt_svr_subscribe_cb(struct ble_gap_event *event) {
/* Check attribute handle */
if (event->subscribe.attr_handle == heart_rate_chr_val_handle) {
if (event->subscribe.conn_handle == BLE_HS_CONN_HANDLE_NONE) {
return;
}
/* Update heart rate subscription status */
heart_rate_chr_conn_handle = event->subscribe.conn_handle;
heart_rate_chr_conn_handle_inited = true;
heart_rate_chr_conn_handle_inited = event->subscribe.cur_indicate;
heart_rate_ind_status = event->subscribe.cur_indicate;
}
}

View File

@@ -15,6 +15,7 @@
#include "host/ble_gap.h"
/* Public function declarations */
void gatt_svr_reset_heart_rate_subscription(void);
void send_heart_rate_indication(void);
void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg);
int gatt_svr_subscribe_cb(struct ble_gap_event *event);

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -59,7 +59,7 @@ static void nimble_host_task(void *param) {
nimble_port_run();
/* Clean up at exit */
vTaskDelete(NULL);
nimble_port_freertos_deinit();
}
static void heart_rate_task(void *param) {
@@ -123,6 +123,7 @@ void app_main(void) {
rc = gap_init();
if (rc != 0) {
ESP_LOGE(TAG, "failed to initialize GAP service, error code: %d", rc);
nimble_port_deinit();
return;
}
#endif
@@ -131,6 +132,7 @@ void app_main(void) {
rc = gatt_svc_init();
if (rc != 0) {
ESP_LOGE(TAG, "failed to initialize GATT server, error code: %d", rc);
nimble_port_deinit();
return;
}
@@ -138,7 +140,12 @@ void app_main(void) {
nimble_host_config_init();
/* Start NimBLE host task thread and return */
xTaskCreate(nimble_host_task, "NimBLE Host", 4*1024, NULL, 5, NULL);
xTaskCreate(heart_rate_task, "Heart Rate", 4*1024, NULL, 5, NULL);
nimble_port_freertos_init(nimble_host_task);
rc = xTaskCreate(heart_rate_task, "Heart Rate", 4 * 1024, NULL, 5, NULL);
if (rc != pdPASS) {
ESP_LOGE(TAG, "failed to create heart rate task");
return;
}
return;
}

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -12,7 +12,6 @@
inline static void format_addr(char *addr_str, uint8_t addr[]);
static void print_conn_desc(struct ble_gap_conn_desc *desc);
static void start_advertising(void);
static void set_random_addr(void);
static int gap_event_handler(struct ble_gap_event *event, void *arg);
/* Private variables */
@@ -52,20 +51,6 @@ static void print_conn_desc(struct ble_gap_conn_desc *desc) {
desc->sec_state.bonded);
}
static void set_random_addr(void) {
/* Local variables */
int rc = 0;
ble_addr_t addr;
/* Generate new non-resolvable private address */
rc = ble_hs_id_gen_rnd(0, &addr);
assert(rc == 0);
/* Set address */
rc = ble_hs_id_set_rnd(addr.val);
assert(rc == 0);
}
static void start_advertising(void) {
/* Local variables */
int rc = 0;
@@ -79,6 +64,9 @@ static void start_advertising(void) {
/* Set device name */
name = ble_svc_gap_device_name();
if (name == NULL) {
name = DEVICE_NAME;
}
adv_fields.name = (uint8_t *)name;
adv_fields.name_len = strlen(name);
adv_fields.name_is_complete = 1;
@@ -201,6 +189,9 @@ static int gap_event_handler(struct ble_gap_event *event, void *arg) {
ESP_LOGI(TAG, "disconnected from peer; reason=%d",
event->disconnect.reason);
/* Reset heart rate subscription state */
gatt_svr_reset_heart_rate_subscription();
/* Restart advertising */
start_advertising();
return rc;
@@ -324,8 +315,9 @@ void adv_init(void) {
int rc = 0;
char addr_str[18] = {0};
/* Make sure we have proper BT identity address set */
set_random_addr();
/* Make sure we have proper BT identity address set.
* ble_hs_util_ensure_addr(1) safely generates a random address only if
* one is not already set, avoiding conflicts on re-sync events. */
rc = ble_hs_util_ensure_addr(1);
if (rc != 0) {
ESP_LOGE(TAG, "device does not have any available bt address!");

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -24,7 +24,7 @@ static uint8_t heart_rate_chr_val[2] = {0};
static uint16_t heart_rate_chr_val_handle;
static const ble_uuid16_t heart_rate_chr_uuid = BLE_UUID16_INIT(0x2A37);
static uint16_t heart_rate_chr_conn_handle = 0;
static uint16_t heart_rate_chr_conn_handle = BLE_HS_CONN_HANDLE_NONE;
static bool heart_rate_chr_conn_handle_inited = false;
static bool heart_rate_ind_status = false;
@@ -165,6 +165,12 @@ error:
}
/* Public functions */
void gatt_svr_reset_heart_rate_subscription(void) {
heart_rate_chr_conn_handle_inited = false;
heart_rate_ind_status = false;
heart_rate_chr_conn_handle = BLE_HS_CONN_HANDLE_NONE;
}
void send_heart_rate_indication(void) {
/* Check if connection handle is initialized */
if (!heart_rate_chr_conn_handle_inited) {
@@ -230,10 +236,19 @@ void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg) {
int gatt_svr_subscribe_cb(struct ble_gap_event *event) {
/* Check attribute handle */
if (event->subscribe.attr_handle == heart_rate_chr_val_handle) {
if (event->subscribe.conn_handle == BLE_HS_CONN_HANDLE_NONE) {
return 0;
}
if (!event->subscribe.cur_indicate) {
gatt_svr_reset_heart_rate_subscription();
return 0;
}
/* Update heart rate subscription status */
heart_rate_chr_conn_handle = event->subscribe.conn_handle;
heart_rate_chr_conn_handle_inited = true;
heart_rate_ind_status = event->subscribe.cur_indicate;
heart_rate_ind_status = true;
/* Check security status */
if (!is_connection_encrypted(event->subscribe.conn_handle)) {