This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

BLE Scanning device, addresses and identification with NRF52 DK

Hello to everyone,

I was told to develop a simple BLE scanner using NRF52 DK (NRF52832). The idea is just to identify surrounding devices but we don't want to initiate connection with them, so it plays only an observer role. The code is a modification version of ble_app_uart_c.

Initially I wanted only to obtain the address but didnt know how to do it because the SDK and Softdevice are a little bit confusing, although this post gave me a really good start and helped me to understand some of the functions, structures and macros: https://devzone.nordicsemi.com/f/nordic-q-a/43747/nrf52832-ble-scan

memset(m_device[idx].addr,
0,
sizeof(p_adv_report->peer_addr.addr));

memcpy(m_device[idx].addr,
p_adv_report->peer_addr.addr,
sizeof(p_adv_report->peer_addr.addr));
printf("Device number %d\r\n",device_number);
printf("Address: ");
for(i=0; i< (uint16_t)(sizeof(p_adv_report->peer_addr.addr));i++)
{
  if(i==0)
  {
    printf("%02X",m_device[idx].addr[i]);
  }
  else
  {
    printf(":%02X",m_device[idx].addr[i]); //add colon in order to give format to address
  }
}
printf("\r\n");


m_device[idx].size = p_adv_report->data.len;

memset(m_device[idx].data_buffer,
0,
p_adv_report->data.len);
memcpy(m_device[idx].data_buffer,
p_adv_report->data.p_data,
p_adv_report->data.len);



printf("Adv Data: ");
for(i=0; i< p_adv_report->data.len;i++)
{
  printf("%x",m_device[idx].data_buffer[i]);
}
printf("\r\n");



//uint8_t * full_name_data = ble_advdata_parse(m_device[idx].data_buffer, m_device[idx].size,BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME);

uint16_t len_full_name = ble_advdata_search(m_device[idx].data_buffer,m_device[idx].size, &offset,BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME);
memset(m_device[idx].dev_name,
0,
len_full_name);


memcpy(m_device[idx].dev_name,
&m_device[idx].data_buffer[offset],
len_full_name);


printf("Device Name: ");
for(i=0; i<len_full_name;i++)
{
  printf("%c",m_device[idx].data_buffer[offset+i]);
}
printf("\r\n");

m_device[idx].rssi = p_adv_report->rssi;
printf("RSSI: %d dBm\r\n",m_device[idx].rssi);

So the idea is the following: every time a NRF_BLE_SCAN_EVT_NOT_FOUND scan event happens (because I'm not using any filter on scanning mode), I call the function add_device_to_list(ble_gap_evt_adv_report_t const * p_adv_report), where the code above is implemented within it and obtains information from the GAP EVT ADV REPORT. This is an example of what I get in the console:

Device number 54
Address: C0:39:F1:28:18:A0
Adv Data: 211abff4c09634c0a805
Device Name:
RSSI: -86 dBm

Device number 55 (Note: this is my phone using NRF Connect app, advertising without any services)
Address: 45:94:68:7D:FA:5C
Adv Data: 211ad94d61746961736950686f6e65
Device Name: MatiasiPhone
RSSI: -30 dBm

Device number 56
Address: 39:7A:9C:6B:34:7F
Adv Data: 211a2acbff4c01064a1e256190cc
Device Name:
RSSI: -87 dBm

I thought that reading the field peer_addr I would easily obtain the MAC address of the peer device and that would be enough. But that is not quite true, as I can tell from this post: https://devzone.nordicsemi.com/f/nordic-q-a/27012/how-to-distinguish-between-random-and-public-gap-addresses

My questions are the following:

1)  is there any way I can identify surrounding devices using a value that doesnt change over time with the adv data packages I'm able to receive? (Could it be anyone of these: https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile/ ?? ), I think I can't use the address because it depends on the peer peripheral configuration and it can change if it is private. And it looks like not every device necessarily advertise a public address (I guess the public address it is the MAC address from the manufacturer? correct me if I'm wrong). Please, veryfy this statement: reading the manufacturer MAC address it will totally depend on if the client device is configurated to advertise it beforehand?

2) does the GAP EVT ADV REPORT already extract information from the adversiting physical channel PDU (Vol 6, Part B, section 2.3)? I'm not sure if p_adv_report->data.p_data is the actual PDU received (header + payload) or just the payload.

3) What kind of Advertising types I'm receiving? and How can I check that? for example if it is a legacy type advertising PDU?

4) is this code, softdevice and SDK suitable for finding EDR/BR Bluetooth devices? How would it be the format and the Adv packet in that case?

5) [just curious] Can anyone explain me how the ble_app_uart_c example works regarding uart and ble? I realized that if I add the UART service in the NRF Connect App and start adversiting, my scanning stops or just freeze in the console. I read in other post that as soon the NRF52 finds that service, it connects automatically to it. Where is that within the code? I can't find it.

6) [just curious] How the softdevices manages the interrupts and priorities? is realted to supervisor calls? Where can I understand and configure that? I would apprecciate a lot the development of a simple BLE application as an example using the softdevice with a flow chart or flow diagram of the program. I'm really concerned about adding others features in the future which can collide with current features or events or interrupt me while I'm doing something.

  • Hi,

    1) 

    is there any way I can identify surrounding devices using a value that doesnt change over time with the adv data packages I'm able to receive?

    You can try to find values that stay constant over time, but note that the only mandatory thing in the advertising packets is the advertising address, and that can as you say, change over time for private addresses. This is to avoid passive observers to track your device. I recommend reding this blog post about privacy by Bluetooth SIG: https://www.bluetooth.com/blog/bluetooth-technology-protecting-your-privacy/

    I guess the public address it is the MAC address from the manufacturer?

    Correct. A public address can be purchased through the IEEE Registration Authority. Most devices use a random address.

    Please, veryfy this statement: reading the manufacturer MAC address it will totally depend on if the client device is configurated to advertise it beforehand?

    No. Advertising requires a device/MAC address to be part of the advertising packet. Here is a snippet from the Bluetooth specification 5.2 that shows the ADV_IND packet:

    2) I believe this is the AdvData part of the payload.

    3) You should check the type field in the ADV REPORT. See this link.

    4) In Bluetooth Classic/ BR/EDR, you don’t have advertising, but inquiry and paging. You won’t be able to scan these. But many BR/EDR devices, such as audio headphones, uses both BR/EDR and Bluetooth Low Energy. So, you will be able to find the LE advertising packets that these devices broadcast.

    5) You can find the documentation for the NUS server and client sample here and here.
    In SDK 16, the connection is done in the scanner module when the UUID matches(nrf_ble_scan.c).

    6) You can find the documentation for the softdevice interrupt priority levels at this link.

Related