This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Read value from several characteristics as central to a custom service

SDK  17.1.0

nRF52840 DK  central + nRF52840 peripheral device

Hello,

I'm attempting to set up reading characteristic values on the nRF52840 DK as a central from a peripheral device which is a nRF52840 module with a SHT40 temperature and humidity sensor.  I've set up a custom service on the peripheral with 3 characteristics for temperature, humidity, and battery voltage.  So far, using examples from the SDK ble_central and posts on this forum, I have managed to scan, connect, complete discovery, and read a single characteristic (temperature).  I'm currently using sd_ble_gattc_char_value_by_uuid_read()  

I'd like to read all three characteristics and haven't figured out how to accomplish this other than to sequence through several sd_ble_gattc_char_value_by_uuid_read() and BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP events.

I've noticed that there is a handle-value pair count in ble_gattc_evt_char_val_by_uuid_read_rsp_t.  Can this somehow be used to read all 3 characteristics?  If so, how do I differentiate between the handle-value pairs? 

I'm not sure how to launch reading all three characteristics either.  My read routine now looks like:

void read_sensor_temp(void)
{
    ret_code_t err_code;

    ble_uuid_t m_temp_uuid;
      m_temp_uuid.type = BLE_UUID_TYPE_VENDOR_BEGIN;
      m_temp_uuid.uuid = BLE_UUID_sht40_TEMP_CHARACTERISTIC;

    ble_gattc_handle_range_t m_handle_range;
      m_handle_range.start_handle = 0x0001;
      m_handle_range.end_handle = 0xFFFF;

    temp_read = true;

    err_code = sd_ble_gattc_char_value_by_uuid_read(m_ble_sht40_c.conn_handle, &m_temp_uuid, &m_handle_range);  
    APP_ERROR_CHECK(err_code);

}
  

 

I know from the forum and examples that using notify is usually used to send characteristic data.  However I've targeted the sensor as a battery operated device and I do not want to remain connected.  I just want to periodically read the data placed in the characteristics and being slow moving temperature and humidity it's not time critical.  I'm hoping to connect, read the data, and disconnect periodically.

Any guidance you can provide much appreciated.

Thanks,

Max

 

  • From the documentation of sd_ble_gattc_char_value_by_uuid_read, it shows that you need to call the function again with an updated handle range if there are more characteristics in this service that need to be read. 

  • Thanks Susheel. 

    This is somewhat helpful in that it tells me I have to resubmit the sd_ble_gattc_char_value_by_uuid_read() function.   However it doesn't provide any details on how to implement the "updated handle range" in my code.  My best guess was to use routines like my code snippet above for each characteristic.

    This appears to be working.  I am able to read the characteristic values for all 3 of my custom service characteristics.  I implemented code to submit the sd_ble_gattc_char_value_by_uuid_read() for each characteristic, then used a timer to check the response had been handled.  Then I launched the sd_ble_gattc_char_value_by_uuid_read() for the next characteristic.  I can't claim this is a "good" solution, just that it seems to work.  The SDK doesn't appear to have examples cover the ble central function to the extent of the ble peripheral functions.  

    Here's what I have in the ble event handler:

            case BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP:
                {
                  if (temp_read)
                    {             
                      ble_gattc_handle_value_t iter;
                      memset(&iter, 0, sizeof(ble_gattc_handle_value_t));
                      while (sd_ble_gattc_evt_char_val_by_uuid_read_rsp_iter(&p_ble_evt->evt.gattc_evt, &iter) == NRF_SUCCESS)
                       {
                         memcpy(temp_value, iter.p_value, p_ble_evt->evt.gattc_evt.params.char_val_by_uuid_read_rsp.value_len);
                       }
                       temp_read = false;
                    }
                  else if (hum_read)
                    {             
                      ble_gattc_handle_value_t iter2;
                      memset(&iter2, 0, sizeof(ble_gattc_handle_value_t));
                      while (sd_ble_gattc_evt_char_val_by_uuid_read_rsp_iter(&p_ble_evt->evt.gattc_evt, &iter2) == NRF_SUCCESS)
                       {
                         memcpy(hum_value, iter2.p_value, p_ble_evt->evt.gattc_evt.params.char_val_by_uuid_read_rsp.value_len);
                       }
                       hum_read = false;
                    }
                  else if (vbatt_read)
                    {             
                      ble_gattc_handle_value_t iter3;
                      memset(&iter3, 0, sizeof(ble_gattc_handle_value_t));
                      while (sd_ble_gattc_evt_char_val_by_uuid_read_rsp_iter(&p_ble_evt->evt.gattc_evt, &iter3) == NRF_SUCCESS)
                       {
                         memcpy(vbatt_value, iter3.p_value, p_ble_evt->evt.gattc_evt.params.char_val_by_uuid_read_rsp.value_len);
                       }
                       vbatt_read = false;
                    }
                  break;
                }
    

    As can be seen, I used some boolean semaphore's to indicate a characteristic was handled and to move on to reading the next one.

    It's still a work in progress, but I'm good with this for now.  Hopefully this code might help someone grappling with the same problem despite the marginal coding style.

    Cheers!

    Max

Related