This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Problems while discovering services on a multilink central

Hi,

I developped a multilink central based on the example code ble_app_multilink_central.

I want to connect to several peripherals with two different custom services as shown in the following schematic.

The connection work but I have problems while discovering the services.

Sometimes the central discover all the services but often some services are not discovered and I don't understand why.

The discovery handler executes many times for each connection and the event type is often BLE_DB_DISCOVERY_ERROR.

Here is my discovery handler :

Here is an example of what can happen during a connection with 2 RFID and 1 Relay :

Here we can see that we have the relay on conn_handle 0x0 and the RFIDs on conn_handle 0x1 and 0x2.

We can see that the RFID service is not discovered on the conn_handle 0x1.

My questions are :

-When does the discovery handler execute for each connection?

-How to obtain the event BLE_DB_DISCOVERY_COMPLETE?

-Why does the discovery handler execute several time on each connection? And why is it not executed again while the service is not discovered?

Parents
  • If I remember correctly there is a limitation with the discovery module. so you should only do service discovery on one peer at the time. Can you try to add a check so you do not start service discovery on the new device if the process is already ongoing?

  • Do you have any other suggestions to improve my service discovery please run_ar?

  • Hi Jules, 

    I think we are getting close, now the problem is around why relay_on_db_disc_evt() (or rfid_on_db_disc_evt() ) wouldn't detect when there is an UUID match (evt_type = 0 ). 

    There is a following check: 

    if (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE &&
    p_evt->params.discovered_db.srv_uuid.uuid == RELAY_UUID &&
    p_evt->params.discovered_db.srv_uuid.type == p_relay_c->uuid_type)

    I suspect it could be something wrong with the uuid_type. If you can print out those values in the log, we may be able to find why the function is called but not executing anything. 

    We can try to test here and debug your application as well. But it doesn't built here. There is some absolute path you set (P:\Nordic\)

    If possible please send the latest source code. Are you still on SDK v15.0 or you moved to SDK v15.3 ? 

  • Hi Hung Bui,

    I added logs so we can see the parameters inside the checks in rfid_on_db_disc_evt() and in relay_on_db_disc_evt() when the event is BLE_DB_DISCOVERY_COMPLETE :

    void rfid_on_db_disc_evt(rfid_c_t * p_rfid_c, ble_db_discovery_evt_t const * p_evt)
    {
        if(p_evt->evt_type == 0)
        {
            NRF_LOG_INFO("rfid_on_db_disc_evt :");
            NRF_LOG_INFO("\tp_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE : %d",p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE);
            NRF_LOG_INFO("\tp_evt->params.discovered_db.srv_uuid.uuid == RFID_UUID : %d",p_evt->params.discovered_db.srv_uuid.uuid == RFID_UUID);
            NRF_LOG_INFO("\tp_evt->params.discovered_db.srv_uuid.type : %d\t\t\tp_rfid_c->uuid_type : %d",p_evt->params.discovered_db.srv_uuid.type,p_rfid_c->uuid_type);
        } 
    
        // Check if the Led Button Service was discovered.
        if (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE &&
            p_evt->params.discovered_db.srv_uuid.uuid == RFID_UUID &&
            p_evt->params.discovered_db.srv_uuid.type == p_rfid_c->uuid_type)
        {
            rfid_c_evt_t evt;
    
            evt.evt_type    = RFID_C_EVT_DISCOVERY_COMPLETE;
            evt.conn_handle = p_evt->conn_handle;
    
            for (uint32_t i = 0; i < p_evt->params.discovered_db.char_count; i++)
            {
                //NRF_LOG_INFO("Discovering characteristics.");
                const ble_gatt_db_char_t * p_char = &(p_evt->params.discovered_db.charateristics[i]);
                switch (p_char->characteristic.uuid.uuid)
                {
                    case SENSORS_FRAME_CHAR_UUID:
                        evt.params.peer_db.sensors_frame_handle      = p_char->characteristic.handle_value;
                        evt.params.peer_db.sensors_frame_cccd_handle = p_char->cccd_handle;
                        break;
                    
                    case MEASURE_REQUEST_CHAR_UUID:
                        evt.params.peer_db.measure_request_handle     = p_char->characteristic.handle_value;
                        break;
    
                    default:
                        break;
                }
            }
    
            //NRF_LOG_INFO("RFID Service discovered at peer.");
            //If the instance has been assigned prior to db_discovery, assign the db_handles
            if (p_rfid_c->conn_handle != BLE_CONN_HANDLE_INVALID)
            {
                if ((p_rfid_c->peer_rfid_db.sensors_frame_handle      == BLE_GATT_HANDLE_INVALID)&&
                    (p_rfid_c->peer_rfid_db.sensors_frame_cccd_handle == BLE_GATT_HANDLE_INVALID))
                {
                    p_rfid_c->peer_rfid_db = evt.params.peer_db;
                }
            }
    
            p_rfid_c->evt_handler(p_rfid_c, &evt);
    
        }
    }
    void relay_on_db_disc_evt(relay_c_t * p_relay_c, ble_db_discovery_evt_t const * p_evt)
    {
        if(p_evt->evt_type == 0)
        {
            NRF_LOG_INFO("relay_on_db_disc_evt :");
            NRF_LOG_INFO("\tp_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE : %d",p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE);
            NRF_LOG_INFO("\tp_evt->params.discovered_db.srv_uuid.uuid == RELAY_UUID : %d",p_evt->params.discovered_db.srv_uuid.uuid == RELAY_UUID);
            NRF_LOG_INFO("\tp_evt->params.discovered_db.srv_uuid.type : %d\t\t\tp_relay_c->uuid_type : %d",p_evt->params.discovered_db.srv_uuid.type,p_relay_c->uuid_type);
        }    
    
        // Check if the Led Button Service was discovered.
        if (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE &&
            p_evt->params.discovered_db.srv_uuid.uuid == RELAY_UUID &&
            p_evt->params.discovered_db.srv_uuid.type == p_relay_c->uuid_type)
        {
            relay_c_evt_t evt;
    
            evt.evt_type    = RELAY_C_EVT_DISCOVERY_COMPLETE;
            evt.conn_handle = p_evt->conn_handle;
    
            for (uint32_t i = 0; i < p_evt->params.discovered_db.char_count; i++)
            {
                //NRF_LOG_INFO("Discovering characteristics.");
                const ble_gatt_db_char_t * p_char = &(p_evt->params.discovered_db.charateristics[i]);
                switch (p_char->characteristic.uuid.uuid)
                {
                    case BLACKLIST_CHAR_UUID:
                        evt.params.peer_db.blacklist_handle      = p_char->characteristic.handle_value;
                        evt.params.peer_db.blacklist_cccd_handle = p_char->cccd_handle;
                        break;
                    case TRAME_CONCENTRATEUR_CHAR_UUID:
                        evt.params.peer_db.trame_concentrateur_handle     = p_char->characteristic.handle_value;
                        break;
                    default:
                        break;
                }
            }
            //NRF_LOG_INFO("RELAY Service discovered at peer.");
            //If the instance has been assigned prior to db_discovery, assign the db_handles
            if (p_relay_c->conn_handle != BLE_CONN_HANDLE_INVALID)
            {
                if ((p_relay_c->peer_relay_db.blacklist_handle      == BLE_GATT_HANDLE_INVALID)&&
                    (p_relay_c->peer_relay_db.blacklist_cccd_handle == BLE_GATT_HANDLE_INVALID))
                {
                    p_relay_c->peer_relay_db = evt.params.peer_db;
                }
            }
            p_relay_c->evt_handler(p_relay_c, &evt);
        }
    }

    You were right, it seems like the problem is coming from the uuid_type, I get this :

    <info> app: ------------------------------------------------------------------------------------------
    <info> app: -------------------------------------Concentrator-----------------------------------------
    <info> app: ------------------------------------------------------------------------------------------
    <info> app: Scanning for RFID and RELAY.
    <info> app: >>>>>RFID found<<<<<
    <info> app: Connection 0x0 established, attempt to find RFID or RELAY
    <info> app: rfid_on_db_disc_evt :
    <info> app: 	p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE : 1
    <info> app: 	p_evt->params.discovered_db.srv_uuid.uuid == RFID_UUID : 1
    <info> app: 	p_evt->params.discovered_db.srv_uuid.type : 2			p_rfid_c->uuid_type : 2
    <info> app: **********RFID service discovered on conn_handle 0x0**********
    <info> app: Scanning for RFID and RELAY.
    <info> app: relay_on_db_disc_evt :
    <info> app: 	p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE : 1
    <info> app: 	p_evt->params.discovered_db.srv_uuid.uuid == RELAY_UUID : 1
    <info> app: 	p_evt->params.discovered_db.srv_uuid.type : 2			p_relay_c->uuid_type : 3
    <info> app: >>>>>RFID found<<<<<
    <info> app: Connection 0x1 established, attempt to find RFID or RELAY
    <info> app: rfid_on_db_disc_evt :
    <info> app: 	p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE : 1
    <info> app: 	p_evt->params.discovered_db.srv_uuid.uuid == RFID_UUID : 1
    <info> app: 	p_evt->params.discovered_db.srv_uuid.type : 2			p_rfid_c->uuid_type : 2
    <info> app: **********RFID service discovered on conn_handle 0x1**********
    <info> app: Scanning for RFID and RELAY.
    <info> app: relay_on_db_disc_evt :
    <info> app: 	p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE : 1
    <info> app: 	p_evt->params.discovered_db.srv_uuid.uuid == RELAY_UUID : 1
    <info> app: 	p_evt->params.discovered_db.srv_uuid.type : 2			p_relay_c->uuid_type : 21
    <info> app: >>>>>RELAY found<<<<<
    <info> app: Connection 0x2 established, attempt to find RFID or RELAY
    <info> app: rfid_on_db_disc_evt :
    <info> app: 	p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE : 1
    <info> app: 	p_evt->params.discovered_db.srv_uuid.uuid == RFID_UUID : 1
    <info> app: 	p_evt->params.discovered_db.srv_uuid.type : 3			p_rfid_c->uuid_type : 2
    <info> app: relay_on_db_disc_evt :
    <info> app: 	p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE : 1
    <info> app: 	p_evt->params.discovered_db.srv_uuid.uuid == RELAY_UUID : 1
    <info> app: 	p_evt->params.discovered_db.srv_uuid.type : 3			p_relay_c->uuid_type : 178
    

    I will send you my source code in a private message.

    (P:\Nordic\) was the folder where I put SDK 15 and SDK 15.3.  (Now it is C:/Dev/nordic/)

    You have to put these two SDK in the folder of your choice and replace the path by the path of the folder you choosed. 

    I use SDK 15 but there is a exception. Only for the ble_db_discovery module, I use the SDK 15.3

    I did this in my .emProject file :

    ...
    
    c_user_include_directories= "... ;C:/Dev/nordic/nRF5_SDK_15.3.0_59ac345/components/ble/ble_db_discovery; ... "
    ...
    <folder Name="nRF_BLE">
    <file file_name="C:/Dev/nordic/nRF5_SDK_15.0.0_a53641a/components/ble/common/ble_advdata.c" />
    <file file_name="C:/Dev/nordic/nRF5_SDK_15.0.0_a53641a/components/ble/ble_advertising/ble_advertising.c" />
    <file file_name="C:/Dev/nordic/nRF5_SDK_15.0.0_a53641a/components/ble/common/ble_conn_state.c" />
    <file file_name="C:/Dev/nordic/nRF5_SDK_15.3.0_59ac345/components/ble/ble_db_discovery/ble_db_discovery.c" />
    <file file_name="C:/Dev/nordic/nRF5_SDK_15.0.0_a53641a/components/ble/common/ble_srv_common.c" />
    <file file_name="C:/Dev/nordic/nRF5_SDK_15.0.0_a53641a/components/ble/nrf_ble_gatt/nrf_ble_gatt.c" />
    </folder>
    ...

  • Hi Jules, 

    I think I found something wrong here. 

    As you can see in the log, the p_relay_c->uuid_type showing quite strange value (21, 178). 

    I think it was because of this function: 

    static void db_disc_handler(ble_db_discovery_evt_t * p_evt)
    {
      rfid_on_db_disc_evt(&m_rfid_c[p_evt->conn_handle], p_evt);
      relay_on_db_disc_evt(&m_relay_c[p_evt->conn_handle], p_evt);
    }

    In our multilink example this work because we only have one service lbs and there can be a simple match between the index of the m_lbs_c array and the index of connection handle. When it's not the case with your application. 

    You are declaring m_rfid_c array with the size of 7 and m_relay_c with size of 1. Calling a function using m_relay_c[p_evt->conn_handle] will cause trouble if the conn_handle is not equal to 0.

    And since you don't know which one will be the first one to connect you can't be sure that the conn_handle = 0 will be always be the relay. 

    So you need to define a table that keep track of the connection handle that match with the relay and the list of active RFID node in an array. And keep that table (array) up to date on each CONNECTED/DISCONNECTED event. (You can detect if a device is a relay or a RFID by the if check inside rfid_on_db_disc_evt() and    relay_on_db_disc_evt() ) 

  • Hi Hung Bui,

    I missed this and the error was due to this, thank you for your help.

    Now I have a table containing the types (RFID_TYPE our RELAY_TYPE) of devices for each conn_handle which is updated on DISCOVERY_COMPLETE and BLE_GAP_EVT_DISCONNECTED.

    I can count the RFID devices to know which instance of m_rfid_c I have to call in db_disc_handler. 

    For the relay, since I always use one relay, I define only one instance of relay client and call this one in db_disc_handler.

  • Hi Jules, 

    Glad that the issue is now fixed :D Sorry that the case has been dragging for some time. It's a bit hard to catch the bug :D

Reply Children
No Data
Related