esp-nimble-cpp/examples/Bluetooth_5/NimBLE_multi_advertiser/main/main.cpp

169 lines
6.2 KiB
C++
Raw Permalink Normal View History

2024-12-09 20:58:14 +01:00
/**
* NimBLE Multi Advertiser Demo:
*
* Demonstrates the Bluetooth 5.x extended advertising capabilities.
*
* This demo will advertise 2 advertisements, and extended scannable instance
* and a connectable legacy instance. They will advertise for 5 seconds then
* sleep for 20 seconds. The extended scannable instance will use the scan
* request callback to update it's data when a scan response is requested.
*
* Created: on April 9 2022
* Author: H2zero
2024-12-09 20:58:14 +01:00
*/
2024-12-09 20:58:14 +01:00
#include <NimBLEDevice.h>
#include <esp_sleep.h>
#define SERVICE_UUID "ABCD"
#define CHARACTERISTIC_UUID "1234"
2024-12-09 20:58:14 +01:00
/** Time in milliseconds to advertise */
static uint32_t advTime = 5000;
2024-12-09 20:58:14 +01:00
/** Time to sleep between advertisements */
static uint32_t sleepTime = 20;
2024-12-09 20:58:14 +01:00
/** Primary PHY used for advertising, can be one of BLE_HCI_LE_PHY_1M or BLE_HCI_LE_PHY_CODED */
static uint8_t primaryPhy = BLE_HCI_LE_PHY_CODED;
2024-12-09 20:58:14 +01:00
/**
* Secondary PHY used for advertising and connecting,
* can be one of BLE_HCI_LE_PHY_1M, BLE_HCI_LE_PHY_2M or BLE_HCI_LE_PHY_CODED
*/
static uint8_t secondaryPhy = BLE_HCI_LE_PHY_1M;
2024-12-09 20:58:14 +01:00
/** Handler class for server events */
class ServerCallbacks : public NimBLEServerCallbacks {
void onConnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo) override {
printf("Client connected: %s\n", connInfo.getAddress().toString().c_str());
2024-12-09 20:58:14 +01:00
}
2024-12-09 20:58:14 +01:00
void onDisconnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo, int reason) override {
printf("Client disconnected\n");
// if still advertising we won't sleep yet.
if (!pServer->getAdvertising()->isAdvertising()) {
2024-12-09 20:58:14 +01:00
printf("Sleeping for %" PRIu32 " seconds\n", sleepTime);
esp_deep_sleep_start();
}
2024-12-09 20:58:14 +01:00
}
} serverCallbacks;
2024-12-09 20:58:14 +01:00
/** Callback class to handle advertising events */
class AdvCallbacks : public NimBLEExtAdvertisingCallbacks {
void onStopped(NimBLEExtAdvertising* pAdv, int reason, uint8_t instId) override {
/* Check the reason advertising stopped, don't sleep if client is connecting */
2024-12-09 20:58:14 +01:00
printf("Advertising instance %u stopped\n", instId);
switch (reason) {
case 0:
printf(" client connecting\n");
return;
case BLE_HS_ETIMEOUT:
2024-12-09 20:58:14 +01:00
printf("Time expired - sleeping for %" PRIu32 " seconds\n", sleepTime);
break;
default:
break;
}
esp_deep_sleep_start();
}
bool m_updatedSR = false;
2024-12-09 20:58:14 +01:00
void onScanRequest(NimBLEExtAdvertising* pAdv, uint8_t instId, NimBLEAddress addr) override {
printf("Scan request for instance %u\n", instId);
// if the data has already been updated we don't need to change it again.
if (!m_updatedSR) {
printf("Updating scan data\n");
NimBLEExtAdvertisement sr;
sr.setServiceData(NimBLEUUID(SERVICE_UUID), std::string("Hello from scan response!"));
2024-12-09 20:58:14 +01:00
pAdv->setScanResponseData(instId, sr);
m_updatedSR = true;
}
}
2024-12-09 20:58:14 +01:00
} advCallbacks;
2024-12-09 20:58:14 +01:00
extern "C" void app_main(void) {
/** Initialize NimBLE and set the device name */
NimBLEDevice::init("Multi advertiser");
2024-12-09 20:58:14 +01:00
/** Create a server for our legacy advertiser */
NimBLEServer* pServer = NimBLEDevice::createServer();
pServer->setCallbacks(&serverCallbacks);
2024-12-09 20:58:14 +01:00
NimBLEService* pService = pServer->createService(SERVICE_UUID);
NimBLECharacteristic* pCharacteristic =
pService->createCharacteristic(CHARACTERISTIC_UUID,
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::NOTIFY);
pCharacteristic->setValue("Hello World");
2024-12-09 20:58:14 +01:00
/** Start the service */
pService->start();
2024-12-09 20:58:14 +01:00
/** Create our multi advertising instances */
2024-12-09 20:58:14 +01:00
/** extended scannable instance advertising on coded and 1m PHY's. */
NimBLEExtAdvertisement extScannable(primaryPhy, secondaryPhy);
2024-12-09 20:58:14 +01:00
/** Legacy advertising as a connectable device. */
NimBLEExtAdvertisement legacyConnectable;
2024-12-09 20:58:14 +01:00
/** Optional scan response data. */
NimBLEExtAdvertisement legacyScanResponse;
2024-12-09 20:58:14 +01:00
/** As per Bluetooth specification, extended advertising cannot be both scannable and connectable */
extScannable.setScannable(true);
extScannable.setConnectable(false);
2024-12-09 20:58:14 +01:00
/** Set the initial data */
extScannable.setServiceData(NimBLEUUID(SERVICE_UUID), std::string("Scan me!"));
2024-12-09 20:58:14 +01:00
/** Enable the scan response callback, we will use this to update the data. */
extScannable.enableScanRequestCallback(true);
2024-12-09 20:58:14 +01:00
/** Optional custom address for this advertisment. */
legacyConnectable.setAddress(NimBLEAddress("DE:AD:BE:EF:BA:AD"));
2024-12-09 20:58:14 +01:00
/** Set the advertising data. */
legacyConnectable.setName("Legacy");
legacyConnectable.setCompleteServices16({NimBLEUUID(SERVICE_UUID)});
2024-12-09 20:58:14 +01:00
/** Set the legacy and connectable flags. */
legacyConnectable.setLegacyAdvertising(true);
legacyConnectable.setConnectable(true);
2024-12-09 20:58:14 +01:00
/** Put some data in the scan response if desired. */
legacyScanResponse.setServiceData(NimBLEUUID(SERVICE_UUID), "Legacy SR");
2024-12-09 20:58:14 +01:00
/** Get the advertising ready */
NimBLEExtAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
2024-12-09 20:58:14 +01:00
/** Set the callbacks to handle advertising events */
pAdvertising->setCallbacks(&advCallbacks);
2024-12-09 20:58:14 +01:00
/**
* Set instance data.
* Up to 5 instances can be used if configured in menuconfig, instance 0 is always available.
*
2024-12-09 20:58:14 +01:00
* We will set the extended scannable data on instance 0 and the legacy data on instance 1.
* Note that the legacy scan response data needs to be set to the same instance (1).
*/
2024-12-09 20:58:14 +01:00
if (pAdvertising->setInstanceData(0, extScannable) && pAdvertising->setInstanceData(1, legacyConnectable) &&
pAdvertising->setScanResponseData(1, legacyScanResponse)) {
/**
* NimBLEExtAdvertising::start takes the advertisement instance ID to start
* and a duration in milliseconds or a max number of advertisements to send (or both).
*/
if (pAdvertising->start(0, advTime) && pAdvertising->start(1, advTime)) {
printf("Started advertising\n");
} else {
printf("Failed to start advertising\n");
}
} else {
2024-12-09 20:58:14 +01:00
printf("Failed to register advertisement data\n");
}
esp_sleep_enable_timer_wakeup(sleepTime * 1000000);
}