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

Can I have multiple but distinct BLE event handlers

I have a multi peripheral sample I am trying to make work

I do a

BLE_NUS_DEF(m_nus) and BLE_HRS_DEF(m_hrs)

this will register two event handlers. 

When an event occurs, say a connection to HRS, I do see the events in both handlers. Is is possible to have only the HRS events to the hrs handler and NUS events to NUS handler ?

Thanks

Parents
  • Hello,

    Yes. This is possible, but please be aware that all the events propagate from the same bluetooth event handler. 

    Please see how the ble_app_uart example set up the nus event handler. Please note that it is not enough to set the nus_init.data_handler = nus_data_handler; You also need to manually send the events from inside the ble event handler in ble_nus.c.

    If you are interrested, there is also a tutorial here that I have used in a couple of courses. It is rather long, but you can see in the section "Step 8 - Propagating Custom Service events to the application" how to send the events to a custom service event handler.

    Please note that by default the HRS example doesn't have an event handler in main.c. But it is possible to set it up, if you follow the same method as the nus data handler, or the tutorial from the link.

    Best regards,

    Edvin

  • Thanks Edwin

    When you say "all events propagate from the same BT event handler". Understood.

    But my understanding is all event handlers will get even events from other sources. IE if I have a handler for NUS events and another for HRS events, each handler will get the other's events. Correct ?

  • Depends on how you trigger the custom event handlers. If you look in the ble_app_uart_example, you can see that the BLE_NUS_EVT_RX_DATA event is one event in the nus_data_handler(). However, this event is not defined by the softdevice. The event comes from the BLE_GATTS_EVT_WRITE event in the NUS' ble_handler in ble_nus.c:

    ble_nus_on_ble_evt() -> BLE_GATTS_EVT_WRITE -> on_write() ->

    Then it checks wether the event has the NUS service's service_handle. If that is true, then it will generate the event BLE_NUS_EVT_RX_DATA on line 171-175 (line numbers from SDK16) in ble_nus.c:

            evt.type                  = BLE_NUS_EVT_RX_DATA;
            evt.params.rx_data.p_data = p_evt_write->data;
            evt.params.rx_data.length = p_evt_write->len;
    
            p_nus->data_handler(&evt);

    Please read through the Step 8 on the tutorial. It has a more thorough walkthrough of this procedure.

Reply
  • Depends on how you trigger the custom event handlers. If you look in the ble_app_uart_example, you can see that the BLE_NUS_EVT_RX_DATA event is one event in the nus_data_handler(). However, this event is not defined by the softdevice. The event comes from the BLE_GATTS_EVT_WRITE event in the NUS' ble_handler in ble_nus.c:

    ble_nus_on_ble_evt() -> BLE_GATTS_EVT_WRITE -> on_write() ->

    Then it checks wether the event has the NUS service's service_handle. If that is true, then it will generate the event BLE_NUS_EVT_RX_DATA on line 171-175 (line numbers from SDK16) in ble_nus.c:

            evt.type                  = BLE_NUS_EVT_RX_DATA;
            evt.params.rx_data.p_data = p_evt_write->data;
            evt.params.rx_data.length = p_evt_write->len;
    
            p_nus->data_handler(&evt);

    Please read through the Step 8 on the tutorial. It has a more thorough walkthrough of this procedure.

Children
  • thanks

    I think I am getting closer and I am trying to read and understand. This could help me :

    When you say "Then it checks wether the event has the NUS service's service_handle", what specific code does this ? 

    I *think* this check is done in the softdevice ? Can you confirm how it's done.

    thanks

  • Please open ble_nus.c and look at the on_write() function. Look at where it is called (inside ble_nus_on_ble_evt()), and what it does. It is all in the source code. The event comes from the softdevice, but the checks and the forwarding of the event is all in the code (not the softdevice).

  • Thanks. Agreed. Correct me where I am wrong

    What you described is when something comes FROM central. I see a BLE_GATTS_EVT_WRITE come in and get sent down to ble_nus_on_ble_evt.

    onWrite gets called and a check of two handles occurs. I believe the SD provides the service handle of the event and it's compared to the service handle obtained during nus_init. If they match the event is propogated to the app. 

    In the opposite direction, when I send data from the peripheral, a connection handle and "service handle obtained during nus_init" are passed to sd_ble_gatts_hvx. I suspect a check done there by getting the service handles from the connection handle and comparing them to "service handle obstained during NUS init". If OK, generates a HVN_TX_COMPLETE. Otherwise fails in sd_ble_gatts_hvx. So this is done is the SD. I believe

    If I am correct, the key is having the service handles associated to the connection handle to do the checks. These service handles are there for some events (like a WRITE) but not other (on connect) for example.

    Correct ?

  • marcag said:
    I believe the SD provides the service handle of the event and it's compared to the service handle obtained during nus_init. If they match the event is propogated to the app. 

     Correct.

     

    marcag said:
    In the opposite direction, when I send data from the peripheral, a connection handle and "service handle obtained during nus_init" are passed to sd_ble_gatts_hvx. I suspect a check done there by getting the service handles from the connection handle and comparing them to "service handle obstained during NUS init". If OK, generates a HVN_TX_COMPLETE.

     Also correct. Just be aware that BLE_GATTS_EVT_HVN_TX_COMPLETE will be issued after (!) a message is ACKed by the central. You can queue up several packets using sd_ble_gatts_hvx(), as long as it returns NRF_SUCCESS. If it return NRF_ERROR_RESOURCES, it means that the sending queue is full, and you must wait for a TX_COMPLETE in order to queue the next packet. Please note that the TX_COMPLETE doesn't belong to a specific service. The BLE_GATTS_EVT_HVN_TX_COMPLETE events are general, telling you that a message was ACKed. But then again, all the services share the same queue.

    I believe this is why the BLE_NUS_EVT_TX_RDY isn't really used in main.c in this example. It is probably more common to use the BLE_GATTS_EVT_HVN_TX_COMPLETE event directly in main.c, but it is up to you.

    Best regards,

    Edvin

  • thanks Edvin, your help has been greatly appreciated !!!

Related