How to discover a service, disconnect from it and discover another one ?

CS_prog.zipRSSI_prog.zip

Hello,

I'm working on Windows 11, with the nRF Connect for VS Code v2025.5.512 extension, with ncs v3.0.2. I'm using the nRF54L15-dk (PCA10156; 0.9.2; 2025.7) development kits.

So, I want to use the channel sounding sample to measure a distance and then send a data if it's below a threshold. I first tried to implement that program with the BLE RSSI instead of using the CS and it works well (cf. RSSI_execution picture).

So my question is how to discover a service, disconnect from it and discover another one ?

Since the CS is using a service, I want to first discover the ranging service then if the measured distance is below the threshold, I want do discover my custom service to send my data. I tried discovering my custom service at the beginning and at the end of the loop that gets the distance in the main (while(true)) but then either it doesn't want to measure the distance and it sends the value directly or it gets the distance but can't send the data. (cf custom_begin and custom_end pictures respectively).

Do you know how I can fix those errors ? I've put my programs and pictures in the zip folders below for both the RSSI and the CS.

Thanks and best regards,

Patrick

Parents
  • Hello Patrick

    So my question is how to discover a service, disconnect from it and discover another one ?

    There is no need to disconnect from the device to discover other services. 

    Is it so that you have both the services working as it should in different applications? If so, look at how the service discovery is done in them. Try combining the two into the same central application. 

    Service discovery should only be done once per connection, and you can trigger it in the connected callback event, like it is done in most of our central application samples (e.g. using gatt_discover() in our central_uart sample). 

    Then, you can use your application logic to start sending notifications from the peripheral to the central whenever the distance is low enough.

    Best regards,

    Edvin

Reply
  • Hello Patrick

    So my question is how to discover a service, disconnect from it and discover another one ?

    There is no need to disconnect from the device to discover other services. 

    Is it so that you have both the services working as it should in different applications? If so, look at how the service discovery is done in them. Try combining the two into the same central application. 

    Service discovery should only be done once per connection, and you can trigger it in the connected callback event, like it is done in most of our central application samples (e.g. using gatt_discover() in our central_uart sample). 

    Then, you can use your application logic to start sending notifications from the peripheral to the central whenever the distance is low enough.

    Best regards,

    Edvin

Children
  • Hello Edvin,

    Thanks for the answer:

    In my program, I'm chaining the service and characteristics discoveries like that : ranging service -> custom service -> write characteristic -> confirm characteristic for the notification. So how can I switch from the ranging service to my custom when the distance is below a certain threshold ? Maybe it's due to the call of discover_custom_service() function that is misplaced in my program ? 

    Indeed, I don't think I need to disconnect from the first service to my custom one. 

    I don't know if my problem is clearer for you, now ?

    Best regards, 

    Patrick

  • Looking at your cs_initiator5.c, it seems like you start the discovery process in your connected_cb() function. 

    Your question is a bit diffuse to me. Your peripheral (reflector) should contain all the services and characteristics at all times. But it is up to your applications when you want to use them. When you connect, start the service discovery, which should store all the characteristic handles. 

    I see that you are using bt_gatt_discover() directly. This is possible, but perhaps you should consider using bt_gatt_dm_start() instead, which is a bit more abstracted. This is used in the NCS\nrf\samples\bluetooth\central_uart sample. Then you will get a discovery complete callback:

    static void discovery_complete(struct bt_gatt_dm *dm,
    			       void *context)
    {
    	struct bt_nus_client *nus = context;
    	LOG_INF("Service discovery completed");
    
    	bt_gatt_dm_data_print(dm);
    
    	bt_nus_handles_assign(dm, nus);
    	bt_nus_subscribe_receive(nus);
    
    	bt_gatt_dm_data_release(dm);
    }

    If you initialize the discovery parameters with service UUID = NULL, it will give you a callback for each service. So you just add handlers for all characteristics that you want to use, that checks if it is the correct service, and if so, register the handle. E.g. if you want to register the NUS (Nordic uart service) and an additional service called "CUS" (Custom service), you can have something like this:

    static void discovery_complete(struct bt_gatt_dm *dm,
    			       void *context)
    {
    	struct bt_nus_client *nus = context;
    	LOG_INF("Service discovery completed");
    
    	bt_gatt_dm_data_print(dm);
    
    	bt_nus_handles_assign(dm, nus);
    	bt_nus_subscribe_receive(nus);
    	bt_cus_handles_assign(dm, cus);
    	bt_cus_subscribe_receive(cus);
    
    	bt_gatt_dm_data_release(dm);
    }

    You can see in the implementation of e.g. bt_nus_handles_assign() in nus_client.c that the first thing it does is checking the UUID:

    int bt_nus_handles_assign(struct bt_gatt_dm *dm,
    			  struct bt_nus_client *nus_c)
    {
    	const struct bt_gatt_dm_attr *gatt_service_attr =
    			bt_gatt_dm_service_get(dm);
    	const struct bt_gatt_service_val *gatt_service =
    			bt_gatt_dm_attr_service_val(gatt_service_attr);
    	const struct bt_gatt_dm_attr *gatt_chrc;
    	const struct bt_gatt_dm_attr *gatt_desc;
    
    	if (bt_uuid_cmp(gatt_service->uuid, BT_UUID_NUS_SERVICE)) {
    		return -ENOTSUP;
    	}
    	...

    And returns if the UUID is not the BT_UUID_NUS_SERVICE, so when it is called on another service that is discovered, it will just ignore that service.

    Once all your services are discovered, you can use them from wherever you prefer in your application.

    Best regards,

    Edvin

  • Hello Edvin, 

    Thanks for the answer. 

    I've actually done it by moving my distance measurement and the discovery call in the callback function to register when the data is ready, that is to say in ranging_data_get_complete_cb().It seems to work fine. I'll consider your solution if something breaks.

    Best regards, 

    Patrick

  • CS2_prog.zip

    Hello Edvin, 

    So I implemented your solution and it works for the first loop.
    But, when the initiator is scanning for the second time, it's blocking here : 

    I've tried a lot of things but I can't get it to work. I have linked my new program in the attached documents. 
    It's working well if I reboot my device instead of scanning again in the disconnected_cb but I want to be able to not use the reboot since it consumes a lot.

    If you have any suggestion on how to solve my problem, it would be very helpful !

    Thanks and best regards, 

    Patrick

  • Hello Patrick,

    Can you please upload your current application, so that I can have a look, and reproduce the issue that you are seeing?

    My initial guess is that it is waiting for the "Security Changed" event, which never occurs, but without seeing your application, it is difficult to say. 

    You still shouldn't need to disconnect -> reconnect in order to use other services, but I am not really sure what your application looks like at this point, or what it is trying to do.

    Best regards,

    Edvin

Related