Sending data to BLE Client using Notifications - nRF Connect SDK

Hello all,

I am currently working in a project that uses the nRF5340 SoC, nRF Connect SDK and Zephyr. The system has multiple sensors to measure various quantities such as temperature, humidity and pressure. All measurements are perfomed periodically and the data gathered is stored internally in form of data sets (each data set contains the measurement values of one iteration; e.g.: temperature, humidity and pressure). The system includes a BLE Server with various custom services, which will send the data sets to a BLE Client after a Client has sent a valid command request.

I have a few questions related to the best way to send the data to the BLE Client and the use of notifications (or indications):

  1. The first doubt is whether notifications or indications should be used. I found this interesting discussion and I understand that notifications are the better approach for my project, as there is indeed an ACK at the link layer and a minimal power consumption is also a desired goal. Do you see any reason to use indications?
  2. In the aforementioned discussion, the first answer states that Notifications "are still guaranteed to reach the target because of the link layer ACK". I am interested to know what happens with the Acknowledge of the link layer. Is Zephyr checking that it is received? How does my implementation know that the ACK has been received?

  3. At the moment, I have implemented a custom service using the Nordic Uart Service (NUS) as reference and I can send data to the BLE Client by calling the function bt_gatt_notify_cb. I am interested in the error situations. First, I tried to send data without any BLE Client being connected to the BLE Server. Secondly, I tried to send data without the BLE Client being subscribed. In both situations the function returns a negative value, which indicates that the function failed and the data could not be sent. So far so good, but shouldn`t the function retry to send the data until the ACK is received/timeout occurs?

  4. The function bt_gatt_notify_cb takes two input parameters. The second paremeter is the struct bt_gatt_notify_params, which contains the notification value callback bt_gatt_complete_func_t. The Zephyr documentation states that this is the "notification complete result callback". Am I right to assume that this callback will be called when the BLE Server has received the ACK of the link layer sent by the BLE Client?



  5. Each data set contains ~50Bytes and will be sent individually. I already modified the MTU in order to be able to send more than the 23 Bytes that are active per default. What would be the best way to send a significant amount of data sets (e.g. 100)? I was thinking of a for loop that calls the bt_gatt_notify_cb function as many times as data sets are to be sent.

  6. When sending multiple consecutive data sets as notifications, is there any way to detect if one or more packages were not sent successfully?

Many thanks in advance Slight smile

Parents
  • Hi,

    The first doubt is whether notifications or indications should be used. I found this interesting discussion and I understand that notifications are the better approach for my project, as there is indeed an ACK at the link layer and a minimal power consumption is also a desired goal. Do you see any reason to use indications?

    The only reason to use indications is if you need confirmation in the application layer that the indication has been received. This is only useful in some very specific cases.

    In the aforementioned discussion, the first answer states that Notifications "are still guaranteed to reach the target because of the link layer ACK". I am interested to know what happens with the Acknowledge of the link layer. Is Zephyr checking that it is received? How does my implementation know that the ACK has been received?

    Yes, the link layer (which is either the Zephyr link layer or the SoftDevice controller) keeps track of transmitted packets and if they are acknowledged or not. If not acknowledged the packets are retransmitted until successfully transferred and acknowledged. If retransmissions keep failing so that there are no packets exchanged during a supervision timeout (which is a basic connection parameter), the link will be closed due to supervision timeout. In that case the application will be notified that a supervision timeout has occurred.

    At the moment, I have implemented a custom service using the Nordic Uart Service (NUS) as reference and I can send data to the BLE Client by calling the function bt_gatt_notify_cb. I am interested in the error situations. First, I tried to send data without any BLE Client being connected to the BLE Server. Secondly, I tried to send data without the BLE Client being subscribed. In both situations the function returns a negative value, which indicates that the function failed and the data could not be sent. So far so good, but shouldn`t the function retry to send the data until the ACK is received/timeout occurs?

    No. You cannot send notifications (or indications) without a connection, and even if connected, the client needs to have enabled notifications/indications. It is correct and appropriate that the bt_gatt_notify_cb() function returns an error in this case.

    The function bt_gatt_notify_cb takes two input parameters. The second paremeter is the struct bt_gatt_notify_params, which contains the notification value callback bt_gatt_complete_func_t. The Zephyr documentation states that this is the "notification complete result callback". Am I right to assume that this callback will be called when the BLE Server has received the ACK of the link layer sent by the BLE Client?

    The callback is called when the packet has been ACKed on the link layer. Any retransmissions etc happen in the link layer without the host knowing about it.

    Each data set contains ~50Bytes and will be sent individually. I already modified the MTU in order to be able to send more than the 23 Bytes that are active per default. What would be the best way to send a significant amount of data sets (e.g. 100)? I was thinking of a for loop that calls the bt_gatt_notify_cb function as many times as data sets are to be sent.

    Yes, you can do that. It could make sense to wait for the callback before you send more in this case.

    When sending multiple consecutive data sets as notifications, is there any way to detect if one or more packages were not sent successfully?

    As long as you did not get any supervision timeout, all packets were sent successfully.

  • Hi Einar,

    thanks for your answers.

    I have a few follow-up questions:

    Yes, the link layer (which is either the Zephyr link layer or the SoftDevice controller) keeps track of transmitted packets and if they are acknowledged or not. If not acknowledged the packets are retransmitted until successfully transferred and acknowledged. If retransmissions keep failing so that there are no packets exchanged during a supervision timeout (which is a basic connection parameter), the link will be closed due to supervision timeout. In that case the application will be notified that a supervision timeout has occurred.

    How will my application be notified that the supervision timeout has occurrred? Is there any callback function to be configured in order to receive that information? Or is it the exact situation as when I disconnect my BLE Client from the BLE Peripheral and Zephyr tells me that the client has disconnected?

    The callback is called when the packet has been ACKed on the link layer. Any retransmissions etc happen in the link layer without the host knowing about it.

    I am a bit confused by the last sentence. What do you mean by "without the host knowing about it"?
    Correct me if my understanding is wrong: bt_gatt_complete_func_t is called when the packet has been ACKed on the link layer and my Application will directly be notified about it. The host layer is "skipped" and the information is directly sent to the application.

    Yes, you can do that. It could make sense to wait for the callback before you send more in this case.

    Ok. I will do that. Do I need to add some kind of delay between transmissions? Is there any limitation on the number of notify packets that can be sent per notification interval?

    Best regards.

  • Hi,

    jbf12 said:
    How will my application be notified that the supervision timeout has occurrred? Is there any callback function to be configured in order to receive that information?

    You will get a callback whenever the link is terminated (assuming you provided a callback function for disconnected in the struct you pass to bt_conn_cb_register()) for any reason, and in that callback there is a status code that informs you of the reason. This Bluetooth standard code is from the Bluetooth specification, and supervision timeout is 8.

    jbf12 said:
    I am a bit confused by the last sentence. What do you mean by "without the host knowing about it"?

    I mean that you will not be informed about any retransmissions, just when the packet has been ACKed (so you don't know if it was immediately or it it took several attempts).

    jbf12 said:
    Ok. I will do that. Do I need to add some kind of delay between transmissions?

    Not in this case. If you wait for the callback, you know you can send/queue another notification. If you like you could also just continue to try to send with a small delay between each time and ignore the error you get before the previous packet is sent. this would be less efficient, though.

    jbf12 said:
    Is there any limitation on the number of notify packets that can be sent per notification interval?

    Yes, but not a hard limit. That depends on the event length and length of the packets. If the event length is long enough, you can send multiple packet. There is no fixed maximum number of packets per connection event. (this means that for high throughput you typically want to set the event length so that the event length is as long as the connection interval).

Reply
  • Hi,

    jbf12 said:
    How will my application be notified that the supervision timeout has occurrred? Is there any callback function to be configured in order to receive that information?

    You will get a callback whenever the link is terminated (assuming you provided a callback function for disconnected in the struct you pass to bt_conn_cb_register()) for any reason, and in that callback there is a status code that informs you of the reason. This Bluetooth standard code is from the Bluetooth specification, and supervision timeout is 8.

    jbf12 said:
    I am a bit confused by the last sentence. What do you mean by "without the host knowing about it"?

    I mean that you will not be informed about any retransmissions, just when the packet has been ACKed (so you don't know if it was immediately or it it took several attempts).

    jbf12 said:
    Ok. I will do that. Do I need to add some kind of delay between transmissions?

    Not in this case. If you wait for the callback, you know you can send/queue another notification. If you like you could also just continue to try to send with a small delay between each time and ignore the error you get before the previous packet is sent. this would be less efficient, though.

    jbf12 said:
    Is there any limitation on the number of notify packets that can be sent per notification interval?

    Yes, but not a hard limit. That depends on the event length and length of the packets. If the event length is long enough, you can send multiple packet. There is no fixed maximum number of packets per connection event. (this means that for high throughput you typically want to set the event length so that the event length is as long as the connection interval).

Children
No Data
Related