Community
cancel
Showing results for 
Search instead for 
Did you mean: 
NMcNa1
Novice
1,462 Views

Scanning for BLE devices in Arduino

Jump to solution

Hi guys,

I have been looking for a way to scan for devices and print them out on the serial terminal in Arduino but i can't seem to find anything useful.

Basically I know the MAC address of the device I want to find and it changes its name every 2 minutes to reflect some data. I want to be able to capture this data by scanning for the device and when the MAC addresses match I want to save the devices name as a character array. I wanted to do this in the Arduino IDE if possible because thats what I have been using and I can send the data to the cloud using it, however I am willing to try other things. Any suggestions?

Regards,

Nick

Tags (1)
1 Solution
idata
Community Manager
107 Views

Hello NickMC,

 

 

If you would like to make a BLE scan from the Arduino IDE, it will be a little bit complex. I mean you can easily send the data to the serial monitor through a system call, nevertheless you would not be able to handle that data as easily. I mean, for example, the instruction that would send a 30 second scan to your serial monitor would be:

 

 

system("timeout -s SIGINT 30s hcitool lescan > /dev/ttyGS0");

 

 

However since this is a system call from the Linux OS inside Edison, it can't be used as data in your code, they are on two separate environments. If you would like to use the Arduino IDE you would have to use an approach similar to what Matthias explains in https://software.intel.com/en-us/blogs/2014/09/22/efficient-communication-between-arduino-and-linux-... or what Raghavendra mentions in https://software.intel.com/en-us/blogs/2015/05/05/efficient-data-sharing-using-interrupts-on-intel-e....

 

 

The other option would be for you to work C/C++, Python, etc from the Linux side of Edison where you can find a third party Linux library for BLE that would probably let you handle the scanning directly on your code.

 

 

I hope this information helps you.

 

-Peter.

View solution in original post

3 Replies
idata
Community Manager
108 Views

Hello NickMC,

 

 

If you would like to make a BLE scan from the Arduino IDE, it will be a little bit complex. I mean you can easily send the data to the serial monitor through a system call, nevertheless you would not be able to handle that data as easily. I mean, for example, the instruction that would send a 30 second scan to your serial monitor would be:

 

 

system("timeout -s SIGINT 30s hcitool lescan > /dev/ttyGS0");

 

 

However since this is a system call from the Linux OS inside Edison, it can't be used as data in your code, they are on two separate environments. If you would like to use the Arduino IDE you would have to use an approach similar to what Matthias explains in https://software.intel.com/en-us/blogs/2014/09/22/efficient-communication-between-arduino-and-linux-... or what Raghavendra mentions in https://software.intel.com/en-us/blogs/2015/05/05/efficient-data-sharing-using-interrupts-on-intel-e....

 

 

The other option would be for you to work C/C++, Python, etc from the Linux side of Edison where you can find a third party Linux library for BLE that would probably let you handle the scanning directly on your code.

 

 

I hope this information helps you.

 

-Peter.

View solution in original post

NMcNa1
Novice
107 Views

Hey Peter,

Thanks for the information i found it very helpful.

Just as an update on this question, what I have done is gone to the Linux side of things and used some C code I found that scans for BLE devices. In the while loop I added a comparison function to find the address of my known device and then used a for loop to display all of the data payload. This displays in HEX as per the code below. From here I plan to perform analysis on the data.

Cheers,

Nick

//

// Intel Edison Playground

// Copyright (c) 2015 Damian Kołakowski. All rights reserved.

//

# include

# include

# include

# include

# include

# include

# include

# include

# include

struct hci_request ble_hci_request(uint16_t ocf, int clen, void * status, void * cparam)

{

struct hci_request rq;

memset(&rq, 0, sizeof(rq));

rq.ogf = OGF_LE_CTL;

rq.ocf = ocf;

rq.cparam = cparam;

rq.clen = clen;

rq.rparam = status;

rq.rlen = 1;

return rq;

}

int main()

