From 745f9c00ed7bdc78f5122172dee3bfbaa98fd9a3 Mon Sep 17 00:00:00 2001 From: h2zero Date: Wed, 1 Jul 2020 17:26:44 -0600 Subject: [PATCH] Implement scan wantDuplicates parameter in callback registration. Also adds: * NimBLEScan::setDuplicateFilter() to tell the controller to filter duplicates before sending the result to the host. * NimBLEScan::setLimitedOnly() to tell the controller only report scan results from devices advertising in limited discovery mode, i.e. directed advertising. * NimBLEScan::setFilterPolicy() to set the filter policy i.e whitelist only devices. --- src/NimBLEAdvertisedDevice.cpp | 3 + src/NimBLEAdvertisedDevice.h | 5 +- src/NimBLERemoteCharacteristic.h | 9 +-- src/NimBLEScan.cpp | 98 +++++++++++++++++++------------- src/NimBLEScan.h | 5 +- 5 files changed, 75 insertions(+), 45 deletions(-) diff --git a/src/NimBLEAdvertisedDevice.cpp b/src/NimBLEAdvertisedDevice.cpp index 3e33b77..c53bb68 100644 --- a/src/NimBLEAdvertisedDevice.cpp +++ b/src/NimBLEAdvertisedDevice.cpp @@ -37,6 +37,8 @@ NimBLEAdvertisedDevice::NimBLEAdvertisedDevice() { m_serviceData = ""; m_txPower = 0; m_pScan = nullptr; + m_payloadLength = 0; + m_payload = nullptr; m_haveAppearance = false; m_haveManufacturerData = false; @@ -45,6 +47,7 @@ NimBLEAdvertisedDevice::NimBLEAdvertisedDevice() { m_haveServiceData = false; m_haveServiceUUID = false; m_haveTXPower = false; + m_callbackSent = false; } // NimBLEAdvertisedDevice diff --git a/src/NimBLEAdvertisedDevice.h b/src/NimBLEAdvertisedDevice.h index 3380f4a..c38d700 100644 --- a/src/NimBLEAdvertisedDevice.h +++ b/src/NimBLEAdvertisedDevice.h @@ -115,7 +115,7 @@ private: bool m_haveTXPower; - NimBLEAddress m_address = NimBLEAddress(""); + NimBLEAddress m_address = NimBLEAddress(""); uint8_t m_advType; uint16_t m_appearance; int m_deviceType; @@ -128,9 +128,10 @@ private: std::string m_serviceData; NimBLEUUID m_serviceDataUUID; uint8_t* m_payload; - size_t m_payloadLength = 0; + size_t m_payloadLength; uint8_t m_addressType; time_t m_timestamp; + bool m_callbackSent; }; /** diff --git a/src/NimBLERemoteCharacteristic.h b/src/NimBLERemoteCharacteristic.h index 657eaf0..54ab19d 100644 --- a/src/NimBLERemoteCharacteristic.h +++ b/src/NimBLERemoteCharacteristic.h @@ -71,9 +71,9 @@ public: return *((T *)pData); } - uint8_t readUInt8() __attribute__ ((deprecated)); - uint16_t readUInt16() __attribute__ ((deprecated)); - uint32_t readUInt32() __attribute__ ((deprecated)); + uint8_t readUInt8() __attribute__ ((deprecated("Use template readValue()"))); + uint16_t readUInt16() __attribute__ ((deprecated("Use template readValue()"))); + uint32_t readUInt32() __attribute__ ((deprecated("Use template readValue()"))); std::string getValue(time_t *timestamp = nullptr); template @@ -90,7 +90,8 @@ public: bool unsubscribe(bool response = true); bool registerForNotify(notify_callback notifyCallback, bool notifications = true, - bool response = true) __attribute__ ((deprecated)); + bool response = true) + __attribute__ ((deprecated("Use subscribe()/unsubscribe()"))); bool writeValue(const uint8_t* data, size_t length, bool response = false); diff --git a/src/NimBLEScan.cpp b/src/NimBLEScan.cpp index b550006..dbf8874 100644 --- a/src/NimBLEScan.cpp +++ b/src/NimBLEScan.cpp @@ -25,41 +25,12 @@ static const char* LOG_TAG = "NimBLEScan"; -/* - * Scanning filter policy - * NO_WL: - * Scanner processes all advertising packets (white list not used) except - * directed, connectable advertising packets not sent to the scanner. - * USE_WL: - * Scanner processes advertisements from white list only. A connectable, - * directed advertisment is ignored unless it contains scanners address. - * NO_WL_INITA: - * Scanner process all advertising packets (white list not used). A - * connectable, directed advertisement shall not be ignored if the InitA - * is a resolvable private address. - * USE_WL_INITA: - * Scanner process advertisements from white list only. A connectable, - * directed advertisement shall not be ignored if the InitA is a - * resolvable private address. - */ - -//#define BLE_HCI_SCAN_FILT_NO_WL (0) -//#define BLE_HCI_SCAN_FILT_USE_WL (1) -//#define BLE_HCI_SCAN_FILT_NO_WL_INITA (2) -//#define BLE_HCI_SCAN_FILT_USE_WL_INITA (3) -//#define BLE_HCI_SCAN_FILT_MAX (3) - /** * @brief Scan constuctor. */ NimBLEScan::NimBLEScan() { - uint8_t own_addr_type; - if(ble_hs_id_infer_auto(0, &own_addr_type) !=0){ - NIMBLE_LOGE(LOG_TAG, "error determining address type\n"); - return; - } - m_own_addr_type = own_addr_type; + m_own_addr_type = 0; m_scan_params.filter_policy = BLE_HCI_SCAN_FILT_NO_WL; m_scan_params.passive = 1; // If set, don’t send scan requests to advertisers (i.e., don’t request additional advertising data). 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) @@ -137,12 +108,17 @@ NimBLEScan::NimBLEScan() { advertisedDevice->m_timestamp = time(nullptr); if (pScan->m_pAdvertisedDeviceCallbacks) { - // If not active scanning report the result to the listener. - if(pScan->m_scan_params.passive || event->disc.event_type == BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) { - pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice); - // Otherwise wait for the scan response so we can report all of the data at once. - } else if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) { - pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice); + if(pScan->m_wantDuplicates || !advertisedDevice->m_callbackSent) { + // If not active scanning report the result to the listener. + if(pScan->m_scan_params.passive || event->disc.event_type == BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) { + advertisedDevice->m_callbackSent = true; + pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice); + + // Otherwise wait for the scan response so we can report all of the data at once. + } else if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) { + advertisedDevice->m_callbackSent = true; + pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice); + } } } @@ -186,13 +162,59 @@ void NimBLEScan::setActiveScan(bool active) { } // setActiveScan +/** + * @brief Set whether or not the BLE controller should only report results + * from devices it has not already seen. + * @param [in] active If true, scanned devices will only be reported once. + * @details The controller has a limited buffer and will start reporting + * dupicate devices once the limit is reached. + */ +void NimBLEScan::setDuplicateFilter(bool active) { + m_scan_params.filter_duplicates = active; +} // setDuplicateFilter + + +/** + * @brief Set whether or not the BLE controller only report scan results + * from devices advertising in limited discovery mode, i.e. directed advertising. + * @param [in] active If true, only limited discovery devices will be in scan results. + */ +void NimBLEScan::setLimitedOnly(bool active) { + m_scan_params.limited = active; +} // setLimited + + +/** + * @brief Sets the scan filter policy. + * @param [in] filter Can be one of: + * BLE_HCI_SCAN_FILT_NO_WL (0) + * Scanner processes all advertising packets (white list not used) except + * directed, connectable advertising packets not sent to the scanner. + * BLE_HCI_SCAN_FILT_USE_WL (1) + * Scanner processes advertisements from white list only. A connectable, + * directed advertisment is ignored unless it contains scanners address. + * BLE_HCI_SCAN_FILT_NO_WL_INITA (2) + * Scanner process all advertising packets (white list not used). A + * connectable, directed advertisement shall not be ignored if the InitA + * is a resolvable private address. + * BLE_HCI_SCAN_FILT_USE_WL_INITA (3) + * Scanner process advertisements from white list only. A connectable, + * directed advertisement shall not be ignored if the InitA is a + * resolvable private address. + */ +void NimBLEScan::setFilterPolicy(uint8_t filter) { + m_scan_params.filter_policy = filter; +} // setFilterPolicy + + /** * @brief Set the 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. */ -void NimBLEScan::setAdvertisedDeviceCallbacks(NimBLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks/*, bool wantDuplicates*/) { - //m_wantDuplicates = wantDuplicates; +void NimBLEScan::setAdvertisedDeviceCallbacks(NimBLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks, + bool wantDuplicates) { + m_wantDuplicates = wantDuplicates; m_pAdvertisedDeviceCallbacks = pAdvertisedDeviceCallbacks; } // setAdvertisedDeviceCallbacks diff --git a/src/NimBLEScan.h b/src/NimBLEScan.h index 06359f9..5bc7bcf 100644 --- a/src/NimBLEScan.h +++ b/src/NimBLEScan.h @@ -62,10 +62,13 @@ class NimBLEScan { public: bool start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResults), bool is_continue = false); NimBLEScanResults start(uint32_t duration, bool is_continue = false); - void setAdvertisedDeviceCallbacks(NimBLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks/*, bool wantDuplicates = false*/); + void setAdvertisedDeviceCallbacks(NimBLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks, bool wantDuplicates = false); void setActiveScan(bool active); void setInterval(uint16_t intervalMSecs); void setWindow(uint16_t windowMSecs); + void setDuplicateFilter(bool active); + void setLimitedOnly(bool active); + void setFilterPolicy(uint8_t filter); bool stop(); void clearResults(); NimBLEScanResults getResults();