diff --git a/examples/NimBLE_active_passive_scan/NimBLE_active_passive_scan.ino b/examples/NimBLE_active_passive_scan/NimBLE_active_passive_scan.ino new file mode 100644 index 0000000..9dceb4e --- /dev/null +++ b/examples/NimBLE_active_passive_scan/NimBLE_active_passive_scan.ino @@ -0,0 +1,48 @@ +/* + * NimBLE Scan active/passive switching demo + * + * Demonstrates the use of the scan callbacks while alternating between passive and active scanning. + */ + +#include "NimBLEDevice.h" +int scanTime = 5 * 1000; // In milliseconds, 0 = scan forever +BLEScan* pBLEScan; + +bool active = false; + +class scanCallbacks: public NimBLEScanCallbacks { + + void onDiscovered(NimBLEAdvertisedDevice* advertisedDevice) { + Serial.printf("Discovered Advertised Device: %s \n", advertisedDevice->toString().c_str()); + } + + void onResult(NimBLEAdvertisedDevice* advertisedDevice) { + Serial.printf("Advertised Device Result: %s \n", advertisedDevice->toString().c_str()); + } + + void onScanEnd(NimBLEScanResults results){ + Serial.println("Scan Ended"); + active = !active; + pBLEScan->setActiveScan(active); + Serial.printf("scan start, active = %u\n", active); + pBLEScan->start(scanTime); + } +}; + + + +void setup() { + Serial.begin(115200); + Serial.println("Scanning..."); + + NimBLEDevice::init(""); + pBLEScan = NimBLEDevice::getScan(); + pBLEScan->setScanCallbacks(new scanCallbacks()); + pBLEScan->setActiveScan(active); + pBLEScan->setInterval(100); + pBLEScan->setWindow(99); + pBLEScan->start(scanTime); +} + +void loop() { +} diff --git a/src/NimBLEAdvertisedDevice.cpp b/src/NimBLEAdvertisedDevice.cpp index 0c38ca4..3ef71f5 100644 --- a/src/NimBLEAdvertisedDevice.cpp +++ b/src/NimBLEAdvertisedDevice.cpp @@ -33,7 +33,7 @@ NimBLEAdvertisedDevice::NimBLEAdvertisedDevice() : { m_advType = 0; m_rssi = -9999; - m_callbackSent = false; + m_callbackSent = 0; m_timestamp = 0; m_advLength = 0; } // NimBLEAdvertisedDevice diff --git a/src/NimBLEAdvertisedDevice.h b/src/NimBLEAdvertisedDevice.h index cb23208..5b7a69f 100644 --- a/src/NimBLEAdvertisedDevice.h +++ b/src/NimBLEAdvertisedDevice.h @@ -164,7 +164,7 @@ private: uint8_t m_advType; int m_rssi; time_t m_timestamp; - bool m_callbackSent; + uint8_t m_callbackSent; uint8_t m_advLength; #if CONFIG_BT_NIMBLE_EXT_ADV bool m_isLegacyAdv; diff --git a/src/NimBLEScan.cpp b/src/NimBLEScan.cpp index d907c54..c7ee07a 100644 --- a/src/NimBLEScan.cpp +++ b/src/NimBLEScan.cpp @@ -135,7 +135,12 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) { event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP)); if (pScan->m_pScanCallbacks) { - if (pScan->m_scan_params.filter_duplicates && advertisedDevice->m_callbackSent) { + if (advertisedDevice->m_callbackSent == 0 || !pScan->m_scan_params.filter_duplicates) { + advertisedDevice->m_callbackSent = 1; + pScan->m_pScanCallbacks->onDiscovered(advertisedDevice); + } + + if (pScan->m_scan_params.filter_duplicates && advertisedDevice->m_callbackSent >= 2) { return 0; } @@ -145,16 +150,16 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) { (advertisedDevice->getAdvType() != BLE_HCI_ADV_TYPE_ADV_IND && advertisedDevice->getAdvType() != BLE_HCI_ADV_TYPE_ADV_SCAN_IND)) { - advertisedDevice->m_callbackSent = true; + advertisedDevice->m_callbackSent = 2; pScan->m_pScanCallbacks->onResult(advertisedDevice); // 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) { - advertisedDevice->m_callbackSent = true; + advertisedDevice->m_callbackSent = 2; pScan->m_pScanCallbacks->onResult(advertisedDevice); } // If not storing results and we have invoked the callback, delete the device. - if(pScan->m_maxResults == 0 && advertisedDevice->m_callbackSent) { + if(pScan->m_maxResults == 0 && advertisedDevice->m_callbackSent >= 2) { pScan->erase(advertisedAddress); } } @@ -165,16 +170,6 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) { NIMBLE_LOGD(LOG_TAG, "discovery complete; reason=%d", event->disc_complete.reason); - // If a device advertised with scan response available and it was not received - // the callback would not have been invoked, so do it here. - if(pScan->m_pScanCallbacks) { - for(auto &it : pScan->m_scanResults.m_advertisedDevicesVector) { - if(!it->m_callbackSent) { - pScan->m_pScanCallbacks->onResult(it); - } - } - } - if(pScan->m_maxResults == 0) { pScan->clearResults(); } diff --git a/src/NimBLEScan.h b/src/NimBLEScan.h index 9bf11bb..f0edcaa 100644 --- a/src/NimBLEScan.h +++ b/src/NimBLEScan.h @@ -104,13 +104,23 @@ private: class NimBLEScanCallbacks { public: virtual ~NimBLEScanCallbacks() {} + /** - * @brief Called when a new scan result is detected. - * - * As we are scanning, we will find new devices. When found, this call back is invoked with a reference to the - * device that was found. During any individual scan, a device will only be detected one time. + * @brief Called when a new device is discovered, before the scan result is received (if applicable). + * @param [in] advertisedDevice The device which was discovered. + */ + virtual void onDiscovered(NimBLEAdvertisedDevice* advertisedDevice) {}; + + /** + * @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. */ virtual void onResult(NimBLEAdvertisedDevice* advertisedDevice) {}; + + /** + * @brief Called when a scan operation ends. + * @param [in] scanResults The results of the scan that ended. + */ virtual void onScanEnd(NimBLEScanResults scanResults) {}; };