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

Multiple Custom Services

I wrote some code that has multiple custom services where my device acts as GATT Server.

I register the handler for every service (3 in total) with NRF_SDH_BLE_OBSERVER as in this example:

#define BLE_CUS_DEF(_name)              \

static ble_cus_t _name;                 \

NRF_SDH_BLE_OBSERVER(_name ## _obs,     \

            BLE_HRS_BLE_OBSERVER_PRIO, \

             ble_cus_on_ble_evt, &_name)
 

The problem is that this will result in the SoftDevice calling all three EventHandler functions every time a service is used. Plus also calls some functions in the Peer manager. My problem is that they interfere with each other. So what would the best solution?

  • Check in the EventHandler function for which service the request came for -> which value could I use for this? I tried to use for example the ServiceHandle but this is the same for all client or the Rx- and Tx-Handles but I have the same problem here.
  • Write one huge callback function -> but then I run into the same problem as above where I need to distinguish the service

Thank you for any help!

Parents
  • Hi,

    This is how the SoftDeviec API is. You can subscribe to BLE events, and then you will get all BLE events. It is then up to the receiver to filter out what is relevant and ignore all other events. You can see how this is done in existing service implementations in the SDK.

    For instance, just to pick an example you can refer to components\ble\ble_services\ble_nus\ble_nus.c where you can see that in the on_write() function that tis called for the BLE_GATTS_EVT_WRITE event, the implementation checks if the write is to one of the two handles that can be written to in the NUS service implementation. If it is not, it is ignored.

  • Ok thank you!

    This helped me figured out that I could save the connection handle inside the if statement with the cccd_handle and would only disconnect if the ble event handle corresponded to the saved handle.

       if ((p_evt_write->handle == psBcpService->rxhandle.cccd_handle) &&
           (p_evt_write->len == 2))
       {
          if (p_client != NULL)
          {
        	_mymodule.UINT16_ConnHandle = psBleEvt->evt.gap_evt.conn_handle;
        	
        	...

          case BLE_GAP_EVT_DISCONNECTED:
    	// Check if the disconnected device is the current  Client
    	if(mymodule.UINT16_ConnHandle == psBleEvt->evt.gap_evt.conn_handle){
    	    mymodule.UINT16_ConnHandle = BLE_CONN_HANDLE_INVALID;
    	} 

    Just one thing I am not sure about. Why do we even bother to store the connection handle? I see that it is given to the DataHandler but then what can it be used for?

Reply
  • Ok thank you!

    This helped me figured out that I could save the connection handle inside the if statement with the cccd_handle and would only disconnect if the ble event handle corresponded to the saved handle.

       if ((p_evt_write->handle == psBcpService->rxhandle.cccd_handle) &&
           (p_evt_write->len == 2))
       {
          if (p_client != NULL)
          {
        	_mymodule.UINT16_ConnHandle = psBleEvt->evt.gap_evt.conn_handle;
        	
        	...

          case BLE_GAP_EVT_DISCONNECTED:
    	// Check if the disconnected device is the current  Client
    	if(mymodule.UINT16_ConnHandle == psBleEvt->evt.gap_evt.conn_handle){
    	    mymodule.UINT16_ConnHandle = BLE_CONN_HANDLE_INVALID;
    	} 

    Just one thing I am not sure about. Why do we even bother to store the connection handle? I see that it is given to the DataHandler but then what can it be used for?

Children
Related