Skip to content

Commit

Permalink
NimbLE: Added multi advertising example
Browse files Browse the repository at this point in the history
  • Loading branch information
IshaESP committed Mar 20, 2023
1 parent e4cf722 commit ec92e96
Show file tree
Hide file tree
Showing 10 changed files with 827 additions and 0 deletions.
10 changes: 10 additions & 0 deletions examples/bluetooth/.build-test-rules.yml
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,16 @@ examples/bluetooth/nimble/ble_l2cap_coc:
temporary: true
reason: The runner doesn't support yet

examples/bluetooth/nimble/ble_multi_adv:
enable:
- if: IDF_TARGET in ["esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32h4", "esp32s3"]
temporary: true
reason: the other targets are not tested yet
disable_test:
- if: IDF_TARGET in ["esp32"]
temporary: true
reason: The runner doesn't support yet

examples/bluetooth/nimble/ble_periodic_adv:
enable:
- if: IDF_TARGET in ["esp32c2", "esp32c3", "esp32c6" , "esp32s3", "esp32h2", "esp32h4" ]
Expand Down
8 changes: 8 additions & 0 deletions examples/bluetooth/nimble/ble_multi_adv/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)

set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/bluetooth/nimble/common/nimble_peripheral_utils)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(ble_multi_adv)
74 changes: 74 additions & 0 deletions examples/bluetooth/nimble/ble_multi_adv/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-H4 | ESP32-S3 |
| ----------------- | -------- | -------- | -------- | -------- | -------- | -------- |

# BLE Multi Adv Example

(See the README.md file in the upper level 'examples' directory for more information about examples.)

This example support legacy as well as extended advertisement for all phy. For multi advertising, random addresses are generated for each instance.

It starts 4 types of advertising:
* Non connectable extended
* Connectable extended
* Scannable legacy
* Legacy withe specified duration(5 sec)

## How to Use Example

Before project configuration and build, be sure to set the correct chip target using:

```bash
idf.py set-target <chip_name>
```

### Configure the Project

Open the project configuration menu:
```
idf.py menuconfig
```

To configure number of advertising instances:

* Component config → Bluetooth → NimBLE Options → Enable BLE 5 feature → Maximum number of extended advertising instances

### Hardware Required

* A development board with ESP32-C3 SoC,ESP32-S3/ESP32-H4/ESP32-C2 SoC and BLE5.0 supported chips (e.g., ESP32-C3-DevKitC, etc.)
* A USB cable for Power supply and programming

See [Development Boards](https://www.espressif.com/en/products/devkits) for more information about it.

### Build and Flash

Run `idf.py -p PORT flash monitor` to build, flash and monitor the project.

(To exit the serial monitor, type ``Ctrl-]``.)

See the [Getting Started Guide](https://idf.espressif.com/) for full steps to configure and use ESP-IDF to build projects.


## Example Output

```
I (404) NimBLE_MULTI_ADV: BLE Host Task Started
I (414) NimBLE_MULTI_ADV: Instance 0 started
I (414) NimBLE_MULTI_ADV: Instance 1 started
I (434) NimBLE_MULTI_ADV: Instance 2 started
I (444) NimBLE_MULTI_ADV: Instance 3 started
I (454) main_task: Returned from app_main()
I (5404) NimBLE: advertise complete; reason=13
I (5404) NimBLE_MULTI_ADV: In ble_legacy_duration_cb, instance = 3
I (5404) NimBLE_MULTI_ADV: Instance 3 started
I (10384) NimBLE: advertise complete; reason=13
I (10384) NimBLE_MULTI_ADV: In ble_legacy_duration_cb, instance = 3
I (10394) NimBLE_MULTI_ADV: Instance 3 started
```
## Troubleshooting

For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.
5 changes: 5 additions & 0 deletions examples/bluetooth/nimble/ble_multi_adv/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
set(srcs "main.c"
"gatt_svr.c")

idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS ".")
169 changes: 169 additions & 0 deletions examples/bluetooth/nimble/ble_multi_adv/main/gatt_svr.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
/*
* SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "host/ble_hs.h"
#include "host/ble_uuid.h"
#include "services/gap/ble_svc_gap.h"
#include "services/gatt/ble_svc_gatt.h"
#include "multi_adv.h"

static const ble_uuid128_t gatt_svr_svc_uuid =
BLE_UUID128_INIT(0x2d, 0x71, 0xa2, 0x59, 0xb4, 0x58, 0xc8, 0x12,
0x99, 0x99, 0x43, 0x95, 0x12, 0x2f, 0x46, 0x59);

/* A characteristic that can be subscribed to */
static uint16_t gatt_svr_chr_val_handle;
static const ble_uuid128_t gatt_svr_chr_uuid =
BLE_UUID128_INIT(0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11,
0x22, 0x22, 0x22, 0x22, 0x33, 0x33, 0x33, 0x33);

