Skip to content

Instantly share code, notes, and snippets.

@hinzundcode
Created July 7, 2019 00:33
Show Gist options
  • Save hinzundcode/19605bc3755a4a2c4e378d1f93f1605d to your computer and use it in GitHub Desktop.
Save hinzundcode/19605bc3755a4a2c4e378d1f93f1605d to your computer and use it in GitHub Desktop.
nrf52840 scan for ble advertisements, based on the nrf5 sdk ble_central/ble_app_hrs_c example
/**
* Copyright (c) 2014 - 2019, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* scans for ble advertisements
* based on the ble_central/ble_app_hrs_c example
*/
#include <stdint.h>
#include <stdio.h>
#include "nrf_sdh.h"
#include "nrf_sdh_ble.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "nrf_ble_scan.h"
#include "ble_advdata.h"
#define APP_BLE_CONN_CFG_TAG 1 /**< A tag identifying the SoftDevice BLE configuration. */
#define SCAN_DURATION_WITELIST 3000 /**< Duration of the scanning in units of 10 milliseconds. */
#define DEV_NAME_LEN ((BLE_GAP_ADV_SET_DATA_SIZE_MAX + 1) - \
AD_DATA_OFFSET) /**< Determines the device name length. */
NRF_BLE_SCAN_DEF(m_scan); /**< Scanning module instance. */
#define MAX_ADDRESS_COUNT 100
uint8_t address_list[MAX_ADDRESS_COUNT][BLE_GAP_ADDR_LEN] = {0};
int address_list_length = 0;
/**< Scan parameters requested for scanning and connection. */
static ble_gap_scan_params_t const m_scan_param =
{
.active = 0x01,
.interval = NRF_BLE_SCAN_SCAN_INTERVAL,
.window = NRF_BLE_SCAN_SCAN_WINDOW,
.filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL, //BLE_GAP_SCAN_FP_WHITELIST,
.timeout = SCAN_DURATION_WITELIST,
.scan_phys = BLE_GAP_PHY_1MBPS,
};
/**@brief Function for initializing the BLE stack.
*
* @details Initializes the SoftDevice and the BLE event interrupt.
*/
static void ble_stack_init(void)
{
ret_code_t err_code;
err_code = nrf_sdh_enable_request();
APP_ERROR_CHECK(err_code);
// Configure the BLE stack using the default settings.
// Fetch the start address of the application RAM.
uint32_t ram_start = 0;
err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
APP_ERROR_CHECK(err_code);
// Enable BLE stack.
err_code = nrf_sdh_ble_enable(&ram_start);
APP_ERROR_CHECK(err_code);
}
/**@brief Function to start scanning.
*/
static void scan_start(void)
{
NRF_LOG_INFO("Starting scan.");
APP_ERROR_CHECK(nrf_ble_scan_start(&m_scan));
}
bool address_list_contains(const uint8_t address[]) {
for (int i = 0; i < address_list_length; i++) {
if (address_list[i][0] == address[0]
&& address_list[i][1] == address[1]
&& address_list[i][2] == address[2]
&& address_list[i][3] == address[3]
&& address_list[i][4] == address[4]
&& address_list[i][5] == address[5]) {
return true;
}
}
return false;
}
bool address_list_add(const uint8_t address[]) {
if (address_list_length < MAX_ADDRESS_COUNT) {
memcpy(address_list[address_list_length], address, BLE_GAP_ADDR_LEN);
address_list_length++;
}
}
void print_address(const ble_gap_evt_adv_report_t* p_adv_report) {
NRF_LOG_INFO("addr: %02x:%02x:%02x:%02x:%02x:%02x",
p_adv_report->peer_addr.addr[5],
p_adv_report->peer_addr.addr[4],
p_adv_report->peer_addr.addr[3],
p_adv_report->peer_addr.addr[2],
p_adv_report->peer_addr.addr[1],
p_adv_report->peer_addr.addr[0]);
}
void print_name(const ble_gap_evt_adv_report_t* p_adv_report) {
uint16_t offset = 0;
char name[DEV_NAME_LEN] = { 0 };
uint16_t length = ble_advdata_search(p_adv_report->data.p_data, p_adv_report->data.len, &offset, BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME);
if (length == 0) {
// Look for the short local name if it was not found as complete.
length = ble_advdata_search(p_adv_report->data.p_data, p_adv_report->data.len, &offset, BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME);
}
if (length != 0) {
memcpy(name, &p_adv_report->data.p_data[offset], length);
NRF_LOG_INFO("name: %s", nrf_log_push(name));
}
}
void print_manufacturer_data(const ble_gap_evt_adv_report_t* p_adv_report) {
uint16_t offset = 0;
uint16_t length = ble_advdata_search(p_adv_report->data.p_data, p_adv_report->data.len, &offset, BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA);
if (length != 0) {
char data_string[1024] = { 0 };
char* pos = data_string;
for (int i = 0; i < length && i < 512; i++) {
sprintf(pos, "%02x", p_adv_report->data.p_data[offset+i]);
pos += 2;
}
NRF_LOG_INFO("manufacturer data: %s", nrf_log_push(data_string));
}
}
static void scan_evt_handler(scan_evt_t const * p_scan_evt)
{
if (p_scan_evt->scan_evt_id == NRF_BLE_SCAN_EVT_SCAN_TIMEOUT) {
NRF_LOG_INFO("Scan timed out.");
scan_start();
return;
}
if (address_list_contains(p_scan_evt->params.filter_match.p_adv_report->peer_addr.addr) != false)
return;
address_list_add(p_scan_evt->params.filter_match.p_adv_report->peer_addr.addr);
/*switch (p_scan_evt->params.filter_match.p_adv_report->peer_addr.addr_type) {
case BLE_GAP_ADDR_TYPE_PUBLIC:
NRF_LOG_INFO("address type BLE_GAP_ADDR_TYPE_PUBLIC");
break;
case BLE_GAP_ADDR_TYPE_RANDOM_STATIC:
NRF_LOG_INFO("address type BLE_GAP_ADDR_TYPE_RANDOM_STATIC");
break;
case BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE:
NRF_LOG_INFO("address type BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE");
break;
case BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE:
NRF_LOG_INFO("address type BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE");
break;
case BLE_GAP_ADDR_TYPE_ANONYMOUS:
NRF_LOG_INFO("address type BLE_GAP_ADDR_TYPE_ANONYMOUS");
break;
}*/
print_address(p_scan_evt->params.filter_match.p_adv_report);
print_name(p_scan_evt->params.filter_match.p_adv_report);
NRF_LOG_INFO("rssi: %d", p_scan_evt->params.filter_match.p_adv_report->rssi);
print_manufacturer_data(p_scan_evt->params.filter_match.p_adv_report);
}
/**@brief Function for initialization scanning and setting filters.
*/
static void scan_init(void)
{
ret_code_t err_code;
nrf_ble_scan_init_t init_scan;
memset(&init_scan, 0, sizeof(init_scan));
init_scan.p_scan_param = &m_scan_param;
init_scan.connect_if_match = false;
init_scan.conn_cfg_tag = APP_BLE_CONN_CFG_TAG;
err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler);
APP_ERROR_CHECK(err_code);
}
int main(void)
{
ret_code_t err_code;
err_code = NRF_LOG_INIT(NULL);
APP_ERROR_CHECK(err_code);
NRF_LOG_DEFAULT_BACKENDS_INIT();
ble_stack_init();
scan_init();
// Start execution.
NRF_LOG_INFO("Start scan");
scan_start();
// Enter main loop.
for (;;)
{
NRF_LOG_FLUSH();
__WFI();
__SEV();
__WFE();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment