Skip to content

Commit b65cc38

Browse files
committed
extmod/modbluetooth: Allow config of scan interval/window.
This adds two additional optional kwargs to `gap_scan()`: - `interval_us`: How long between scans. - `window_us`: How long to scan for during a scan. The default with NimBLE is a 11.25ms window with a 1.28s interval. Changing these parameters is important for detecting low-frequency advertisements (e.g. beacons). Note: these params are in microseconds, not milliseconds in order to allow the 625us granularity offered by the spec.
1 parent 06ae818 commit b65cc38

File tree

3 files changed

+22
-19
lines changed

3 files changed

+22
-19
lines changed

extmod/modbluetooth.c

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -501,23 +501,26 @@ STATIC mp_obj_t bluetooth_ble_gap_connect(size_t n_args, const mp_obj_t *args) {
501501
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gap_connect_obj, 3, 4, bluetooth_ble_gap_connect);
502502

503503
STATIC mp_obj_t bluetooth_ble_gap_scan(size_t n_args, const mp_obj_t *args) {
504-
if (n_args == 2 && args[1] == mp_const_none) {
505-
int err = mp_bluetooth_gap_scan_stop();
506-
return bluetooth_handle_errno(err);
507-
} else {
508-
mp_int_t duration_ms = 0;
509-
if (n_args == 2) {
510-
if (!mp_obj_is_int(args[1])) {
511-
mp_raise_ValueError("invalid duration");
504+
// Default is indefinite scan, with the NimBLE "background scan" interval and window.
505+
mp_int_t duration_ms = 0;
506+
mp_int_t interval_us = 1280000;
507+
mp_int_t window_us = 11250;
508+
if (n_args > 1) {
509+
if (args[1] == mp_const_none) {
510+
// scan(None) --> stop scan.
511+
return bluetooth_handle_errno(mp_bluetooth_gap_scan_stop());
512+
}
513+
duration_ms = mp_obj_get_int(args[1]);
514+
if (n_args > 2) {
515+
interval_us = mp_obj_get_int(args[2]);
516+
if (n_args > 3) {
517+
window_us = mp_obj_get_int(args[3]);
512518
}
513-
duration_ms = mp_obj_get_int(args[1]);
514519
}
515-
516-
int err = mp_bluetooth_gap_scan_start(duration_ms);
517-
return bluetooth_handle_errno(err);
518520
}
521+
return bluetooth_handle_errno(mp_bluetooth_gap_scan_start(duration_ms, interval_us, window_us));
519522
}
520-
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gap_scan_obj, 1, 2, bluetooth_ble_gap_scan);
523+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gap_scan_obj, 1, 4, bluetooth_ble_gap_scan);
521524
#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
522525

523526
STATIC mp_obj_t bluetooth_ble_gap_disconnect(mp_obj_t self_in, mp_obj_t conn_handle_in) {

extmod/modbluetooth.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ int mp_bluetooth_gap_disconnect(uint16_t conn_handle);
186186

187187
#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
188188
// Start a discovery (scan). Set duration to zero to run continuously.
189-
int mp_bluetooth_gap_scan_start(int32_t duration_ms);
189+
int mp_bluetooth_gap_scan_start(int32_t duration_ms, int32_t interval_us, int32_t window_us);
190190

191191
// Stop discovery (if currently active).
192192
int mp_bluetooth_gap_scan_stop(void);

extmod/modbluetooth_nimble.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -614,16 +614,16 @@ STATIC int gap_scan_cb(struct ble_gap_event *event, void *arg) {
614614
return 0;
615615
}
616616

617-
int mp_bluetooth_gap_scan_start(int32_t duration_ms) {
617+
int mp_bluetooth_gap_scan_start(int32_t duration_ms, int32_t interval_us, int32_t window_us) {
618618
if (duration_ms == 0) {
619619
duration_ms = BLE_HS_FOREVER;
620620
}
621-
STATIC const struct ble_gap_disc_params discover_params = {
622-
.itvl = BLE_GAP_SCAN_SLOW_INTERVAL1,
623-
.window = BLE_GAP_SCAN_SLOW_WINDOW1,
621+
struct ble_gap_disc_params discover_params = {
622+
.itvl = MAX(BLE_HCI_SCAN_ITVL_MIN, MIN(BLE_HCI_SCAN_ITVL_MAX, interval_us / BLE_HCI_SCAN_ITVL)),
623+
.window = MAX(BLE_HCI_SCAN_WINDOW_MIN, MIN(BLE_HCI_SCAN_WINDOW_MAX, window_us / BLE_HCI_SCAN_ITVL)),
624624
.filter_policy = BLE_HCI_CONN_FILT_NO_WL,
625625
.limited = 0,
626-
.passive = 0,
626+
.passive = 1, // TODO: Handle BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP in gap_scan_cb above.
627627
.filter_duplicates = 0,
628628
};
629629
int err = ble_gap_disc(BLE_OWN_ADDR_PUBLIC, duration_ms, &discover_params, gap_scan_cb, NULL);

0 commit comments

Comments
 (0)