Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Notification length greater than current connection MTU size (not MTU max size)

Hey Guys,

Have been playing around with various MTU sizes to better understand throughput.  I'm curious about one scenario though.  Let's say for example that we are using the UART service and our MAX_MTU size is 158.  The UART service sets the characteristic to use a max length of MAX_MTU.

Then let's say in my code I do ble_nus_string_send(&m_nus, data, dataLength), where dataLength = 100.

For phones capable of higher MTUs & DLE this will work fine and we'll get higher throughput.  However, what happens if a older phone who is only capable of an MTU size of 23 connects?

I've tested this on my phone by connecting and then manually setting the MTU connection size to 23.  It looks like my code doesn't throw an errors, I still see TX complete events.  However, in nrfConnect, I don't see any data being read back.

What is the expected behavior here?  Or is it expected that I need to keep track of the MTU size and adjust the notification length appropriately?

Parents
  • Hi,

    Bluetooth Specification Version 5.0 | Vol 3, Part F,  3.4.7.1 Handle Value Notification has this to say about notifications: 

    "If the attribute value is longer than (ATT_MTU-3) octets, then only the first (ATT_MTU-3) octets of this attributes value can be sent in a notification"

    A workaround is to implement a mechanism that splits the characteristic value into several ATT_MTU-3 bytes long pieces and send them using multiple notifications. The offset field in the ble_gatts_hvx_params_t structure comes in handy here. 

     

  • Hi ,

    Thanks for the tip.  Does this mean that the SDK will truncate data and then send it through?  Or will it just error out?  Or will there be unexpected behaviour?

    As I mentioned it seems like I'm still getting TX complete events but I'm not seeing any data on the TX characteristic on nrfConnect when I would otherwise.

  • Hi,

    It should just truncate the data. However, this is the definition of the function you reference in the OP:

    uint32_t ble_nus_string_send(ble_nus_t * p_nus, uint8_t * p_string, uint16_t * p_length)
    {
        ble_gatts_hvx_params_t hvx_params;
    
        VERIFY_PARAM_NOT_NULL(p_nus);
    
        if ((p_nus->conn_handle == BLE_CONN_HANDLE_INVALID) || (!p_nus->is_notification_enabled))
        {
            return NRF_ERROR_INVALID_STATE;
        }
    
        if (*p_length > BLE_NUS_MAX_DATA_LEN)
        {
            return NRF_ERROR_INVALID_PARAM;
        }
    
        memset(&hvx_params, 0, sizeof(hvx_params));
    
        hvx_params.handle = p_nus->tx_handles.value_handle;
        hvx_params.p_data = p_string;
        hvx_params.p_len  = p_length;
        hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
    
        return sd_ble_gatts_hvx(p_nus->conn_handle, &hvx_params);
    }

    You can see there is an if (*p_length > BLE_NUS_MAX_DATA_LEN) statement. Could this be the reason why nothing is sent? Are you checking the return codes of ble_nus_string_send()?

Reply
  • Hi,

    It should just truncate the data. However, this is the definition of the function you reference in the OP:

    uint32_t ble_nus_string_send(ble_nus_t * p_nus, uint8_t * p_string, uint16_t * p_length)
    {
        ble_gatts_hvx_params_t hvx_params;
    
        VERIFY_PARAM_NOT_NULL(p_nus);
    
        if ((p_nus->conn_handle == BLE_CONN_HANDLE_INVALID) || (!p_nus->is_notification_enabled))
        {
            return NRF_ERROR_INVALID_STATE;
        }
    
        if (*p_length > BLE_NUS_MAX_DATA_LEN)
        {
            return NRF_ERROR_INVALID_PARAM;
        }
    
        memset(&hvx_params, 0, sizeof(hvx_params));
    
        hvx_params.handle = p_nus->tx_handles.value_handle;
        hvx_params.p_data = p_string;
        hvx_params.p_len  = p_length;
        hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
    
        return sd_ble_gatts_hvx(p_nus->conn_handle, &hvx_params);
    }

    You can see there is an if (*p_length > BLE_NUS_MAX_DATA_LEN) statement. Could this be the reason why nothing is sent? Are you checking the return codes of ble_nus_string_send()?

Children
Related