From db42285fac922fd4d3eef2bfbda1515eecc45096 Mon Sep 17 00:00:00 2001 From: XuGuohui Date: Wed, 13 Dec 2023 15:59:33 +0800 Subject: [PATCH 1/2] Add a BLE scan option to allow duplicate results --- hal/src/nRF52840/ble_hal.cpp | 34 ---------------------- user/tests/app/ble/scanner/application.cpp | 16 ++++++++-- user/tests/wiring/api/ble.cpp | 3 ++ wiring/inc/spark_wiring_ble.h | 13 ++++++++- wiring/src/spark_wiring_ble.cpp | 16 ++++++++++ 5 files changed, 44 insertions(+), 38 deletions(-) diff --git a/hal/src/nRF52840/ble_hal.cpp b/hal/src/nRF52840/ble_hal.cpp index 9602797cb3..1bb0e4edcd 100644 --- a/hal/src/nRF52840/ble_hal.cpp +++ b/hal/src/nRF52840/ble_hal.cpp @@ -374,9 +374,6 @@ class BleObject::Observer { int processAdvReportEventFromThread(const ble_evt_t* event); private: - bool isCachedDevice(const hal_ble_addr_t& address) const; - int addCachedDevice(const hal_ble_addr_t& address); - void clearCachedDevice(); hal_ble_scan_result_evt_t* getPendingResult(const hal_ble_addr_t& address); int addPendingResult(const hal_ble_scan_result_evt_t& resultEvt); void removePendingResult(const hal_ble_addr_t& address); @@ -396,7 +393,6 @@ class BleObject::Observer { hal_ble_on_scan_result_cb_t scanResultCallback_; /**< Callback function on scan result. */ void* context_; /**< Context of the scan result callback function. */ os_timer_t scanGuardTimer_; /**< Timer to guard the scanning procedure is terminated successfully. */ - Vector cachedDevices_; Vector pendingResults_; }; @@ -1424,7 +1420,6 @@ void BleObject::Observer::onScanGuardTimerExpired(os_timer_t timer) { int BleObject::Observer::startScanning(hal_ble_on_scan_result_cb_t callback, void* context) { CHECK_FALSE(isScanning_, SYSTEM_ERROR_INVALID_STATE); SCOPE_GUARD ({ - clearCachedDevice(); clearPendingResult(); }); ble_gap_scan_params_t bleGapScanParams = toPlatformScanParams(); @@ -1493,24 +1488,6 @@ ble_gap_scan_params_t BleObject::Observer::toPlatformScanParams() const { return params; } -bool BleObject::Observer::isCachedDevice(const hal_ble_addr_t& address) const { - for (const auto& addr : cachedDevices_) { - if (addressEqual(addr, address)) { - return true; - } - } - return false; -} - -int BleObject::Observer::addCachedDevice(const hal_ble_addr_t& address) { - CHECK_TRUE(cachedDevices_.append(address), SYSTEM_ERROR_NO_MEMORY); - return SYSTEM_ERROR_NONE; -} - -void BleObject::Observer::clearCachedDevice() { - cachedDevices_.clear(); -} - hal_ble_scan_result_evt_t* BleObject::Observer::getPendingResult(const hal_ble_addr_t& address) { for (auto& result : pendingResults_) { if (addressEqual(result.peer_addr, address)) { @@ -1590,17 +1567,11 @@ int BleObject::Observer::processAdvReportEventFromThread(const ble_evt_t* event) } const ble_gap_evt_adv_report_t& advReport = event->evt.gap_evt.params.adv_report; hal_ble_addr_t newAddr = toHalAddress(advReport.peer_addr); - if (isCachedDevice(newAddr)) { - // This has been checked in the ISR. Check it here just for sure. - // Free the allocated RAM for the advertising data. - goto free; - } if ((!scanParams_.active || !advReport.type.scannable) && !advReport.type.scan_response) { // No scan response data is expected. hal_ble_scan_result_evt_t result = {}; constructObserverEvent(result, advReport); notifyScanResultEvent(result); - addCachedDevice(newAddr); goto continue_scanning; } if (!advReport.type.scan_response) { @@ -1620,7 +1591,6 @@ int BleObject::Observer::processAdvReportEventFromThread(const ble_evt_t* event) } constructObserverEvent(*result, advReport); notifyScanResultEvent(*result); - addCachedDevice(newAddr); removePendingResult(newAddr); } goto continue_scanning; @@ -1644,10 +1614,6 @@ void BleObject::Observer::processObserverEvents(const ble_evt_t* event, void* co } const ble_gap_evt_adv_report_t& report = event->evt.gap_evt.params.adv_report; hal_ble_addr_t newAddr = toHalAddress(report.peer_addr); - if (observer->isCachedDevice(newAddr)) { - observer->continueScanning(); - break; - } if (observer->scanParams_.active && report.type.scannable && !report.type.scan_response) { // Advertising data packet, scan response data is expected. if (observer->getPendingResult(newAddr) != nullptr) { diff --git a/user/tests/app/ble/scanner/application.cpp b/user/tests/app/ble/scanner/application.cpp index 4f398b1f69..04406388f8 100644 --- a/user/tests/app/ble/scanner/application.cpp +++ b/user/tests/app/ble/scanner/application.cpp @@ -17,7 +17,7 @@ #include "Particle.h" -#define SCAN_RESULT_COUNT 30 +#define SCAN_RESULT_COUNT 100 #define BLE_ADV_DATA_MAX 31 SYSTEM_MODE(MANUAL); @@ -31,13 +31,23 @@ void setup() { } +bool flag = false; + void loop() { - int count = BLE.scan(results, SCAN_RESULT_COUNT); + int count; + flag = !flag; + if (flag) { + Log.info(">>>> start scanning, filter duplicates"); + count = BLE.scan(results, SCAN_RESULT_COUNT); + } else { + Log.info(">>>> start scanning, allow duplicates"); + count = BLE.scanWithFilter(BleScanFilter().allowDuplicates(true), results, SCAN_RESULT_COUNT); + } if (count > 0) { Log.info("%d devices are found:", count); for (int i = 0; i < count; i++) { - Log.info(" -------- MAC: %s | RSSI: %dBm --------", results[i].address().toString().c_str(), results[i].rssi()); + Log.info(" -------- MAC: %s | RSSI: %d dBm --------", results[i].address().toString().c_str(), results[i].rssi()); String name = results[i].advertisingData().deviceName(); if (name.length() > 0) { diff --git a/user/tests/wiring/api/ble.cpp b/user/tests/wiring/api/ble.cpp index 4059b0091c..a37d54d541 100644 --- a/user/tests/wiring/api/ble.cpp +++ b/user/tests/wiring/api/ble.cpp @@ -594,6 +594,9 @@ test(ble_scan_filter) { API_COMPILE({ uint8_t buf[1]; BleScanFilter f = filter.customData(buf, 0); (void)f; }); API_COMPILE({ size_t len; const uint8_t* buf = filter.customData(&len); (void)len; (void)buf; }); + + API_COMPILE({ BleScanFilter f = filter.allowDuplicates(true); (void)f; }); + API_COMPILE({ bool ret = filter.allowDuplicates(); (void)ret; }); } test(ble_peer_device) { diff --git a/wiring/inc/spark_wiring_ble.h b/wiring/inc/spark_wiring_ble.h index f4e138f296..923711447a 100644 --- a/wiring/inc/spark_wiring_ble.h +++ b/wiring/inc/spark_wiring_ble.h @@ -716,7 +716,8 @@ class BleScanFilter { : minRssi_(BLE_RSSI_INVALID), maxRssi_(BLE_RSSI_INVALID), customData_(nullptr), - customDataLen_(0) { + customDataLen_(0), + allowDuplicates_(false) { } ~BleScanFilter() = default; @@ -813,6 +814,15 @@ class BleScanFilter { return *this; } + BleScanFilter& allowDuplicates(bool allow) { + allowDuplicates_ = allow; + return *this; + } + + bool allowDuplicates() const { + return allowDuplicates_; + } + private: Vector deviceNames_; Vector serviceUuids_; @@ -822,6 +832,7 @@ class BleScanFilter { int8_t maxRssi_; const uint8_t* customData_; size_t customDataLen_; + bool allowDuplicates_; }; diff --git a/wiring/src/spark_wiring_ble.cpp b/wiring/src/spark_wiring_ble.cpp index 51b4d4f72e..0663680df9 100644 --- a/wiring/src/spark_wiring_ble.cpp +++ b/wiring/src/spark_wiring_ble.cpp @@ -2378,6 +2378,12 @@ class BleScanDelegator { */ static void onScanResultCallback(const hal_ble_scan_result_evt_t* event, void* context) { BleScanDelegator* delegator = static_cast(context); + + if (!delegator->filter_.allowDuplicates() && delegator->isCachedDevice(event->peer_addr)) { + return; + } + delegator->cachedDevices_.append(event->peer_addr); + BleScanResult result = {}; result.address(event->peer_addr).rssi(event->rssi) .scanResponse(event->sr_data, event->sr_data_len) @@ -2554,6 +2560,15 @@ class BleScanDelegator { return true; } + bool isCachedDevice(const BleAddress& address) const { + for (const auto& addr : cachedDevices_) { + if (address == addr) { + return true; + } + } + return false; + } + Vector resultsVector_; BleScanResult* resultsPtr_; size_t targetCount_; @@ -2561,6 +2576,7 @@ class BleScanDelegator { std::function scanResultCallback_; BleOnScanResultStdFunction scanResultCallbackRef_; BleScanFilter filter_; + Vector cachedDevices_; }; int BleLocalDevice::setScanTimeout(uint16_t timeout) const { From 9881648abf119bfe07ea9d6c1e08ebf3a3a851b8 Mon Sep 17 00:00:00 2001 From: XuGuohui Date: Wed, 13 Dec 2023 23:09:06 +0800 Subject: [PATCH 2/2] [wiring] fixes BLE scanning cache --- wiring/src/spark_wiring_ble.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/wiring/src/spark_wiring_ble.cpp b/wiring/src/spark_wiring_ble.cpp index 0663680df9..8edfd72abc 100644 --- a/wiring/src/spark_wiring_ble.cpp +++ b/wiring/src/spark_wiring_ble.cpp @@ -2379,10 +2379,12 @@ class BleScanDelegator { static void onScanResultCallback(const hal_ble_scan_result_evt_t* event, void* context) { BleScanDelegator* delegator = static_cast(context); - if (!delegator->filter_.allowDuplicates() && delegator->isCachedDevice(event->peer_addr)) { - return; + if (!delegator->filter_.allowDuplicates()) { + if (delegator->isCachedDevice(event->peer_addr)) { + return; + } + delegator->cachedDevices_.append(event->peer_addr); } - delegator->cachedDevices_.append(event->peer_addr); BleScanResult result = {}; result.address(event->peer_addr).rssi(event->rssi)