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

Updating characteristic values while disconnected?

I am developing an application as a peripheral based on the NRF52 SoC which regularly reads a sensor and publishes the reading to a BLE characteristic. A central (a smartphone app) connects to the NRF52 peripheral and immediately requests the current value of the characteristic value so it can display its UI.

The problem I'm having is that the characteristic value retrieved is out of date. This is because I am following the SDK examples and surrounding calls to sd_ble_gatts_hvx with a conditional statement such that they are only executed if the connection is valid, eg:

 if(peripheral->conn_handle != BLE_CONN_HANDLE_INVALID) {

    hvx_params = [sensor reading]

    err_code = sd_ble_gatts_hvx(p_datalogger->conn_handle, &hvx_params);
  
    return err_code;
}

What is the best way to ensure that the characteristic value is reflective of the latest sensor reading when the central connects? I thought about calling sd_ble_gatts_hvx immediately when a connection is established, but I am concerned this could lead to a race condition.

Any advice gratefully received!

  • Very simple - as well as notifying the characteristic as you are doing, also keep the value of it up to date. When the client connects, as well as having it subscribe for notifications, also have it read the current value with a normal characteristic read. That's all you have to do.

  • Thanks for your feedback.

    Presumably sd_ble_gatts_value_set is used for this task? So I would replace my code as follows:

    if(peripheral->conn_handle != BLE_CONN_HANDLE_INVALID) {
        hvx_params = [sensor reading]
        err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params);
    } else {
        p_value = [sensor reading]
        err_code = sd_ble_gatts_value_set(conn_handle, attr_handle, &p_value);
    }
    return err_code;
    

    Is that correct?

    Just noting that both functions require a connection handle - is it safe to call sd_ble_gatts_value_set when there is no valid connection?

  • I wouldn't even bother with the else. Send HVX if there is a connection (need the if for that) but set the current value anyway so any new connection can read the initial value. It just keeps the current value in memory so anything initial connecting can read it.

    Yes you can call sd_ble_gatts_value_set with the default connection handle, it sets the value for the whole instance (I don't think the change to multi peripheral altered that).

    and those are the right calls.

  • I've just found this having had (almost) the same question.

    The Characteristics Tutorial is unhelpful, as it only covers doing notification - there is no help, guidance or even any mention of keeping the value updated while not connected.

    Disappointed

    Yes you can call sd_ble_gatts_value_set with the default connection handle

    Not just "can" - you must!

    The sd_ble_gatts_value_set documentation is misleading in this respect:

     * @param[in] conn_handle  Connection handle. Ignored if the value does not belong to a system attribute.

    It seems that it is not ignored at all - it must be a valid connection handle.

Related