The BLEScanner class is used in Central Mode, and facilitates scanning for BLE peripherals in range and parsing the advertising data that is being sent out by the peripherals.
The BLEScanner class is normally accessed via the Bluefruit class (instantiated at startup), as shown below:
/* Start Central Scanning * - Enable auto scan if disconnected * - Filter for devices with a min RSSI of -80 dBm * - Interval = 100 ms, window = 50 ms * - Use active scan (requests the optional scan response packet) * - Start(0) = will scan forever since no timeout is given */ Bluefruit.Scanner.setRxCallback(scan_callback); Bluefruit.Scanner.restartOnDisconnect(true); Bluefruit.Scanner.filterRssi(-80); // Only invoke callback when RSSI >= -80 dBm Bluefruit.Scanner.setInterval(160, 80); // in units of 0.625 ms Bluefruit.Scanner.useActiveScan(true); // Request scan response data Bluefruit.Scanner.start(0); // 0 = Don't stop scanning after n seconds
typedef void (*rx_callback_t) (ble_gap_evt_adv_report_t*); typedef void (*stop_callback_t) (void); BLEScanner(void); ble_gap_scan_params_t* getParams(void); bool isRunning(void); void useActiveScan(bool enable); void setInterval(uint16_t interval, uint16_t window); void setIntervalMS(uint16_t interval, uint16_t window); void restartOnDisconnect(bool enable); void filterRssi(int8_t min_rssi); void filterMSD(uint16_t manuf_id); void filterUuid(BLEUuid ble_uuid); void filterUuid(BLEUuid ble_uuid1, BLEUuid ble_uuid2); void filterUuid(BLEUuid ble_uuid1, BLEUuid ble_uuid2, BLEUuid ble_uuid3); void filterUuid(BLEUuid ble_uuid1, BLEUuid ble_uuid2, BLEUuid ble_uuid3, BLEUuid ble_uuid4); void filterUuid(BLEUuid ble_uuid[], uint8_t count); void clearFilters(void); bool start(uint16_t timeout = 0); bool stop(void); /*------------- Callbacks -------------*/ void setRxCallback(rx_callback_t fp); void setStopCallback(stop_callback_t fp); /*------------- Data Parser -------------*/ uint8_t parseReportByType(const uint8_t* scandata, uint8_t scanlen, uint8_t type, uint8_t* buf, uint8_t bufsize = 0); uint8_t parseReportByType(const ble_gap_evt_adv_report_t* report, uint8_t type, uint8_t* buf, uint8_t bufsize = 0); bool checkReportForUuid(const ble_gap_evt_adv_report_t* report, BLEUuid ble_uuid); bool checkReportForService(const ble_gap_evt_adv_report_t* report, BLEClientService svc); bool checkReportForService(const ble_gap_evt_adv_report_t* report, BLEService svc);
setRxCallback(rx_callback_t fp)
Whenever a valid advertising packet is detected (based on any optional filters that are applied in the BLEScanner class), a dedicated callback function (see rx_callback_t
) will be called.
The callback function has the following signature:
NOTE: ble_gap_evt_adv_report_t
is part of the Nordic nRF52 SD and is defined in ble_gap.h
void scan_callback(ble_gap_evt_adv_report_t* report) { /* Display the timestamp and device address */ if (report->scan_rsp) { /* This is a Scan Response packet */ Serial.printf("[SR%10d] Packet received from ", millis()); } else { /* This is a normal advertising packet */ Serial.printf("[ADV%9d] Packet received from ", millis()); } Serial.printBuffer(report->peer_addr.addr, 6, ':'); Serial.print("\n"); /* Raw buffer contents */ Serial.printf("%14s %d bytes\n", "PAYLOAD", report->dlen); if (report->dlen) { Serial.printf("%15s", " "); Serial.printBuffer(report->data, report->dlen, '-'); Serial.println(); } /* RSSI value */ Serial.printf("%14s %d dBm\n", "RSSI", report->rssi); /* Adv Type */ Serial.printf("%14s ", "ADV TYPE"); switch (report->type) { case BLE_GAP_ADV_TYPE_ADV_IND: Serial.printf("Connectable undirected\n"); break; case BLE_GAP_ADV_TYPE_ADV_DIRECT_IND: Serial.printf("Connectable directed\n"); break; case BLE_GAP_ADV_TYPE_ADV_SCAN_IND: Serial.printf("Scannable undirected\n"); break; case BLE_GAP_ADV_TYPE_ADV_NONCONN_IND: Serial.printf("Non-connectable undirected\n"); break; } /* Check for BLE UART UUID */ if ( Bluefruit.Scanner.checkReportForUuid(report, BLEUART_UUID_SERVICE) ) { Serial.printf("%14s %s\n", "BLE UART", "UUID Found!"); } /* Check for DIS UUID */ if ( Bluefruit.Scanner.checkReportForUuid(report, UUID16_SVC_DEVICE_INFORMATION) ) { Serial.printf("%14s %s\n", "DIS", "UUID Found!"); } Serial.println(); }
void useActiveScan(bool enable);
Enabling 'Active Scan' by setting the enable
parameter to 1 will cause the device to request the optional Scan Response advertising packet, which is a second 31 byte advertising packet that can be used to transmit additional information.
By default active scanning is disabled, so no Scan Response packets will be received by BLEScanner unless this function is called and set to 1 before calling Bluefruit.Scanner.start(0)
.
void filterRssi(int8_t min_rssi);
void filterMSD(uint16_t manuf_id);
void filterUuid(BLEUuid ble_uuid);
void filterUuid(BLEUuid ble_uuid1, BLEUuid ble_uuid2);
void filterUuid(BLEUuid ble_uuid1, BLEUuid ble_uuid2, BLEUuid ble_uuid3);
void filterUuid(BLEUuid ble_uuid1, BLEUuid ble_uuid2, BLEUuid ble_uuid3, BLEUuid ble_uuid4);
void filterUuid(BLEUuid ble_uuid[], uint8_t count);
Filters can be applied to BLEScanner to narrow down the data sent to the callback handler, and make processing advertising packets easier for you.
As of BSP 0.7.0 the following three filters are present:
-
filterRssi(int8_t min_rssi)
: Filters advertising results to devices with at least the specified RSSI value, which allows you to ignore devices that are too far away or whose signal is too weak. The higher the number, the strong the signal so -90 is a very weak signal, and -60 is a much stronger one. -
filterUuid(BLEUuid ble_uuid)
: Filters advertising results to devices that advertise themselves as having the specified service UUID. If multiple UUIDs are entered, they will be filtered with boolean OR logic, meaning any single UUID present will be considered a match. -
void filterMSD(uint16_t manuf_id)
: Fitlers advertising results to devices that contain a Manufacturer Specific Data data type, and who use the specifed Bluetooth Customer ID (manuf_id)
. This can be useful to filter iBeacon versus Eddystone devices, for example, which both used the MSD field, or to look for custom MSD data matching your own CID.
bool start(uint16_t timeout = 0);
bool stop(void);
The .start
and .stop
functions can be used to start and stop scanning, and should be called after all of the main parameters (timing, filters, etc.) have been set.
The .start
function has a single parameter called timeout, which sets the number of seconds to scan for advertising packets. Setting this to '0' (the default value) will cause the device to scan forever.
void restartOnDisconnect(bool enable);
Setting this function to '1' will cause the scanning process to start again as soon as you disconnect from a peripheral device. The default behaviour is to automatically restart scanning on disconnect.
Examples
For an example that uses almost all of the BLEScanner and advertising API in Central mode, see central_scan_advanced.ino in the Central examples folder.
Text editor powered by tinymce.