Connecting to Custom Service/Characteristic of BLE peripheral with nRF52 acting as central.

I am currently connected to a BLE peripheral with the nRF52 acting as the central. I am able to scan using the device's name and connect. I created a custom file to handle the central functions including adding the custom UUID and starting the discovery. This done here

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_uuid;
    // TODO for V Link
    ble_uuid128_t obd_base_uuid = OBD_BASE_UUID;
    obd_uuid.uuid = BLE_UUID_OBD_SERVICE;
    obd_uuid.type = BLE_UUID_TYPE_VENDOR_BEGIN;

    VERIFY_PARAM_NOT_NULL(p_obd_service_client);
    VERIFY_PARAM_NOT_NULL(p_ble_obd_c_init);

    err_code = sd_ble_uuid_vs_add(&obd_base_uuid, &obd_uuid.type);
    VERIFY_SUCCESS(err_code);

    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_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_VENDOR_BEGIN;

    return ble_db_discovery_evt_register(&obd_uuid);
}

The discovery runs smoothly and finds the Service. The issue is that the characteristic is not there, so I am unable to read and write to the device. This is where I try and find the characteristic. The uuid type is returning as 4, but I thought there was only 0, 1, and 2 (I set it to 2, the BLE_UUID_TYPE_VENDOR_BEGIN).

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_OBD_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_OBD_CHARACTERISTIC:
                    // Found OBD characteristic inside the OBD Service.
                    p_obd_service_client->obd_service_char = p_chars[i].characteristic;
                    NRF_LOG_INFO("Discovered 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);
        }
    }
}

These are my defines for the custom service/characteristics of the OBD device 

#define OBD_BASE_UUID {{0xF2, 0xC3, 0xF0, 0xAE, 0xA9, 0xFA, 0x15, 0x8C, 0x9D, 0x49, 0xAE, 0x73, 0x71, 0x0A, 0x81, 0xE7}}

#define BLE_UUID_OBD_SERVICE 0x0A71                   //< The UUID of the OBD Service. 
#define BLE_UUID_OBD_CHARACTERISTIC 0xD6C9  // < The UUID of the RX and TX Characteristic. 

I attached an image of the service/characteristic from nRF52 connect. 

I have another OBD device that uses 16 bit UUIDS and was able to do this easily, but since these use 128 bit UUIDs, I am running into some issues.

I have attached my wireshark capture from when I establish a connection, search for the service and then search for the characteristic for a working device and the non-working one. The LE Link Capture is working while the VLINK does not.

3225.VLINK Capture from connecting.pcapng5381.LE LINK Capture from connecting.pcapngVLINK to iOS Capture from connecting.pcapng

