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

How to send notification for a large custom attribute

I am using nRF52 S132 and latest SDK V11. I defined a custom service with a custom characteristic which is 509 bytes (based on your tutorial). Read operation is fine from a client. But when using sd_ble_gatts_hvx() to send notification, only the first 20 bytes are received. The return code of this function is 0x3401, which means BLE_ERROR_GATTS_SYS_ATTR_MISSING. But it does not make sense to me. So I reduce the size from 509 to 10. The notification is sent and received. But the error code is still 0x3401. How to send notification properly?

Parents
  • Another approach which seems to work, is to queue up multiple notifications using a characteristic with short length. By updating the characteristic value between each call to sd_ble_gatts_hvx() it results in multiple notifications, each with the portion you want to send.

            uint16_t len = BLOCK_SIZE;
            ble_gatts_hvx_params_t hvx_params;
            hvx_params.handle = m_p_resp->handles.value_handle;
            hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
            hvx_params.offset = 0;
            hvx_params.p_data = NULL;
            hvx_params.p_len  = &len;
            // Notify full value as three individual piece notifications.
            for (int i = 0 ; i < (3 * BLOCK_SIZE) ; i += len)
            {
                static uint8_t fill = 0;
                memset(m_response, fill++, sizeof(m_response));
    
                uint32_t err_code = sd_ble_gatts_hvx(
                    p_ble_event->evt.gatts_evt.conn_handle,
                    &hvx_params
                    );
                APP_ERROR_CHECK(err_code);
            }
    

    Another way to do this would be to break the longer characteristic into multiple short characteristics and notify on each one.

  • Yes, it is definitely misleading how the offset doesn't work as one might expect in this situation. Would have been much simpler to implement if the offset would allow sending different parts of the value without having to copy each piece down into the lower portion (and then restore the full value in case there is a read by a peer afterwards).

    I wound up writing a function: "notify_long_chx()" which handles the general case. It gets called to send a long value as a series of shorter notifications and also handles running out of TX buffers--indicating so in the return value--so that it can be called again to finish on a subsequent BLE_EVT_TX_COMPLETE. Sorry I can't share the code since it was written for a client.

    Good luck - Tony

Reply
  • Yes, it is definitely misleading how the offset doesn't work as one might expect in this situation. Would have been much simpler to implement if the offset would allow sending different parts of the value without having to copy each piece down into the lower portion (and then restore the full value in case there is a read by a peer afterwards).

    I wound up writing a function: "notify_long_chx()" which handles the general case. It gets called to send a long value as a series of shorter notifications and also handles running out of TX buffers--indicating so in the return value--so that it can be called again to finish on a subsequent BLE_EVT_TX_COMPLETE. Sorry I can't share the code since it was written for a client.

    Good luck - Tony

Children
No Data
Related