Connecting to peripheral BLE device using BMD 350 (nrf52 based chip) as central BLE device.

I have been able to connect and initialize two different Bluetooth OBD II Devices. I am running into issues with the third device I am trying to add as an option. I add the Primary Services in the code below.

 

/**@brief Function for initializing the OBD client.
 *
 * @param[in] p_obd_service_client Pointer to the OBD client structure.
 * @param[in] p_ble_obd_c_init     Pointer to the OBD initialization structure.
 *
 * @return NRF_SUCCESS on successful initialization, otherwise an error code.
 */
uint32_t ble_obd_c_init(ble_obd_c_t * p_obd_service_client, ble_obd_c_init_t * p_ble_obd_c_init)
{
    uint32_t err_code;
    ble_uuid_t obd_uuids[] = 
    {
        { .uuid = BLE_UUID_LELINK_SERVICE, .type = BLE_UUID_TYPE_BLE },
        { .uuid = BLE_UUID_VLINK_SERVICE, .type = BLE_UUID_TYPE_BLE },
        { .uuid = BLE_UUID_FIXD_SERVICE, .type = BLE_UUID_TYPE_BLE }
    };

    VERIFY_PARAM_NOT_NULL(p_obd_service_client);
    VERIFY_PARAM_NOT_NULL(p_ble_obd_c_init);

    p_obd_service_client->conn_handle                       = BLE_CONN_HANDLE_INVALID;
    p_obd_service_client->evt_handler                       = p_ble_obd_c_init->evt_handler;
    p_obd_service_client->error_handler                     = p_ble_obd_c_init->error_handler;
    p_obd_service_client->obd_service_rx_char.handle_value  = BLE_GATT_HANDLE_INVALID;
    p_obd_service_client->obd_service_tx_char.handle_value  = BLE_GATT_HANDLE_INVALID;
    p_obd_service_client->p_gatt_queue                      = p_ble_obd_c_init->p_gatt_queue;
    p_obd_service_client->uuid_type                         = BLE_UUID_TYPE_BLE;

    // Register all UUIDs
    for (uint8_t i = 0; i < sizeof(obd_uuids) / sizeof(obd_uuids[0]); i++)
    {
        err_code = ble_db_discovery_evt_register(&obd_uuids[i]);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    }

    return NRF_SUCCESS;
}

I add filters to find the devices by name. After I connect to the found device, I start the database discovery. 

case BLE_GAP_EVT_CONNECTED:
            obd_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
            NRF_LOG_INFO("Connected to OBD with conn_handle: %d", obd_conn_handle);

            // Use discovery to find ble services
            err_code = ble_db_discovery_start(&m_db_disc, obd_conn_handle);
            APP_ERROR_CHECK(err_code);
            break;

The following snippet shows my code for my database discovery event. 

/**@brief Function for handling database discovery events for the OBD service.
 *
 * @param[in] p_obd_service_client Pointer to the OBD client instance.
 * @param[in] p_evt                Pointer to the discovery event structure.
 */
void ble_obd_c_on_db_disc_evt(ble_obd_c_t * p_obd_service_client, ble_db_discovery_evt_t * p_evt)
{
    memset(&obd_c_evt, 0, sizeof(ble_obd_c_evt_t));

    ble_gatt_db_char_t * p_chars = p_evt->params.discovered_db.charateristics;  

    // Check if the OBD was discovered.
    if (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE &&
        (p_evt->params.discovered_db.srv_uuid.uuid == BLE_UUID_LELINK_SERVICE || 
         p_evt->params.discovered_db.srv_uuid.uuid == BLE_UUID_VLINK_SERVICE || 
         p_evt->params.discovered_db.srv_uuid.uuid == BLE_UUID_FIXD_SERVICE) &&
        (p_evt->params.discovered_db.srv_uuid.type == p_obd_service_client->uuid_type))
    {
        for (uint32_t i = 0; i < p_evt->params.discovered_db.char_count; i++)
        {
            switch (p_chars[i].characteristic.uuid.uuid)
            {
                case BLE_UUID_LELINK_RX_CHARACTERISTIC:
                case BLE_UUID_VLINK_RX_CHARACTERISTIC:
                case BLE_UUID_FIXD_RX_CHARACTERISTIC:
                    // Found OBD characteristic inside the OBD Service.
                    p_obd_service_client->obd_service_rx_char = p_chars[i].characteristic;
                    p_obd_service_client->obd_cccd_handle = p_chars[i].cccd_handle;
                    NRF_LOG_INFO("Discovered rx characteristic handle: %i", p_chars[i].characteristic.handle_value);
                    break;
                case BLE_UUID_LELINK_TX_CHARACTERISTIC:
                case BLE_UUID_VLINK_TX_CHARACTERISTIC:
                case BLE_UUID_FIXD_TX_CHARACTERISTIC:
                    // Found OBD characteristic inside the OBD Service.
                    p_obd_service_client->obd_service_tx_char = p_chars[i].characteristic;
                    NRF_LOG_INFO("Discovered tx characteristic handle: %i", p_chars[i].characteristic.handle_value);
                    break;
                default:
                    break;
            }
        }
        if (p_obd_service_client->evt_handler != NULL)
        {
            obd_c_evt.conn_handle = p_evt->conn_handle;
            obd_c_evt.evt_type    = BLE_OBD_C_EVT_DISCOVERY_COMPLETE;
            p_obd_service_client->evt_handler(p_obd_service_client, &obd_c_evt);
        }
    }
    else if (p_evt->evt_type == BLE_DB_DISCOVERY_SRV_NOT_FOUND)
    {
        if (p_evt->params.discovered_db.srv_uuid.uuid == BLE_UUID_FIXD_SERVICE)
        {
            NRF_LOG_INFO("Service Not Found, UUID: 0x%04X", p_evt->params.discovered_db.srv_uuid.uuid);
        }
    }
}

