fix(ble): update the example docs for pawr

(cherry picked from commit 164fec9e74)

Co-authored-by: cjin <jinchen@espressif.com>
This commit is contained in:
Jin Chen
2025-10-16 20:13:21 +08:00
parent 89b5daa883
commit 99cef53f59
13 changed files with 198 additions and 171 deletions

View File

@@ -230,12 +230,12 @@ examples/bluetooth/nimble/ble_multi_conn:
examples/bluetooth/nimble/ble_pawr_adv:
<<: *bt_default_depends
enable:
- if: IDF_TARGET == "esp32c6"
- if: SOC_ESP_NIMBLE_CONTROLLER == 1 and IDF_TARGET != "esp32c2"
examples/bluetooth/nimble/ble_pawr_adv_conn:
<<: *bt_default_depends
enable:
- if: IDF_TARGET == "esp32c6"
- if: SOC_ESP_NIMBLE_CONTROLLER == 1 and IDF_TARGET != "esp32c2"
examples/bluetooth/nimble/ble_periodic_adv:
<<: *bt_default_depends

View File

@@ -1,9 +1,5 @@
| Supported Targets | ESP32-C6 |
| ----------------- | -------- |
# Important Note
*This example currently requires an external Bluetooth controller supporting PAwR functionality, as the ESP chips listed above do not have native controller support for PAwR features and under development phase*
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 |
| ----------------- | -------- | -------- | --------- | -------- |
# BLE Periodic Advertiser With Response (PAwR) Advertiser Example
@@ -14,7 +10,7 @@
This example starts PAwR advertising with configurable subevents and response slots.
It uses external Bluetooth controller and NimBLE stack based BLE host.
It uses Bluetooth controller and NimBLE stack based BLE host.
This example aims at understanding PAwR advertisement and related NimBLE APIs.

View File

@@ -11,6 +11,7 @@
#include "host/ble_hs.h"
#define BLE_PAWR_EVENT_INTERVAL (600)
#define BLE_PAWR_PERIODIC_EVENT_INTERVAL_MS (3000)
#define BLE_PAWR_NUM_SUBEVTS (10)
#define BLE_PAWR_SUB_INTERVAL (44) /*!< Interval between subevents (N * 1.25 ms) */
#define BLE_PAWR_RSP_SLOT_DELAY (20) /*!< The first response slot delay (N * 1.25 ms)*/
@@ -135,8 +136,8 @@ start_periodic_adv(void)
/* configure periodic advertising */
memset(&pparams, 0, sizeof(pparams));
pparams.include_tx_power = 0;
pparams.itvl_min = BLE_GAP_PERIODIC_ITVL_MS(3000);
pparams.itvl_max = BLE_GAP_PERIODIC_ITVL_MS(3000);
pparams.itvl_min = BLE_GAP_PERIODIC_ITVL_MS(BLE_PAWR_PERIODIC_EVENT_INTERVAL_MS);
pparams.itvl_max = BLE_GAP_PERIODIC_ITVL_MS(BLE_PAWR_PERIODIC_EVENT_INTERVAL_MS);
/* Configure the parameters of PAwR. */
pparams.num_subevents = BLE_PAWR_NUM_SUBEVTS;
pparams.subevent_interval = BLE_PAWR_SUB_INTERVAL;

View File

