This blog is to give a demo how to scan the ble advertiser and show the RSSI and MAC address in sorting order. It is the feature similar to the mobile phone. For example, as below, the scanner is kept to get the nearby advertiser. It would get all the corresponding advertising payload, peer address and RSSI value.

In this blog, I used the ble_app_blinky and add the observer role (I select passive scanning instead of active scanning). Because I prefer to scan more devices instead of sending scan requests and getting scan responses.

Passive Scanning

In this type of scanning, the Scanner simply listens for advertising packets. The Advertiser is never aware that packets were received:

Active Scanning

This type of scan is typically used when the potential Central device would like more information than can be provided in an ADV_IND packet, before making a decision to connect to it.

In an advertising interval, the Scanner issues a SCAN_REQ packet. The Advertiser responds with more information in a SCAN_RSP packet.

Basically, I used the demo firmware ble_app_blinky example and added the observer role (passive scanner).

static ret_code_t scan_init(dm_ble_scan_t * const p_scan_ctx)

/* We expect better performance when using extended advertising/scanning. However, for simplicity this example uses legacy scanning/advertising. */
        p_scan_ctx->scan_params.extended      = APP_SCAN_EXTENDED_ENABLED;
        p_scan_ctx->scan_params.extended      = APP_SCAN_EXTENDED_DISABLED;
        p_scan_ctx->        = APP_SCAN_ACTIVE_DISABLED;
        p_scan_ctx->scan_params.interval      = APP_SCAN_SCAN_INTERVAL;
        p_scan_ctx->scan_params.window        = APP_SCAN_SCAN_WINDOW;
        p_scan_ctx->scan_params.filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL;
        p_scan_ctx->scan_params.timeout       = APP_SCAN_DURATION;
        p_scan_ctx->scan_params.scan_phys     = BLE_GAP_PHY_1MBPS;

// Assign a buffer where the advertising reports are to be stored by the SoftDevice.
        p_scan_ctx->scan_buffer.p_data = p_scan_ctx->scan_buffer_data;
        p_scan_ctx->scan_buffer.len    = sizeof(p_scan_ctx->scan_buffer_data);

        return NRF_SUCCESS;
static ret_code_t scan_start(dm_ble_scan_t const * const p_scan_ctx)

        ret_code_t err_code;
        // Start the scanning.
        err_code = sd_ble_gap_scan_start(&p_scan_ctx->scan_params, &p_scan_ctx->scan_buffer);

        // It is okay to ignore this error, because the scan stopped earlier.
        if ((err_code != NRF_ERROR_INVALID_STATE) && (err_code != NRF_SUCCESS))
                NRF_LOG_ERROR("sd_ble_gap_scan_start returned 0x%x", err_code);
                return (err_code);
        NRF_LOG_INFO("Starting scan.");
        m_scanning_is_start = true;

        return NRF_SUCCESS;

I used 3 x nRF52840 DK boards for this demo.

Attached is the HEX file.

3 nRF52840 DK board is running the BLE Advertising + Scanner at the same time.

Yello bracket is advertising report, Bed one is the combined list.

BLE Configuration

The scanner would get the list of the advertisers every 5 seconds. It would show the MAC address and RSSI value on the terminal.

Welcome to give any comments.