mirror of
https://github.com/h2zero/esp-nimble-cpp.git
synced 2024-11-22 21:20:55 +01:00
[BREAKING] - Refactor NimBLEScan
* 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`
This commit is contained in:
parent
5f2730de02
commit
2151386057
14 changed files with 318 additions and 290 deletions
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
|
@ -22,11 +22,7 @@ jobs:
|
||||||
example:
|
example:
|
||||||
- Advanced/NimBLE_Client
|
- Advanced/NimBLE_Client
|
||||||
- Advanced/NimBLE_Server
|
- Advanced/NimBLE_Server
|
||||||
- basic/BLE_client
|
- Continuous_scan
|
||||||
- basic/BLE_notify
|
|
||||||
- basic/BLE_scan
|
|
||||||
- basic/BLE_server
|
|
||||||
- basic/BLE_uart
|
|
||||||
- Bluetooth_5/NimBLE_extended_client
|
- Bluetooth_5/NimBLE_extended_client
|
||||||
- Bluetooth_5/NimBLE_extended_server
|
- Bluetooth_5/NimBLE_extended_server
|
||||||
- Bluetooth_5/NimBLE_multi_advertiser
|
- Bluetooth_5/NimBLE_multi_advertiser
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
extern "C" {void app_main(void);}
|
extern "C" {void app_main(void);}
|
||||||
|
|
||||||
static NimBLEAdvertisedDevice* advDevice;
|
static const NimBLEAdvertisedDevice* advDevice;
|
||||||
|
|
||||||
static bool doConnect = false;
|
static bool doConnect = false;
|
||||||
static uint32_t scanTime = 0; /** scan time in milliseconds, 0 = scan forever */
|
static uint32_t scanTime = 0; /** scan time in milliseconds, 0 = scan forever */
|
||||||
|
@ -67,7 +67,7 @@ class ClientCallbacks : public NimBLEClientCallbacks {
|
||||||
|
|
||||||
/** Define a class to handle the callbacks when advertisments are received */
|
/** Define a class to handle the callbacks when advertisments are received */
|
||||||
class scanCallbacks: public NimBLEScanCallbacks {
|
class scanCallbacks: public NimBLEScanCallbacks {
|
||||||
void onResult(NimBLEAdvertisedDevice* advertisedDevice) {
|
void onResult(const NimBLEAdvertisedDevice* advertisedDevice) {
|
||||||
printf("Advertised Device found: %s\n", advertisedDevice->toString().c_str());
|
printf("Advertised Device found: %s\n", advertisedDevice->toString().c_str());
|
||||||
if(advertisedDevice->isAdvertisingService(NimBLEUUID("DEAD")))
|
if(advertisedDevice->isAdvertisingService(NimBLEUUID("DEAD")))
|
||||||
{
|
{
|
||||||
|
@ -82,8 +82,8 @@ class scanCallbacks: public NimBLEScanCallbacks {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Callback to process the results of the completed scan or restart it */
|
/** Callback to process the results of the completed scan or restart it */
|
||||||
void onScanEnd(NimBLEScanResults results) {
|
void onScanEnd(const NimBLEScanResults& results, int reason) {
|
||||||
printf("Scan Ended\n");
|
printf("Scan Ended, reason: %d, device count: %d\n", reason, results.getCount());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
6
examples/Continuous_scan/CMakeLists.txt
Normal file
6
examples/Continuous_scan/CMakeLists.txt
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# 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.5)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
project(Continuous_scan)
|
4
examples/Continuous_scan/main/CMakeLists.txt
Normal file
4
examples/Continuous_scan/main/CMakeLists.txt
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
set(COMPONENT_SRCS "main.cpp")
|
||||||
|
set(COMPONENT_ADD_INCLUDEDIRS ".")
|
||||||
|
|
||||||
|
register_component()
|
45
examples/Continuous_scan/main/main.cpp
Normal file
45
examples/Continuous_scan/main/main.cpp
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/**
|
||||||
|
* 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 March 24 2020
|
||||||
|
* Author: H2zero
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "NimBLEDevice.h"
|
||||||
|
|
||||||
|
static constexpr uint32_t scanTime = 30 * 1000; // 30 seconds scan time.
|
||||||
|
|
||||||
|
class scanCallbacks : public NimBLEScanCallbacks {
|
||||||
|
// Initial discovery, advertisement data only.
|
||||||
|
void onDiscovered(const NimBLEAdvertisedDevice* advertisedDevice) override {
|
||||||
|
printf("Discovered Device: %s\n", advertisedDevice->toString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
printf("Device result: %s\n", advertisedDevice->toString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void onScanEnd(const NimBLEScanResults& results, int reason) override {
|
||||||
|
printf("Scan ended reason = %d; restarting scan\n", reason);
|
||||||
|
NimBLEDevice::getScan()->start(scanTime, false, true);
|
||||||
|
}
|
||||||
|
} scanCallbacks; // create a callback class instance.
|
||||||
|
|
||||||
|
extern "C" void app_main() {
|
||||||
|
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.
|
||||||
|
printf("Scanning...\n");
|
||||||
|
}
|
12
examples/Continuous_scan/sdkconfig.defaults
Normal file
12
examples/Continuous_scan/sdkconfig.defaults
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# Override some defaults so BT stack is enabled
|
||||||
|
# in this example
|
||||||
|
|
||||||
|
#
|
||||||
|
# BT config
|
||||||
|
#
|
||||||
|
CONFIG_BT_ENABLED=y
|
||||||
|
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
|
||||||
|
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
|
||||||
|
CONFIG_BTDM_CTRL_MODE_BTDM=n
|
||||||
|
CONFIG_BT_BLUEDROID_ENABLED=n
|
||||||
|
CONFIG_BT_NIMBLE_ENABLED=y
|
|
@ -25,7 +25,7 @@ class ClientCallbacks : public NimBLEClientCallbacks {
|
||||||
} clientCB;
|
} clientCB;
|
||||||
|
|
||||||
class scanCallbacks : public NimBLEScanCallbacks {
|
class scanCallbacks : public NimBLEScanCallbacks {
|
||||||
void onResult(NimBLEAdvertisedDevice* advertisedDevice) {
|
void onResult(const NimBLEAdvertisedDevice* advertisedDevice) {
|
||||||
printf("Advertised Device found: %s\n", advertisedDevice->toString().c_str());
|
printf("Advertised Device found: %s\n", advertisedDevice->toString().c_str());
|
||||||
if (advertisedDevice->haveName() && advertisedDevice->getName() == "NimBLE-Server") {
|
if (advertisedDevice->haveName() && advertisedDevice->getName() == "NimBLE-Server") {
|
||||||
printf("Found Our Device\n");
|
printf("Found Our Device\n");
|
||||||
|
|
|
@ -24,7 +24,7 @@ static bool doConnect = false;
|
||||||
static bool connected = false;
|
static bool connected = false;
|
||||||
static bool doScan = false;
|
static bool doScan = false;
|
||||||
static BLERemoteCharacteristic* pRemoteCharacteristic;
|
static BLERemoteCharacteristic* pRemoteCharacteristic;
|
||||||
static BLEAdvertisedDevice* myDevice;
|
static const BLEAdvertisedDevice* myDevice;
|
||||||
|
|
||||||
static void notifyCallback(
|
static void notifyCallback(
|
||||||
BLERemoteCharacteristic* pBLERemoteCharacteristic,
|
BLERemoteCharacteristic* pBLERemoteCharacteristic,
|
||||||
|
@ -137,7 +137,7 @@ class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
|
||||||
|
|
||||||
/*** Only a reference to the advertised device is passed now
|
/*** Only a reference to the advertised device is passed now
|
||||||
void onResult(BLEAdvertisedDevice advertisedDevice) { **/
|
void onResult(BLEAdvertisedDevice advertisedDevice) { **/
|
||||||
void onResult(BLEAdvertisedDevice* advertisedDevice) {
|
void onResult(const BLEAdvertisedDevice* advertisedDevice) {
|
||||||
printf("BLE Advertised Device found: %s\n", advertisedDevice->toString().c_str());
|
printf("BLE Advertised Device found: %s\n", advertisedDevice->toString().c_str());
|
||||||
|
|
||||||
// We have found a device, let us now see if it contains the service we are looking for.
|
// We have found a device, let us now see if it contains the service we are looking for.
|
||||||
|
|
|
@ -21,7 +21,7 @@ int scanTime = 5 * 1000; // In milliseconds, 0 = scan forever
|
||||||
BLEScan* pBLEScan;
|
BLEScan* pBLEScan;
|
||||||
|
|
||||||
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
|
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
|
||||||
void onResult(BLEAdvertisedDevice* advertisedDevice) {
|
void onResult(const BLEAdvertisedDevice* advertisedDevice) {
|
||||||
printf("Advertised Device: %s \n", advertisedDevice->toString().c_str());
|
printf("Advertised Device: %s \n", advertisedDevice->toString().c_str());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -757,6 +757,14 @@ bool NimBLEAdvertisedDevice::isConnectable() const {
|
||||||
return (m_advType & BLE_HCI_ADV_CONN_MASK) || (m_advType & BLE_HCI_ADV_DIRECT_MASK);
|
return (m_advType & BLE_HCI_ADV_CONN_MASK) || (m_advType & BLE_HCI_ADV_DIRECT_MASK);
|
||||||
} // isConnectable
|
} // 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
|
* @brief Check if this advertisement is a legacy or extended type
|
||||||
* @return True if legacy (Bluetooth 4.x), false if extended (bluetooth 5.x).
|
* @return True if legacy (Bluetooth 4.x), false if extended (bluetooth 5.x).
|
||||||
|
|
|
@ -82,6 +82,7 @@ class NimBLEAdvertisedDevice {
|
||||||
bool haveType(uint16_t type) const;
|
bool haveType(uint16_t type) const;
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
bool isConnectable() const;
|
bool isConnectable() const;
|
||||||
|
bool isScannable() const;
|
||||||
bool isLegacyAdvertisement() const;
|
bool isLegacyAdvertisement() const;
|
||||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
uint8_t getSetId() const;
|
uint8_t getSetId() const;
|
||||||
|
|
|
@ -723,15 +723,7 @@ void NimBLEDevice::onReset(int reason) {
|
||||||
|
|
||||||
m_synced = false;
|
m_synced = false;
|
||||||
|
|
||||||
NIMBLE_LOGE(LOG_TAG, "Resetting state; reason=%d, %s", reason, NimBLEUtils::returnCodeToString(reason));
|
NIMBLE_LOGE(LOG_TAG, "Host reset; 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
|
|
||||||
} // onReset
|
} // onReset
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -15,33 +15,26 @@
|
||||||
#include "nimconfig.h"
|
#include "nimconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
|
|
||||||
#include "NimBLEScan.h"
|
# include "NimBLEScan.h"
|
||||||
#include "NimBLEDevice.h"
|
# include "NimBLEDevice.h"
|
||||||
#include "NimBLELog.h"
|
# include "NimBLELog.h"
|
||||||
|
|
||||||
#include <string>
|
# include <string>
|
||||||
#include <climits>
|
# include <climits>
|
||||||
|
|
||||||
static const char* LOG_TAG = "NimBLEScan";
|
static const char* LOG_TAG = "NimBLEScan";
|
||||||
|
static NimBLEScanCallbacks defaultScanCallbacks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Scan constuctor.
|
* @brief Scan constructor.
|
||||||
*/
|
*/
|
||||||
NimBLEScan::NimBLEScan() {
|
NimBLEScan::NimBLEScan()
|
||||||
m_scan_params.filter_policy = BLE_HCI_SCAN_FILT_NO_WL;
|
: m_pScanCallbacks{&defaultScanCallbacks},
|
||||||
m_scan_params.passive = 1; // If set, don’t send scan requests to advertisers (i.e., don’t request additional advertising data).
|
// default interval + window, no whitelist scan filter,not limited scan, no scan response, filter_duplicates
|
||||||
m_scan_params.itvl = 0; // This is defined as the time interval from when the Controller started its last LE scan until it begins the subsequent LE scan. (units=0.625 msec)
|
m_scanParams{0, 0, BLE_HCI_SCAN_FILT_NO_WL, 0, 1, 1},
|
||||||
m_scan_params.window = 0; // The duration of the LE scan. LE_Scan_Window shall be less than or equal to LE_Scan_Interval (units=0.625 msec)
|
m_duration{BLE_HS_FOREVER},
|
||||||
m_scan_params.limited = 0; // If set, only discover devices in limited discoverable mode.
|
m_pTaskData{nullptr},
|
||||||
m_scan_params.filter_duplicates = 1; // If set, the controller ignores all but the first advertisement from each device.
|
m_maxResults{0xFF} {}
|
||||||
m_pScanCallbacks = nullptr;
|
|
||||||
m_ignoreResults = false;
|
|
||||||
m_pTaskData = nullptr;
|
|
||||||
m_duration = BLE_HS_FOREVER; // make sure this is non-zero in the event of a host reset
|
|
||||||
m_maxResults = 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Scan destructor, release any allocated resources.
|
* @brief Scan destructor, release any allocated resources.
|
||||||
|
@ -55,32 +48,26 @@ NimBLEScan::~NimBLEScan() {
|
||||||
* @param [in] event The event type for this event.
|
* @param [in] event The event type for this event.
|
||||||
* @param [in] param Parameter data for this event.
|
* @param [in] param Parameter data for this event.
|
||||||
*/
|
*/
|
||||||
/*STATIC*/
|
|
||||||
int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
|
int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
|
||||||
(void)arg;
|
(void)arg;
|
||||||
NimBLEScan* pScan = NimBLEDevice::getScan();
|
NimBLEScan* pScan = NimBLEDevice::getScan();
|
||||||
|
|
||||||
switch(event->type) {
|
switch (event->type) {
|
||||||
|
|
||||||
case BLE_GAP_EVENT_EXT_DISC:
|
case BLE_GAP_EVENT_EXT_DISC:
|
||||||
case BLE_GAP_EVENT_DISC: {
|
case BLE_GAP_EVENT_DISC: {
|
||||||
if(pScan->m_ignoreResults) {
|
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
NIMBLE_LOGI(LOG_TAG, "Scan op in progress - ignoring results");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
|
||||||
const auto& disc = event->ext_disc;
|
const auto& disc = event->ext_disc;
|
||||||
const bool isLegacyAdv = disc.props & BLE_HCI_ADV_LEGACY_MASK;
|
const bool isLegacyAdv = disc.props & BLE_HCI_ADV_LEGACY_MASK;
|
||||||
const auto event_type = isLegacyAdv ? disc.legacy_event_type : disc.props;
|
const auto event_type = isLegacyAdv ? disc.legacy_event_type : disc.props;
|
||||||
#else
|
# else
|
||||||
const auto& disc = event->disc;
|
const auto& disc = event->disc;
|
||||||
const bool isLegacyAdv = true;
|
const bool isLegacyAdv = true;
|
||||||
const auto event_type = disc.event_type;
|
const auto event_type = disc.event_type;
|
||||||
#endif
|
# endif
|
||||||
NimBLEAddress advertisedAddress(disc.addr);
|
NimBLEAddress advertisedAddress(disc.addr);
|
||||||
|
|
||||||
// Examine our list of ignored addresses and stop processing if we don't want to see it or are already connected
|
// stop processing if we don't want to see it or are already connected
|
||||||
if(NimBLEDevice::isIgnored(advertisedAddress)) {
|
if (NimBLEDevice::isIgnored(advertisedAddress)) {
|
||||||
NIMBLE_LOGI(LOG_TAG, "Ignoring device: address: %s", advertisedAddress.toString().c_str());
|
NIMBLE_LOGI(LOG_TAG, "Ignoring device: address: %s", advertisedAddress.toString().c_str());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -88,85 +75,79 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
|
||||||
NimBLEAdvertisedDevice* advertisedDevice = nullptr;
|
NimBLEAdvertisedDevice* advertisedDevice = nullptr;
|
||||||
|
|
||||||
// If we've seen this device before get a pointer to it from the vector
|
// If we've seen this device before get a pointer to it from the vector
|
||||||
for(auto &it: pScan->m_scanResults.m_advertisedDevicesVector) {
|
for (const auto& dev : pScan->m_scanResults.m_deviceVec) {
|
||||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
// Same address but different set ID should create a new advertised device.
|
// Same address but different set ID should create a new advertised device.
|
||||||
if (it->getAddress() == advertisedAddress && it->getSetId() == disc.sid) {
|
if (dev->getAddress() == advertisedAddress && dev->getSetId() == disc.sid)
|
||||||
#else
|
# else
|
||||||
if (it->getAddress() == advertisedAddress) {
|
if (dev->getAddress() == advertisedAddress)
|
||||||
#endif
|
# endif
|
||||||
advertisedDevice = it;
|
{
|
||||||
|
advertisedDevice = dev;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we haven't seen this device before; create a new instance and insert it in the vector.
|
// If we haven't seen this device before; create a new instance and insert it in the vector.
|
||||||
// Otherwise just update the relevant parameters of the already known device.
|
// Otherwise just update the relevant parameters of the already known device.
|
||||||
if (advertisedDevice == nullptr &&
|
if (advertisedDevice == nullptr) {
|
||||||
(!isLegacyAdv || event_type != BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP)) {
|
|
||||||
// Check if we have reach the scan results limit, ignore this one if so.
|
// Check if we have reach the scan results limit, ignore this one if so.
|
||||||
// We still need to store each device when maxResults is 0 to be able to append the scan results
|
// We still need to store each device when maxResults is 0 to be able to append the scan results
|
||||||
if (pScan->m_maxResults > 0 && pScan->m_maxResults < 0xFF &&
|
if (pScan->m_maxResults > 0 && pScan->m_maxResults < 0xFF &&
|
||||||
(pScan->m_scanResults.m_advertisedDevicesVector.size() >= pScan->m_maxResults)) {
|
(pScan->m_scanResults.m_deviceVec.size() >= pScan->m_maxResults)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isLegacyAdv && event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
|
||||||
|
NIMBLE_LOGI(LOG_TAG, "Scan response without advertisement: %s", advertisedAddress.toString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
advertisedDevice = new NimBLEAdvertisedDevice(event, event_type);
|
advertisedDevice = new NimBLEAdvertisedDevice(event, event_type);
|
||||||
pScan->m_scanResults.m_advertisedDevicesVector.push_back(advertisedDevice);
|
pScan->m_scanResults.m_deviceVec.push_back(advertisedDevice);
|
||||||
NIMBLE_LOGI(LOG_TAG, "New advertiser: %s", advertisedAddress.toString().c_str());
|
NIMBLE_LOGI(LOG_TAG, "New advertiser: %s", advertisedAddress.toString().c_str());
|
||||||
} else if (advertisedDevice != nullptr) {
|
|
||||||
advertisedDevice->update(event, event_type);
|
|
||||||
NIMBLE_LOGI(LOG_TAG, "Updated advertiser: %s", advertisedAddress.toString().c_str());
|
|
||||||
} else {
|
} else {
|
||||||
// Scan response from unknown device
|
advertisedDevice->update(event, event_type);
|
||||||
return 0;
|
if (isLegacyAdv && event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
|
||||||
|
NIMBLE_LOGI(LOG_TAG, "Scan response from: %s", advertisedAddress.toString().c_str());
|
||||||
|
} else {
|
||||||
|
NIMBLE_LOGI(LOG_TAG, "Duplicate; updated: %s", advertisedAddress.toString().c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pScan->m_pScanCallbacks) {
|
if (!advertisedDevice->m_callbackSent) {
|
||||||
if (advertisedDevice->m_callbackSent == 0 || !pScan->m_scan_params.filter_duplicates) {
|
|
||||||
advertisedDevice->m_callbackSent = 1;
|
|
||||||
pScan->m_pScanCallbacks->onDiscovered(advertisedDevice);
|
pScan->m_pScanCallbacks->onDiscovered(advertisedDevice);
|
||||||
}
|
advertisedDevice->m_callbackSent++;
|
||||||
|
|
||||||
if (pScan->m_scan_params.filter_duplicates && advertisedDevice->m_callbackSent >= 2) {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not active scanning or scan response is not available
|
// If not active scanning or scan response is not available
|
||||||
// or extended advertisement scanning, report the result to the callback now.
|
// or extended advertisement scanning, report the result to the callback now.
|
||||||
if(pScan->m_scan_params.passive || !isLegacyAdv ||
|
if (pScan->m_scanParams.passive || !isLegacyAdv || !advertisedDevice->isScannable()) {
|
||||||
(advertisedDevice->getAdvType() != BLE_HCI_ADV_TYPE_ADV_IND &&
|
|
||||||
advertisedDevice->getAdvType() != BLE_HCI_ADV_TYPE_ADV_SCAN_IND))
|
|
||||||
{
|
|
||||||
advertisedDevice->m_callbackSent = 2;
|
|
||||||
pScan->m_pScanCallbacks->onResult(advertisedDevice);
|
pScan->m_pScanCallbacks->onResult(advertisedDevice);
|
||||||
|
advertisedDevice->m_callbackSent++;
|
||||||
// Otherwise, wait for the scan response so we can report the complete data.
|
|
||||||
} else if (isLegacyAdv && event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
|
} else if (isLegacyAdv && event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
|
||||||
advertisedDevice->m_callbackSent = 2;
|
// got the scan response report the full data.
|
||||||
pScan->m_pScanCallbacks->onResult(advertisedDevice);
|
pScan->m_pScanCallbacks->onResult(advertisedDevice);
|
||||||
|
advertisedDevice->m_callbackSent++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not storing results and we have invoked the callback, delete the device.
|
// If not storing results and we have invoked the callback, delete the device.
|
||||||
if(pScan->m_maxResults == 0 && advertisedDevice->m_callbackSent >= 2) {
|
if (pScan->m_maxResults == 0 && advertisedDevice->m_callbackSent >= 2) {
|
||||||
pScan->erase(advertisedAddress);
|
pScan->erase(advertisedDevice);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case BLE_GAP_EVENT_DISC_COMPLETE: {
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "discovery complete; reason=%d",
|
|
||||||
event->disc_complete.reason);
|
|
||||||
|
|
||||||
if(pScan->m_maxResults == 0) {
|
case BLE_GAP_EVENT_DISC_COMPLETE: {
|
||||||
|
NIMBLE_LOGD(LOG_TAG, "discovery complete; reason=%d", event->disc_complete.reason);
|
||||||
|
|
||||||
|
if (pScan->m_maxResults == 0) {
|
||||||
pScan->clearResults();
|
pScan->clearResults();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pScan->m_pScanCallbacks != nullptr) {
|
pScan->m_pScanCallbacks->onScanEnd(pScan->m_scanResults, event->disc_complete.reason);
|
||||||
pScan->m_pScanCallbacks->onScanEnd(pScan->m_scanResults);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(pScan->m_pTaskData != nullptr) {
|
if (pScan->m_pTaskData != nullptr) {
|
||||||
NimBLEUtils::taskRelease(*pScan->m_pTaskData, event->disc_complete.reason);
|
NimBLEUtils::taskRelease(*pScan->m_pTaskData, event->disc_complete.reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,8 +157,7 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} // gapEventHandler
|
} // handleGapEvent
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Should we perform an active or passive scan?
|
* @brief Should we perform an active or passive scan?
|
||||||
|
@ -185,10 +165,9 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
|
||||||
* @param [in] active If true, we perform an active scan otherwise a passive scan.
|
* @param [in] active If true, we perform an active scan otherwise a passive scan.
|
||||||
*/
|
*/
|
||||||
void NimBLEScan::setActiveScan(bool active) {
|
void NimBLEScan::setActiveScan(bool active) {
|
||||||
m_scan_params.passive = !active;
|
m_scanParams.passive = !active;
|
||||||
} // setActiveScan
|
} // setActiveScan
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set whether or not the BLE controller should only report results
|
* @brief Set whether or not the BLE controller should only report results
|
||||||
* from devices it has not already seen.
|
* from devices it has not already seen.
|
||||||
|
@ -197,20 +176,18 @@ void NimBLEScan::setActiveScan(bool active) {
|
||||||
* duplicate devices once the limit is reached.
|
* duplicate devices once the limit is reached.
|
||||||
*/
|
*/
|
||||||
void NimBLEScan::setDuplicateFilter(bool enabled) {
|
void NimBLEScan::setDuplicateFilter(bool enabled) {
|
||||||
m_scan_params.filter_duplicates = enabled;
|
m_scanParams.filter_duplicates = enabled;
|
||||||
} // setDuplicateFilter
|
} // setDuplicateFilter
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set whether or not the BLE controller only report scan results
|
* @brief Set whether or not the BLE controller only reports scan results
|
||||||
* from devices advertising in limited discovery mode, i.e. directed advertising.
|
* from devices advertising in limited discovery mode.
|
||||||
* @param [in] enabled If true, only limited discovery devices will be in scan results.
|
* @param [in] enabled If true, only limited discovery devices will be in scan results.
|
||||||
*/
|
*/
|
||||||
void NimBLEScan::setLimitedOnly(bool enabled) {
|
void NimBLEScan::setLimitedOnly(bool enabled) {
|
||||||
m_scan_params.limited = enabled;
|
m_scanParams.limited = enabled;
|
||||||
} // setLimited
|
} // setLimited
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the scan filter policy.
|
* @brief Sets the scan filter policy.
|
||||||
* @param [in] filter Can be one of:
|
* @param [in] filter Can be one of:
|
||||||
|
@ -230,10 +207,9 @@ void NimBLEScan::setLimitedOnly(bool enabled) {
|
||||||
* resolvable private address.
|
* resolvable private address.
|
||||||
*/
|
*/
|
||||||
void NimBLEScan::setFilterPolicy(uint8_t filter) {
|
void NimBLEScan::setFilterPolicy(uint8_t filter) {
|
||||||
m_scan_params.filter_policy = filter;
|
m_scanParams.filter_policy = filter;
|
||||||
} // setFilterPolicy
|
} // setFilterPolicy
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the max number of results to store.
|
* @brief Sets the max number of results to store.
|
||||||
* @param [in] maxResults The number of results to limit storage to\n
|
* @param [in] maxResults The number of results to limit storage to\n
|
||||||
|
@ -243,36 +219,36 @@ void NimBLEScan::setMaxResults(uint8_t maxResults) {
|
||||||
m_maxResults = maxResults;
|
m_maxResults = maxResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the call backs to be invoked.
|
* @brief Set the call backs to be invoked.
|
||||||
* @param [in] pScanCallbacks Call backs to be invoked.
|
* @param [in] pScanCallbacks Call backs to be invoked.
|
||||||
* @param [in] wantDuplicates True if we wish to be called back with duplicates. Default is false.
|
* @param [in] wantDuplicates True if we wish to be called back with duplicates, default: false.
|
||||||
*/
|
*/
|
||||||
void NimBLEScan::setScanCallbacks(NimBLEScanCallbacks* pScanCallbacks, bool wantDuplicates) {
|
void NimBLEScan::setScanCallbacks(NimBLEScanCallbacks* pScanCallbacks, bool wantDuplicates) {
|
||||||
setDuplicateFilter(!wantDuplicates);
|
setDuplicateFilter(!wantDuplicates);
|
||||||
|
if (pScanCallbacks == nullptr) {
|
||||||
|
m_pScanCallbacks = &defaultScanCallbacks;
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_pScanCallbacks = pScanCallbacks;
|
m_pScanCallbacks = pScanCallbacks;
|
||||||
} // setScanCallbacks
|
} // setScanCallbacks
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the interval to scan.
|
* @brief Set the interval to scan.
|
||||||
* @param [in] intervalMSecs The scan interval (how often) in milliseconds.
|
* @param [in] intervalMSecs The scan interval (how often) in milliseconds.
|
||||||
*/
|
*/
|
||||||
void NimBLEScan::setInterval(uint16_t intervalMSecs) {
|
void NimBLEScan::setInterval(uint16_t intervalMSecs) {
|
||||||
m_scan_params.itvl = intervalMSecs / 0.625;
|
m_scanParams.itvl = (intervalMSecs * 16) / 10;
|
||||||
} // setInterval
|
} // setInterval
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the window to actively scan.
|
* @brief Set the window to actively scan.
|
||||||
* @param [in] windowMSecs How long to actively scan.
|
* @param [in] windowMSecs How long during the interval to actively scan.
|
||||||
*/
|
*/
|
||||||
void NimBLEScan::setWindow(uint16_t windowMSecs) {
|
void NimBLEScan::setWindow(uint16_t windowMSecs) {
|
||||||
m_scan_params.window = windowMSecs / 0.625;
|
m_scanParams.window = (windowMSecs * 16) / 10;
|
||||||
} // setWindow
|
} // setWindow
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the status of the scanner.
|
* @brief Get the status of the scanner.
|
||||||
* @return true if scanning or scan starting.
|
* @return true if scanning or scan starting.
|
||||||
|
@ -281,14 +257,15 @@ bool NimBLEScan::isScanning() {
|
||||||
return ble_gap_disc_active();
|
return ble_gap_disc_active();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Start scanning.
|
* @brief Start scanning.
|
||||||
* @param [in] duration The duration in milliseconds for which to scan. 0 == scan forever.
|
* @param [in] duration The duration in milliseconds for which to scan. 0 == scan forever.
|
||||||
* @param [in] is_continue Set to true to save previous scan results, false to clear them.
|
* @param [in] isContinue Set to true to save previous scan results, false to clear them.
|
||||||
|
* @param [in] restart Set to true to restart the scan if already in progress.
|
||||||
|
* this is useful to clear the duplicate filter so all devices are reported again.
|
||||||
* @return True if scan started or false if there was an error.
|
* @return True if scan started or false if there was an error.
|
||||||
*/
|
*/
|
||||||
bool NimBLEScan::start(uint32_t duration, bool is_continue) {
|
bool NimBLEScan::start(uint32_t duration, bool isContinue, bool restart) {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> start: duration=%" PRIu32, duration);
|
NIMBLE_LOGD(LOG_TAG, ">> start: duration=%" PRIu32, duration);
|
||||||
|
|
||||||
if (ble_gap_conn_active()) {
|
if (ble_gap_conn_active()) {
|
||||||
|
@ -296,51 +273,52 @@ bool NimBLEScan::start(uint32_t duration, bool is_continue) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isScanning()) {
|
||||||
|
if (restart) {
|
||||||
|
NIMBLE_LOGI(LOG_TAG, "Scan already in progress, restarting it");
|
||||||
|
if (!stop()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NIMBLE_LOGI(LOG_TAG, "Scan already in progress");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isContinue) {
|
||||||
|
clearResults();
|
||||||
|
}
|
||||||
|
|
||||||
// Save the duration in the case that the host is reset so we can reuse it.
|
// Save the duration in the case that the host is reset so we can reuse it.
|
||||||
m_duration = duration;
|
m_duration = duration;
|
||||||
|
|
||||||
// If 0 duration specified then we assume a continuous scan is desired.
|
// If 0 duration specified then we assume a continuous scan is desired.
|
||||||
if(duration == 0){
|
if (duration == 0) {
|
||||||
duration = BLE_HS_FOREVER;
|
duration = BLE_HS_FOREVER;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the flag to ignore the results while we are deleting the vector
|
|
||||||
if(!is_continue) {
|
|
||||||
m_ignoreResults = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
ble_gap_ext_disc_params scan_params;
|
ble_gap_ext_disc_params scan_params;
|
||||||
scan_params.passive = m_scan_params.passive;
|
scan_params.passive = m_scanParams.passive;
|
||||||
scan_params.itvl = m_scan_params.itvl;
|
scan_params.itvl = m_scanParams.itvl;
|
||||||
scan_params.window = m_scan_params.window;
|
scan_params.window = m_scanParams.window;
|
||||||
int rc = ble_gap_ext_disc(NimBLEDevice::m_ownAddrType,
|
int rc = ble_gap_ext_disc(NimBLEDevice::m_ownAddrType,
|
||||||
duration/10,
|
duration / 10,
|
||||||
0,
|
0,
|
||||||
m_scan_params.filter_duplicates,
|
m_scanParams.filter_duplicates,
|
||||||
m_scan_params.filter_policy,
|
m_scanParams.filter_policy,
|
||||||
m_scan_params.limited,
|
m_scanParams.limited,
|
||||||
&scan_params,
|
&scan_params,
|
||||||
&scan_params,
|
&scan_params,
|
||||||
NimBLEScan::handleGapEvent,
|
NimBLEScan::handleGapEvent,
|
||||||
NULL);
|
NULL);
|
||||||
#else
|
# else
|
||||||
int rc = ble_gap_disc(NimBLEDevice::m_ownAddrType,
|
int rc = ble_gap_disc(NimBLEDevice::m_ownAddrType, duration, &m_scanParams, NimBLEScan::handleGapEvent, NULL);
|
||||||
duration,
|
# endif
|
||||||
&m_scan_params,
|
switch (rc) {
|
||||||
NimBLEScan::handleGapEvent,
|
|
||||||
NULL);
|
|
||||||
#endif
|
|
||||||
switch(rc) {
|
|
||||||
case 0:
|
case 0:
|
||||||
if(!is_continue) {
|
|
||||||
clearResults();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BLE_HS_EALREADY:
|
case BLE_HS_EALREADY:
|
||||||
// Clear the cache if already scanning in case an advertiser was missed.
|
NIMBLE_LOGD(LOG_TAG, "Scan started");
|
||||||
clearDuplicateCache();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BLE_HS_EBUSY:
|
case BLE_HS_EBUSY:
|
||||||
|
@ -355,21 +333,14 @@ bool NimBLEScan::start(uint32_t duration, bool is_continue) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
NIMBLE_LOGE(LOG_TAG, "Error initiating GAP discovery procedure; rc=%d, %s",
|
NIMBLE_LOGE(LOG_TAG, "Error starting scan; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
rc, NimBLEUtils::returnCodeToString(rc));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ignoreResults = false;
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< start()");
|
NIMBLE_LOGD(LOG_TAG, "<< start()");
|
||||||
|
return rc == 0 || rc == BLE_HS_EALREADY;
|
||||||
if(rc != 0 && rc != BLE_HS_EALREADY) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} // start
|
} // start
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stop an in progress scan.
|
* @brief Stop an in progress scan.
|
||||||
* @return True if successful.
|
* @return True if successful.
|
||||||
|
@ -383,15 +354,11 @@ bool NimBLEScan::stop() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_maxResults == 0) {
|
if (m_maxResults == 0) {
|
||||||
clearResults();
|
clearResults();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc != BLE_HS_EALREADY && m_pScanCallbacks != nullptr) {
|
if (m_pTaskData != nullptr) {
|
||||||
m_pScanCallbacks->onScanEnd(m_scanResults);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_pTaskData != nullptr) {
|
|
||||||
NimBLEUtils::taskRelease(*m_pTaskData);
|
NimBLEUtils::taskRelease(*m_pTaskData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -399,56 +366,46 @@ bool NimBLEScan::stop() {
|
||||||
return true;
|
return true;
|
||||||
} // stop
|
} // stop
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Clears the duplicate scan filter cache.
|
|
||||||
*/
|
|
||||||
void NimBLEScan::clearDuplicateCache() {
|
|
||||||
#ifdef CONFIG_IDF_TARGET_ESP32 // Not available for ESP32C3
|
|
||||||
esp_ble_scan_dupilcate_list_flush();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Delete peer device from the scan results vector.
|
* @brief Delete peer device from the scan results vector.
|
||||||
* @param [in] address The address of the device to delete from the results.
|
* @param [in] address The address of the device to delete from the results.
|
||||||
* @details After disconnecting, it may be required in the case we were connected to a device without a public address.
|
|
||||||
*/
|
*/
|
||||||
void NimBLEScan::erase(const NimBLEAddress &address) {
|
void NimBLEScan::erase(const NimBLEAddress& address) {
|
||||||
NIMBLE_LOGD(LOG_TAG, "erase device: %s", address.toString().c_str());
|
NIMBLE_LOGD(LOG_TAG, "erase device: %s", address.toString().c_str());
|
||||||
|
for (auto it = m_scanResults.m_deviceVec.begin(); it != m_scanResults.m_deviceVec.end(); ++it) {
|
||||||
for(auto it = m_scanResults.m_advertisedDevicesVector.begin(); it != m_scanResults.m_advertisedDevicesVector.end(); ++it) {
|
if ((*it)->getAddress() == address) {
|
||||||
if((*it)->getAddress() == address) {
|
|
||||||
delete *it;
|
delete *it;
|
||||||
m_scanResults.m_advertisedDevicesVector.erase(it);
|
m_scanResults.m_deviceVec.erase(it);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Called when host reset, we set a flag to stop scanning until synced.
|
* @brief Delete peer device from the scan results vector.
|
||||||
|
* @param [in] device The device to delete from the results.
|
||||||
*/
|
*/
|
||||||
void NimBLEScan::onHostReset() {
|
void NimBLEScan::erase(const NimBLEAdvertisedDevice* device) {
|
||||||
m_ignoreResults = true;
|
NIMBLE_LOGD(LOG_TAG, "erase device: %s", device->getAddress().toString().c_str());
|
||||||
|
for (auto it = m_scanResults.m_deviceVec.begin(); it != m_scanResults.m_deviceVec.end(); ++it) {
|
||||||
|
if ((*it) == device) {
|
||||||
|
delete *it;
|
||||||
|
m_scanResults.m_deviceVec.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief If the host reset and re-synced this is called.
|
* @brief If the host reset and re-synced this is called.
|
||||||
* If the application was scanning indefinitely with a callback, restart it.
|
* If the application was scanning indefinitely with a callback, restart it.
|
||||||
*/
|
*/
|
||||||
void NimBLEScan::onHostSync() {
|
void NimBLEScan::onHostSync() {
|
||||||
m_ignoreResults = false;
|
if (m_duration == 0 && m_pScanCallbacks != &defaultScanCallbacks) {
|
||||||
|
|
||||||
if(m_duration == 0 && m_pScanCallbacks != nullptr) {
|
|
||||||
start(0, false);
|
start(0, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Start scanning and block until scanning has been completed.
|
* @brief Start scanning and block until scanning has been completed.
|
||||||
* @param [in] duration The duration in milliseconds for which to scan.
|
* @param [in] duration The duration in milliseconds for which to scan.
|
||||||
|
@ -456,14 +413,19 @@ void NimBLEScan::onHostSync() {
|
||||||
* @return The scan results.
|
* @return The scan results.
|
||||||
*/
|
*/
|
||||||
NimBLEScanResults NimBLEScan::getResults(uint32_t duration, bool is_continue) {
|
NimBLEScanResults NimBLEScan::getResults(uint32_t duration, bool is_continue) {
|
||||||
if(duration == 0) {
|
if (duration == 0) {
|
||||||
NIMBLE_LOGW(LOG_TAG, "Blocking scan called with duration = forever");
|
NIMBLE_LOGW(LOG_TAG, "Blocking scan called with duration = forever");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_pTaskData != nullptr) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Scan already in progress");
|
||||||
|
return m_scanResults;
|
||||||
|
}
|
||||||
|
|
||||||
NimBLETaskData taskData;
|
NimBLETaskData taskData;
|
||||||
m_pTaskData = &taskData;
|
m_pTaskData = &taskData;
|
||||||
|
|
||||||
if(start(duration, is_continue)) {
|
if (start(duration, is_continue)) {
|
||||||
NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER);
|
NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,7 +433,6 @@ NimBLEScanResults NimBLEScan::getResults(uint32_t duration, bool is_continue) {
|
||||||
return m_scanResults;
|
return m_scanResults;
|
||||||
} // getResults
|
} // getResults
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the results of the scan.
|
* @brief Get the results of the scan.
|
||||||
* @return NimBLEScanResults object.
|
* @return NimBLEScanResults object.
|
||||||
|
@ -480,82 +441,87 @@ NimBLEScanResults NimBLEScan::getResults() {
|
||||||
return m_scanResults;
|
return m_scanResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Clear the results of the scan.
|
* @brief Clear the stored results of the scan.
|
||||||
*/
|
*/
|
||||||
void NimBLEScan::clearResults() {
|
void NimBLEScan::clearResults() {
|
||||||
for(auto &it: m_scanResults.m_advertisedDevicesVector) {
|
for (const auto& dev : m_scanResults.m_deviceVec) {
|
||||||
delete it;
|
delete dev;
|
||||||
}
|
}
|
||||||
m_scanResults.m_advertisedDevicesVector.clear();
|
std::vector<NimBLEAdvertisedDevice*>().swap(m_scanResults.m_deviceVec);
|
||||||
clearDuplicateCache();
|
} // clearResults
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Dump the scan results to the log.
|
* @brief Dump the scan results to the log.
|
||||||
*/
|
*/
|
||||||
void NimBLEScanResults::dump() {
|
void NimBLEScanResults::dump() const {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> Dump scan results:");
|
for (const auto& dev : m_deviceVec) {
|
||||||
for (int i=0; i<getCount(); i++) {
|
NIMBLE_LOGI(LOG_TAG, "- %s", dev->toString().c_str());
|
||||||
NIMBLE_LOGI(LOG_TAG, "- %s", getDevice(i).toString().c_str());
|
|
||||||
}
|
}
|
||||||
} // dump
|
} // dump
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the count of devices found in the last scan.
|
* @brief Get the count of devices found in the last scan.
|
||||||
* @return The number of devices found in the last scan.
|
* @return The number of devices found in the last scan.
|
||||||
*/
|
*/
|
||||||
int NimBLEScanResults::getCount() {
|
int NimBLEScanResults::getCount() const {
|
||||||
return m_advertisedDevicesVector.size();
|
return m_deviceVec.size();
|
||||||
} // getCount
|
} // getCount
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Return the specified device at the given index.
|
* @brief Return the specified device at the given index.
|
||||||
* The index should be between 0 and getCount()-1.
|
* The index should be between 0 and getCount()-1.
|
||||||
* @param [in] i The index of the device.
|
* @param [in] idx The index of the device.
|
||||||
* @return The device at the specified index.
|
* @return The device at the specified index.
|
||||||
*/
|
*/
|
||||||
NimBLEAdvertisedDevice NimBLEScanResults::getDevice(uint32_t i) {
|
const NimBLEAdvertisedDevice* NimBLEScanResults::getDevice(uint32_t idx) const {
|
||||||
return *m_advertisedDevicesVector[i];
|
return m_deviceVec[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get iterator to the beginning of the vector of advertised device pointers.
|
* @brief Get iterator to the beginning of the vector of advertised device pointers.
|
||||||
* @return An iterator to the beginning of the vector of advertised device pointers.
|
* @return An iterator to the beginning of the vector of advertised device pointers.
|
||||||
*/
|
*/
|
||||||
std::vector<NimBLEAdvertisedDevice*>::iterator NimBLEScanResults::begin() {
|
std::vector<NimBLEAdvertisedDevice*>::const_iterator NimBLEScanResults::begin() const {
|
||||||
return m_advertisedDevicesVector.begin();
|
return m_deviceVec.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get iterator to the end of the vector of advertised device pointers.
|
* @brief Get iterator to the end of the vector of advertised device pointers.
|
||||||
* @return An iterator to the end of the vector of advertised device pointers.
|
* @return An iterator to the end of the vector of advertised device pointers.
|
||||||
*/
|
*/
|
||||||
std::vector<NimBLEAdvertisedDevice*>::iterator NimBLEScanResults::end() {
|
std::vector<NimBLEAdvertisedDevice*>::const_iterator NimBLEScanResults::end() const {
|
||||||
return m_advertisedDevicesVector.end();
|
return m_deviceVec.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get a pointer to the specified device at the given address.
|
* @brief Get a pointer to the specified device at the given address.
|
||||||
* If the address is not found a nullptr is returned.
|
* If the address is not found a nullptr is returned.
|
||||||
* @param [in] address The address of the device.
|
* @param [in] address The address of the device.
|
||||||
* @return A pointer to the device at the specified address.
|
* @return A pointer to the device at the specified address.
|
||||||
*/
|
*/
|
||||||
NimBLEAdvertisedDevice *NimBLEScanResults::getDevice(const NimBLEAddress &address) {
|
const NimBLEAdvertisedDevice* NimBLEScanResults::getDevice(const NimBLEAddress& address) const {
|
||||||
for(size_t index = 0; index < m_advertisedDevicesVector.size(); index++) {
|
for (const auto& dev : m_deviceVec) {
|
||||||
if(m_advertisedDevicesVector[index]->getAddress() == address) {
|
if (dev->getAddress() == address) {
|
||||||
return m_advertisedDevicesVector[index];
|
return dev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char* CB_TAG = "NimBLEScanCallbacks";
|
||||||
|
|
||||||
|
void NimBLEScanCallbacks::onDiscovered(const NimBLEAdvertisedDevice* pAdvertisedDevice) {
|
||||||
|
NIMBLE_LOGD(CB_TAG, "Discovered: %s", pAdvertisedDevice->toString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void NimBLEScanCallbacks::onResult(const NimBLEAdvertisedDevice* pAdvertisedDevice) {
|
||||||
|
NIMBLE_LOGD(CB_TAG, "Result: %s", pAdvertisedDevice->toString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void NimBLEScanCallbacks::onScanEnd(const NimBLEScanResults& results, int reason) {
|
||||||
|
NIMBLE_LOGD(CB_TAG, "Scan ended; reason %d, num results: %d", reason, results.getCount());
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_OBSERVER */
|
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_OBSERVER */
|
||||||
|
|
|
@ -17,16 +17,16 @@
|
||||||
#include "nimconfig.h"
|
#include "nimconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
|
|
||||||
#include "NimBLEAdvertisedDevice.h"
|
# include "NimBLEAdvertisedDevice.h"
|
||||||
#include "NimBLEUtils.h"
|
# include "NimBLEUtils.h"
|
||||||
|
|
||||||
#if defined(CONFIG_NIMBLE_CPP_IDF)
|
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||||
#include "host/ble_gap.h"
|
# include "host/ble_gap.h"
|
||||||
#else
|
# else
|
||||||
#include "nimble/nimble/host/include/host/ble_gap.h"
|
# include "nimble/nimble/host/include/host/ble_gap.h"
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
#include <vector>
|
# include <vector>
|
||||||
|
|
||||||
class NimBLEDevice;
|
class NimBLEDevice;
|
||||||
class NimBLEScan;
|
class NimBLEScan;
|
||||||
|
@ -42,17 +42,17 @@ class NimBLEAddress;
|
||||||
* index (starting at 0) of the desired device.
|
* index (starting at 0) of the desired device.
|
||||||
*/
|
*/
|
||||||
class NimBLEScanResults {
|
class NimBLEScanResults {
|
||||||
public:
|
public:
|
||||||
void dump();
|
void dump() const;
|
||||||
int getCount();
|
int getCount() const;
|
||||||
NimBLEAdvertisedDevice getDevice(uint32_t i);
|
const NimBLEAdvertisedDevice* getDevice(uint32_t idx) const;
|
||||||
std::vector<NimBLEAdvertisedDevice*>::iterator begin();
|
const NimBLEAdvertisedDevice* getDevice(const NimBLEAddress& address) const;
|
||||||
std::vector<NimBLEAdvertisedDevice*>::iterator end();
|
std::vector<NimBLEAdvertisedDevice*>::const_iterator begin() const;
|
||||||
NimBLEAdvertisedDevice *getDevice(const NimBLEAddress &address);
|
std::vector<NimBLEAdvertisedDevice*>::const_iterator end() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend NimBLEScan;
|
friend NimBLEScan;
|
||||||
std::vector<NimBLEAdvertisedDevice*> m_advertisedDevicesVector;
|
std::vector<NimBLEAdvertisedDevice*> m_deviceVec;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -61,8 +61,8 @@ private:
|
||||||
* Scanning is associated with a %BLE client that is attempting to locate BLE servers.
|
* Scanning is associated with a %BLE client that is attempting to locate BLE servers.
|
||||||
*/
|
*/
|
||||||
class NimBLEScan {
|
class NimBLEScan {
|
||||||
public:
|
public:
|
||||||
bool start(uint32_t duration, bool is_continue = false);
|
bool start(uint32_t duration, bool isContinue = false, bool restart = true);
|
||||||
bool isScanning();
|
bool isScanning();
|
||||||
void setScanCallbacks(NimBLEScanCallbacks* pScanCallbacks, bool wantDuplicates = false);
|
void setScanCallbacks(NimBLEScanCallbacks* pScanCallbacks, bool wantDuplicates = false);
|
||||||
void setActiveScan(bool active);
|
void setActiveScan(bool active);
|
||||||
|
@ -71,30 +71,27 @@ public:
|
||||||
void setDuplicateFilter(bool enabled);
|
void setDuplicateFilter(bool enabled);
|
||||||
void setLimitedOnly(bool enabled);
|
void setLimitedOnly(bool enabled);
|
||||||
void setFilterPolicy(uint8_t filter);
|
void setFilterPolicy(uint8_t filter);
|
||||||
void clearDuplicateCache();
|
|
||||||
bool stop();
|
bool stop();
|
||||||
void clearResults();
|
void clearResults();
|
||||||
NimBLEScanResults getResults();
|
NimBLEScanResults getResults();
|
||||||
NimBLEScanResults getResults(uint32_t duration, bool is_continue = false);
|
NimBLEScanResults getResults(uint32_t duration, bool is_continue = false);
|
||||||
void setMaxResults(uint8_t maxResults);
|
void setMaxResults(uint8_t maxResults);
|
||||||
void erase(const NimBLEAddress &address);
|
void erase(const NimBLEAddress& address);
|
||||||
|
void erase(const NimBLEAdvertisedDevice* device);
|
||||||
|
|
||||||
|
private:
|
||||||
private:
|
|
||||||
friend class NimBLEDevice;
|
friend class NimBLEDevice;
|
||||||
|
|
||||||
NimBLEScan();
|
NimBLEScan();
|
||||||
~NimBLEScan();
|
~NimBLEScan();
|
||||||
static int handleGapEvent(ble_gap_event* event, void* arg);
|
static int handleGapEvent(ble_gap_event* event, void* arg);
|
||||||
void onHostReset();
|
|
||||||
void onHostSync();
|
void onHostSync();
|
||||||
|
|
||||||
NimBLEScanCallbacks* m_pScanCallbacks;
|
NimBLEScanCallbacks* m_pScanCallbacks;
|
||||||
ble_gap_disc_params m_scan_params;
|
ble_gap_disc_params m_scanParams;
|
||||||
bool m_ignoreResults;
|
|
||||||
NimBLEScanResults m_scanResults;
|
NimBLEScanResults m_scanResults;
|
||||||
uint32_t m_duration;
|
uint32_t m_duration;
|
||||||
NimBLETaskData *m_pTaskData;
|
NimBLETaskData* m_pTaskData;
|
||||||
uint8_t m_maxResults;
|
uint8_t m_maxResults;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -102,26 +99,27 @@ private:
|
||||||
* @brief A callback handler for callbacks associated device scanning.
|
* @brief A callback handler for callbacks associated device scanning.
|
||||||
*/
|
*/
|
||||||
class NimBLEScanCallbacks {
|
class NimBLEScanCallbacks {
|
||||||
public:
|
public:
|
||||||
virtual ~NimBLEScanCallbacks() {}
|
virtual ~NimBLEScanCallbacks() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Called when a new device is discovered, before the scan result is received (if applicable).
|
* @brief Called when a new device is discovered, before the scan result is received (if applicable).
|
||||||
* @param [in] advertisedDevice The device which was discovered.
|
* @param [in] advertisedDevice The device which was discovered.
|
||||||
*/
|
*/
|
||||||
virtual void onDiscovered(NimBLEAdvertisedDevice* advertisedDevice) {};
|
virtual void onDiscovered(const NimBLEAdvertisedDevice* advertisedDevice);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Called when a new scan result is complete, including scan response data (if applicable).
|
* @brief Called when a new scan result is complete, including scan response data (if applicable).
|
||||||
* @param [in] advertisedDevice The device for which the complete result is available.
|
* @param [in] advertisedDevice The device for which the complete result is available.
|
||||||
*/
|
*/
|
||||||
virtual void onResult(NimBLEAdvertisedDevice* advertisedDevice) {};
|
virtual void onResult(const NimBLEAdvertisedDevice* advertisedDevice);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Called when a scan operation ends.
|
* @brief Called when a scan operation ends.
|
||||||
* @param [in] scanResults The results of the scan that ended.
|
* @param [in] scanResults The results of the scan that ended.
|
||||||
|
* @param [in] reason The reason code for why the scan ended.
|
||||||
*/
|
*/
|
||||||
virtual void onScanEnd(NimBLEScanResults scanResults) {};
|
virtual void onScanEnd(const NimBLEScanResults& scanResults, int reason);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* CONFIG_BT_ENABLED CONFIG_BT_NIMBLE_ROLE_OBSERVER */
|
#endif /* CONFIG_BT_ENABLED CONFIG_BT_NIMBLE_ROLE_OBSERVER */
|
||||||
|
|
Loading…
Reference in a new issue