@@ -113,6 +113,7 @@ typedef struct {
113
113
int32_t conn_id ;
114
114
uint16_t mtu ;
115
115
esp_gatt_if_t gatt_if ;
116
+ esp_ble_addr_type_t addr_type ;
116
117
} bt_connection_obj_t ;
117
118
118
119
typedef struct {
@@ -258,7 +259,6 @@ static esp_ble_adv_params_t bt_adv_params = {
258
259
259
260
static bool mod_bt_allow_resume_deinit ;
260
261
static uint16_t mod_bt_gatts_mtu_restore = 0 ;
261
- static bool mod_bt_is_conn_restore_available ;
262
262
263
263
static nvs_handle modbt_nvs_handle ;
264
264
static uint8_t tx_pwr_level_to_dbm [] = {-12 , -9 , -6 , -3 , 0 , 3 , 6 , 9 };
@@ -278,7 +278,7 @@ STATIC void gattc_char_callback_handler(void *arg);
278
278
STATIC void gatts_char_callback_handler (void * arg );
279
279
static mp_obj_t modbt_start_scan (mp_obj_t timeout );
280
280
static mp_obj_t modbt_conn_disconnect (mp_obj_t self_in );
281
- static mp_obj_t modbt_connect (mp_obj_t addr );
281
+ static mp_obj_t modbt_connect (mp_obj_t addr , esp_ble_addr_type_t addr_type );
282
282
283
283
/******************************************************************************
284
284
DEFINE PUBLIC FUNCTIONS
@@ -317,7 +317,6 @@ void modbt_init0(void) {
317
317
esp_bt_controller_mem_release (ESP_BT_MODE_CLASSIC_BT );
318
318
319
319
mod_bt_allow_resume_deinit = false;
320
- mod_bt_is_conn_restore_available = false;
321
320
}
322
321
323
322
void modbt_deinit (bool allow_reconnect )
@@ -356,11 +355,14 @@ void modbt_deinit(bool allow_reconnect)
356
355
xEventGroupWaitBits (bt_event_group , MOD_BT_GATTS_DISCONN_EVT | MOD_BT_GATTS_CLOSE_EVT , true, true, 1000 /portTICK_PERIOD_MS );
357
356
}
358
357
358
+ esp_ble_gattc_app_unregister (MOD_BT_CLIENT_APP_ID );
359
+ esp_ble_gatts_app_unregister (MOD_BT_SERVER_APP_ID );
360
+
359
361
esp_bluedroid_disable ();
360
362
esp_bluedroid_deinit ();
361
363
esp_bt_controller_disable ();
364
+ esp_bt_controller_deinit ();
362
365
bt_obj .init = false;
363
- mod_bt_is_conn_restore_available = false;
364
366
xEventGroupClearBits (bt_event_group , MOD_BT_GATTC_MTU_EVT | MOD_BT_GATTS_MTU_EVT | MOD_BT_GATTS_DISCONN_EVT | MOD_BT_GATTS_CLOSE_EVT );
365
367
}
366
368
}
@@ -381,39 +383,48 @@ void bt_resume(bool reconnect)
381
383
nlr_raise (mp_obj_new_exception_msg (& mp_type_OSError , "Bluetooth enable failed" ));
382
384
}
383
385
386
+ esp_ble_gap_register_callback (gap_events_handler );
387
+ esp_ble_gattc_register_callback (gattc_events_handler );
388
+ esp_ble_gatts_register_callback (gatts_event_handler );
389
+
384
390
esp_ble_gattc_app_register (MOD_BT_CLIENT_APP_ID );
385
391
esp_ble_gatts_app_register (MOD_BT_SERVER_APP_ID );
386
392
387
393
esp_ble_gatt_set_local_mtu (mod_bt_gatts_mtu_restore );
388
394
389
- bt_connection_obj_t * connection_obj = NULL ;
390
-
391
- if (MP_STATE_PORT (btc_conn_list ).len > 0 )
395
+ // If this list has 0 elements it means there were no active connections
396
+ if (MP_STATE_PORT (btc_conn_list ).len > 0 && reconnect )
392
397
{
393
- /* Get the Last gattc connection obj before sleep */
394
- connection_obj = ((bt_connection_obj_t * )(MP_STATE_PORT (btc_conn_list ).items [MP_STATE_PORT (btc_conn_list ).len - 1 ]));
395
- }
398
+ /* Enable Scan */
399
+ modbt_start_scan (MP_OBJ_NEW_SMALL_INT (-1 ));
400
+ mp_hal_delay_ms (50 );
401
+ while (!bt_obj .scanning ){
402
+ /* Wait for scanning to start */
403
+ }
396
404
397
- if (reconnect )
398
- {
399
- /* Check if there was a gattc connection Active before sleep */
400
- if (connection_obj != NULL ) {
401
- if (connection_obj -> conn_id >= 0 ) {
402
- /* Enable Scan */
403
- modbt_start_scan (MP_OBJ_NEW_SMALL_INT (-1 ));
404
- mp_hal_delay_ms (50 );
405
- while (!bt_obj .scanning ){
406
- /* Wait for scanning to start */
407
- }
408
- /* re-connect to Last Connection */
409
- mp_obj_list_remove ((void * )& MP_STATE_PORT (btc_conn_list ), connection_obj );
410
- mp_obj_list_append ((void * )& MP_STATE_PORT (btc_conn_list ), modbt_connect (mp_obj_new_bytes ((const byte * )connection_obj -> srv_bda , 6 )));
405
+ /* Re-connect to all previously existing connections */
406
+ // Need to save the old connections into a temporary list because during connect the original list is manipulated (items added)
407
+ mp_obj_list_t btc_conn_list_tmp ;
408
+ mp_obj_list_init (& btc_conn_list_tmp , 0 );
409
+ for (mp_uint_t i = 0 ; i < MP_STATE_PORT (btc_conn_list ).len ; i ++ ) {
410
+ bt_connection_obj_t * connection_obj = ((bt_connection_obj_t * )(MP_STATE_PORT (btc_conn_list ).items [i ]));
411
+ mp_obj_list_append (& btc_conn_list_tmp , connection_obj );
412
+ }
411
413
412
- mod_bt_is_conn_restore_available = true;
414
+ // Connect to the old connections
415
+ for (mp_uint_t i = 0 ; i < btc_conn_list_tmp .len ; i ++ ) {
416
+ bt_connection_obj_t * connection_obj = ((bt_connection_obj_t * )(btc_conn_list_tmp .items [i ]));
417
+ // Initiates re-connection
418
+ bt_connection_obj_t * new_connection_obj = modbt_connect (mp_obj_new_bytes ((const byte * )connection_obj -> srv_bda , 6 ), connection_obj -> addr_type );
419
+ // If new connection object has been created then overwrite the original one so from the MicroPython code the same reference can be used
420
+ if (new_connection_obj != mp_const_none ) {
421
+ memcpy (connection_obj , new_connection_obj , sizeof (bt_connection_obj_t ));
422
+ // As modbt_connect appends the new connection to the original list, it needs to be removed because it is not needed
423
+ mp_obj_list_remove ((void * )& MP_STATE_PORT (btc_conn_list ), new_connection_obj );
413
424
}
414
425
}
415
426
416
- /* See if there was an averstisment active before Sleep */
427
+ /* See if there was an advertisement active before Sleep */
417
428
if (bt_obj .advertising ) {
418
429
esp_ble_gap_start_advertising (& bt_adv_params );
419
430
}
@@ -456,19 +467,19 @@ static void create_hash(uint32_t pin, uint8_t *h_value)
456
467
{
457
468
bt_hash_obj_t pin_hash ;
458
469
mbedtls_sha1_context sha1_context ;
459
-
470
+
460
471
mbedtls_sha1_init (& sha1_context );
461
472
mbedtls_sha1_starts_ret (& sha1_context );
462
-
473
+
463
474
pin_hash .pin = pin ;
464
475
mbedtls_sha1_update_ret (& sha1_context , pin_hash .value , 4 );
465
-
476
+
466
477
mbedtls_sha1_finish_ret (& sha1_context , h_value );
467
478
mbedtls_sha1_free (& sha1_context );
468
479
}
469
480
470
- static bool pin_changed (uint32_t new_pin )
471
- {
481
+ static bool pin_changed (uint32_t new_pin )
482
+ {
472
483
bool ret = false;
473
484
uint32_t h_size = MOD_BT_HASH_SIZE ;
474
485
uint8_t h_stored [MOD_BT_HASH_SIZE ] = {0 };
@@ -480,17 +491,17 @@ static bool pin_changed(uint32_t new_pin)
480
491
mp_printf (& mp_plat_print , "Error opening secure BLE NVS namespace!\n" );
481
492
}
482
493
nvs_get_blob (modbt_nvs_handle , key , h_stored , & h_size );
483
-
494
+
484
495
create_hash (new_pin , h_created );
485
-
496
+
486
497
if (memcmp (h_stored , h_created , MOD_BT_HASH_SIZE ) != 0 ) {
487
498
esp_err = nvs_set_blob (modbt_nvs_handle , key , h_created , h_size );
488
499
if (esp_err == ESP_OK ) {
489
500
nvs_commit (modbt_nvs_handle );
490
501
ret = true;
491
502
}
492
503
}
493
-
504
+
494
505
nvs_close (modbt_nvs_handle );
495
506
496
507
return ret ;
@@ -547,8 +558,7 @@ static void set_pin(uint32_t new_pin)
547
558
static void close_connection (int32_t conn_id ) {
548
559
for (mp_uint_t i = 0 ; i < MP_STATE_PORT (btc_conn_list ).len ; i ++ ) {
549
560
bt_connection_obj_t * connection_obj = ((bt_connection_obj_t * )(MP_STATE_PORT (btc_conn_list ).items [i ]));
550
- /* Only reset Conn Id if it is a normal disconnect not module de-init to mark conn obj to be restored */
551
- if (connection_obj -> conn_id == conn_id && (!mod_bt_allow_resume_deinit )) {
561
+ if (connection_obj -> conn_id == conn_id ) {
552
562
connection_obj -> conn_id = -1 ;
553
563
mp_obj_list_remove ((void * )& MP_STATE_PORT (btc_conn_list ), connection_obj );
554
564
}
@@ -1371,13 +1381,19 @@ STATIC mp_obj_t bt_events(mp_obj_t self_in) {
1371
1381
}
1372
1382
STATIC MP_DEFINE_CONST_FUN_OBJ_1 (bt_events_obj , bt_events );
1373
1383
1374
- static mp_obj_t bt_connect_helper (mp_obj_t addr , TickType_t timeout ){
1384
+ static mp_obj_t bt_connect_helper (mp_obj_t addr , TickType_t timeout , esp_ble_addr_type_t addr_type ){
1375
1385
1376
1386
bt_event_result_t bt_event ;
1377
1387
EventBits_t uxBits ;
1378
1388
1379
1389
if (bt_obj .busy ) {
1380
- nlr_raise (mp_obj_new_exception_msg (& mp_type_OSError , "operation already in progress" ));
1390
+ // Only drop exception if not called from bt_resume() API, otherwise return with mp_const_none on error
1391
+ if (mod_bt_allow_resume_deinit == false) {
1392
+ nlr_raise (mp_obj_new_exception_msg (& mp_type_OSError , "operation already in progress" ));
1393
+ }
1394
+ else {
1395
+ return mp_const_none ;
1396
+ }
1381
1397
}
1382
1398
1383
1399
if (bt_obj .scanning ) {
@@ -1393,23 +1409,37 @@ static mp_obj_t bt_connect_helper(mp_obj_t addr, TickType_t timeout){
1393
1409
bt_obj .busy = true;
1394
1410
1395
1411
/* Initiate a background connection, esp_ble_gattc_open returns immediately */
1396
- if (ESP_OK != esp_ble_gattc_open (bt_obj .gattc_if , bufinfo .buf , BLE_ADDR_TYPE_PUBLIC , true)) {
1397
- nlr_raise (mp_obj_new_exception_msg (& mp_type_OSError , mpexception_os_operation_failed ));
1412
+ if (ESP_OK != esp_ble_gattc_open (bt_obj .gattc_if , bufinfo .buf , addr_type , true)) {
1413
+ // Only drop exception if not called from bt_resume() API, otherwise return with mp_const_none on error
1414
+ if (mod_bt_allow_resume_deinit == false) {
1415
+ nlr_raise (mp_obj_new_exception_msg (& mp_type_OSError , mpexception_os_operation_failed ));
1416
+ }
1417
+ else {
1418
+ return mp_const_none ;
1419
+ }
1398
1420
}
1421
+
1399
1422
MP_THREAD_GIL_EXIT ();
1400
1423
if (xQueueReceive (xScanQueue , & bt_event , timeout ) == pdTRUE )
1401
1424
{
1402
1425
MP_THREAD_GIL_ENTER ();
1403
1426
1404
1427
if (bt_event .connection .conn_id < 0 ) {
1405
- nlr_raise (mp_obj_new_exception_msg (& mp_type_OSError , "connection refused" ));
1428
+ // Only drop exception if not called from bt_resume() API, otherwise return with mp_const_none on error
1429
+ if (mod_bt_allow_resume_deinit == false) {
1430
+ nlr_raise (mp_obj_new_exception_msg (& mp_type_OSError , "connection refused" ));
1431
+ }
1432
+ else {
1433
+ return mp_const_none ;
1434
+ }
1406
1435
}
1407
1436
1408
1437
// setup the object
1409
1438
bt_connection_obj_t * conn = m_new_obj (bt_connection_obj_t );
1410
1439
conn -> base .type = (mp_obj_t )& mod_bt_connection_type ;
1411
1440
conn -> conn_id = bt_event .connection .conn_id ;
1412
1441
conn -> gatt_if = bt_event .connection .gatt_if ;
1442
+ conn -> addr_type = addr_type ;
1413
1443
1414
1444
MP_THREAD_GIL_EXIT ();
1415
1445
uxBits = xEventGroupWaitBits (bt_event_group , MOD_BT_GATTC_MTU_EVT , true, true, 1000 /portTICK_PERIOD_MS );
@@ -1421,14 +1451,22 @@ static mp_obj_t bt_connect_helper(mp_obj_t addr, TickType_t timeout){
1421
1451
}
1422
1452
memcpy (conn -> srv_bda , bt_event .connection .srv_bda , 6 );
1423
1453
mp_obj_list_append ((void * )& MP_STATE_PORT (btc_conn_list ), conn );
1454
+
1424
1455
return conn ;
1425
1456
}
1426
1457
else
1427
1458
{
1428
1459
MP_THREAD_GIL_ENTER ();
1429
1460
1430
1461
(void )esp_ble_gap_disconnect (bufinfo .buf );
1431
- nlr_raise (mp_obj_new_exception_msg (& mp_type_TimeoutError , "timed out" ));
1462
+
1463
+ // Only drop exception if not called from bt_resume() API, otherwise return with mp_const_none on error
1464
+ if (mod_bt_allow_resume_deinit == false) {
1465
+ nlr_raise (mp_obj_new_exception_msg (& mp_type_TimeoutError , "timed out" ));
1466
+ }
1467
+ else {
1468
+ return mp_const_none ;
1469
+ }
1432
1470
}
1433
1471
return mp_const_none ;
1434
1472
}
@@ -1439,6 +1477,7 @@ STATIC mp_obj_t bt_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t
1439
1477
STATIC const mp_arg_t allowed_args [] = {
1440
1478
{ MP_QSTR_addr , MP_ARG_REQUIRED | MP_ARG_OBJ , },
1441
1479
{ MP_QSTR_timeout , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = MP_OBJ_NULL } },
1480
+ { MP_QSTR_addr_type , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = MP_OBJ_NULL }},
1442
1481
};
1443
1482
1444
1483
// parse arguments
@@ -1447,7 +1486,7 @@ STATIC mp_obj_t bt_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t
1447
1486
1448
1487
mp_obj_t addr = args [0 ].u_obj ;
1449
1488
1450
- /* Timeout parameter is in miliseconds */
1489
+ /* Timeout parameter is in milliseconds */
1451
1490
TickType_t timeout ;
1452
1491
if (args [1 ].u_obj == MP_OBJ_NULL ){
1453
1492
timeout = portMAX_DELAY ;
@@ -1463,13 +1502,30 @@ STATIC mp_obj_t bt_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t
1463
1502
}
1464
1503
}
1465
1504
1466
- return bt_connect_helper (addr , timeout );
1505
+ /* addr_type parameter */
1506
+ uint32_t addr_type ;
1507
+ if (args [2 ].u_obj == MP_OBJ_NULL ){
1508
+ addr_type = BLE_ADDR_TYPE_PUBLIC ;
1509
+ }
1510
+ else
1511
+ {
1512
+ if (MP_OBJ_IS_SMALL_INT (args [2 ].u_obj ) == true) {
1513
+ addr_type = mp_obj_get_int (args [2 ].u_obj );
1514
+ }
1515
+ else
1516
+ {
1517
+ nlr_raise (mp_obj_new_exception_msg (& mp_type_ValueError , "If addr_type is specified it must be a valid integer number" ));
1518
+ }
1519
+ }
1520
+
1521
+
1522
+ return bt_connect_helper (addr , timeout , addr_type );
1467
1523
}
1468
1524
STATIC MP_DEFINE_CONST_FUN_OBJ_KW (bt_connect_obj , 1 , bt_connect );
1469
1525
1470
- static mp_obj_t modbt_connect (mp_obj_t addr )
1526
+ static mp_obj_t modbt_connect (mp_obj_t addr , esp_ble_addr_type_t addr_type )
1471
1527
{
1472
- return bt_connect_helper (addr , portMAX_DELAY );
1528
+ return bt_connect_helper (addr , portMAX_DELAY , addr_type );
1473
1529
}
1474
1530
1475
1531
@@ -1482,7 +1538,7 @@ STATIC mp_obj_t bt_set_advertisement_params (mp_uint_t n_args, const mp_obj_t *p
1482
1538
{ MP_QSTR_channel_map , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = MP_OBJ_NULL } },
1483
1539
{ MP_QSTR_adv_filter_policy , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = MP_OBJ_NULL } },
1484
1540
};
1485
-
1541
+
1486
1542
// parse args
1487
1543
mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
1488
1544
mp_arg_parse_all (n_args - 1 , pos_args + 1 , kw_args , MP_ARRAY_SIZE (args ), allowed_args , args );
@@ -1635,14 +1691,14 @@ STATIC mp_obj_t bt_set_advertisement_raw(mp_obj_t self_in, mp_obj_t raw_data) {
1635
1691
memcpy (data , (uint8_t * )bufinfo .buf , sizeof (data ));
1636
1692
data_len = sizeof (data );
1637
1693
}
1638
-
1694
+
1639
1695
esp_ble_gap_config_adv_data_raw (data , data_len );
1640
-
1696
+
1641
1697
// wait for the advertisement data to be configured
1642
1698
bt_gatts_event_result_t gatts_event ;
1643
1699
xQueueReceive (xGattsQueue , & gatts_event , portMAX_DELAY );
1644
1700
}
1645
-
1701
+
1646
1702
return mp_const_none ;
1647
1703
}
1648
1704
STATIC MP_DEFINE_CONST_FUN_OBJ_2 (bt_set_advertisement_raw_obj , bt_set_advertisement_raw );
@@ -2241,8 +2297,9 @@ STATIC mp_obj_t bt_conn_disconnect(mp_obj_t self_in) {
2241
2297
if (self -> conn_id >= 0 ) {
2242
2298
esp_ble_gattc_close (bt_obj .gattc_if , self -> conn_id );
2243
2299
esp_ble_gap_disconnect (self -> srv_bda );
2244
- /* Only reset Conn Id if it is a normal disconnect not module de-init to mark conn obj to be restored */
2245
- if (!mod_bt_allow_resume_deinit )
2300
+ /* Only reset Conn Id if it is needed that the connection should be established again after wakeup
2301
+ * otherwise this connection will be completely removed in close_connection() call triggered by ESP_GATTC_DISCONNECT_EVT event */
2302
+ if (mod_bt_allow_resume_deinit )
2246
2303
{
2247
2304
self -> conn_id = -1 ;
2248
2305
}
0 commit comments