@@ -182,25 +182,30 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
182
182
return false ;
183
183
}
184
184
185
- if (isConnected () || m_pTaskData != nullptr ) {
185
+ if (isConnected () || m_connEstablished || m_pTaskData != nullptr ) {
186
186
NIMBLE_LOGE (LOG_TAG, " Client busy, connected to %s, id=%d" ,
187
187
std::string (m_peerAddress).c_str (), getConnId ());
188
188
return false ;
189
189
}
190
190
191
+ ble_addr_t peerAddr_t;
192
+ memcpy (&peerAddr_t.val , address.getNative (),6 );
193
+ peerAddr_t.type = address.getType ();
194
+ if (ble_gap_conn_find_by_addr (&peerAddr_t, NULL ) == 0 ) {
195
+ NIMBLE_LOGE (LOG_TAG, " A connection to %s already exists" ,
196
+ address.toString ().c_str ());
197
+ return false ;
198
+ }
199
+
191
200
if (address == NimBLEAddress (" " )) {
192
201
NIMBLE_LOGE (LOG_TAG, " Invalid peer address;(NULL)" );
193
202
return false ;
194
- } else if (m_peerAddress != address) {
203
+ } else {
195
204
m_peerAddress = address;
196
205
}
197
206
198
- ble_addr_t peerAddr_t;
199
- memcpy (&peerAddr_t.val , m_peerAddress.getNative (),6 );
200
- peerAddr_t.type = m_peerAddress.getType ();
201
-
202
-
203
207
ble_task_data_t taskData = {this , xTaskGetCurrentTaskHandle (), 0 , nullptr };
208
+ m_pTaskData = &taskData;
204
209
int rc = 0 ;
205
210
206
211
/* Try to connect the the advertiser. Allow 30 seconds (30000 ms) for
@@ -213,39 +218,43 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
213
218
NimBLEClient::handleGapEvent, this );
214
219
switch (rc) {
215
220
case 0 :
216
- m_pTaskData = &taskData;
217
221
break ;
218
222
219
223
case BLE_HS_EBUSY:
220
224
// Scan was still running, stop it and try again
221
225
if (!NimBLEDevice::getScan ()->stop ()) {
222
- return false ;
226
+ rc = BLE_HS_EUNKNOWN ;
223
227
}
224
228
break ;
225
229
226
230
case BLE_HS_EDONE:
227
231
// A connection to this device already exists, do not connect twice.
228
232
NIMBLE_LOGE (LOG_TAG, " Already connected to device; addr=%s" ,
229
233
std::string (m_peerAddress).c_str ());
230
- return false ;
234
+ break ;
231
235
232
236
case BLE_HS_EALREADY:
233
237
// Already attemting to connect to this device, cancel the previous
234
238
// attempt and report failure here so we don't get 2 connections.
235
239
NIMBLE_LOGE (LOG_TAG, " Already attempting to connect to %s - cancelling" ,
236
240
std::string (m_peerAddress).c_str ());
237
241
ble_gap_conn_cancel ();
238
- return false ;
242
+ break ;
239
243
240
244
default :
241
245
NIMBLE_LOGE (LOG_TAG, " Failed to connect to %s, rc=%d; %s" ,
242
246
std::string (m_peerAddress).c_str (),
243
247
rc, NimBLEUtils::returnCodeToString (rc));
244
- return false ;
248
+ break ;
245
249
}
246
250
247
251
} while (rc == BLE_HS_EBUSY);
248
252
253
+ if (rc != 0 ) {
254
+ m_pTaskData = nullptr ;
255
+ return false ;
256
+ }
257
+
249
258
// Wait for the connect timeout time +1 second for the connection to complete
250
259
if (ulTaskNotifyTake (pdTRUE, pdMS_TO_TICKS (m_connectTimeout + 1000 )) == pdFALSE) {
251
260
m_pTaskData = nullptr ;
@@ -255,7 +264,7 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
255
264
disconnect ();
256
265
} else {
257
266
// workaround; if the controller doesn't cancel the connection
258
- // at the timeout cancel it here.
267
+ // at the timeout, cancel it here.
259
268
NIMBLE_LOGE (LOG_TAG, " Connect timeout - cancelling" );
260
269
ble_gap_conn_cancel ();
261
270
}
@@ -269,7 +278,7 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
269
278
// If the failure was not a result of a disconnection
270
279
// make sure we disconnect now to avoid dangling connections
271
280
if (isConnected ()) {
272
- ble_gap_terminate (m_conn_id, BLE_ERR_REM_USER_CONN_TERM );
281
+ disconnect ( );
273
282
}
274
283
return false ;
275
284
} else {
@@ -325,26 +334,35 @@ bool NimBLEClient::secureConnection() {
325
334
*/
326
335
int NimBLEClient::disconnect (uint8_t reason) {
327
336
NIMBLE_LOGD (LOG_TAG, " >> disconnect()" );
328
-
329
337
int rc = 0 ;
330
- if (isConnected ()){
338
+ if (isConnected ()) {
339
+ // If the timer was already started, ignore this call.
340
+ if (ble_npl_callout_is_active (&m_dcTimer)) {
341
+ NIMBLE_LOGI (LOG_TAG, " Already disconnecting, timer started" );
342
+ return BLE_HS_EALREADY;
343
+ }
344
+
345
+ ble_gap_conn_desc desc;
346
+ if (ble_gap_conn_find (m_conn_id, &desc) != 0 ){
347
+ NIMBLE_LOGI (LOG_TAG, " Connection ID not found" );
348
+ return BLE_HS_EALREADY;
349
+ }
350
+
351
+ // We use a timer to detect a controller error in the event that it does
352
+ // not inform the stack when disconnection is complete.
353
+ // This is a common error in certain esp-idf versions.
354
+ // The disconnect timeout time is the supervison timeout time + 1 second.
355
+ // In the case that the event happenss shortly after the supervision timeout
356
+ // we don't want to prematurely reset the host.
357
+ ble_npl_time_t ticks;
358
+ ble_npl_time_ms_to_ticks ((desc.supervision_timeout + 100 ) * 10 , &ticks);
359
+ ble_npl_callout_reset (&m_dcTimer, ticks);
360
+
331
361
rc = ble_gap_terminate (m_conn_id, reason);
332
- if (rc == 0 ) {
333
- ble_addr_t peerAddr_t;
334
- memcpy (&peerAddr_t.val , m_peerAddress.getNative (),6 );
335
- peerAddr_t.type = m_peerAddress.getType ();
336
-
337
- // Set the disconnect timeout to the supervison timeout time + 1 second
338
- // In case the event triggers shortly after the supervision timeout.
339
- // We don't want to prematurely reset the host.
340
- ble_gap_conn_desc desc;
341
- if (ble_gap_conn_find_by_addr (&peerAddr_t, &desc) == 0 ){
342
- ble_npl_time_t ticks;
343
- ble_npl_time_ms_to_ticks ((desc.supervision_timeout + 100 ) * 10 , &ticks);
344
- ble_npl_callout_reset (&m_dcTimer, ticks);
345
- NIMBLE_LOGD (LOG_TAG, " DC TIMEOUT = %dms" , (desc.supervision_timeout + 100 ) * 10 );
362
+ if (rc != 0 ) {
363
+ if (rc != BLE_HS_EALREADY) {
364
+ ble_npl_callout_stop (&m_dcTimer);
346
365
}
347
- } else if (rc != BLE_HS_EALREADY) {
348
366
NIMBLE_LOGE (LOG_TAG, " ble_gap_terminate failed: rc=%d %s" ,
349
367
rc, NimBLEUtils::returnCodeToString (rc));
350
368
}
@@ -797,14 +815,15 @@ uint16_t NimBLEClient::getMTU() {
797
815
break ;
798
816
}
799
817
800
- client->m_conn_id = BLE_HS_CONN_HANDLE_NONE;
801
-
802
818
// Stop the disconnect timer since we are now disconnected.
803
819
ble_npl_callout_stop (&client->m_dcTimer );
804
820
805
821
// Remove the device from ignore list so we will scan it again
806
822
NimBLEDevice::removeIgnored (client->m_peerAddress );
807
823
824
+ // No longer connected, clear the connection ID.
825
+ client->m_conn_id = BLE_HS_CONN_HANDLE_NONE;
826
+
808
827
// If we received a connected event but did not get established (no PDU)
809
828
// then a disconnect event will be sent but we should not send it to the
810
829
// app for processing. Instead we will ensure the task is released
0 commit comments