Skip to content

Commit e8b5df4

Browse files
committed
fix memory leak, add multi connection features
1 parent b3ff6cc commit e8b5df4

File tree

2 files changed

+82
-51
lines changed

2 files changed

+82
-51
lines changed

cpp_utils/BLEScan.cpp

Lines changed: 72 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -48,22 +48,21 @@ void BLEScan::handleGAPEvent(
4848
esp_gap_ble_cb_event_t event,
4949
esp_ble_gap_cb_param_t* param) {
5050

51-
switch (event) {
52-
53-
// ESP_GAP_BLE_SCAN_RESULT_EVT
54-
// ---------------------------
55-
// scan_rst:
56-
// esp_gap_search_evt_t search_evt
57-
// esp_bd_addr_t bda
58-
// esp_bt_dev_type_t dev_type
59-
// esp_ble_addr_type_t ble_addr_type
60-
// esp_ble_evt_type_t ble_evt_type
61-
// int rssi
62-
// uint8_t ble_adv[ESP_BLE_ADV_DATA_LEN_MAX]
63-
// int flag
64-
// int num_resps
65-
// uint8_t adv_data_len
66-
// uint8_t scan_rsp_len
51+
switch(event) {
52+
53+
// ---------------------------
54+
// scan_rst:
55+
// esp_gap_search_evt_t search_evt
56+
// esp_bd_addr_t bda
57+
// esp_bt_dev_type_t dev_type
58+
// esp_ble_addr_type_t ble_addr_type
59+
// esp_ble_evt_type_t ble_evt_type
60+
// int rssi
61+
// uint8_t ble_adv[ESP_BLE_ADV_DATA_LEN_MAX]
62+
// int flag
63+
// int num_resps
64+
// uint8_t adv_data_len
65+
// uint8_t scan_rsp_len
6766
case ESP_GAP_BLE_SCAN_RESULT_EVT: {
6867

6968
switch(param->scan_rst.search_evt) {
@@ -73,11 +72,12 @@ void BLEScan::handleGAPEvent(
7372
// Event that indicates that the duration allowed for the search has completed or that we have been
7473
// asked to stop.
7574
case ESP_GAP_SEARCH_INQ_CMPL_EVT: {
75+
ESP_LOGW(LOG_TAG, "ESP_GAP_SEARCH_INQ_CMPL_EVT");
7676
m_stopped = true;
77+
m_semaphoreScanEnd.give();
7778
if (m_scanCompleteCB != nullptr) {
7879
m_scanCompleteCB(m_scanResults);
7980
}
80-
m_semaphoreScanEnd.give();
8181
break;
8282
} // ESP_GAP_SEARCH_INQ_CMPL_EVT
8383

@@ -90,52 +90,58 @@ void BLEScan::handleGAPEvent(
9090
break;
9191
}
9292

93-
// Examine our list of previously scanned addresses and, if we found this one already,
94-
// ignore it.
93+
// Examine our list of previously scanned addresses and, if we found this one already,
94+
// ignore it.
9595
BLEAddress advertisedAddress(param->scan_rst.bda);
9696
bool found = false;
9797

98-
for (uint32_t i = 0; i < m_scanResults.getCount(); i++) {
99-
if (m_scanResults.getDevice(i).getAddress().equals(advertisedAddress)) {
100-
found = true;
101-
break;
102-
}
98+
if (m_scanResults.m_vectorAdvertisedDevices.count(advertisedAddress.toString()) != 0) {
99+
found = true;
103100
}
101+
104102
if (found && !m_wantDuplicates) { // If we found a previous entry AND we don't want duplicates, then we are done.
105103
ESP_LOGD(LOG_TAG, "Ignoring %s, already seen it.", advertisedAddress.toString().c_str());
104+
vTaskDelay(1); // <--- allow to switch task in case we scan infinity and dont have new devices to report, or we will blocked here
106105
break;
107106
}
108107

109108
// We now construct a model of the advertised device that we have just found for the first
110109
// time.
111-
BLEAdvertisedDevice advertisedDevice;
112-
advertisedDevice.setAddress(advertisedAddress);
113-
advertisedDevice.setRSSI(param->scan_rst.rssi);
114-
advertisedDevice.setAdFlag(param->scan_rst.flag);
115-
advertisedDevice.parseAdvertisement((uint8_t*)param->scan_rst.ble_adv);
116-
advertisedDevice.setScan(this);
110+
// ESP_LOG_BUFFER_HEXDUMP(LOG_TAG, (uint8_t*)param->scan_rst.ble_adv, param->scan_rst.adv_data_len + param->scan_rst.scan_rsp_len, ESP_LOG_DEBUG);
111+
// ESP_LOGW(LOG_TAG, "bytes length: %d + %d, addr type: %d", param->scan_rst.adv_data_len, param->scan_rst.scan_rsp_len, param->scan_rst.ble_addr_type);
112+
BLEAdvertisedDevice *advertisedDevice = new BLEAdvertisedDevice();
113+
advertisedDevice->setAddress(advertisedAddress);
114+
advertisedDevice->setRSSI(param->scan_rst.rssi);
115+
advertisedDevice->setAdFlag(param->scan_rst.flag);
116+
advertisedDevice->parseAdvertisement((uint8_t*)param->scan_rst.ble_adv, param->scan_rst.adv_data_len + param->scan_rst.scan_rsp_len);
117+
advertisedDevice->setScan(this);
118+
advertisedDevice->setAddressType(param->scan_rst.ble_addr_type);
117119

118-
if (m_pAdvertisedDeviceCallbacks) {
119-
m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
120+
if (!found) { // If we have previously seen this device, don't record it again.
121+
m_scanResults.m_vectorAdvertisedDevices.insert(std::pair<std::string, BLEAdvertisedDevice*>(advertisedAddress.toString(), advertisedDevice));
120122
}
121123

122-
if (!found) { // If we have previously seen this device, don't record it again.
123-
m_scanResults.m_vectorAdvertisedDevices.push_back(advertisedDevice);
124+
if (m_pAdvertisedDeviceCallbacks) {
125+
m_pAdvertisedDeviceCallbacks->onResult(*advertisedDevice);
124126
}
127+
if(found)
128+
delete advertisedDevice;
125129

126130
break;
127131
} // ESP_GAP_SEARCH_INQ_RES_EVT
128132

129-
default:
133+
default: {
130134
break;
135+
}
131136
} // switch - search_evt
132137

133138

134139
break;
135140
} // ESP_GAP_BLE_SCAN_RESULT_EVT
136141

137-
default:
142+
default: {
138143
break;
144+
} // default
139145
} // End switch
140146
} // gapEventHandler
141147

@@ -188,15 +194,23 @@ void BLEScan::setWindow(uint16_t windowMSecs) {
188194
* @brief Start scanning.
189195
* @param [in] duration The duration in seconds for which to scan.
190196
* @param [in] scanCompleteCB A function to be called when scanning has completed.
197+
* @param [in] are we continue scan (true) or we want to clear stored devices (false)
191198
* @return True if scan started or false if there was an error.
192199
*/
193-
bool BLEScan::start(uint32_t duration, void (*scanCompleteCB)(BLEScanResults)) {
200+
bool BLEScan::start(uint32_t duration, void (*scanCompleteCB)(BLEScanResults), bool is_continue) {
194201
ESP_LOGD(LOG_TAG, ">> start(duration=%d)", duration);
195202

196203
m_semaphoreScanEnd.take(std::string("start"));
197204
m_scanCompleteCB = scanCompleteCB; // Save the callback to be invoked when the scan completes.
198205

199-
m_scanResults.m_vectorAdvertisedDevices.clear();
206+
// if we are connecting to devices that are advertising even after being connected, multiconnecting peripherals
207+
// then we should not clear map or we will connect the same device few times
208+
if(!is_continue) {
209+
for(auto _dev : m_scanResults.m_vectorAdvertisedDevices){
210+
delete _dev.second;
211+
}
212+
m_scanResults.m_vectorAdvertisedDevices.clear();
213+
}
200214

201215
esp_err_t errRc = ::esp_ble_gap_set_scan_params(&m_scan_params);
202216

@@ -226,8 +240,8 @@ bool BLEScan::start(uint32_t duration, void (*scanCompleteCB)(BLEScanResults)) {
226240
* @param [in] duration The duration in seconds for which to scan.
227241
* @return The BLEScanResults.
228242
*/
229-
BLEScanResults BLEScan::start(uint32_t duration) {
230-
if (start(duration, nullptr)) {
243+
BLEScanResults BLEScan::start(uint32_t duration, bool is_continue) {
244+
if(start(duration, nullptr, is_continue)) {
231245
m_semaphoreScanEnd.wait("start"); // Wait for the semaphore to release.
232246
}
233247
return m_scanResults;
@@ -244,24 +258,31 @@ void BLEScan::stop() {
244258
esp_err_t errRc = ::esp_ble_gap_stop_scanning();
245259

246260
m_stopped = true;
261+
m_semaphoreScanEnd.give();
247262

248263
if (errRc != ESP_OK) {
249264
ESP_LOGE(LOG_TAG, "esp_ble_gap_stop_scanning: err: %d, text: %s", errRc, GeneralUtils::errorToString(errRc));
250265
return;
251266
}
252267

253-
m_semaphoreScanEnd.give();
254-
255268
ESP_LOGD(LOG_TAG, "<< stop()");
256269
} // stop
257270

271+
// delete peer device from cache after disconnecting, it is required in case we are connecting to devices with not public address
272+
void BLEScan::erase(BLEAddress address) {
273+
ESP_LOGI(LOG_TAG, "erase device: %s", address.toString().c_str());
274+
BLEAdvertisedDevice *advertisedDevice = m_scanResults.m_vectorAdvertisedDevices.find(address.toString())->second;
275+
m_scanResults.m_vectorAdvertisedDevices.erase(address.toString());
276+
delete advertisedDevice;
277+
}
278+
258279

259280
/**
260281
* @brief Dump the scan results to the log.
261282
*/
262283
void BLEScanResults::dump() {
263284
ESP_LOGD(LOG_TAG, ">> Dump scan results:");
264-
for (uint32_t i = 0; i < getCount(); i++) {
285+
for (int i=0; i<getCount(); i++) {
265286
ESP_LOGD(LOG_TAG, "- %s", getDevice(i).toString().c_str());
266287
}
267288
} // dump
@@ -283,7 +304,14 @@ int BLEScanResults::getCount() {
283304
* @return The device at the specified index.
284305
*/
285306
BLEAdvertisedDevice BLEScanResults::getDevice(uint32_t i) {
286-
return m_vectorAdvertisedDevices.at(i);
307+
uint32_t x = 0;
308+
BLEAdvertisedDevice dev = *m_vectorAdvertisedDevices.begin()->second;
309+
for (auto it = m_vectorAdvertisedDevices.begin(); it != m_vectorAdvertisedDevices.end(); it++) {
310+
dev = *it->second;
311+
if (x==i) break;
312+
x++;
313+
}
314+
return dev;
287315
}
288316

289317

cpp_utils/BLEScan.h

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
#if defined(CONFIG_BT_ENABLED)
1212
#include <esp_gap_ble_api.h>
1313

14-
#include <vector>
14+
// #include <vector>
15+
#include <string>
1516
#include "BLEAdvertisedDevice.h"
1617
#include "BLEClient.h"
1718
#include "FreeRTOS.h"
@@ -37,7 +38,7 @@ class BLEScanResults {
3738

3839
private:
3940
friend BLEScan;
40-
std::vector<BLEAdvertisedDevice> m_vectorAdvertisedDevices;
41+
std::map<std::string, BLEAdvertisedDevice*> m_vectorAdvertisedDevices;
4142
};
4243

4344
/**
@@ -53,22 +54,24 @@ class BLEScan {
5354
bool wantDuplicates = false);
5455
void setInterval(uint16_t intervalMSecs);
5556
void setWindow(uint16_t windowMSecs);
56-
bool start(uint32_t duration, void (*scanCompleteCB)(BLEScanResults));
57-
BLEScanResults start(uint32_t duration);
57+
bool start(uint32_t duration, void (*scanCompleteCB)(BLEScanResults), bool is_continue = false);
58+
BLEScanResults start(uint32_t duration, bool is_continue = false);
5859
void stop();
60+
void erase(BLEAddress address);
61+
// void setPower(esp_power_level_t powerLevel);
5962

6063
private:
6164
BLEScan(); // One doesn't create a new instance instead one asks the BLEDevice for the singleton.
6265
friend class BLEDevice;
6366
void handleGAPEvent(
6467
esp_gap_ble_cb_event_t event,
6568
esp_ble_gap_cb_param_t* param);
66-
void parseAdvertisement(BLEClient* pRemoteDevice, uint8_t* payload);
69+
void parseAdvertisement(BLEClient* pRemoteDevice, uint8_t *payload);
6770

6871

6972
esp_ble_scan_params_t m_scan_params;
70-
BLEAdvertisedDeviceCallbacks* m_pAdvertisedDeviceCallbacks;
71-
bool m_stopped;
73+
BLEAdvertisedDeviceCallbacks* m_pAdvertisedDeviceCallbacks = nullptr;
74+
bool m_stopped = true;
7275
FreeRTOS::Semaphore m_semaphoreScanEnd = FreeRTOS::Semaphore("ScanEnd");
7376
BLEScanResults m_scanResults;
7477
bool m_wantDuplicates;

0 commit comments

Comments
 (0)