Bluetooth LE Device Name not being found when using find name function

I am currently developing a BLE central device to find devices based on their name to extract data from their advertising packet without connecting. I was able to do this using the UUID, but since all of these devices will be transmitting the same UUID, I need to do it based on name. I was able to find the top device in my picture using ble_advdata_name_find, but I am unable to find the device below. I am setting the device name as such for now static char const target_device_name[] = "92094"; I have attached my ble event handler as well where this data processing is done. Any help is appreciated why one device is found but the other is not!

 

/**@brief Function for handling BLE events.
 *
 * @param[in]   p_ble_evt   Bluetooth stack event.
 * @param[in]   p_context   Unused.
 */
static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
    ret_code_t err_code;

    // For readability.
    ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;

    switch (p_ble_evt->header.evt_id)
    {
        // Upon connection, check which peripheral is connected, initiate DB
        // discovery, update LEDs status, and resume scanning, if necessary.
        case BLE_GAP_EVT_CONNECTED:
        {
            NRF_LOG_INFO("Connection 0x%x established, starting DB discovery.",
                         p_gap_evt->conn_handle);

            APP_ERROR_CHECK_BOOL(p_gap_evt->conn_handle < NRF_SDH_BLE_CENTRAL_LINK_COUNT);

            err_code = ble_lbs_c_handles_assign(&m_lbs_c[p_gap_evt->conn_handle],
                                                p_gap_evt->conn_handle,
                                                NULL);
            APP_ERROR_CHECK(err_code);

            err_code = ble_db_discovery_start(&m_db_disc[p_gap_evt->conn_handle],
                                              p_gap_evt->conn_handle);
            APP_ERROR_CHECK(err_code);

            // Update LEDs status and check whether it is needed to look for more
            // peripherals to connect to.
            bsp_board_led_on(CENTRAL_CONNECTED_LED);
            if (ble_conn_state_central_conn_count() == NRF_SDH_BLE_CENTRAL_LINK_COUNT)
            {
                bsp_board_led_off(CENTRAL_SCANNING_LED);
            }
            else
            {
                // Resume scanning.
                bsp_board_led_on(CENTRAL_SCANNING_LED);
                scan_start();
            }
        } break; // BLE_GAP_EVT_CONNECTED

        // Upon disconnection, reset the connection handle of the peer that disconnected, update
        // the LEDs status and start scanning again.
        case BLE_GAP_EVT_DISCONNECTED:
        {
            NRF_LOG_INFO("LBS central link 0x%x disconnected (reason: 0x%x)",
                         p_gap_evt->conn_handle,
                         p_gap_evt->params.disconnected.reason);

            if (ble_conn_state_central_conn_count() == 0)
            {
                err_code = app_button_disable();
                APP_ERROR_CHECK(err_code);

                // Turn off the LED that indicates the connection.
                bsp_board_led_off(CENTRAL_CONNECTED_LED);
            }

            // Start scanning.
            scan_start();

            // Turn on the LED for indicating scanning.
            bsp_board_led_on(CENTRAL_SCANNING_LED);

        } break;

        case BLE_GAP_EVT_TIMEOUT:
        {
            // Timeout for scanning is not specified, so only the connection requests can time out.
            if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN)
            {
                NRF_LOG_DEBUG("Connection request timed out.");
            }
        } break;

        case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
        {
            NRF_LOG_DEBUG("BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST.");
            // Accept parameters requested by peer.
            err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle,
                                        &p_gap_evt->params.conn_param_update_request.conn_params);
            APP_ERROR_CHECK(err_code);
        } break;

        case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
        {
            NRF_LOG_DEBUG("PHY update request.");
            ble_gap_phys_t const phys =
            {
                .rx_phys = BLE_GAP_PHY_AUTO,
                .tx_phys = BLE_GAP_PHY_AUTO,
            };
            err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
            APP_ERROR_CHECK(err_code);
        } break;

        case BLE_GATTC_EVT_TIMEOUT:
        {
            // Disconnect on GATT client timeout event.
            NRF_LOG_DEBUG("GATT client timeout.");
            err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
        } break;

        case BLE_GATTS_EVT_TIMEOUT:
        {
            // Disconnect on GATT server timeout event.
            NRF_LOG_DEBUG("GATT server timeout.");
            err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
        } break;
