Skip to content

Commit

Permalink
[BREAKING] - Refactor NimBLEScan
Browse files Browse the repository at this point in the history
* General code cleanup
* `NimBLEScan::start` will no longer clear cache or results if scanning is already in progress.
* `NimBLEScan::clearResults` will now reset the vector capacity to 0.
* `NimBLEScan::stop` will no longer call the `onScanEnd` callback as the caller should know its been stopped when this is called.
* `NimBLEScan::clearDuplicateCache` has been removed as it was problematic and only for the esp32. Stop and start the scanner for the same effect.
* `NimBLEScan::start` takes a new bool parameter `restart`, default `true`, that will restart an already in progress scan and clear the duplicate filter so all devices will be discovered again.
* Scan response data that is received without advertisement first will now create the device and send a callback.
* Added new method: `NimBLEAdvertisedDevice::isScannable()` that returns true if the device is scannable.
* Added default callbacks for `NimBLEScanCallbacks`
* `NimBLEScanCallbacks` function signatures updated:
* - `onDiscovered` now takes a `const NimBLEAdvertisedDevice*`
* - `onResult` now takes a `const NimBLEAdvertisedDevice*`
* - `onScanEnd` now takes a `const NimBLEScanResults&` and `int reason`
* Added new erase overload: `NimBLEScan::erase(const NimBLEAdvertisedDevice* device)`
* `NimBLEScanResults::getDevice` methods now return `const NimBLEAdvertisedDevice*`
* `NimBLEScanResults` iterators are now `const_iterator`
  • Loading branch information
h2zero committed Nov 21, 2024
1 parent b719a39 commit 6ac6241
Show file tree
Hide file tree
Showing 12 changed files with 299 additions and 354 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#define SERVICE_UUID "ABCD"
#define CHARACTERISTIC_UUID "1234"

static NimBLEAdvertisedDevice* advDevice;
static const NimBLEAdvertisedDevice* advDevice;
static bool doConnect = false;
static uint32_t scanTime = 10 * 1000; // In milliseconds, 0 = scan forever

