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

What is the purpose of the hvx 'offset' parameter and how is it used?

I have created a characteristic for sending up to 60 data bytes in a buffer using a sequence of 20 byte notifications sent to an external device. This works quite well for rapidly streaming out the data. I trigger streaming notifications on a write to a certain write characteristic. Here is the code that gets executed on that specific write event...

                // Define number of required notifications to send...
                maxNotificationLen = 20;
                numNotifications = (numBytesToSend / 20) + 1;
                // Define number of remaining bytes to send in last notification...
                lastNotificationLen = numBytesToSend % 20;
                // If the number of bytes to send is a multiple of the notification length...
                if (lastNotificationLen == 0)
                {
                  // Adjust accordingly...
                  numNotifications--;
                  lastNotificationLen = 20;
                }
                notificationIndex = 0;

                memset(&hvx_params, 0, sizeof(hvx_params));
                hvx_params.handle = customService.charHandles[BCI_BLOB_NT].value_handle;
                hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;

                while(err_code == NRF_SUCCESS)
                {
                  // Check if we have data to send...
                  if(numNotifications > 0)
                  {
                    hvx_params.p_data = dataBuffer + (notificationIndex * 20);
                    // hvx_params.offset = notificationIndex * 20;
                    // If this is not the last notification to send...
                    if (numNotifications > 1)
                    {
                      hvx_params.p_len = &maxNotificationLen;
                    }
                    // Otherwise...
                    else
                    {
                      hvx_params.p_len = &lastNotificationLen;
                    }
                    err_code = sd_ble_gatts_hvx(customService.connHandle, &hvx_params);
                    if (err_code == NRF_SUCCESS)
                    {
                      notificationIndex++;
                      numNotifications--;
                    }
                  }
                  else
                  {
                    break;
                  }
                }

If the call to sd_ble_gatts_hvx does not return NRF_SUCCESS, I will get a BLE_EVT_TX_COMPLETE event. In this case, I continue the while loop to finish sending the remaining notifications. If I leave hvx_params.offset set to 0 and simply adjust the p_data pointer, each notification sends the next 20 bytes in the buffer until it sends the final remaining bytes as part of the last notification. However, if I set hvx_params.offset = notificationIndex * 20, the size of each notification increases by 20 bytes until the entire string of bytes in the buffer get sent in the last notification (I have increased the MTU size to support this) even though hvx_params.p_len is either fixed to &maxNotificationLen or &lastNotificationLen. This seems rather strange to me. Can you please explain the purpose of hvx_params.offset and how it is supposed to be used? Thanks for the help.

  • The value of the offset sets where in the attribute value the data should be updated. So if you have a 30 byte attribute value size, a data length of 20, and an offset of 0 you will update the 20 first bytes, if you have a offset of 10 you will update the 20 last bytes. The offset shouldn't have anything to do with the notification size, that should be determined by the data length (p_len).

Related