/* NOTE This is where we read in scanned BLE packet. We use uuid_find to filter based on UUIDs. */
/* The ble_uuid is currently set to 0x18FF which is the LE of the Pressure Sensors Watchlist data packet */
        case BLE_GAP_EVT_ADV_REPORT: 
     
            // Initialize advertisement report for parsing.
            bleData = p_ble_evt->evt.gap_evt.params.adv_report.data;
            bool found = false;
            uint8_t * p_encoded_data = bleData.p_data;
            uint16_t data_len = bleData.len;

            found = ble_advdata_name_find(p_encoded_data,
                                  data_len,
                                  target_device_name);

            //found = ble_advdata_uuid_find(p_encoded_data,
            //                      data_len,
            //                      &ble_uuid);
            if(found)
            { 
                // Copy the entire advertising data
                memcpy(pressure_data, m_scan.scan_buffer_data, BLE_PRESSURE_ADV_DATA_BUFFER_SIZE);
                process_ble_data();
            }
            break;

        default:
            // No implementation needed.
            break;
    }
}

 

Parents
  • Hi,

    Can you share the details about the advertising data of the device you find and the device you do not find?

    Also, how do you determine weather it is a hit or miss? 

    Lastly, a quite common issue is if some of the data is in the advertising packets while other is in the scan response packet, and your filtering is based on them being in the same. That may not be the problem here, but I do not see all of your code (for instance not your process_ble_data()), so it might be something there (note that you will see this data merged in nRF Connect for Android, so it can look like everything is in the same packet, while in reality it may not be) - so a sniffer trace showing the actual advertising data could be useful.

  • The device I am finding is the one advertised above with the 8 character name (I do not know what type of device it is, just a local BLE device within range). I have attached the adv. packet data I am finding as well with the Local Name. I am able to now find the device name, but when I use the find uuid function, the data does not match the advertising packet as seen with the BLE sniffer app I have. The first set of code finds the device, but it cannot find the data using the uuid. The second set of code can find the data using the uuid but no device filter. I may have many of these devices nearby at times, so I need to differentiate by using the name first to make sure I am getting the correct device's data.

    case BLE_GAP_EVT_ADV_REPORT:
    /* NOTE This doesnt work.
                bleData = p_ble_evt->evt.gap_evt.params.adv_report.data;
                bool found = false;
    
                uint8_t * p_adv_data = bleData.p_data;
                uint16_t data_len = bleData.len;
    
                uint16_t   dev_name_offset = 0;
                uint16_t   field_len;
    
                // Search for advertising names.
                field_len = ble_advdata_search(p_adv_data,
                                       data_len,
                                       &dev_name_offset,
                                       BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME);
                if (field_len == 0)
                {
                    // If data cannot be parsed, then exit.
                    return;
                }
                
    
                memcpy(dev_name, &p_adv_data[dev_name_offset], field_len);
                dev_name[field_len] = 0;
    
                if(strcmp(target_device_name, dev_name) == 0)
                {
                    // Look for 0x18FF UUID
                    found = ble_advdata_uuid_find(p_adv_data,
                                          data_len,
                                          &ble_uuid);
                    if(found)
                    { 
                        // Copy the entire advertising data
                        memcpy(pressure_data, m_scan.scan_buffer_data, BLE_PRESSURE_ADV_DATA_BUFFER_SIZE);
                        process_ble_data();
                    }
                }
    
                /* NOTE This works good.
    
                found = ble_advdata_uuid_find(p_encoded_data,
                                      data_len,
                                      &ble_uuid);
                if(found)
                { 
                    // Copy the entire advertising data
                    memcpy(pressure_data, m_scan.scan_buffer_data, BLE_PRESSURE_ADV_DATA_BUFFER_SIZE);
                    process_ble_data();
                }
                }break; */

  • Or would a Name Scan filter work better? On a name match, parse the advertising data packet? 

  • inspiringdev123 said:
    I am able to now find the device name, but when I use the find uuid function, the data does not match the advertising packet as seen with the BLE sniffer app I have.

    That is why I am wondering if this data is really int he same packet, or if part of it is in the advertising packet and other parts in the scan response packets? You will not see that from Android, as the API's merge the data. So if you are for instance looking for both a service UUID and a name in the same packet, it may not work. This is why it would be useful to see what is actually going on on air (for instance using the nRF Sniffer for Bluetooth LE.

    inspiringdev123 said:
    Or would a Name Scan filter work better? On a name match, parse the advertising data packet? 

    The order does not matter much in practice. You could also consider using the Scanning module filtering as is done in most central examples in the SDK, but it just a layer on top of the SoftDevice APIs that makes things a bit simpler.

    In any case, in order for me to give you better answers I would need two things. Firstly, a sniffer trace of the advertising (and scan response) packets so that I know what you are parsing, and all the relevant code doing the parsing. With that, we should be able to see why the filtering does not work as intended.

  • This is the advertising packet with the data I want. 

Reply Children
Related