For the LE Link and VLINK devices, the event type is BLE_DB_DISCOVERY_COMPLETE and gets their service uuids that contain the tx and rx characteristics. The issue is with the FIXD device. The output says "<info> ble_obd_c: Service Not Found, UUID: 0xFFF0" yet this is the service I am looking for. The event type says "BLE_DB_DISCOVERY_SRV_NOT_FOUND" yet the uuid is equal to the BLE_UUID_FIXD_SERVICE (which is 0xFFF0). I have attached the attribute table from the nRF52 connect app which connects to the FIXD Device fine. 

I also have wireshark logs of a OBD II phone app connecting to the device and what the nRF52 does when trying to connect if that helps at all as well. This was all developed using nRF52 sdk 17.0.2.

4073.VLINK to iOS Capture from connecting.pcapngVLINK to nRF52 Capture from connecting.pcapng

  • Hi Matt,

    I can see that you are using nRF5SDK. Your discovery is failing because the FIXD device's service UUID 0xFFF0 is not a standard 16-I think your BLE UUID, it's a 128-bit vendor-specific UUID, even though it appears as 0xFFF0 in nRF Connect.

    You registered it as a 16-bit UUID which you should do if the UUID is a BLE standard UUID of type BLE_UUID_TYPE_BLE .

    { .uuid = BLE_UUID_FIXD_SERVICE, .type = BLE_UUID_TYPE_BLE }
    

    The screenshot in the nrf connect app confirms this as it seems 0XFFF0 as unknown service

    In your code you have this check

    (p_evt->params.discovered_db.srv_uuid.type == p_obd_service_client->uuid_type)
    

    This check fails before BLE_UUID_TYPE_BLE != BLE_UUID_TYPE_VENDOR_BEGIN + X

    You need to add a full 128 bit UUID for your FIXD service/Device something like this

    #define FIXD_BASE_UUID  { 0xAB, 0xCD, 0xEF, 0x00, 0x12, 0x34, 0x56, 0x78, \
                              0x9A, 0xBC, 0xDE, 0xF0, 0xF0, 0xFF, 0x00, 0x00 }
    

    See that 0XFFF0 is represented in your base UUID in the little endian format.

    Register this to the softdevice uuid database

    ble_uuid128_t base_uuid = { FIXD_BASE_UUID };
    uint8_t uuid_type;
    
    err_code = sd_ble_uuid_vs_add(&base_uuid, &uuid_type);
    APP_ERROR_CHECK(err_code);
    ...
    ...
    // Then when you are registering for callback for discovery event of your service, you do this
    ble_uuid_t fixd_uuid;
    fixd_uuid.uuid = 0xFFF0;
    fixd_uuid.type = uuid_type;
    
    err_code = ble_db_discovery_evt_register(&fixd_uuid);
    

    You clearly need to have your uuid.type updated so that your compare in the discovery callback is comparing the right things.

    p_obd_service_client->uuid_type = uuid_type;
    
    in discovery callback you do this
    if (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE &&
        (p_evt->params.discovered_db.srv_uuid.uuid == BLE_UUID_FIXD_SERVICE) &&
        (p_evt->params.discovered_db.srv_uuid.type == p_obd_service_client->uuid_type))
    
    

    This should work now

  •   

    I have added the following code to add the uuid. 

    uint8_t uuid_type;
        uint32_t err_code;
        ble_uuid128_t base_uuid = { FIXD_BASE_UUID };
    
        err_code = sd_ble_uuid_vs_add(&base_uuid, &uuid_type);
        APP_ERROR_CHECK(err_code);
    
        ble_uuid_t obd_uuids[] = 
        {
            { .uuid = BLE_UUID_LELINK_SERVICE, .type = BLE_UUID_TYPE_BLE },
            { .uuid = BLE_UUID_VLINK_SERVICE, .type = BLE_UUID_TYPE_BLE },
            { .uuid = BLE_UUID_FIXD_SERVICE, .type = uuid_type } 
        };

    But after adding the uuid, the uuid type is 0x04 instead of 0x02. I cannot find anywhere that says what 0x04 for uuid type would mean after registering it? It should be 0x02 if it is vendor specific correct?

    EDIT: I see in the documentation, after each call it increments the uuid type by one. I call for ble_nus and dfu so 4 makes sense since this is the third call. 

    But I am still getting the service not found in the discovery event callback.

  • Hi

    Check out this case that discusses how to use ble_db_discovery to find the DFU service for example. I think that should give you some intel in the issue you're seeing here.

    Best regards,

    Simon

Related