<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Sending large amounts of data from phone to nrf52840</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/43360/sending-large-amounts-of-data-from-phone-to-nrf52840</link><description>I realise this question must have been asked a thousand times, but the more answers I read, the more confused I am! 
 I am looking to transfer 7kb of data occasionally (maybe once every hour) from an Android phone to an NRF52840. From my research it seems</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Fri, 22 Feb 2019 14:41:29 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/43360/sending-large-amounts-of-data-from-phone-to-nrf52840" /><item><title>RE: Sending large amounts of data from phone to nrf52840</title><link>https://devzone.nordicsemi.com/thread/172543?ContentTypeID=1</link><pubDate>Fri, 22 Feb 2019 14:41:29 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:729e75d8-664a-4f5d-bccd-321c94c356be</guid><dc:creator>bjorn-spockeli</dc:creator><description>&lt;p&gt;Hi Chris,&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I apologize for the late reply.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;It turns out that a Queued Write is the same as a&amp;nbsp;&lt;/span&gt;long write, i.e. multiple Prepare Write Requests in sequence with offsets followed by a Write Execute,see &lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href="https://www.nordicsemi.com/DocLib/Content/SoftDevice_API_Doc/S140/v6-1-0/group_ble_gattc_value_long_write_msc"&gt;GATTC Characteristic or Descriptor Value Long Write&lt;/a&gt;&amp;nbsp;and &lt;a href="https://www.nordicsemi.com/DocLib/Content/SoftDevice_API_Doc/S140/v6-1-0/group_ble_gatts_queued_write_nobuf_noauth_msc"&gt;GATTS Queued Writes: App handled, no attributes require authorization&lt;/a&gt;. So the QWR module should be able to do what you&amp;#39;re looking for.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Are you still having issues with getting this to work as it should?&lt;/p&gt;
&lt;p&gt;Best regards&lt;/p&gt;
&lt;p&gt;Bjørn&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Sending large amounts of data from phone to nrf52840</title><link>https://devzone.nordicsemi.com/thread/169786?ContentTypeID=1</link><pubDate>Wed, 06 Feb 2019 16:04:54 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:239fc085-3d1d-4169-8150-71e548d5f27d</guid><dc:creator>cirlam</dc:creator><description>&lt;p&gt;Ahhh, that would make sense - the Queued Write module is initialized, as I have converted my application from the ble_cscs example. &lt;/p&gt;
&lt;p&gt;I think the thing that is confusing me is that Queued/Reliable Writes are different to Long Writes - so wasn&amp;#39;t aware you could implement both different methods using the Queued Write module. &lt;/p&gt;
&lt;p&gt;With the queued write example, am I correct in thinking it shows the Queued/Reliable write implementation? If so, what would I need to modify to make it a Long Write? &lt;/p&gt;
&lt;p&gt;The nrf_ble_qwr_evet_type_t values of EXECUTE_WRITE and AUTH_REQUEST sound very specific to Queued/Reliable writes, and not something useful in a Long Write?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Sending large amounts of data from phone to nrf52840</title><link>https://devzone.nordicsemi.com/thread/169783?ContentTypeID=1</link><pubDate>Wed, 06 Feb 2019 15:49:10 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c59ba64e-34a7-41f1-b3ca-ee780cc6a5fe</guid><dc:creator>bjorn-spockeli</dc:creator><description>&lt;p&gt;Hi Chris,&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I agree, the fact that you&amp;#39;re getting the&amp;nbsp;BLE_EVT_USER_MEM_REQUEST event should&amp;nbsp; rule out that there is no user memory request pending.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;However, are you initializing the Queued Write module in services_init(), i.e. calling&amp;nbsp;nrf_ble_qwr_init()?&amp;nbsp; If so then it could be that the event has already been handled by&amp;nbsp;nrf_ble_qwr_on_ble_evt().&amp;nbsp;&lt;/p&gt;
&lt;p&gt;You could try to use the&amp;nbsp;&lt;a href="https://www.nordicsemi.com/DocLib/Content/SDK_Doc/nRF5_SDK/v15-2-0/lib_ble_queued_write"&gt;Queued Writes&lt;/a&gt;&amp;nbsp;module instead of handling the&amp;nbsp;&lt;span&gt;BLE_EVT_USER_MEM_REQUEST yourself?&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Sending large amounts of data from phone to nrf52840</title><link>https://devzone.nordicsemi.com/thread/169667?ContentTypeID=1</link><pubDate>Wed, 06 Feb 2019 09:19:50 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:6274dea6-7e30-489e-9b74-de2b695f1f05</guid><dc:creator>cirlam</dc:creator><description>&lt;p&gt;Hi Bjorn,&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve fixed some fairly obvious bugs in the above code (namely, removing the CCCD seeing as its not a notifiable characteristic), and have tried testing the long write by sending a ~8600byte transfer to this characteristic (I&amp;#39;m using Nordic Android BLE Libary to issue this transfer from my Pixel 2 phone).&lt;/p&gt;
&lt;p&gt;BLE_EVT_USER_MEM_REQUEST is successfully called in my peripheral, but when I go to &amp;quot;sd_ble_user_mem_reply&amp;quot;, I get a return value of 8, which is NRF_ERROR_INVALID_STATE.&lt;/p&gt;
&lt;p&gt;I can see this is either &amp;quot;Invalid Connection state or no user memory request pending.&amp;quot;. Obviously the call to BLE_EVT_USER_MEM_REQUEST should mean the softdevice is expecting a memory block to be passed to it, so that leaves Invalid Connection State - but I am definitely connected at this stage, as the device continues to issue notifications (other characteristics) to the phone both before and directly after this event, with no disconnects inbetween. Any idea what could be wrong here?&lt;/p&gt;
&lt;p&gt;My code now is as follows:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#define LONG_WRITE_LENGTH 9000

