[NimBLEScan] Use controller duplicate filter and add max result limit.

* Adds setMaxResults to NimBLEScan to limit the number of advertised devices stored.
  If set to 0 no devices will be stored in memory and only the callback will be invoked.
  If set to 0xFF (default) stored devices will be unlimited. Any other value will be the limit.

* Uses the controller to filter duplicate devices from the scan results when wantDuplicates == false.
This commit is contained in:
h2zero 2021-01-30 18:27:06 -07:00
parent 9527c41486
commit 82524c80e3
2 changed files with 54 additions and 34 deletions

View file

@ -38,9 +38,9 @@ NimBLEScan::NimBLEScan() {
m_scan_params.filter_duplicates = 0; // If set, the controller ignores all but the first advertisement from each device. m_scan_params.filter_duplicates = 0; // If set, the controller ignores all but the first advertisement from each device.
m_pAdvertisedDeviceCallbacks = nullptr; m_pAdvertisedDeviceCallbacks = nullptr;
m_ignoreResults = false; m_ignoreResults = false;
m_wantDuplicates = false;
m_pTaskData = nullptr; m_pTaskData = nullptr;
m_duration = BLE_HS_FOREVER; // make sure this is non-zero in the event of a host reset m_duration = BLE_HS_FOREVER; // make sure this is non-zero in the event of a host reset
m_maxResults = 0xFF;
} }
@ -88,35 +88,37 @@ NimBLEScan::~NimBLEScan() {
// 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 && event->disc.event_type != BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP){
// 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
if(pScan->m_maxResults > 0 && pScan->m_maxResults < 0xFF &&
(pScan->m_scanResults.m_advertisedDevicesVector.size() >= pScan->m_maxResults))
{
return 0;
}
advertisedDevice = new NimBLEAdvertisedDevice(); advertisedDevice = new NimBLEAdvertisedDevice();
advertisedDevice->setAddress(advertisedAddress); advertisedDevice->setAddress(advertisedAddress);
advertisedDevice->setAdvType(event->disc.event_type); advertisedDevice->setAdvType(event->disc.event_type);
pScan->m_scanResults.m_advertisedDevicesVector.push_back(advertisedDevice); pScan->m_scanResults.m_advertisedDevicesVector.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 { } else if(advertisedDevice != nullptr) {
NIMBLE_LOGI(LOG_TAG, "Updated advertiser: %s", advertisedAddress.toString().c_str()); NIMBLE_LOGI(LOG_TAG, "Updated advertiser: %s", advertisedAddress.toString().c_str());
} else {
// Scan response from unknown device
return 0;
} }
advertisedDevice->m_timestamp = time(nullptr); advertisedDevice->m_timestamp = time(nullptr);
advertisedDevice->setRSSI(event->disc.rssi); advertisedDevice->setRSSI(event->disc.rssi);
advertisedDevice->setPayload(event->disc.data, event->disc.length_data,
if(event->disc.length_data > 0) { event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP);
if(event->disc.event_type != BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
advertisedDevice->setPayload(event->disc.data, event->disc.length_data, false);
} else {
advertisedDevice->setPayload(event->disc.data, event->disc.length_data, true);
}
}
if (pScan->m_pAdvertisedDeviceCallbacks) { if (pScan->m_pAdvertisedDeviceCallbacks) {
if(pScan->m_wantDuplicates || !advertisedDevice->m_callbackSent) {
// If not active scanning or scan response is not available // If not active scanning or scan response is not available
// report the result to the callback now. // report the result to the callback now.
if(pScan->m_scan_params.passive || if(pScan->m_scan_params.passive ||
(event->disc.event_type != BLE_HCI_ADV_TYPE_ADV_IND && (advertisedDevice->getAdvType() != BLE_HCI_ADV_TYPE_ADV_IND &&
event->disc.event_type != BLE_HCI_ADV_TYPE_ADV_SCAN_IND)) advertisedDevice->getAdvType() != BLE_HCI_ADV_TYPE_ADV_SCAN_IND))
{ {
advertisedDevice->m_callbackSent = true; advertisedDevice->m_callbackSent = true;
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice); pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
@ -126,6 +128,9 @@ NimBLEScan::~NimBLEScan() {
advertisedDevice->m_callbackSent = true; advertisedDevice->m_callbackSent = true;
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice); pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
} }
// If not storing results and we have invoked the callback, delete the device.
if(pScan->m_maxResults == 0 && advertisedDevice->m_callbackSent) {
pScan->erase(advertisedAddress);
} }
} }
@ -145,6 +150,10 @@ NimBLEScan::~NimBLEScan() {
} }
} }
if(pScan->m_maxResults == 0) {
pScan->clearResults();
}
if (pScan->m_scanCompleteCB != nullptr) { if (pScan->m_scanCompleteCB != nullptr) {
pScan->m_scanCompleteCB(pScan->m_scanResults); pScan->m_scanCompleteCB(pScan->m_scanResults);
} }
@ -165,15 +174,11 @@ NimBLEScan::~NimBLEScan() {
/** /**
* @brief Should we perform an active or passive scan? * @brief Should we perform an active or passive scan?
* The default is a passive scan. An active scan means that we will wish a scan response. * The default is a passive scan. An active scan means that we will request a scan response.
* @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) {
if (active) { m_scan_params.passive = !active;
m_scan_params.passive = 0;
} else {
m_scan_params.passive = 1;
}
} // setActiveScan } // setActiveScan
@ -222,6 +227,16 @@ void NimBLEScan::setFilterPolicy(uint8_t filter) {
} // setFilterPolicy } // setFilterPolicy
/**
* @brief Sets the max number of results to store.
* @param [in] maxResults The number of results to limit storage to\n
* 0 == none (callbacks only) 0xFF == unlimited, any other value is the limit.
*/
void NimBLEScan::setMaxResults(uint8_t maxResults) {
m_maxResults = maxResults;
}
/** /**
* @brief Set the call backs to be invoked. * @brief Set the call backs to be invoked.
* @param [in] pAdvertisedDeviceCallbacks Call backs to be invoked. * @param [in] pAdvertisedDeviceCallbacks Call backs to be invoked.
@ -229,7 +244,7 @@ void NimBLEScan::setFilterPolicy(uint8_t filter) {
*/ */
void NimBLEScan::setAdvertisedDeviceCallbacks(NimBLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks, void NimBLEScan::setAdvertisedDeviceCallbacks(NimBLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks,
bool wantDuplicates) { bool wantDuplicates) {
m_wantDuplicates = wantDuplicates; setDuplicateFilter(!wantDuplicates);
m_pAdvertisedDeviceCallbacks = pAdvertisedDeviceCallbacks; m_pAdvertisedDeviceCallbacks = pAdvertisedDeviceCallbacks;
} // setAdvertisedDeviceCallbacks } // setAdvertisedDeviceCallbacks
@ -366,6 +381,10 @@ bool NimBLEScan::stop() {
return false; return false;
} }
if(m_maxResults == 0) {
clearResults();
}
if (rc != BLE_HS_EALREADY && m_scanCompleteCB != nullptr) { if (rc != BLE_HS_EALREADY && m_scanCompleteCB != nullptr) {
m_scanCompleteCB(m_scanResults); m_scanCompleteCB(m_scanResults);
} }

View file

@ -73,6 +73,7 @@ public:
bool stop(); bool stop();
void clearResults(); void clearResults();
NimBLEScanResults getResults(); NimBLEScanResults getResults();
void setMaxResults(uint8_t maxResults);
void erase(const NimBLEAddress &address); void erase(const NimBLEAddress &address);
@ -89,10 +90,10 @@ private:
void (*m_scanCompleteCB)(NimBLEScanResults scanResults); void (*m_scanCompleteCB)(NimBLEScanResults scanResults);
ble_gap_disc_params m_scan_params; ble_gap_disc_params m_scan_params;
bool m_ignoreResults; bool m_ignoreResults;
bool m_wantDuplicates;
NimBLEScanResults m_scanResults; NimBLEScanResults m_scanResults;
uint32_t m_duration; uint32_t m_duration;
ble_task_data_t *m_pTaskData; ble_task_data_t *m_pTaskData;
uint8_t m_maxResults;
}; };
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)