/* A custom descriptor */
static uint8_t gatt_svr_dsc_val;
static const ble_uuid128_t gatt_svr_dsc_uuid =
BLE_UUID128_INIT(0x01, 0x01, 0x01, 0x01, 0x12, 0x12, 0x12, 0x12,
0x23, 0x23, 0x23, 0x23, 0x34, 0x34, 0x34, 0x34);

static int
gatt_svc_access(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt,
void *arg);

static const struct ble_gatt_svc_def gatt_svr_svcs[] = {
{
/*** Service ***/
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = &gatt_svr_svc_uuid.u,
.characteristics = (struct ble_gatt_chr_def[])
{ {
/*** This characteristic can be subscribed to by writing 0x00 and 0x01 to the CCCD ***/
.uuid = &gatt_svr_chr_uuid.u,
.access_cb = gatt_svc_access,
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_INDICATE,
.val_handle = &gatt_svr_chr_val_handle,
.descriptors = (struct ble_gatt_dsc_def[]) {
{
.uuid = &gatt_svr_dsc_uuid.u,
.att_flags = BLE_ATT_F_READ,
.access_cb = gatt_svc_access,
}, {
0, /* No more descriptors in this characteristic */
}
},
}, {
0, /* No more characteristics in this service. */
}
},
},

{
0, /* No more services. */
},
};

/**
* Access callback whenever a characteristic/descriptor is read or written to.
* Here reads and writes need to be handled.
* ctxt->op tells weather the operation is read or write and
* weather it is on a characteristic or descriptor,
* ctxt->dsc->uuid tells which characteristic/descriptor is accessed.
* attr_handle give the value handle of the attribute being accessed.
* Accordingly do:
* Append the value to ctxt->om if the operation is READ
* Write ctxt->om to the value if the operation is WRITE
**/
static int
gatt_svc_access(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt, void *arg)
{
switch (ctxt->op) {
case BLE_GATT_ACCESS_OP_READ_CHR:
MODLOG_DFLT(INFO, "Characteristic read; conn_handle=%d attr_handle=%d\n",
conn_handle, attr_handle);
return 0;

case BLE_GATT_ACCESS_OP_WRITE_CHR:
MODLOG_DFLT(INFO, "Characteristic write; conn_handle=%d attr_handle=%d",
conn_handle, attr_handle);
return 0;

case BLE_GATT_ACCESS_OP_READ_DSC:
MODLOG_DFLT(INFO, "Descriptor read; conn_handle=%d attr_handle=%d\n",
conn_handle, attr_handle);
return 0;

case BLE_GATT_ACCESS_OP_WRITE_DSC:
goto unknown;

default:
goto unknown;
}

unknown:
/* Unknown characteristic/descriptor;
* The NimBLE host should not have called this function;
*/
assert(0);
return BLE_ATT_ERR_UNLIKELY;
}

void
gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
{
char buf[BLE_UUID_STR_LEN];

switch (ctxt->op) {
case BLE_GATT_REGISTER_OP_SVC:
MODLOG_DFLT(DEBUG, "registered service %s with handle=%d\n",
ble_uuid_to_str(ctxt->svc.svc_def->uuid, buf),
ctxt->svc.handle);
break;

case BLE_GATT_REGISTER_OP_CHR:
MODLOG_DFLT(DEBUG, "registering characteristic %s with "
"def_handle=%d val_handle=%d\n",
ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf),
ctxt->chr.def_handle,
ctxt->chr.val_handle);
break;

case BLE_GATT_REGISTER_OP_DSC:
MODLOG_DFLT(DEBUG, "registering descriptor %s with handle=%d\n",
ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf),
ctxt->dsc.handle);
break;

default:
assert(0);
break;
}
}

int
gatt_svr_init(void)
{
int rc;

ble_svc_gap_init();
ble_svc_gatt_init();

rc = ble_gatts_count_cfg(gatt_svr_svcs);
if (rc != 0) {
return rc;
}

rc = ble_gatts_add_svcs(gatt_svr_svcs);
if (rc != 0) {
return rc;
}

/* Setting a value for the read-only descriptor */
gatt_svr_dsc_val = 0x99;

return 0;
}
Loading

0 comments on commit ec92e96

Please sign in to comment.