static uint8_t queued_write_buffer[LONG_WRITE_LENGTH];
static ble_user_mem_block_t mem_block;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static uint32_t assist_gps_char_add(ble_peripheral_service_t *p_peripheral_service) {
  // OUR_JOB: Step 2.A, Add a custom characteristic UUID
  uint32_t err_code;
  ble_gatts_char_md_t char_md;
//  ble_gatts_attr_md_t cccd_md;
  ble_gatts_attr_t attr_char_value;
  ble_gatts_attr_md_t attr_md;

  uint8_t encoded_gps_meas[ASSIST_GPS_MEAS_LEN];

  ble_uuid_t char_uuid;
  ble_uuid128_t base_uuid = BLE_UUID_PERIPHERAL_BASE_UUID;
  char_uuid.uuid = BLE_UUID_GPS_ASSIST_CHARACTERISTIC_UUID;

  err_code = sd_ble_uuid_vs_add(&amp;amp;base_uuid, &amp;amp;char_uuid.type);
  APP_ERROR_CHECK(err_code);

//  memset(&amp;amp;cccd_md, 0, sizeof(cccd_md));
//  BLE_GAP_CONN_SEC_MODE_SET_OPEN(&amp;amp;cccd_md.read_perm);
//  BLE_GAP_CONN_SEC_MODE_SET_OPEN(&amp;amp;cccd_md.write_perm);
//  cccd_md.vloc = BLE_GATTS_VLOC_STACK;

  memset(&amp;amp;char_md, 0, sizeof(char_md));
  char_md.char_props.read = 1;
  char_md.char_props.write = 1;
  char_md.char_props.notify = 0;
  char_md.p_char_user_desc = NULL;
  char_md.p_char_pf = NULL;
  char_md.p_user_desc_md = NULL;
  char_md.p_cccd_md = NULL;
  char_md.p_sccd_md = NULL;  

  memset(&amp;amp;attr_md, 0, sizeof(attr_md));
  BLE_GAP_CONN_SEC_MODE_SET_OPEN(&amp;amp;attr_md.read_perm); 
  BLE_GAP_CONN_SEC_MODE_SET_OPEN(&amp;amp;attr_md.write_perm);
  attr_md.vloc = BLE_GATTS_VLOC_STACK;
  attr_md.rd_auth = 0;
  attr_md.wr_auth = 0;
  attr_md.vlen = 1;

  memset(&amp;amp;attr_char_value, 0, sizeof(attr_char_value));

  memset(&amp;amp;encoded_gps_meas, 0, ASSIST_GPS_MEAS_LEN);

  attr_char_value.p_uuid = &amp;amp;char_uuid;
  attr_char_value.p_attr_md = &amp;amp;attr_md;
  attr_char_value.init_len = ASSIST_GPS_MEAS_LEN;
  attr_char_value.init_offs = 0;
  attr_char_value.max_len = LONG_WRITE_LENGTH;
  attr_char_value.p_value = encoded_gps_meas;

  return sd_ble_gatts_characteristic_add(p_peripheral_service-&amp;gt;service_handle,
      &amp;amp;char_md,
      &amp;amp;attr_char_value,
      &amp;amp;p_peripheral_service-&amp;gt;gps_assist_char_handle);
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;case BLE_EVT_USER_MEM_REQUEST: {
  ret_code_t err_code;
    memset(&amp;amp;mem_block, 0, sizeof(mem_block));
    memset(&amp;amp;queued_write_buffer[0],0,LONG_WRITE_LENGTH);
    mem_block.len = LONG_WRITE_LENGTH;
    mem_block.p_mem = &amp;amp;queued_write_buffer[0];
     if (p_peripheral_service-&amp;gt;conn_handle != BLE_CONN_HANDLE_INVALID) {
    err_code = sd_ble_user_mem_reply(p_peripheral_service-&amp;gt;conn_handle, &amp;amp;mem_block);
    if (err_code != NRF_SUCCESS) {
      SEGGER_RTT_printf(0,&amp;quot;ERROR sd_ble_user_mem_reply: %u\r\n&amp;quot;, (unsigned int)err_code);
    } else {
      SEGGER_RTT_printf(0,&amp;quot;USER_MEM_REQUEST OK\r\n&amp;quot;);
    }
    }
    }
    break;
  case BLE_EVT_USER_MEM_RELEASE:
    SEGGER_RTT_printf(0, &amp;quot;MEM RELEASE\n&amp;quot;);
    if ((p_ble_evt-&amp;gt;evt.common_evt.params.user_mem_release.mem_block.p_mem == mem_block.p_mem) &amp;amp;&amp;amp; (p_ble_evt-&amp;gt;evt.common_evt.params.user_mem_release.mem_block.len == mem_block.len)) {
      SEGGER_RTT_printf(0, &amp;quot;MEM RELEASED!\n&amp;quot;);
    }
    break;&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Sending large amounts of data from phone to nrf52840</title><link>https://devzone.nordicsemi.com/thread/169570?ContentTypeID=1</link><pubDate>Tue, 05 Feb 2019 15:01:02 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:616f2b18-d128-4911-84f7-1172702246b1</guid><dc:creator>cirlam</dc:creator><description>&lt;p&gt;Thank you Bjorn. &lt;/p&gt;
&lt;p&gt;I&amp;#39;ve set up my long write support as follows:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;void ble_peripheral_service_on_ble_evt(ble_evt_t const *p_ble_evt, void *p_context) {
  ble_peripheral_service_t *p_peripheral_service = (ble_peripheral_service_t *)p_context;

  if (p_peripheral_service == NULL || p_ble_evt == NULL) {
    return;
  }

//  SEGGER_RTT_printf(0, &amp;quot;Peripheral on BLE EVT: %d\n&amp;quot;, p_ble_evt-&amp;gt;header.evt_id);

  switch (p_ble_evt-&amp;gt;header.evt_id) {
  case BLE_GAP_EVT_CONNECTED:
    SEGGER_RTT_printf(0, &amp;quot;Connected as Peripheral\n&amp;quot;);
    on_connect(p_peripheral_service, p_ble_evt);
    break;
  case BLE_GAP_EVT_DISCONNECTED:
    SEGGER_RTT_printf(0, &amp;quot;Disconnected as Peripheral\n&amp;quot;);
    on_disconnect(p_peripheral_service, p_ble_evt);
    break;
  case BLE_GATTS_EVT_WRITE:
    SEGGER_RTT_printf(0, &amp;quot;Write as Peripheral\n&amp;quot;);
    on_write(p_peripheral_service, p_ble_evt);
    break;
  case BLE_EVT_USER_MEM_REQUEST:
    mem_block.len = 7000;
    mem_block.p_mem = &amp;amp;queued_write_buffer[0];
    ret_code_t err_code = sd_ble_user_mem_reply(p_peripheral_service-&amp;gt;conn_handle, &amp;amp;mem_block);
    if (err_code != NRF_SUCCESS) {
      SEGGER_RTT_printf(0,&amp;quot;ERROR sd_ble_user_mem_reply: %u\r\n&amp;quot;, (unsigned int)err_code);
    } else {
      SEGGER_RTT_printf(0,&amp;quot;USER_MEM_REQUEST OK\r\n&amp;quot;);
    }
    break;
  case BLE_EVT_USER_MEM_RELEASE:
    SEGGER_RTT_printf(0, &amp;quot;MEM RELEASE\n&amp;quot;);
    if ((p_ble_evt-&amp;gt;evt.common_evt.params.user_mem_release.mem_block.p_mem == mem_block.p_mem) &amp;amp;&amp;amp; (p_ble_evt-&amp;gt;evt.common_evt.params.user_mem_release.mem_block.len == mem_block.len)) {
      SEGGER_RTT_printf(0, &amp;quot;MEM RELEASED!\n&amp;quot;);
    }
    break;
  default:
    // No implementation needed.
    break;
  }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Characteristic initilization:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static uint32_t assist_gps_char_add(ble_peripheral_service_t *p_peripheral_service) {
  // OUR_JOB: Step 2.A, Add a custom characteristic UUID
  uint32_t err_code;
  ble_gatts_char_md_t char_md;
  ble_gatts_attr_md_t cccd_md;
  ble_gatts_attr_t attr_char_value;
  ble_gatts_attr_md_t attr_md;

  uint8_t encoded_gps_meas[ASSIST_GPS_MEAS_LEN];

  ble_uuid_t char_uuid;
  ble_uuid128_t base_uuid = BLE_UUID_PERIPHERAL_BASE_UUID;
  char_uuid.uuid = BLE_UUID_GPS_ASSIST_CHARACTERISTIC_UUID;

  err_code = sd_ble_uuid_vs_add(&amp;amp;base_uuid, &amp;amp;char_uuid.type);
  APP_ERROR_CHECK(err_code);

  memset(&amp;amp;cccd_md, 0, sizeof(cccd_md));
  BLE_GAP_CONN_SEC_MODE_SET_OPEN(&amp;amp;cccd_md.read_perm);
  BLE_GAP_CONN_SEC_MODE_SET_OPEN(&amp;amp;cccd_md.write_perm);
  cccd_md.vloc = BLE_GATTS_VLOC_STACK;

  memset(&amp;amp;char_md, 0, sizeof(char_md));
  char_md.char_props.read = 1;
  char_md.char_props.write = 1;
  char_md.char_props.notify = 0;
  char_md.p_char_user_desc = NULL;
  char_md.p_char_pf = NULL;
  char_md.p_user_desc_md = NULL;
  char_md.p_cccd_md = &amp;amp;cccd_md;
  char_md.p_sccd_md = NULL;  

  BLE_GAP_CONN_SEC_MODE_SET_OPEN(&amp;amp;attr_md.read_perm); //was open
  BLE_GAP_CONN_SEC_MODE_SET_OPEN(&amp;amp;attr_md.write_perm);
  attr_md.vloc = BLE_GATTS_VLOC_STACK;
  attr_md.rd_auth = 0;
  attr_md.wr_auth = 0;
  attr_md.vlen = 1;

  memset(&amp;amp;attr_char_value, 0, sizeof(attr_char_value));

  memset(&amp;amp;encoded_gps_meas, 0, ASSIST_GPS_MEAS_LEN);

  attr_char_value.p_uuid = &amp;amp;char_uuid;
  attr_char_value.p_attr_md = &amp;amp;attr_md;
  attr_char_value.init_len = ASSIST_GPS_MEAS_LEN;
  attr_char_value.init_offs = 0;
  attr_char_value.max_len = ASSIST_GPS_MEAS_LEN;
  attr_char_value.p_value = encoded_gps_meas;

  return sd_ble_gatts_characteristic_add(p_peripheral_service-&amp;gt;service_handle,
      &amp;amp;char_md,
      &amp;amp;attr_char_value,
      &amp;amp;p_peripheral_service-&amp;gt;gps_assist_char_handle);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#39;m thinking this part of the characterisitc initalization may need tweaking? or the long write behaviour completely independant to the characteristic initilization, and will work on any writable characteristic? &lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;attr_char_value.init_len = ASSIST_GPS_MEAS_LEN;
attr_char_value.init_offs = 0;
attr_char_value.max_len = ASSIST_GPS_MEAS_LEN;&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Sending large amounts of data from phone to nrf52840</title><link>https://devzone.nordicsemi.com/thread/169524?ContentTypeID=1</link><pubDate>Tue, 05 Feb 2019 13:17:31 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:3be00205-a553-488a-954f-4de553ccfadf</guid><dc:creator>bjorn-spockeli</dc:creator><description>&lt;p&gt;Hi Chris,&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Yes, increasing the MTU size will give you a higher throughput compared to using the default ATT MTU size of 23, which gives you 20 byte payload. Although, the maximum size of a GATT attribute is 512 byte, the largest allowed MTU size in SDK v15.2.0 is 247 bytes.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Long write is simply multiple Write Requests to the same characteristic with offsets and this is the method that I would choose.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Reliable and Queued Write are essentially the same thing, but reliable writes have a lot of overhead as the value is sent in both directions before the actual write is being performed. You can write up-to 512 bytes using this method as its limited to the maximum attribute size.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If you want to set the ATT MTU on the nRF side to 247, then you need to&amp;nbsp;use the GATT library( nrf_ble_gatt.c ) which will handle the &lt;a href="https://www.nordicsemi.com/DocLib/Content/SoftDevice_API_Doc/S132/v6-0-0/group_ble_gatts_mtu_exchange"&gt;GATTS ATT_MTU Exchange&lt;/a&gt;&amp;nbsp;for you. You can use the ble_app_uart example as a reference.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;/**@brief Function for initializing the GATT library. */
void gatt_init(void)
{
    ret_code_t err_code;

    err_code = nrf_ble_gatt_init(&amp;amp;m_gatt, gatt_evt_handler);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_ble_gatt_att_mtu_periph_set(&amp;amp;m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
    APP_ERROR_CHECK(err_code);
}

// where NRF_SDH_BLE_GATT_MAX_MTU_SIZE == 247.&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>