Parents
  • inspiringdev123 said:
    The peripheral is from an outside source, so I do not have any control over the code.

    So it is not possible to adjust this, as I see.

    What  I notice is that the service and characteristic doesn't have the same base UUID (service starting with 0xe781, and characteristic starting with 0xbef8), which may be causing the issues that you are seeing. 

    If your implementation is based off the NUS_C implementation, there is a check in the callback handler:

        // Check if the NUS was discovered.
        if (    (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE)
            &&  (p_evt->params.discovered_db.srv_uuid.uuid == BLE_UUID_NUS_SERVICE)
            &&  (p_evt->params.discovered_db.srv_uuid.type == p_ble_nus_c->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_NUS_RX_CHARACTERISTIC:
                        nus_c_evt.handles.nus_rx_handle = p_chars[i].characteristic.handle_value;
                        break;
    

    But I am not sure these will end up in the same callback if the Service's base UUID and characteristic's base UUID are different. Perhaps you can step through, or try to print the UUIDs in the callback to see how it behaves. 

    Best regards,

    Edvin

Reply
  • inspiringdev123 said:
    The peripheral is from an outside source, so I do not have any control over the code.

    So it is not possible to adjust this, as I see.

    What  I notice is that the service and characteristic doesn't have the same base UUID (service starting with 0xe781, and characteristic starting with 0xbef8), which may be causing the issues that you are seeing. 

    If your implementation is based off the NUS_C implementation, there is a check in the callback handler:

        // Check if the NUS was discovered.
        if (    (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE)
            &&  (p_evt->params.discovered_db.srv_uuid.uuid == BLE_UUID_NUS_SERVICE)
            &&  (p_evt->params.discovered_db.srv_uuid.type == p_ble_nus_c->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_NUS_RX_CHARACTERISTIC:
                        nus_c_evt.handles.nus_rx_handle = p_chars[i].characteristic.handle_value;
                        break;
    

    But I am not sure these will end up in the same callback if the Service's base UUID and characteristic's base UUID are different. Perhaps you can step through, or try to print the UUIDs in the callback to see how it behaves. 

    Best regards,

    Edvin

Children
  •   

    What would cause the p_evt->params.discovered_db.srv_uuid.type to equal 4? This does not seemed defined for UUID type. My custom service is stating it is type 4 even though when I register it as BLE_UUID_TYPE_VENDOR here

    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_uuid;
        // TODO VLINK 
        ble_uuid128_t obd_base_uuid = OBD_BASE_UUID;
    
        obd_uuid.uuid = BLE_UUID_OBD_SERVICE;
        // TODO LE LINK 
        // obd_uuid.type = BLE_UUID_TYPE_BLE;
        // TODO VLINK 
        obd_uuid.type = BLE_UUID_TYPE_VENDOR_BEGIN;
    
        VERIFY_PARAM_NOT_NULL(p_obd_service_client);
        VERIFY_PARAM_NOT_NULL(p_ble_obd_c_init);
        
        // TODO VLINK
        err_code = sd_ble_uuid_vs_add(&obd_base_uuid, &obd_uuid.type);
        VERIFY_SUCCESS(err_code);
    
        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_char.handle_value  = BLE_GATT_HANDLE_INVALID;
        p_obd_service_client->p_gatt_queue                   = p_ble_obd_c_init->p_gatt_queue;
        // TODO LE LINK 
        // p_obd_service_client->uuid_type                      = BLE_UUID_TYPE_BLE;
        // TODO VLINK
        p_obd_service_client->uuid_type                      = BLE_UUID_TYPE_VENDOR_BEGIN;
    
        return ble_db_discovery_evt_register(&obd_uuid);
    }

  • I agree with Edvin about the inconsistency of the base UUID which may lead to this issue. Thus, something wrong with the UUID setup in the central custom service.

    Basically, the central custom service has to look for the service UUID and characteristic UUID of the peripheral device.

    I did a primary service discovery with the VLINK device in the nRF52 firmware and only found 4 Primary Services, 0x1800, 0x1801, 0x18F0, and 0x180A. It never found the Unknown Primary Service (e7810a71-73ae-499d-8c15-faa9aef0c3f2). This is the service with the read and write characteristic. 

    The base uuid should be used for different services (i.e., different service UUIDs). Make sure you use correct service UUID in your central custom BLE.

    Regarding the uuid type, you shouldn't assign it either BLE_UUID_TYPE_BLE or BLE_UUID_TYPE_VENDOR_BEGIN as it's supposed to detect by the central custom BLE. This info was obtained from the peripheral device. That's why you were trying to assign it, but it gave you a different return number.

    Edit1: Can you take a capture of nRF connect app in the case that you can use iOS app to read and write your peripheral device? You can show all services available and expand the one that allows you to notify/read/write.

  • This is from iOS wireshark capture, it even didn't detect ATT from this service UUID: e7810a71-73ae-499d-8c15-faa9aef0c3f2. Thus, I don't think it's a correct service that you were looking for to read/write to your peripheral device.

  •  

    You are right. The service is 0X18F. The RX Characteristic is 0x2AF0 and the Notify Characteristic is 0x2AF1

  • So I guess you just need to update the following parameters and have a test. Hope it works. Otherwise, you can share your whole central custom ble service so that we can check if the issue is still there.

    #define BLE_UUID_OBD_SERVICE 0x0A71                   //< The UUID of the OBD Service. 
    #define BLE_UUID_OBD_CHARACTERISTIC 0xD6C9  // < The UUID of the RX and TX Characteristic. 

Related