improve & fix BLEScan when wantDuplicates (#3995)

* improve & fix BLEScan when too many BLE devices
- when wantDuplicates, no need to check duplicate and no more insert into vector
- delete advertisedDevice when not insert into vector, fix memory leak
- add showParse when you just want raw advertised data
This commit is contained in:
saknarak 2020-11-03 01:41:50 +07:00 committed by GitHub
parent c2346c37da
commit dccb4e8608
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 38 additions and 17 deletions

View File

@ -388,6 +388,15 @@ void BLEAdvertisedDevice::parseAdvertisement(uint8_t* payload, size_t total_len)
} // !finished } // !finished
} // parseAdvertisement } // parseAdvertisement
/**
* @brief Parse the advertising payload.
* @param [in] payload The payload of the advertised device.
* @param [in] total_len The length of payload
*/
void BLEAdvertisedDevice::setPayload(uint8_t* payload, size_t total_len) {
m_payload = payload;
m_payloadLength = total_len;
} // setPayload
/** /**
* @brief Set the address of the advertised device. * @brief Set the address of the advertised device.

View File

@ -64,6 +64,7 @@ private:
friend class BLEScan; friend class BLEScan;
void parseAdvertisement(uint8_t* payload, size_t total_len=62); void parseAdvertisement(uint8_t* payload, size_t total_len=62);
void setPayload(uint8_t* payload, size_t total_len=62);
void setAddress(BLEAddress address); void setAddress(BLEAddress address);
void setAdFlag(uint8_t adFlag); void setAdFlag(uint8_t adFlag);
void setAdvertizementResult(uint8_t* payload); void setAdvertizementResult(uint8_t* payload);

View File

@ -30,6 +30,7 @@ BLEScan::BLEScan() {
m_pAdvertisedDeviceCallbacks = nullptr; m_pAdvertisedDeviceCallbacks = nullptr;
m_stopped = true; m_stopped = true;
m_wantDuplicates = false; m_wantDuplicates = false;
m_shouldParse = true;
setInterval(100); setInterval(100);
setWindow(100); setWindow(100);
} // BLEScan } // BLEScan
@ -90,16 +91,19 @@ void BLEScan::handleGAPEvent(
// ignore it. // ignore it.
BLEAddress advertisedAddress(param->scan_rst.bda); BLEAddress advertisedAddress(param->scan_rst.bda);
bool found = false; bool found = false;
bool shouldDelete = true;
if (!m_wantDuplicates) {
if (m_scanResults.m_vectorAdvertisedDevices.count(advertisedAddress.toString()) != 0) { if (m_scanResults.m_vectorAdvertisedDevices.count(advertisedAddress.toString()) != 0) {
found = true; found = true;
} }
if (found && !m_wantDuplicates) { // If we found a previous entry AND we don't want duplicates, then we are done. if (found) { // If we found a previous entry AND we don't want duplicates, then we are done.
log_d("Ignoring %s, already seen it.", advertisedAddress.toString().c_str()); log_d("Ignoring %s, already seen it.", advertisedAddress.toString().c_str());
vTaskDelay(1); // <--- allow to switch task in case we scan infinity and dont have new devices to report, or we are blocked here vTaskDelay(1); // <--- allow to switch task in case we scan infinity and dont have new devices to report, or we are blocked here
break; break;
} }
}
// We now construct a model of the advertised device that we have just found for the first // We now construct a model of the advertised device that we have just found for the first
// time. // time.
@ -109,19 +113,23 @@ void BLEScan::handleGAPEvent(
advertisedDevice->setAddress(advertisedAddress); advertisedDevice->setAddress(advertisedAddress);
advertisedDevice->setRSSI(param->scan_rst.rssi); advertisedDevice->setRSSI(param->scan_rst.rssi);
advertisedDevice->setAdFlag(param->scan_rst.flag); advertisedDevice->setAdFlag(param->scan_rst.flag);
if (m_shouldParse) {
advertisedDevice->parseAdvertisement((uint8_t*)param->scan_rst.ble_adv, param->scan_rst.adv_data_len + param->scan_rst.scan_rsp_len); advertisedDevice->parseAdvertisement((uint8_t*)param->scan_rst.ble_adv, param->scan_rst.adv_data_len + param->scan_rst.scan_rsp_len);
} else {
advertisedDevice->setPayload((uint8_t*)param->scan_rst.ble_adv, param->scan_rst.adv_data_len + param->scan_rst.scan_rsp_len);
}
advertisedDevice->setScan(this); advertisedDevice->setScan(this);
advertisedDevice->setAddressType(param->scan_rst.ble_addr_type); advertisedDevice->setAddressType(param->scan_rst.ble_addr_type);
if (!found) { // If we have previously seen this device, don't record it again. if (m_pAdvertisedDeviceCallbacks) { // if has callback, no need to record to vector
m_scanResults.m_vectorAdvertisedDevices.insert(std::pair<std::string, BLEAdvertisedDevice*>(advertisedAddress.toString(), advertisedDevice));
}
if (m_pAdvertisedDeviceCallbacks) {
m_pAdvertisedDeviceCallbacks->onResult(*advertisedDevice); m_pAdvertisedDeviceCallbacks->onResult(*advertisedDevice);
} else if (!m_wantDuplicates && !found) { // if no callback and not want duplicate, and not already in vector, record it
m_scanResults.m_vectorAdvertisedDevices.insert(std::pair<std::string, BLEAdvertisedDevice*>(advertisedAddress.toString(), advertisedDevice));
shouldDelete = false;
} }
if(found) if (shouldDelete) {
delete advertisedDevice; delete advertisedDevice;
}
break; break;
} // ESP_GAP_SEARCH_INQ_RES_EVT } // ESP_GAP_SEARCH_INQ_RES_EVT
@ -161,13 +169,14 @@ void BLEScan::setActiveScan(bool active) {
* @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.
* @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 is false.
* @param [in] shouldParse True if we wish to parse advertised package or raw payload. Default is true.
*/ */
void BLEScan::setAdvertisedDeviceCallbacks(BLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks, bool wantDuplicates) { void BLEScan::setAdvertisedDeviceCallbacks(BLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks, bool wantDuplicates, bool shouldParse) {
m_wantDuplicates = wantDuplicates; m_wantDuplicates = wantDuplicates;
m_pAdvertisedDeviceCallbacks = pAdvertisedDeviceCallbacks; m_pAdvertisedDeviceCallbacks = pAdvertisedDeviceCallbacks;
m_shouldParse = shouldParse;
} // setAdvertisedDeviceCallbacks } // setAdvertisedDeviceCallbacks
/** /**
* @brief Set the interval to scan. * @brief Set the interval to scan.
* @param [in] The interval in msecs. * @param [in] The interval in msecs.

View File

@ -51,7 +51,8 @@ public:
void setActiveScan(bool active); void setActiveScan(bool active);
void setAdvertisedDeviceCallbacks( void setAdvertisedDeviceCallbacks(
BLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks, BLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks,
bool wantDuplicates = false); bool wantDuplicates = false,
bool shouldParse = true);
void setInterval(uint16_t intervalMSecs); void setInterval(uint16_t intervalMSecs);
void setWindow(uint16_t windowMSecs); void setWindow(uint16_t windowMSecs);
bool start(uint32_t duration, void (*scanCompleteCB)(BLEScanResults), bool is_continue = false); bool start(uint32_t duration, void (*scanCompleteCB)(BLEScanResults), bool is_continue = false);
@ -73,6 +74,7 @@ private:
esp_ble_scan_params_t m_scan_params; esp_ble_scan_params_t m_scan_params;
BLEAdvertisedDeviceCallbacks* m_pAdvertisedDeviceCallbacks = nullptr; BLEAdvertisedDeviceCallbacks* m_pAdvertisedDeviceCallbacks = nullptr;
bool m_stopped = true; bool m_stopped = true;
bool m_shouldParse = true;
FreeRTOS::Semaphore m_semaphoreScanEnd = FreeRTOS::Semaphore("ScanEnd"); FreeRTOS::Semaphore m_semaphoreScanEnd = FreeRTOS::Semaphore("ScanEnd");
BLEScanResults m_scanResults; BLEScanResults m_scanResults;
bool m_wantDuplicates; bool m_wantDuplicates;