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

Can nou update Characteristic value

I've created read onle characteristic called "log". In  main.c i try to update it by calling : ulogd_characteristic_update(&m_ulog_service,Log_Data_arr)

But nothing happens, can you solve my issue (p.s. I am new to ble)


void ulogd_characteristic_update(ble_ulog_service_t *p_ulog_service, int32_t *log_data)
{
if (p_ulog_service->conn_handle != BLE_CONN_HANDLE_INVALID)
{
uint16_t len = 10;
ble_gatts_hvx_params_t hvx_params;
memset(&hvx_params, 0, sizeof(hvx_params));

hvx_params.handle = p_ulog_service->ulog_char_handles.value_handle;
hvx_params.type = BLE_GATT_HVX_NOTIFICATION;
hvx_params.offset = 0;
hvx_params.p_len = &len;
hvx_params.p_data = log_data;


sd_ble_gatts_hvx(p_ulog_service->conn_handle, &hvx_params);
}

}

  • log_service.h


    #ifndef LOG_SERVICE_H
    #define LOG_SERVICE_H

    #include <stdint.h>
    #include "boards.h"
    #include "ble.h"
    #include "ble_srv_common.h"
    #include "nrf_sdh_ble.h"

    #define BLE_ULOG_SERVICE_BLE_OBSERVER_PRIO 2
    #define BLE_ULOG_SERVICE_DEF(_name) \
    static ble_ulog_service_t _name; \
    NRF_SDH_BLE_OBSERVER(_name ## _obs, \
    BLE_ULOG_SERVICE_BLE_OBSERVER_PRIO, \
    ble_ulog_service_on_ble_evt, &_name)
    // Base UUID: E54B0000-67F5-479E-8711-B3B99198CE6C
    #define BLE_UUID_ULOG_SERVICE_BASE_UUID {0x6C, 0xCE, 0x98, 0x91, 0xB9, 0xB3, 0x11, 0x87, 0x9E, 0x47, 0xF5, 0x67, 0x00, 0x00, 0x4B, 0xE5}
    // Service & characteristics UUIDs
    #define BLE_UUID_ULOG_SERVICE_UUID 0xF000
    #define BLE_UUID_ULOG_CHAR_UUID 0xF00A
    #define BLE_UUID_ULOGTIME_CHAR_UUID 0xF00C
    // Forward declaration of the custom_service_t type.
    typedef struct ble_ulog_service_s ble_ulog_service_t;
    //typedef void (*ble_ulog_service_ulog_write_handler_t) (uint16_t conn_handle, ble_ulog_service_t * p_ulog_service, uint8_t new_state);
    typedef void (*ble_ulog_service_ulogtime_write_handler_t) (uint16_t conn_handle, ble_ulog_service_t * p_ulogtime_service, uint8_t* new_state);

    typedef struct
    {
    // ble_ulog_service_ulog_write_handler_t ulog_write_handler;
    ble_ulog_service_ulogtime_write_handler_t ulogtime_write_handler; /**< ulogtime */
    } ble_ulog_service_init_t;

    typedef struct ble_ulog_service_s
    {
    uint16_t conn_handle;
    uint16_t service_handle;
    uint8_t uuid_type;
    ble_gatts_char_handles_t ulog_char_handles;
    ble_gatts_char_handles_t ulogtime_char_handles;
    // ble_ulog_service_ulog_write_handler_t ulog_write_handler;
    ble_ulog_service_ulogtime_write_handler_t ulogtime_write_handler;

    } ble_ulog_service_t;

    uint32_t ble_ulog_service_init(ble_ulog_service_t * p_ulog_service, const ble_ulog_service_init_t * p_ulog_service_init);
    void ble_ulog_service_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context);
    void ulogd_characteristic_update(ble_ulog_service_t *p_ulog_service, int32_t *log_data);

    #endif

  • log_service.c

    #include <string.h>

    #include "nrf_log.h"
    #include "log_service.h"

    static const uint8_t ULOGCharName[] = "Log";
    static const uint8_t ULOGTIMECharName[] = "Time";

    static void on_connect(ble_ulog_service_t * p_ulog_service, ble_evt_t const * p_ble_evt)
    {
    p_ulog_service->conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
    }

    static void on_disconnect(ble_ulog_service_t * p_ulog_service, ble_evt_t const * p_ble_evt)
    {
    UNUSED_PARAMETER(p_ble_evt);
    p_ulog_service->conn_handle = BLE_CONN_HANDLE_INVALID;
    }

    static void on_write(ble_ulog_service_t * p_ulog_service, ble_evt_t const * p_ble_evt)
    {
    ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;

    /* if ( (p_evt_write->handle == p_ulog_service->ulog_char_handles.value_handle)
    && (p_evt_write->len == 1)
    && (p_ulog_service->ulog_write_handler != NULL))
    {
    p_ulog_service->ulog_write_handler(p_ble_evt->evt.gap_evt.conn_handle, p_ulog_service, p_evt_write->data[0]);
    }
    */
    if ( (p_evt_write->handle == p_ulog_service->ulogtime_char_handles.value_handle)
    && (p_evt_write->len == 5)
    && (p_ulog_service->ulogtime_write_handler != NULL))
    {
    p_ulog_service->ulogtime_write_handler(p_ble_evt->evt.gap_evt.conn_handle, p_ulog_service, p_evt_write->data);
    }
    }

    static uint32_t ulog_char_add(ble_ulog_service_t * p_ulog_service)
    {
    ble_gatts_char_md_t char_md;
    ble_gatts_attr_t attr_char_value;
    ble_gatts_attr_md_t attr_md;
    ble_uuid_t ble_uuid;

    memset(&char_md, 0, sizeof(char_md));
    memset(&attr_md, 0, sizeof(attr_md));
    memset(&attr_char_value, 0, sizeof(attr_char_value));

    char_md.char_props.read = 1;
    //char_md.char_props.write = 1;
    char_md.p_char_user_desc = ULOGCharName ;
    char_md.char_user_desc_size = sizeof(ULOGCharName);
    char_md.char_user_desc_max_size = sizeof(ULOGCharName);
    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;
    ble_uuid.type = p_ulog_service->uuid_type;
    ble_uuid.uuid = BLE_UUID_ULOG_CHAR_UUID ;

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
    // Attribute Metadata settings
    attr_md.vloc = BLE_GATTS_VLOC_STACK;
    attr_md.rd_auth = 0;
    attr_md.wr_auth = 0;
    attr_md.vlen = 0;
    // Attribute Value settings
    attr_char_value.p_uuid = &ble_uuid;
    attr_char_value.p_attr_md = &attr_md;
    attr_char_value.init_len = 10;
    attr_char_value.init_offs = 0;
    attr_char_value.max_len = 10;
    uint8_t value[10] = {0xAA,0xBB,0xCC,0xDD,0xEE,0xFF,0x11,0x22,0x33,0x44};
    attr_char_value.p_value = value;


    return sd_ble_gatts_characteristic_add(p_ulog_service->service_handle, &char_md,
    &attr_char_value,
    &p_ulog_service->ulog_char_handles);
    }

    static uint32_t ulogtime_char_add(ble_ulog_service_t * p_ulog_service)
    {
    ble_gatts_char_md_t char_md;
    ble_gatts_attr_t attr_char_value;
    ble_gatts_attr_md_t attr_md;
    ble_uuid_t ble_uuid;

    memset(&char_md, 0, sizeof(char_md));
    memset(&attr_md, 0, sizeof(attr_md));
    memset(&attr_char_value, 0, sizeof(attr_char_value));

    char_md.char_props.read = 1;
    char_md.char_props.write = 1;
    char_md.p_char_user_desc = ULOGTIMECharName;
    char_md.char_user_desc_size = sizeof(ULOGTIMECharName);
    char_md.char_user_desc_max_size = sizeof(ULOGTIMECharName);
    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;
    ble_uuid.type = p_ulog_service->uuid_type;
    ble_uuid.uuid = BLE_UUID_ULOGTIME_CHAR_UUID ;
    // Set permissions on the Characteristic value
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
    // Attribute Metadata settings
    attr_md.vloc = BLE_GATTS_VLOC_STACK;
    attr_md.rd_auth = 0;
    attr_md.wr_auth = 0;
    attr_md.vlen = 0;
    // Attribute Value settings
    attr_char_value.p_uuid = &ble_uuid;
    attr_char_value.p_attr_md = &attr_md;
    attr_char_value.init_len = 5;
    attr_char_value.init_offs = 0;
    attr_char_value.max_len = 5;
    uint8_t value[5] = {0x20,0x01,0x29,0x18,0x30};
    attr_char_value.p_value = value;

    return sd_ble_gatts_characteristic_add(p_ulog_service->service_handle, &char_md,
    &attr_char_value,
    &p_ulog_service->ulogtime_char_handles);
    }

    uint32_t ble_ulog_service_init(ble_ulog_service_t * p_ulog_service, const ble_ulog_service_init_t * p_ulog_service_init)
    {
    uint32_t err_code;
    ble_uuid_t ble_uuid;
    // Initialize service structure
    p_ulog_service->conn_handle = BLE_CONN_HANDLE_INVALID;
    p_ulog_service->ulogtime_write_handler = p_ulog_service_init->ulogtime_write_handler;
    // Add service UUID
    ble_uuid128_t base_uuid = {BLE_UUID_ULOG_SERVICE_BASE_UUID};
    err_code = sd_ble_uuid_vs_add(&base_uuid, &p_ulog_service->uuid_type);
    if (err_code != NRF_SUCCESS)
    {
    return err_code;
    }
    // Set up the UUID for the service (base + service-specific)
    ble_uuid.type = p_ulog_service->uuid_type;
    ble_uuid.uuid = BLE_UUID_ULOG_SERVICE_UUID;
    // Set up and add the service
    err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_ulog_service->service_handle);
    if (err_code != NRF_SUCCESS)
    {
    return err_code;
    }

    err_code = ulog_char_add(p_ulog_service);
    if (err_code != NRF_SUCCESS)
    {
    return err_code;
    }

    err_code = ulogtime_char_add(p_ulog_service);
    if (err_code != NRF_SUCCESS)
    {
    return err_code;
    }

    return NRF_SUCCESS;
    }

    void ble_ulog_service_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
    {
    ble_ulog_service_t * p_ulog_service = (ble_ulog_service_t *)p_context;
    switch (p_ble_evt->header.evt_id)
    {
    case BLE_GAP_EVT_CONNECTED:
    on_connect(p_ulog_service, p_ble_evt);
    break;
    case BLE_GATTS_EVT_WRITE:
    on_write(p_ulog_service, p_ble_evt);
    break;
    case BLE_GAP_EVT_DISCONNECTED:
    on_disconnect(p_ulog_service, p_ble_evt);
    break;
    default:
    // No implementation needed.
    break;
    }
    }

    void ulogd_characteristic_update(ble_ulog_service_t *p_ulog_service, int32_t *log_data)
    {
    if (p_ulog_service->conn_handle != BLE_CONN_HANDLE_INVALID)
    {
    uint16_t len = 10;
    ble_gatts_hvx_params_t hvx_params;
    memset(&hvx_params, 0, sizeof(hvx_params));

    hvx_params.handle = p_ulog_service->ulog_char_handles.value_handle;
    hvx_params.type = BLE_GATT_HVX_NOTIFICATION;
    hvx_params.offset = 0;
    hvx_params.p_len = &len;
    hvx_params.p_data = log_data;


    sd_ble_gatts_hvx(p_ulog_service->conn_handle, &hvx_params);
    }

    }

  • Hi,

    • Are you already in a connection before you call sd_ble_gatts_hvx?
      • if you are in a connection, what does sd_ble_gatts_hvx() return? 
    • Do you only want to update the characteristic or do you also want to notify the central that the characteristic has changed? If you only want to update the characteristic then you should use sd_ble_gatts_value_set() instead. 
Related