{

int ret, status;

// Get HCI device.

const int device = hci_open_dev(hci_get_route(NULL));

if ( device < 0 ) {

perror("Failed to open HCI device.");

return 0;

}

// Set BLE scan parameters.

le_set_scan_parameters_cp scan_params_cp;

memset(&scan_params_cp, 0, sizeof(scan_params_cp));

scan_params_cp.type = 0x00;

scan_params_cp.interval = htobs(0x0010);

scan_params_cp.window = htobs(0x0010);

scan_params_cp.own_bdaddr_type = 0x00; // Public Device Address (default).

scan_params_cp.filter = 0x00; // Accept all.

struct hci_request scan_params_rq = ble_hci_request(OCF_LE_SET_SCAN_PARAMETERS, LE_SET_SCAN_PARAMETERS_CP_SIZE, &status, &scan_params_cp);

ret = hci_send_req(device, &scan_params_rq, 1000);

if ( ret < 0 ) {

hci_close_dev(device);

perror("Failed to set scan parameters data.");

return 0;

}

// Set BLE events report mask.

le_set_event_mask_cp event_mask_cp;

memset(&event_mask_cp, 0, sizeof(le_set_event_mask_cp));

int i = 0;

for ( i = 0 ; i < 8 ; i++ ) event_mask_cp.mask[i] = 0xFF;

struct hci_request set_mask_rq = ble_hci_request(OCF_LE_SET_EVENT_MASK, LE_SET_EVENT_MASK_CP_SIZE, &status, &event_mask_cp);

ret = hci_send_req(device, &set_mask_rq, 1000);

if ( ret < 0 ) {

hci_close_dev(device);

perror("Failed to set event mask.");

return 0;

}

// Enable scanning.

le_set_scan_enable_cp scan_cp;

memset(&scan_cp, 0, sizeof(scan_cp));

scan_cp.enable = 0x01; // Enable flag.

scan_cp.filter_dup = 0x00; // Filtering disabled.

struct hci_request enable_adv_rq = ble_hci_request(OCF_LE_SET_SCAN_ENABLE, LE_SET_SCAN_ENABLE_CP_SIZE, &status, &scan_cp);

ret = hci_send_req(device, &enable_adv_rq, 1000);

if ( ret < 0 ) {

hci_close_dev(device);

perror("Failed to enable scan.");

return 0;

}

// Get Results.

struct hci_filter nf;

hci_filter_clear(&nf);

hci_filter_set_ptype(HCI_EVENT_PKT, &nf);

hci_filter_set_event(EVT_LE_META_EVENT, &nf);

if ( setsockopt(device, SOL_HCI, HCI_FILTER, &nf, sizeof(nf)) < 0 ) {

hci_close_dev(device);

perror("Could not set socket options\n");

return 0;

}

printf("Scanning....\n");

uint8_t buf[HCI_MAX_EVENT_SIZE];

evt_le_meta_event * meta_event;

le_advertising_info * info;

int len = 1;

int dataIt =0 ;

while ( 1 )

{

len = read(device, buf, sizeof(buf));

if ( len >= HCI_EVENT_HDR_SIZE )

{

meta_event = (evt_le_meta_event*)(buf+HCI_EVENT_HDR_SIZE+1);

if ( meta_event->subevent == EVT_LE_ADVERTISING_REPORT )

{

uint8_t reports_count = meta_event->data[0];

void * offset = meta_event->data + 1;

while ( reports_count-- )

{

info = (le_advertising_info *)offset;

char addr[18];

char *addr2 = "B0:B4:48:D9:5E:F0"; // set your known MAC here to match

char *addr3 = "B0:B4:48:D9:5E:F0"; // set your known MAC here to match

char name[18];

ba2str(&(info->bdaddr), addr);

int ans = strcmp(addr, addr2);

if ( ans == 0)

{

printf("%s \t", addr);

for (dataIt = 0; dataIt < (info->length); dataIt++) //pulls advertising data

{

printf("%02X", info->data[dataIt]);

}

printf("\n");//this needs to print out after data to show in terminal

sleep(10);

printf("%02X%02X%02X%02X%02X", info->data[5], info->data[6], info->data[7], info->data[8], info->data[9]);//use this to pull individual data

printf("\n"); //this needs to print out after data to show in terminal

}

offset = info->data + info->length + 2;

}

}

}

}

// Disable scanning.

memset(&scan_cp, 0, sizeof(scan_cp));

scan_cp.enable = 0x00; // Disable flag.

struct hci_request disable_adv_rq = ble_hci_request(OCF_LE_SET_SCAN_ENABLE, LE_SET_SCAN_ENABLE_CP_SIZE, &status, &scan_cp);

ret = hci_send_req(device, &disable_adv_rq, 1000);

if ( ret < 0 ) {

hci_close_dev(device);

perror("Failed to disable scan.");

return 0;

}

hci_close_dev(device);

return 0;

}

idata
Community Manager
107 Views

Hi Nick,

 

 

Thanks for sharing your update. Your project looks very promising and we will be waiting for hearing more about it. I invite you to share your updates with the community, they could be of help for other users.

 

 

-Peter.
Reply