Skip to content

Commit

Permalink
Merge branch 'feature/periodic_adv_example' into 'master'
Browse files Browse the repository at this point in the history
Nimble: support for periodic adv / sync example

See merge request espressif/esp-idf!19963
  • Loading branch information
RoshanESP committed Sep 26, 2022
2 parents 3d8bf6d + 10eacf0 commit c51d4ab
Show file tree
Hide file tree
Showing 16 changed files with 892 additions and 0 deletions.
12 changes: 12 additions & 0 deletions examples/bluetooth/.build-test-rules.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,18 @@ examples/bluetooth/nimble/ble_l2cap_coc:
temporary: true
reason: the other targets are not tested yet

examples/bluetooth/nimble/ble_periodic_adv:
enable:
- if: IDF_TARGET in ["esp32c2", "esp32c3", "esp32s3"]
temporary: true
reason: the other targets are not tested yet

examples/bluetooth/nimble/ble_periodic_sync:
enable:
- if: IDF_TARGET in ["esp32c2", "esp32c3", "esp32s3"]
temporary: true
reason: the other targets are not tested yet

examples/bluetooth/nimble/ble_phy:
enable:
- if: IDF_TARGET in ["esp32c2", "esp32c3", "esp32s3"]
Expand Down
7 changes: 7 additions & 0 deletions examples/bluetooth/nimble/ble_periodic_adv/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# 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 ${CMAKE_CURRENT_LIST_DIR}/../common/nimble_peripheral_utils)

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

# BLE Periodic Advertiser Example

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

This example starts periodic advertising with non resolvable private address.

It uses Bluetooth controller and NimBLE stack based BLE host.

This example aims at understanding periodic advertisement and related NimBLE APIs.


To test this demo, any BLE Periodic Sync app can be used.


Note :

* Make sure to run `python -m pip install --user -r $IDF_PATH/requirements.txt -r $IDF_PATH/tools/ble/requirements.txt` to install the dependency packages needed.
* Currently this Python utility is only supported on Linux (BLE communication is via BLuez + DBus).

## 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:

```bash
idf.py menuconfig
```

In the `Example Configuration` menu:

* Select I/O capabilities of device from `Example Configuration --> I/O Capability`, default is `Just_works`.

### 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

There is this console output when periodic_adv is started:

```
I (313) BTDM_INIT: BT controller compile version [2ee0168]
I (313) phy_init: phy_version 912,d001756,Jun 2 2022,16:28:07
I (353) system_api: Base MAC address is not set
I (353) system_api: read default base MAC address from EFUSE
I (353) BTDM_INIT: Bluetooth MAC: 84:f7:03:08:14:8e
I (363) NimBLE_BLE_PERIODIC_ADV: BLE Host Task Started
I (373) NimBLE: Device Address:
I (373) NimBLE: d0:42:3a:95:84:05
I (373) NimBLE:
I (383) NimBLE: instance 1 started (periodic)
```

## Note
* Periodic sync transfer is not implemented for now.

## 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.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
set(srcs "main.c")

idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS ".")
15 changes: 15 additions & 0 deletions examples/bluetooth/nimble/ble_periodic_adv/main/Kconfig.projbuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
menu "Example Configuration"

config EXAMPLE_EXTENDED_ADV
bool
default y if SOC_ESP_NIMBLE_CONTROLLER
prompt "Enable Extended Adv"
help
Use this option to enable extended advertising in the example

config EXAMPLE_RANDOM_ADDR
bool
prompt "Advertise RANDOM Address"
help
Use this option to advertise a random address instead of public address
endmenu
221 changes: 221 additions & 0 deletions examples/bluetooth/nimble/ble_periodic_adv/main/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/

#include "esp_log.h"
#include "nvs_flash.h"
/* BLE */
#include "nimble/nimble_port.h"
#include "nimble/nimble_port_freertos.h"
#include "host/ble_hs.h"
#include "host/util/util.h"
#include "console/console.h"
#include "services/gap/ble_svc_gap.h"
#include "periodic_adv.h"
#include "host/ble_gap.h"
#include "host/ble_hs_adv.h"
#include "patterns.h"

#if CONFIG_EXAMPLE_EXTENDED_ADV
static uint8_t periodic_adv_raw_data[] = {'E', 'S', 'P', '_', 'P', 'E', 'R', 'I', 'O', 'D', 'I', 'C', '_', 'A', 'D', 'V'};
static uint8_t id_addr_type;
#endif

static const char *tag = "NimBLE_BLE_PERIODIC_ADV";
#if CONFIG_EXAMPLE_RANDOM_ADDR
static uint8_t own_addr_type = BLE_OWN_ADDR_RANDOM;
#else
static uint8_t own_addr_type;
#endif

void ble_store_config_init(void);