@@ -2,7 +2,7 @@
## Introduction
This tutorial examines the BLE Periodic Advertisement with Responses (PAwR) example code for ESP32 chipsets with BLE 5.0+ support. The code demonstrates how to implement PAwR functionality using NimBLE APIs, which enables bidirectional communication between advertiser and scanner devices in a power-efficient manner.
This tutorial examines the BLE Periodic Advertisement with Responses (PAwR) example code for ESP32 chipsets with BLE 5.0+ support. The code demonstrates how to implement PAwR functionality using NimBLE APIs, which enables bidirectional communication between advertiser and scanner devices.
## Includes
@@ -123,7 +123,7 @@ esp_err_t esp_nimble_init(void)
The example defines several PAwR parameters
```c
#define BLE_PAWR_EVENT_INTERVAL (600)
#define BLE_PAWR_PERIODIC_EVENT_INTERVAL_MS (3000)
#define BLE_PAWR_NUM_SUBEVTS (10)
#define BLE_PAWR_SUB_INTERVAL (44) /*!< Interval between subevents (N * 1.25 ms) */
#define BLE_PAWR_RSP_SLOT_DELAY (20) /*!< The first response slot delay (N * 1.25 ms) */
@@ -142,22 +142,6 @@ These parameters control:
- Data length for subevent payloads
## Periodic Advertising Configuration
```c
memset(&pparams, 0, sizeof(pparams));
pparams.include_tx_power = 0;
pparams.itvl_min = BLE_GAP_PERIODIC_ITVL_MS(3000);
pparams.itvl_max = BLE_GAP_PERIODIC_ITVL_MS(3000);
pparams.num_subevents = BLE_PAWR_NUM_SUBEVTS;
pparams.subevent_interval = BLE_PAWR_SUB_INTERVAL;
pparams.response_slot_delay = BLE_PAWR_RSP_SLOT_DELAY;
pparams.response_slot_spacing = BLE_PAWR_RSP_SLOT_SPACING;
pparams.num_response_slots = BLE_PAWR_NUM_RSP_SLOTS;
rc = ble_gap_periodic_adv_configure(instance, &pparams);
assert(rc == 0);
```
## Key PAwR Parameters:
- num_subevents: Number of subevents per periodic interval (10)
@@ -226,8 +210,8 @@ start_periodic_adv(void)
/* configure periodic advertising */
memset(&pparams, 0, sizeof(pparams));
pparams.include_tx_power = 0;
pparams.itvl_min = BLE_GAP_PERIODIC_ITVL_MS(3000);
pparams.itvl_max = BLE_GAP_PERIODIC_ITVL_MS(3000);
pparams.itvl_min = BLE_GAP_PERIODIC_ITVL_MS(BLE_PAWR_PERIODIC_EVENT_INTERVAL_MS);
pparams.itvl_max = BLE_GAP_PERIODIC_ITVL_MS(BLE_PAWR_PERIODIC_EVENT_INTERVAL_MS);
/* Configure the parameters of PAwR. */
pparams.num_subevents = BLE_PAWR_NUM_SUBEVTS;
pparams.subevent_interval = BLE_PAWR_SUB_INTERVAL;
@@ -312,9 +296,7 @@ This PAwR example demonstrates:
2. Bidirectional communication between advertiser and scanners
3. Efficient power usage through scheduled communication windows
4. Use of extended advertising to announce PAwR capabilities
3. Use of extended advertising to announce PAwR capabilities
The implementation shows how to:
@@ -326,4 +308,4 @@ The implementation shows how to:
- Manage the advertising lifecycle
PAwR is particularly useful for applications requiring periodic, bidirectional communication with multiple devices while maintaining low power consumption.
PAwR is particularly useful for applications requiring periodic, bidirectional communication with multiple devices

View File

@@ -1,8 +1,5 @@
| Supported Targets | ESP32-C6 |
| ----------------- | -------- |
# Important Note
*This example currently requires an external Bluetooth controller supporting PAwR functionality, as the ESP chips listed above do not have native controller support for PAwR features and under development phase*
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 |
| ----------------- | -------- | -------- | --------- | -------- |
# BLE Periodic Advertiser With Response (PAwR) Sync Example
@@ -20,6 +17,7 @@ To test this demo, any BLE advertiser supporting PAwR can be used.(check /exampl
- Configurable synchronization parameters (skip factor, timeout)
- Detailed reporting of PAwR advertisement data
- Handling of synchronization loss events
- Configuration of PAwR response data
Note :

View File

@@ -13,7 +13,9 @@
#define TAG "NimBLE_BLE_PAwR"
#define TARGET_NAME "Nimble_PAwR"
#define BLE_PAWR_RSP_DATA_IDX (2)
#define BLE_PAWR_RSP_DATA_LEN (16)
static uint8_t sub_data_pattern[BLE_PAWR_RSP_DATA_LEN] = {0};
static int create_periodic_sync(struct ble_gap_ext_disc_desc *disc);
@@ -60,7 +62,7 @@ gap_event_cb(struct ble_gap_event *event, void *arg)
.request_event = event->periodic_report.event_counter,
.request_subevent = event->periodic_report.subevent,
.response_subevent = event->periodic_report.subevent,
.response_slot = 2,
.response_slot = BLE_PAWR_RSP_DATA_IDX,
};
struct os_mbuf *data = os_msys_get_pkthdr(BLE_PAWR_RSP_DATA_LEN, 0);

View File

@@ -140,6 +140,7 @@ The example defines several key parameters:
```c
#define TAG "NimBLE_BLE_PAwR"
#define TARGET_NAME "Nimble_PAwR"
#define BLE_PAWR_RSP_DATA_IDX (2)
#define BLE_PAWR_RSP_DATA_LEN (16)
static uint8_t sub_data_pattern[BLE_PAWR_RSP_DATA_LEN] = {0};
```
@@ -147,6 +148,8 @@ These parameters control:
- Target advertiser name to sync with
- Response slot index to send response data at
- Response data length
- Data pattern for responses
@@ -232,7 +235,7 @@ case BLE_GAP_EVENT_PERIODIC_REPORT:
.request_event = event->periodic_report.event_counter,
.request_subevent = event->periodic_report.subevent,
.response_subevent = event->periodic_report.subevent,
.response_slot = rsp_slot_idx
.response_slot = BLE_PAWR_RSP_DATA_IDX
};
// Prepare response data
@@ -245,9 +248,12 @@ case BLE_GAP_EVENT_PERIODIC_REPORT:
event->periodic_report.sync_handle, &param, data);
break;
```
By default the response data will be sent within the same subevent where the periodic advertising report is received.
## Subevent Configuration
After sync establishment:
After sync establishment, sync to configurable subevents:
```c
// Choose subevents to listen to
@@ -256,6 +262,8 @@ int result = ble_gap_periodic_adv_sync_subev(
event->periodic_sync.sync_handle, 0, sizeof(subevents), subevents);
```
The subevents sync selection depends on the subevent number of the Periodic Advertising device.
## Error Handling
When sync is lost:
```c
@@ -270,4 +278,4 @@ case BLE_GAP_EVENT_PERIODIC_SYNC_LOST:
## Conclusion
This implementation demonstrates a complete PAwR synchronization solution, showcasing advertiser discovery via extended scanning, periodic sync establishment with configurable subevents (0-4), and efficient bidirectional communication through managed response slots. The robust architecture handles sync loss recovery while maintaining low-power operation, making it ideal for IoT applications requiring scheduled, bidirectional communication with multiple endpoints. The solution leverages BLE 5.0's PAwR features to optimize power efficiency and reliability in dense RF environments.
This implementation demonstrates a complete PAwR synchronization solution, showcasing advertiser discovery via extended scanning, periodic sync establishment with configurable subevents (0-4), and efficient bidirectional communication through managed response slots. The robust architecture handles sync loss recovery, making it ideal for IoT applications requiring scheduled, bidirectional communication with multiple endpoints.

View File

@@ -1,8 +1,5 @@
| Supported Targets | ESP32-C6 |
| ----------------- | -------- |
# Important Note
*This example currently requires an external Bluetooth controller supporting PAwR functionality, as the ESP chips listed above do not have native controller support for PAwR features and under development phase*
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 |
| ----------------- | -------- | -------- | --------- | -------- |
# BLE Periodic Advertiser With Response (PAwR) Advertiser Connection Example

View File

@@ -10,7 +10,7 @@
#include "nimble/nimble_port_freertos.h"
#include "host/ble_hs.h"
#define BLE_PAWR_EVENT_INTERVAL (520)
#define BLE_PAWR_EVENT_PERIODIC_INTERVAL_MS (3000)
#define BLE_PAWR_NUM_SUBEVTS (10)
#define BLE_PAWR_SUB_INTERVAL (52) /*!< Interval between subevents (N * 1.25 ms) */
#define BLE_PAWR_RSP_SLOT_DELAY (5) /*!< The first response slot delay (N * 1.25 ms)*/
@@ -217,8 +217,8 @@ start_periodic_adv(void)
/* configure periodic advertising */
memset(&pparams, 0, sizeof(pparams));
pparams.include_tx_power = 0;
pparams.itvl_min = BLE_GAP_PERIODIC_ITVL_MS(3000);
pparams.itvl_max = BLE_GAP_PERIODIC_ITVL_MS(3000);
pparams.itvl_min = BLE_GAP_PERIODIC_ITVL_MS(BLE_PAWR_EVENT_PERIODIC_INTERVAL_MS);
pparams.itvl_max = BLE_GAP_PERIODIC_ITVL_MS(BLE_PAWR_EVENT_PERIODIC_INTERVAL_MS);
/* Configure the parameters of PAwR. */
pparams.num_subevents = BLE_PAWR_NUM_SUBEVTS;
pparams.subevent_interval = BLE_PAWR_SUB_INTERVAL;

View File

@@ -123,6 +123,7 @@ esp_err_t esp_nimble_init(void)
## PAwR Configuration
```c
#define BLE_PAWR_EVENT_INTERVAL (520)
#define BLE_PAWR_EVENT_PERIODIC_INTERVAL_MS (3000)
#define BLE_PAWR_NUM_SUBEVTS (10)
#define BLE_PAWR_SUB_INTERVAL (52)
#define BLE_PAWR_RSP_SLOT_DELAY (5)
@@ -130,33 +131,123 @@ esp_err_t esp_nimble_init(void)
#define BLE_PAWR_NUM_RSP_SLOTS (25)
#define BLE_PAWR_SUB_DATA_LEN (20)
```
These parameters configure PAwR interval, subevents, response slot timing, and payload length.
These parameters control:
## Periodic Advertising Configuration
- The interval between periodic advertising events
```c
memset(&pparams, 0, sizeof(pparams));
pparams.include_tx_power = 0;
pparams.itvl_min = BLE_GAP_PERIODIC_ITVL_MS(3000);
pparams.itvl_max = BLE_GAP_PERIODIC_ITVL_MS(3000);
pparams.num_subevents = BLE_PAWR_NUM_SUBEVTS;
pparams.subevent_interval = BLE_PAWR_SUB_INTERVAL;
pparams.response_slot_delay = BLE_PAWR_RSP_SLOT_DELAY;
pparams.response_slot_spacing = BLE_PAWR_RSP_SLOT_SPACING;
pparams.num_response_slots = BLE_PAWR_NUM_RSP_SLOTS;
```
- Number of subevents per periodic interval
These values are passed to ble_gap_periodic_adv_configure() to start PAwR.
- Timing of response slots
- Data length for subevent payloads
## Key PAwR Parameters:
- num_subevents: Number of subevents per periodic interval (10)
- subevent_interval: Time between subevents (44 × 1.25ms = 55ms)
- response_slot_delay: First response slot delay (20 × 1.25ms = 25ms)
- response_slot_spacing: Time between slots (32 × 0.125ms = 4ms)
- num_response_slots: Number of response slots per subevent (5)
## PAwR Advertisement
The start_periodic_adv() function:
- Configures extended advertising parameters
- Sets up periodic advertising using subevent and slot parameters
- Starts extended + periodic advertising
The start_periodic_adv() function configures and starts PAwR:
```c
static void
start_periodic_adv(void)
{
int rc;
uint8_t addr[6];
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 = 0;
#if MYNEWT_VAL(BLE_PERIODIC_ADV_ENH)
struct ble_gap_periodic_adv_enable_params eparams;
memset(&eparams, 0, sizeof(eparams));
#endif
/* Get the local public address. */
rc = ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, addr, NULL);
assert (rc == 0);
ESP_LOGI(TAG, "Device Address %02x:%02x:%02x:%02x:%02x:%02x", addr[5], addr[4], addr[3],
addr[2], addr[1], addr[0]);
/* For periodic we use instance with non-connectable advertising */
memset (&params, 0, sizeof(params));
params.own_addr_type = BLE_OWN_ADDR_PUBLIC;
params.primary_phy = BLE_HCI_LE_PHY_CODED;
params.secondary_phy = BLE_HCI_LE_PHY_1M;
params.sid = 0;
params.itvl_min = BLE_GAP_ADV_ITVL_MS(50);
params.itvl_max = BLE_GAP_ADV_ITVL_MS(50);
rc = ble_gap_ext_adv_configure(instance, &params, NULL, gap_event_cb, NULL);
assert (rc == 0);
memset(&adv_fields, 0, sizeof(adv_fields));
adv_fields.name = (const uint8_t *)"Nimble_PAwR_CONN";
adv_fields.name_len = strlen((char *)adv_fields.name);
/* 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 = BLE_GAP_PERIODIC_ITVL_MS(BLE_PAWR_EVENT_PERIODIC_INTERVAL_MS);
pparams.itvl_max = BLE_GAP_PERIODIC_ITVL_MS(BLE_PAWR_EVENT_PERIODIC_INTERVAL_MS);
/* Configure the parameters of PAwR. */
pparams.num_subevents = BLE_PAWR_NUM_SUBEVTS;
pparams.subevent_interval = BLE_PAWR_SUB_INTERVAL;
pparams.response_slot_delay = BLE_PAWR_RSP_SLOT_DELAY;
pparams.response_slot_spacing = BLE_PAWR_RSP_SLOT_SPACING;
pparams.num_response_slots = BLE_PAWR_NUM_RSP_SLOTS;
rc = ble_gap_periodic_adv_configure(instance, &pparams);
assert(rc == 0);
/* start periodic advertising */
#if MYNEWT_VAL(BLE_PERIODIC_ADV_ENH)
eparams.include_adi = 1;
rc = ble_gap_periodic_adv_start(instance, &eparams);
#else
rc = ble_gap_periodic_adv_start(instance);
#endif
assert (rc == 0);
/* start advertising */
rc = ble_gap_ext_adv_start(instance, 0, 0);
assert (rc == 0);
ESP_LOGI(TAG, "instance %u started (periodic)\n", instance);
}
```
Key steps:
- Configure extended advertising parameters
- Set up periodic advertising with subevent and response slot parameters
- Start both periodic and extended advertising
## Need of Extended Advertisement in Periodic Advertisement
Extended advertisements contain synchronization info that lets scanners align with periodic advertising. This enables precise subevent-based communicati
Extended advertisements contain synchronization info that lets scanners align with periodic advertising. This enables precise subevent-based communication.
## GAP Event Callback
@@ -175,7 +266,7 @@ case BLE_GAP_EVENT_DISCONNECT:
## Using ble_gap_connect_with_synced()
The API ble_gap_connect_with_synced() is a NimBLE API used by a PAwR Advertiser to initiate a BLE connection with a synced scanner. This allows the advertiser to transition from scheduled subevent-based communication to a higher-throughput, lower-latency connection with a specific scanner.
The API ble_gap_connect_with_synced() is a NimBLE API used by a PAwR Advertiser to initiate a BLE connection with a synced scanner as central role. This allows the advertiser to transition from scheduled subevent-based communication to a higher-throughput, lower-latency connection with a specific scanner.
This is especially useful in use cases where on-demand, peer-to-peer data exchange is needed.
```c
@@ -207,41 +298,6 @@ void pawr_host_task(void *param)
nimble_port_freertos_deinit();
}
```
## Parameter Configuration
The below snippets represent the parameter configuration for extended and periodic advertisement.
### For Extended Advertisement
```c
params.own_addr_type = BLE_OWN_ADDR_RANDOM; //Own address type is set to Random
params.primary_phy = BLE_HCI_LE_PHY_1M; // Primary advertising PHY is set to 1M
params.secondary_phy = BLE_HCI_LE_PHY_2M; // Secondary advertising PHY is set to 2M
params.sid = 2; // Advertising set Id is assigned with value 2.
```
### For Periodic Advertisement
```c
memset(&pparams, 0, sizeof(pparams));
pparams.include_tx_power = 0; // Indicates that TX power is not included in advertising PDU
pparams.itvl_min = BLE_GAP_ADV_ITVL_MS(120); // Minimum advertising interval of 240ms
pparams.itvl_max = BLE_GAP_ADV_ITVL_MS(240); //Maximum advertising interval of 480ms
```
Periodic advertisement is started for a particular advertisement instance by calling the API `ble_gap_periodic_adv_start(instance)`. This function takes instance-id as an input parameter. It defines the hci command by initializing the command parameters which are represented in the following lines.
```c
struct ble_hci_le_set_periodic_adv_enable_cp cmd;
cmd.enable = 0x01;
cmd.adv_handle = instance;
```
Extended advertising is invoked for a particular instance using the API call `ble_gap_ext_adv_start(instance, 0, 0)`.Instance-id, duration, and max_events are input parameters for this API call respectively.
Duration represents the time for which the adverteiment will take place. Upon expiration, the advertising procedure ends, and the BLE_GAP_EVENT_ADV_COMPLETE event is reported.0 value is used for no expiration.
max_events Number of advertising events that should be sent before advertising ends and a BLE_GAP_EVENT_ADV_COMPLETE event is reported.0 value is used for no limit.
## Conclusion
@@ -252,5 +308,5 @@ This PAwR with connection example demonstrates:
- Periodic advertising with subevents and response slots
- Dynamic connection initiation based on scanner responses
- Use of extended advertisement for synchronization
- Efficient, scalable, low-power bidirectional communication
- Efficient, scalable, bidirectional communication

View File

@@ -1,8 +1,5 @@
| Supported Targets | ESP32-C6 |
| ----------------- | -------- |
## Important Note
*This example currently requires an external Bluetooth controller supporting PAwR functionality, as the ESP chips listed above do not have native controller support for PAwR features and under development phase*
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 |
| ----------------- | -------- | -------- | --------- | -------- |
# BLE Periodic Advertiser With Response (PAwR) Sync Connection Example

View File

@@ -13,6 +13,7 @@
#define TAG "NimBLE_BLE_PAwR_CONN"
#define TARGET_NAME "Nimble_PAwR_CONN"
#define BLE_PAWR_RSP_SLOT_INDEX (2)
#define BLE_PAWR_RSP_DATA_LEN (10)
static uint8_t sub_data_pattern[BLE_PAWR_RSP_DATA_LEN] = {0};
@@ -114,7 +115,7 @@ gap_event_cb(struct ble_gap_event *event, void *arg)
.request_event = event->periodic_report.event_counter,
.request_subevent = event->periodic_report.subevent,
.response_subevent = event->periodic_report.subevent,
.response_slot = 2,
.response_slot = BLE_PAWR_RSP_SLOT_INDEX,
};
struct os_mbuf *data = os_msys_get_pkthdr(BLE_PAWR_RSP_DATA_LEN, 0);

View File

@@ -114,19 +114,14 @@ esp_err_t esp_nimble_init(void)
Configures a passive extended scan to detect periodic advertisers:
```c
static void start_scan(void) {
struct ble_gap_ext_disc_params d = {
.itvl = BLE_GAP_SCAN_ITVL_MS(600), // Scan every 600ms
.window = BLE_GAP_SCAN_ITVL_MS(300), // Listen for 300ms
.passive= 1 // Do not send scan requests
};
// Start discovery; gap_event_cb handles each advertisement
ble_gap_ext_disc(BLE_OWN_ADDR_PUBLIC, 0, 0, 1, 0, 0,
NULL, &d, gap_event_cb, NULL);
}
```
memset(&disc_params, 0, sizeof(disc_params));
disc_params.itvl = BLE_GAP_SCAN_ITVL_MS(600);
disc_params.window = BLE_GAP_SCAN_ITVL_MS(300);
disc_params.passive = 1;
- BLE_OWN_ADDR_PUBLIC: Use the devices public address.
rc = ble_gap_ext_disc(BLE_OWN_ADDR_PUBLIC, 0, 0, 1, 0, 0, NULL, &disc_params,
gap_event_cb, NULL);
```
- gap_event_cb: Processes discovery events (EXT_DISC) to find our target.`
@@ -151,60 +146,54 @@ static int create_periodic_sync(struct ble_gap_ext_disc_desc *disc) {
```
- disc->addr / sid: Address and Sync ID identify the PAwR train.
- ble_gap_periodic_adv_sync_create: Starts low-power sync to periodic events.
- ble_gap_periodic_adv_sync_create: Starts sync to periodic events.
## Subevent Synchronization
After sync establishment, sync to configurable subevents:
```c
// Choose subevents to listen to
uint8_t subevents[] = {0, 1, 2, 3, 4};
int result = ble_gap_periodic_adv_sync_subev(
event->periodic_sync.sync_handle, 0, sizeof(subevents), subevents);
```
The subevents sync selection depends on the subevent number of the Periodic Advertising device.
## Sending Response Data
Once synchronized, respond during periodic reports:
Respond after receiving periodic reports:
```c
case BLE_GAP_EVENT_PERIODIC_REPORT:
ESP_LOGI(TAG, "[Periodic Adv Report] handle:%d, event_counter(%d), subevent(%d)",
event->periodic_report.sync_handle,
event->periodic_report.event_counter,
event->periodic_report.subevent);
case BLE_GAPCreate Periodic Sync
struct ble_gap_periodic_adv_response_params param = {
.request_event = event->periodic_report.event_counter,
.request_subevent = event->periodic_report.subevent,
.response_subevent = event->periodic_report.subevent,
.response_slot = BLE_PAWR_RSP_SLOT_INDEX,
};
When a periodic advertiser is found, request synchronization:
struct os_mbuf *data = os_msys_get_pkthdr(BLE_PAWR_RSP_DATA_LEN, 0);
if (!data) {
ESP_LOGE(TAG, "No memory");
return 0;
}
// create a special data for checking manually in ADV side
static int create_periodic_sync(struct ble_gap_ext_disc_desc *disc) {
struct ble_gap_periodic_sync_params p = {
.skip = 0, // Do not skip any events
.sync_timeout = 4000, // Give 4000ms to establish sync
.reports_disabled= 0, // Keep reports enabled
#if CONFIG_EXAMPLE_PERIODIC_ADV_ENH
.filter_duplicates = 1, // Only receive when data-id changes
#endif
};
// Initiate sync; callback will receive PERIODIC_SYNC
return ble_gap_periodic_adv_sync_create(
&disc->addr, disc->sid, &p,
gap_event_cb, NULL);
}
sub_data_pattern[0] = event->periodic_report.subevent;
rc = ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, device_addr, NULL);
sub_data_pattern[1] = param.response_slot;
memcpy(&sub_data_pattern[2],device_addr,BLE_DEV_ADDR_LEN);
disc->addr / sid: Address and Sync ID identify the PAwR train.
os_mbuf_append(data, sub_data_pattern, BLE_PAWR_RSP_DATA_LEN);
ble_gap_periodic_adv_sync_create: Starts low-power sync to periodic events.
_EVENT_PERIODIC_REPORT: {
struct ble_gap_periodic_adv_response_params r = {
.request_event = event->periodic_report.event_counter,
.request_subevent = event->periodic_report.subevent,
.response_subevent= event->periodic_report.subevent,
.response_slot = 2, // Always use slot 2
};
// Allocate buffer for response payload
struct os_mbuf *m = os_msys_get_pkthdr(BLE_PAWR_RSP_DATA_LEN, 0);
// First byte: subevent index
sub_data_pattern[0] = event->periodic_report.subevent;
// Next 6 bytes: our public address
ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, device_addr, NULL);
memcpy(&sub_data_pattern[1], device_addr, BLE_DEV_ADDR_LEN);
// Fill remaining bytes with slot index
sub_data_pattern[7] = r.response_slot;
os_mbuf_append(m, sub_data_pattern, BLE_PAWR_RSP_DATA_LEN);
// Send response data back to advertiser
ble_gap_periodic_adv_set_response_data(
event->periodic_report.sync_handle,
&r, m);
break;
}
rc = ble_gap_periodic_adv_set_response_data(event->periodic_report.sync_handle, &param, data);
```
- os_msys_get_pkthdr: Allocates memory for the response.
@@ -263,7 +252,7 @@ This PAwR Sync + Conn example demonstrates:
- Passive discovery of periodic advertisers.
- Low-power synchronization to scheduled subevents.
- Synchronization to scheduled subevents.
- Slot-based responses with custom payload.