3 Replies Latest reply on Jun 15, 2016 1:12 PM by Intel Corporation

    Scanning for BLE devices in Arduino

    NickMC

      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

        • 1. Re: Scanning for BLE devices in Arduino
          Intel Corporation
          This message was posted on behalf of Intel Corporation

          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-native-processes or what Raghavendra mentions in https://software.intel.com/en-us/blogs/2015/05/05/efficient-data-sharing-using-interrupts-on-intel-edison.
           
          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.

          1 of 1 people found this helpful
          • 2. Re: Scanning for BLE devices in Arduino
            NickMC

            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 <stdlib.h>

            #include <errno.h>

            #include <curses.h>

            #include <unistd.h>

            #include <sys/ioctl.h>

            #include <sys/socket.h>

            #include <bluetooth/bluetooth.h>

            #include <bluetooth/hci.h>

            #include <bluetooth/hci_lib.h>

             

            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;

            }

            • 3. Re: Scanning for BLE devices in Arduino
              Intel Corporation
              This message was posted on behalf of Intel Corporation

              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.