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

sd_ble_gatts_hvx don't update gatt value, sd_ble_gatts_value_set throws unexpected error

I've based my application on ble_peripheral ble_app_blinky example.

So I used the following Code as model:

            NRF_LOG_INFO("Send button state change.");
            err_code = ble_lbs_on_button_change(m_conn_handle, &m_lbs, button_action);
            if (err_code != NRF_SUCCESS &&
                err_code != BLE_ERROR_INVALID_CONN_HANDLE &&
                err_code != NRF_ERROR_INVALID_STATE &&
                err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
            {
                APP_ERROR_CHECK(err_code);
            }
            break;

with:

uint32_t ble_lbs_on_button_change(uint16_t conn_handle, ble_lbs_t * p_lbs, uint8_t button_state)
{
    ble_gatts_hvx_params_t params;
    uint16_t len = sizeof(button_state);

    memset(&params, 0, sizeof(params));
    params.type   = BLE_GATT_HVX_NOTIFICATION;
    params.handle = p_lbs->button_char_handles.value_handle;
    params.p_data = &button_state;
    params.p_len  = &len;

    return sd_ble_gatts_hvx(conn_handle, &params);
}

for update and notification of a charachteristic value.

This and the documentation under https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v15.0.0%2Flib_ble_advertising.html (function sd_ble_gatts_hvx) suggest that the sd_ble_gatts_value_set function is not needed.

With this approach, the value at the client remains 0 when the notification is switched on and the correct value only appears after the first update. This can take a very long time. This is unsatisfactory.

Therefore I tried to set the value before with sd_ble_gatts_value_set.

void ble_temp_char_update(uint16_t conn_handle, ble_mein_service_t *p_mein_service, int16_t data)
{
  ret_code_t rc;
  ble_gatts_hvx_params_t params;
  uint16_t len = sizeof(data);
  ble_gatts_value_t gv;

  memset(&gv, 0, sizeof(gv));
  gv.len     = sizeof(data);
  gv.offset  = 0;
  gv.p_value = (uint8_t *)&data;

  memset(&params, 0, sizeof(params));
  params.type   = BLE_GATT_HVX_NOTIFICATION;
  params.handle = p_mein_service->temp_char_handles.value_handle;
  params.p_data = (uint8_t *)&data;
  params.p_len  = &len;

  rc = sd_ble_gatts_hvx(conn_handle, &params);
  switch (rc) {
    case NRF_SUCCESS:
      break;
    case BLE_ERROR_INVALID_CONN_HANDLE:
    //keine Connection vorhanden
    case NRF_ERROR_INVALID_STATE:
    //Notification nicht eingeschaltet
    //...dann setze den Wert, falls mit Read gelesen wird
      rc = sd_ble_gatts_value_set(conn_handle, p_mein_service->temp_char_handles.value_handle, &gv);
      APP_ERROR_CHECK(rc); // <=== Error 0x3002
      break;
    case BLE_ERROR_GATTS_SYS_ATTR_MISSING:
      //bei einem bekannten Peer muss wohl hier sd_ble_gatts_sys_attr_set() aufgerufen werden
      break;
    default:
      APP_ERROR_CHECK(rc);
  }
}

This works so far. But after disconnecting the connection an error 0x3002 occurs when the update function is called again (Line 29 in the last Codebox).
What can I do?

Parents
  • Hi Stefan, 

    What you described is pretty strange. The function sd_ble_gatts_hvx() should update the characteristic value and then send the notification. 
    Have you made sure the function sd_ble_gatts_hvx() returns NRF_SUCCESS ? 

    Which SDK are you testing with ?

    Please simply test with ble_app_blinky and press the button, would the first press get notified on the phone (you can use nrf blinky app on the phone) ?

    If you receive BLE_ERROR_INVALID_CONN_HANDLE( 0x3002) when calling  sd_ble_gatts_value_set() maybe you are setting the value of a CCCD. Please double check if the handle id was correct. 

  • The timing is as follows (without using function sd_ble_gatts_value_set) :
    1. no BLE connection
    2. a value changes (calling sd_ble_gatts_hvx returns NRF_ERROR_INVALID_STATE)
    3. client connects
    4. client enables notification for the value
    5. client displays the value 0
    6. the value changes again
    7. the value is transmitted

    My problem is step 5. Whenever the initial value is not 0, I have a problem. Why does the function sd_ble_gatts_hvx  not store the new value in Softdevice RAM even when no client is connected.  If a client connects and immediately turns on notification, it does not get the current value. I use the function so that it is only called when the value has changed.

    The value is for example the temperature. Sometimes it does not change for a long time.

    The blinky example is too simple for this. You might have to press the key before a client connects.

    I have tested with sdk 15.3 and Softdevice S140 6.1.1 so far.

    Code snippet for this (first) problem:

    void ble_adc_char_update(uint16_t conn_handle, ble_mein_service_t *p_mein_service, int32_t data)
    {
      ret_code_t rc;
      ble_gatts_hvx_params_t params;
      uint16_t len = sizeof(data);
    
      memset(&params, 0, sizeof(params));
      params.type   = BLE_GATT_HVX_NOTIFICATION;
      params.handle = p_mein_service->adc_char_handles.value_handle;
      params.p_data = (uint8_t *)&data;
      params.p_len  = &len;
    
      rc = sd_ble_gatts_hvx(conn_handle, &params);
      if (rc != NRF_SUCCESS &&
          rc != BLE_ERROR_INVALID_CONN_HANDLE &&
          rc != NRF_ERROR_INVALID_STATE &&
          rc != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
      {
          APP_ERROR_CHECK(rc);
      }
    }

  • Hi Stefan, 

    When the function sd_ble_gatts_hvx() return NRF_ERROR_INVALID_STATE. It will not take any effect nor updating the characteristic's value. 

    You would need to call sd_ble_gatts_value_set() when you get that error. This function should work if you use the correct handle. Please try again and if you see the issue, please send us the code (a minimum project so we can test here). 

  • Yeah, I noticed that. But why does the description say:

    "Note: The local attribute value may be updated even if an outgoing packet is not sent to the peer due to an error during execution. The Attribute Table has been updated if one of the following error codes is returned: NRF_ERROR_INVALID_STATE, NRF_ERROR_BUSY, NRF_ERROR_FORBIDDEN, BLE_ERROR_GATTS_SYS_ATTR_MISSING and NRF_ERROR_RESOURCES." (https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.s140.api.v6.1.1/group___b_l_e___g_a_t_t_s___f_u_n_c_t_i_o_n_s.html#ga313fe43c2e93267da668572e885945db) ?

    When I use the sd_ble_gatts_value_set() function, it gives error 0x3002 when the client was connected and then disconnected and an update of the value is called. See third codebox in my first post line 29.

Reply Children
Related