Expand All @@ -40,7 +40,7 @@ class ClientCallbacks : public NimBLEClientCallbacks {
/* Define a class to handle the callbacks when advertisements are received */
class scanCallbacks: public NimBLEScanCallbacks {

void onResult(NimBLEAdvertisedDevice* advertisedDevice) {
void onResult(const NimBLEAdvertisedDevice* advertisedDevice) {
Serial.printf("Advertised Device found: %s\n", advertisedDevice->toString().c_str());
if(advertisedDevice->isAdvertisingService(NimBLEUUID("ABCD")))
{
Expand All @@ -55,8 +55,8 @@ class scanCallbacks: public NimBLEScanCallbacks {
}

/** Callback to process the results of the completed scan or restart it */
void onScanEnd(NimBLEScanResults results) {
Serial.println("Scan Ended");
void onScanEnd(const NimBLEScanResults& results, int reason) {
Serial.print("Scan Ended; reason = "); Serial.println(reason);
}
};

Expand Down
6 changes: 3 additions & 3 deletions examples/NimBLE_Async_Client/NimBLE_Async_Client.ino
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class ClientCallbacks : public NimBLEClientCallbacks {
} clientCB;

class scanCallbacks : public NimBLEScanCallbacks {
void onResult(NimBLEAdvertisedDevice* advertisedDevice) {
void onResult(const NimBLEAdvertisedDevice* advertisedDevice) {
Serial.printf("Advertised Device found: %s\n", advertisedDevice->toString().c_str());
if (advertisedDevice->haveName() && advertisedDevice->getName() == "NimBLE-Server") {
Serial.println("Found Our Device");
Expand All @@ -48,8 +48,8 @@ class scanCallbacks : public NimBLEScanCallbacks {
}
}

void onScanEnd(NimBLEScanResults results) {
Serial.println("Scan Ended");
void onScanEnd(const NimBLEScanResults& results, int reason) {
Serial.print("Scan Ended; reason = "); Serial.println(reason);
NimBLEDevice::getScan()->start(scanTimeMs);
}
};
Expand Down
8 changes: 4 additions & 4 deletions examples/NimBLE_Client/NimBLE_Client.ino
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

#include <NimBLEDevice.h>

static NimBLEAdvertisedDevice* advDevice;
static const NimBLEAdvertisedDevice* advDevice;

static bool doConnect = false;
static uint32_t scanTime = 0 * 1000; // In milliseconds, 0 = scan forever
Expand Down Expand Up @@ -85,7 +85,7 @@ class ClientCallbacks : public NimBLEClientCallbacks {
/** Define a class to handle the callbacks when advertisments are received */
class scanCallbacks: public NimBLEScanCallbacks {

void onResult(NimBLEAdvertisedDevice* advertisedDevice) {
void onResult(const NimBLEAdvertisedDevice* advertisedDevice) {
Serial.print("Advertised Device found: ");
Serial.println(advertisedDevice->toString().c_str());
if(advertisedDevice->isAdvertisingService(NimBLEUUID("DEAD")))
Expand All @@ -101,8 +101,8 @@ class scanCallbacks: public NimBLEScanCallbacks {
}

/** Callback to process the results of the completed scan or restart it */
void onScanEnd(NimBLEScanResults results) {
Serial.println("Scan Ended");
void onScanEnd(const NimBLEScanResults& results, int reason) {
Serial.print("Scan Ended; reason = "); Serial.println(reason);
}
};

Expand Down
90 changes: 34 additions & 56 deletions examples/NimBLE_Scan_Continuous/NimBLE_Scan_Continuous.ino
Original file line number Diff line number Diff line change
@@ -1,71 +1,49 @@
/** Example of continuous scanning for BLE advertisements.
* This example will scan forever while consuming as few resources as possible
* and report all advertisments on the serial monitor.
/**
* Continuous Scan Example
*
* This example demonstrates how to continuously scan for BLE devices.
* When devices are found the onDiscovered and onResults callbacks will be called with the device data.
* The scan will not store the results, only the callbacks will be used
* When the scan timeout is reached the onScanEnd callback will be called and the scan will be restarted.
* This will clear the duplicate cache in the controller and allow the same devices to be reported again.
*
* Created: on January 31 2021
* Author: H2zero
*
*/

#include "NimBLEDevice.h"

NimBLEScan* pBLEScan;
static constexpr uint32_t scanTime = 30 * 1000; // 30 seconds scan time.

class scanCallbacks: public NimBLEScanCallbacks {
void onResult(NimBLEAdvertisedDevice* advertisedDevice) {
Serial.printf("Advertised Device: %s \n", advertisedDevice->toString().c_str());
class scanCallbacks : public NimBLEScanCallbacks {
// Initial discovery, advertisement data only.
void onDiscovered(const NimBLEAdvertisedDevice* advertisedDevice) override {
Serial.printf("Discovered Device: %s\n", advertisedDevice->toString().c_str());
}
};

void setup() {
Serial.begin(115200);
Serial.println("Scanning...");

/** *Optional* Sets the filtering mode used by the scanner in the BLE controller.
*
* Can be one of:
* CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE (0) (default)
* Filter by device address only, advertisements from the same address will be reported only once.
*
* CONFIG_BTDM_SCAN_DUPL_TYPE_DATA (1)
* Filter by data only, advertisements with the same data will only be reported once,
* even from different addresses.
*
* CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE (2)
* Filter by address and data, advertisements from the same address will be reported only once,
* except if the data in the advertisement has changed, then it will be reported again.
*
* Can only be used BEFORE calling NimBLEDevice::init.
*/
NimBLEDevice::setScanFilterMode(CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE);

/** *Optional* Sets the scan filter cache size in the BLE controller.
* When the number of duplicate advertisements seen by the controller
* reaches this value it will clear the cache and start reporting previously
* seen devices. The larger this number, the longer time between repeated
* device reports. Range 10 - 1000. (default 20)
*
* Can only be used BEFORE calling NimBLEDevice::init.
*/
NimBLEDevice::setScanDuplicateCacheSize(200);
// If active scanning the result here will have the scan response data.
// If not active scanning then this will be the same as onDiscovered.
void onResult(const NimBLEAdvertisedDevice* advertisedDevice) override {
Serial.printf("Device result: %s\n", advertisedDevice->toString().c_str());
}

NimBLEDevice::init("");
void onScanEnd(const NimBLEScanResults& results, int reason) override {
Serial.printf("Scan ended reason = %d; restarting scan\n", reason);
NimBLEDevice::getScan()->start(scanTime, false, true);
}
} scanCallbacks; // create a callback class instance.

pBLEScan = NimBLEDevice::getScan(); //create new scan
// Set the callback for when devices are discovered, no duplicates.
pBLEScan->setScanCallbacks(new scanCallbacks(), false);
pBLEScan->setActiveScan(true); // Set active scanning, this will get more data from the advertiser.
pBLEScan->setInterval(97); // How often the scan occurs / switches channels; in milliseconds,
pBLEScan->setWindow(37); // How long to scan during the interval; in milliseconds.
pBLEScan->setMaxResults(0); // do not store the scan results, use callback only.
void setup() {
Serial.begin(115200);
NimBLEDevice::init(""); // Initialize the device, you can specify a device name if you want.
NimBLEScan* pBLEScan = NimBLEDevice::getScan(); // Create the scan object.
pBLEScan->setScanCallbacks(&scanCallbacks, false); // Set the callback for when devices are discovered, no duplicates.
pBLEScan->setActiveScan(true); // Set active scanning, this will get more data from the advertiser.
pBLEScan->setMaxResults(0); // Do not store the scan results, use callback only.
pBLEScan->start(scanTime, false, true); // duration, not a continuation of last scan, restart to get all devices again.
Serial.println("Scanning...");
}

void loop() {
// If an error occurs that stops the scan, it will be restarted here.
if(pBLEScan->isScanning() == false) {
// Start scan with: duration = 0 seconds(forever), no scan end callback, not a continuation of a previous scan.
pBLEScan->start(0, false);
}

delay(2000);
}
delay(2000);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ bool active = false;

class scanCallbacks: public NimBLEScanCallbacks {

void onDiscovered(NimBLEAdvertisedDevice* advertisedDevice) {
void onDiscovered(const NimBLEAdvertisedDevice* advertisedDevice) {
Serial.printf("Discovered Advertised Device: %s \n", advertisedDevice->toString().c_str());
}

void onResult(NimBLEAdvertisedDevice* advertisedDevice) {
void onResult(const NimBLEAdvertisedDevice* advertisedDevice) {
Serial.printf("Advertised Device Result: %s \n", advertisedDevice->toString().c_str());
}

void onScanEnd(NimBLEScanResults results){
Serial.println("Scan Ended");
void onScanEnd(const NimBLEScanResults& results, int reason) {
Serial.print("Scan Ended; reason = "); Serial.println(reason);
active = !active;
pBLEScan->setActiveScan(active);
Serial.printf("scan start, active = %u\n", active);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;
static BLEAdvertisedDevice* myDevice;
/* const required now */
/* static BLEAdvertisedDevice* myDevice;*/
static const BLEAdvertisedDevice* myDevice;

static void notifyCallback(
BLERemoteCharacteristic* pBLERemoteCharacteristic,
Expand Down Expand Up @@ -128,9 +130,9 @@ class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
* Called for each advertising BLE server.
*/

/*** Only a reference to the advertised device is passed now
/*** Only a const pointer to the advertised device is passed now
void onResult(BLEAdvertisedDevice advertisedDevice) { **/
void onResult(BLEAdvertisedDevice* advertisedDevice) {
void onResult(const BLEAdvertisedDevice* advertisedDevice) {
Serial.print("BLE Advertised Device found: ");
Serial.println(advertisedDevice->toString().c_str());

Expand Down
4 changes: 2 additions & 2 deletions examples/Refactored_original_examples/BLE_scan/BLE_scan.ino
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ int scanTime = 5 * 1000; // In milliseconds, 0 = scan forever
BLEScan* pBLEScan;

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
/*** Only a reference to the advertised device is passed now
/*** Only a const pointer to the advertised device is passed now
void onResult(BLEAdvertisedDevice advertisedDevice) { **/
void onResult(BLEAdvertisedDevice* advertisedDevice) {
void onResult(const BLEAdvertisedDevice* advertisedDevice) {
/** Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str()); **/
Serial.printf("Advertised Device: %s \n", advertisedDevice->toString().c_str());
}
Expand Down
8 changes: 8 additions & 0 deletions src/NimBLEAdvertisedDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,14 @@ bool NimBLEAdvertisedDevice::isConnectable() const {
return (m_advType & BLE_HCI_ADV_CONN_MASK) || (m_advType & BLE_HCI_ADV_DIRECT_MASK);
} // isConnectable

/**
* @brief Check if this device is advertising as scannable.
* @return True if the device is scannable.
*/
bool NimBLEAdvertisedDevice::isScannable() const {
return isLegacyAdvertisement() && (m_advType == BLE_HCI_ADV_TYPE_ADV_IND || m_advType == BLE_HCI_ADV_TYPE_ADV_SCAN_IND);
} // isScannable

/**
* @brief Check if this advertisement is a legacy or extended type
* @return True if legacy (Bluetooth 4.x), false if extended (bluetooth 5.x).
Expand Down
1 change: 1 addition & 0 deletions src/NimBLEAdvertisedDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class NimBLEAdvertisedDevice {
bool haveType(uint16_t type) const;
std::string toString() const;
bool isConnectable() const;
bool isScannable() const;
bool isLegacyAdvertisement() const;
# if CONFIG_BT_NIMBLE_EXT_ADV
uint8_t getSetId() const;
Expand Down
10 changes: 1 addition & 9 deletions src/NimBLEDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -723,15 +723,7 @@ void NimBLEDevice::onReset(int reason) {

m_synced = false;

NIMBLE_LOGE(LOG_TAG, "Resetting state; reason=%d, %s", reason, NimBLEUtils::returnCodeToString(reason));

# if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
if (m_initialized) {
if (m_pScan != nullptr) {
m_pScan->onHostReset();
}
}
# endif
NIMBLE_LOGE(LOG_TAG, "Host reset; reason=%d, %s", reason, NimBLEUtils::returnCodeToString(reason));
} // onReset

/**
Expand Down
Loading

0 comments on commit 6ac6241

Please sign in to comment.