#if CONFIG_EXAMPLE_EXTENDED_ADV
/**
* Enables advertising with the following parameters:
* o General discoverable mode.
* o Undirected connectable mode.
*/
static void
start_periodic_adv(void)
{
int rc = ble_hs_util_ensure_addr(0);
assert(rc == 0);
/* configure global address */
rc = ble_hs_id_infer_auto(0, &id_addr_type);
assert(rc == 0);

struct ble_gap_periodic_adv_params pparams;
struct ble_gap_ext_adv_params params;
struct ble_hs_adv_fields adv_fields;
struct os_mbuf *data;
uint8_t instance = 1;
ble_addr_t addr;

/* For periodic we use instance with non-connectable advertising */
memset (&params, 0, sizeof(params));

/* advertise using random addr */
params.own_addr_type = BLE_OWN_ADDR_RANDOM;
params.primary_phy = BLE_HCI_LE_PHY_1M;
params.secondary_phy = BLE_HCI_LE_PHY_2M;
params.sid = 2;

/* configure instance 1 */
rc = ble_gap_ext_adv_configure(instance, &params, NULL, NULL, NULL);
assert (rc == 0);

/* set random (NRPA) address for instance */
rc = ble_hs_id_gen_rnd(1, &addr);
assert (rc == 0);

rc = ble_gap_ext_adv_set_addr(instance, &addr );
assert (rc == 0);

memset(&adv_fields, 0, sizeof(adv_fields));
adv_fields.name = (const uint8_t *)"Periodic ADV";
adv_fields.name_len = strlen((char *)adv_fields.name);

/* Default to legacy PDUs size, mbuf chain will be increased if needed
*/
data = os_msys_get_pkthdr(BLE_HCI_MAX_ADV_DATA_LEN, 0);
assert(data);

rc = ble_hs_adv_set_fields_mbuf(&adv_fields, data);
assert(rc == 0);

rc = ble_gap_ext_adv_set_data(instance, data);
assert(rc == 0);

/* configure periodic advertising */
memset(&pparams, 0, sizeof(pparams));
pparams.include_tx_power = 0;
pparams.itvl_min = 160;
pparams.itvl_max = 240;

rc = ble_gap_periodic_adv_configure(instance, &pparams);
assert(rc == 0);

/* get mbuf for periodic data */
data = os_msys_get_pkthdr(sizeof(ext_adv_pattern_1), 0);
assert(data);

/* fill mbuf with periodic data */

rc = os_mbuf_append(data, ext_adv_pattern_1, sizeof(ext_adv_pattern_1));
assert(rc == 0);

data = os_msys_get_pkthdr(sizeof(periodic_adv_raw_data), 0);
assert(data);

rc = os_mbuf_append(data, periodic_adv_raw_data, sizeof(periodic_adv_raw_data));
assert(rc == 0);
rc = ble_gap_periodic_adv_set_data(instance, data);
assert (rc == 0);

/* start periodic advertising */
rc = ble_gap_periodic_adv_start(instance);
assert (rc == 0);

/* start advertising */
rc = ble_gap_ext_adv_start(instance, 0, 0);
assert (rc == 0);

MODLOG_DFLT(INFO, "instance %u started (periodic)\n", instance);
}
#endif
static void
periodic_adv_on_reset(int reason)
{
MODLOG_DFLT(ERROR, "Resetting state; reason=%d\n", reason);
}

#if CONFIG_EXAMPLE_RANDOM_ADDR
static void
periodic_adv_set_addr(void)
{
ble_addr_t addr;
int rc;

/* generate new non-resolvable private address */
rc = ble_hs_id_gen_rnd(0, &addr);
assert(rc == 0);

/* set generated address */
rc = ble_hs_id_set_rnd(addr.val);

assert(rc == 0);
}
#endif

static void
periodic_adv_on_sync(void)
{
int rc;

#if CONFIG_EXAMPLE_RANDOM_ADDR
/* Generate a non-resolvable private address. */
periodic_adv_set_addr();
/* Make sure we have proper identity address set (public preferred) */
rc = ble_hs_util_ensure_addr(1);
#else
rc = ble_hs_util_ensure_addr(0);
#endif
assert(rc == 0);

/* Figure out address to use while advertising (no privacy for now) */
rc = ble_hs_id_infer_auto(0, &own_addr_type);
if (rc != 0) {
MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
return;
}

/* Printing ADDR */
uint8_t addr_val[6] = {0};
rc = ble_hs_id_copy_addr(own_addr_type, addr_val, NULL);

MODLOG_DFLT(INFO, "Device Address: ");
print_addr(addr_val);
MODLOG_DFLT(INFO, "\n");
/* Begin advertising. */
#if CONFIG_EXAMPLE_EXTENDED_ADV
start_periodic_adv();
#endif
}

void periodic_adv_host_task(void *param)
{
ESP_LOGI(tag, "BLE Host Task Started");
/* This function will return only when nimble_port_stop() is executed */
nimble_port_run();

nimble_port_freertos_deinit();
}

void
app_main(void)
{
int rc;
/* Initialize NVS — it is used to store PHY calibration data */
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
nimble_port_init();
/* Initialize the NimBLE host configuration. */
ble_hs_cfg.reset_cb = periodic_adv_on_reset;
ble_hs_cfg.sync_cb = periodic_adv_on_sync;
ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
/* Set the default device name. */
rc = ble_svc_gap_device_name_set("nimble_periodic_adv");
assert(rc == 0);

/* XXX Need to have template for store */
ble_store_config_init();

nimble_port_freertos_init(periodic_adv_host_task);
}
Loading

0 comments on commit c51d4ab

Please sign in to comment.