Example #1
0
/**@brief Function for adding a characteristic for the Continuous Glucose Meter Measurement.
 *
 * @param[in] p_cgms Service instance.
 *
 * @return NRF_SUCCESS if characteristic was successfully added, otherwise an error code.
 */
ret_code_t cgms_meas_char_add(nrf_ble_cgms_t * p_cgms)
{
    uint8_t               num_recs;
    uint8_t               encoded_cgms_meas[NRF_BLE_CGMS_MEAS_LEN_MAX];
    ble_add_char_params_t add_char_params;
    ble_cgms_rec_t        initial_cgms_rec_value;

    memset(&add_char_params, 0, sizeof(add_char_params));
    memset(&initial_cgms_rec_value, 0, sizeof(ble_cgms_rec_t));

    num_recs = cgms_db_num_records_get();
    if (num_recs > 0)
    {
        uint32_t err_code = cgms_db_record_get(num_recs - 1, &initial_cgms_rec_value);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    }

    add_char_params.uuid     = BLE_UUID_CGM_MEASUREMENT;
    add_char_params.max_len  = NRF_BLE_CGMS_MEAS_LEN_MAX;
    add_char_params.init_len = cgms_meas_encode(p_cgms,
                                                &initial_cgms_rec_value.meas,
                                                encoded_cgms_meas);
    add_char_params.p_init_value      = encoded_cgms_meas;
    add_char_params.is_var_len        = true;
    add_char_params.char_props.notify = true;
    add_char_params.cccd_write_access = SEC_JUST_WORKS;


    return characteristic_add(p_cgms->service_handle,
                              &add_char_params,
                              &p_cgms->char_handles.measurment);
}
Example #2
0
/**@brief Function for adding the Bond Management Feature characteristic.
 *
 * @param[in]   p_bms       Bond Management Service structure.
 * @param[in]   p_bms_init  Information needed to initialize the service.
 *
 * @return  NRF_SUCCESS on success, otherwise an error code returned by @ref characteristic_add.
 */
static ret_code_t feature_char_add(nrf_ble_bms_t * p_bms, nrf_ble_bms_init_t const * p_bms_init)
{
    uint8_t                  encoded_feature[NRF_BLE_BMS_FEATURE_LEN];
    uint8_t                  init_value_len;
    ble_add_char_params_t    add_char_params;
    nrf_ble_bms_features_t * p_feature = &p_bms->feature;

    if ((p_feature->delete_all_auth) ||
        (p_feature->delete_all_but_requesting_auth) ||
        (p_feature->delete_requesting_auth))
    {
        VERIFY_PARAM_NOT_NULL(p_bms_init->evt_handler);
    }

    if ((p_feature->delete_requesting_auth) ||
        (p_feature->delete_requesting))
    {
        VERIFY_PARAM_NOT_NULL(p_bms_init->bond_callbacks.delete_requesting);
    }

    if ((p_feature->delete_all) ||
        (p_feature->delete_all_auth))
    {
        VERIFY_PARAM_NOT_NULL(p_bms_init->bond_callbacks.delete_all);
    }

    if ((p_feature->delete_all_but_requesting) ||
        (p_feature->delete_all_but_requesting_auth))
    {
        VERIFY_PARAM_NOT_NULL(p_bms_init->bond_callbacks.delete_all_except_requesting);
    }

    init_value_len = feature_encode(&p_bms->feature, encoded_feature);

    memset(&add_char_params, 0, sizeof(add_char_params));
    add_char_params.uuid            = BLE_UUID_BMS_FEATURE;
    add_char_params.char_props.read = true;
    add_char_params.max_len         = init_value_len;
    add_char_params.p_init_value    = encoded_feature;
    add_char_params.init_len        = init_value_len;
    add_char_params.read_access     = p_bms_init->bms_feature_sec_req;
    add_char_params.write_access    = SEC_NO_ACCESS;

    return characteristic_add(p_bms->service_handle, &add_char_params, &p_bms->feature_handles);
}
Example #3
0
uint32_t ble_sc_ctrlpt_init(ble_sc_ctrlpt_t            * p_sc_ctrlpt,
                            const ble_cs_ctrlpt_init_t * p_sc_ctrlpt_init)
{
    if (p_sc_ctrlpt == NULL || p_sc_ctrlpt_init == NULL)
    {
        return NRF_ERROR_NULL;
    }

    ble_add_char_params_t add_char_params;

    p_sc_ctrlpt->conn_handle      = BLE_CONN_HANDLE_INVALID;
    p_sc_ctrlpt->procedure_status = BLE_SCPT_NO_PROC_IN_PROGRESS;

    p_sc_ctrlpt->size_list_supported_locations = p_sc_ctrlpt_init->size_list_supported_locations;

    if ((p_sc_ctrlpt_init->size_list_supported_locations != 0) &&
        (p_sc_ctrlpt_init->list_supported_locations != NULL))
    {
        memcpy(p_sc_ctrlpt->list_supported_locations,
               p_sc_ctrlpt_init->list_supported_locations,
               p_sc_ctrlpt->size_list_supported_locations * sizeof(ble_sensor_location_t));
    }

    p_sc_ctrlpt->service_handle         = p_sc_ctrlpt_init->service_handle;
    p_sc_ctrlpt->evt_handler            = p_sc_ctrlpt_init->evt_handler;
    p_sc_ctrlpt->supported_functions    = p_sc_ctrlpt_init->supported_functions;
    p_sc_ctrlpt->sensor_location_handle = p_sc_ctrlpt_init->sensor_location_handle;
    p_sc_ctrlpt->error_handler          = p_sc_ctrlpt_init->error_handler;

    // Add speed and cadence control point characteristic
    memset(&add_char_params, 0, sizeof(add_char_params));
    add_char_params.uuid                = BLE_UUID_SC_CTRLPT_CHAR;
    add_char_params.max_len             = BLE_SC_CTRLPT_MAX_LEN;
    add_char_params.is_var_len          = true;
    add_char_params.char_props.indicate = 1;
    add_char_params.char_props.write    = 1;
    add_char_params.cccd_write_access   = p_sc_ctrlpt_init->sc_ctrlpt_cccd_wr_sec;
    add_char_params.write_access        = p_sc_ctrlpt_init->sc_ctrlpt_wr_sec;
    add_char_params.is_defered_write    = true;

    return characteristic_add(p_sc_ctrlpt->service_handle,
                              &add_char_params,
                              &p_sc_ctrlpt->sc_ctrlpt_handles);
}
Example #4
0
/**@brief Function for adding the Bond Management Control Point characteristic.
 *
 * @param[in]   p_bms       Bond Management Service structure.
 * @param[in]   p_bms_init  Information needed to initialize the service.
 *
 * @return  NRF_SUCCESS on success, otherwise an error code returned by @ref characteristic_add.
 */
static ret_code_t ctrlpt_char_add(nrf_ble_bms_t * p_bms, nrf_ble_bms_init_t const * p_bms_init)
{
    ble_add_char_params_t add_char_params;

    memset(&add_char_params, 0, sizeof(add_char_params));
    add_char_params.uuid             = BLE_UUID_BMS_CTRLPT;
    add_char_params.char_props.write = 1;
    add_char_params.is_defered_write = true;
    add_char_params.is_var_len       = true;
    add_char_params.max_len          = NRF_BLE_BMS_CTRLPT_MAX_LEN;
    add_char_params.read_access      = SEC_NO_ACCESS;
    add_char_params.write_access     = p_bms_init->bms_ctrlpt_sec_req;

    if (p_bms_init->p_qwr != NULL)
    {
        add_char_params.char_ext_props.reliable_wr = 1;
    }

    return characteristic_add(p_bms->service_handle, &add_char_params, &p_bms->ctrlpt_handles);
}
Example #5
0
/**@brief Function for adding a characteristic for the Record Access Control Point.
 *
 * @param[in] p_cgms  Service instance.
 *
 * @return NRF_SUCCESS if characteristic was successfully added, otherwise an error code.
 */
ret_code_t cgms_racp_char_add(nrf_ble_cgms_t * p_cgms)
{
    ble_add_char_params_t add_char_params;

    memset(&add_char_params, 0, sizeof(add_char_params));

    add_char_params.uuid                = BLE_UUID_RECORD_ACCESS_CONTROL_POINT_CHAR;
    add_char_params.max_len             = BLE_L2CAP_MTU_DEF;
    add_char_params.init_len            = 0;
    add_char_params.p_init_value        = 0;
    add_char_params.is_var_len          = true;
    add_char_params.write_access        = SEC_JUST_WORKS;
    add_char_params.char_props.write    = true;
    add_char_params.char_props.indicate = true;
    add_char_params.cccd_write_access   = SEC_JUST_WORKS;
    add_char_params.is_defered_write    = 1;

    return characteristic_add(p_cgms->service_handle,
                              &add_char_params,
                              &p_cgms->char_handles.racp);
}
Example #6
0
/**@brief Function for adding a status characteristic for the CGMS.
 *
 * @param[in]   p_cgms   Service instance.
 *
 * @return      NRF_SUCCESS if characteristic was successfully added, otherwise an error code.
 */
static uint32_t status_char_add(nrf_ble_cgms_t * p_cgms)
{
    uint8_t               init_value_len;
    uint8_t               encoded_initial_status[NRF_BLE_CGMS_STATUS_LEN];
    ble_add_char_params_t add_char_params;

    memset(&add_char_params, 0, sizeof(add_char_params));

    init_value_len = encode_status(encoded_initial_status, p_cgms);

    add_char_params.uuid         = BLE_UUID_CGM_STATUS;
    add_char_params.max_len      = init_value_len;
    add_char_params.init_len     = init_value_len;
    add_char_params.p_init_value = encoded_initial_status;
    add_char_params.read_access  = SEC_JUST_WORKS;
    add_char_params.write_access = SEC_NO_ACCESS;

    return characteristic_add(p_cgms->service_handle,
                              &add_char_params,
                              &p_cgms->char_handles.status);
}
Example #7
0
/**@brief Function for adding a characteristic for the Session Start Time.
 *
 * @param[in]   p_cgms   Service instance.
 *
 * @return      NRF_SUCCESS if characteristic was successfully added, otherwise an error code.
 */
ret_code_t cgms_sst_char_add(nrf_ble_cgms_t * p_cgms)
{
    ble_add_char_params_t add_char_params;
    uint8_t               init_value[NRF_BLE_CGMS_SST_LEN] = {0};

    memset(&add_char_params, 0, sizeof(add_char_params));

    add_char_params.uuid    = BLE_UUID_CGM_SESSION_START_TIME;
    add_char_params.max_len = NRF_BLE_CGMS_SST_LEN;

    add_char_params.init_len     = NRF_BLE_CGMS_SST_LEN;
    add_char_params.p_init_value = init_value;

    add_char_params.read_access      = SEC_JUST_WORKS;
    add_char_params.write_access     = SEC_JUST_WORKS;
    add_char_params.is_defered_write = 1;
    add_char_params.char_props.write = true;

    return characteristic_add(p_cgms->service_handle,
                              &add_char_params,
                              &p_cgms->char_handles.sst);
}
Example #8
0
/**@brief Function for adding a characteristic for the Session Run Time.
 *
 * @param[in]   p_cgms   Service instance.
 *
 * @return      NRF_SUCCESS if characteristic was successfully added, otherwise an error code.
 */
static uint32_t srt_char_add(nrf_ble_cgms_t * p_cgms)
{
    uint8_t               len = 0;
    uint8_t               encoded_initial_srt[NRF_BLE_CGMS_SRT_LEN];
    ble_add_char_params_t add_char_params;

    memset(&add_char_params, 0, sizeof(add_char_params));


    len += uint16_encode(p_cgms->session_run_time, &(encoded_initial_srt[len]));

    add_char_params.uuid         = BLE_UUID_CGM_SESSION_RUN_TIME;
    add_char_params.max_len      = NRF_BLE_CGMS_SRT_LEN;
    add_char_params.init_len     = len;
    add_char_params.p_init_value = encoded_initial_srt;
    add_char_params.read_access  = SEC_JUST_WORKS;
    add_char_params.write_access = SEC_NO_ACCESS;

    return characteristic_add(p_cgms->service_handle,
                              &add_char_params,
                              &p_cgms->char_handles.srt);
}
Example #9
0
/**@brief Function for adding a characteristic for the glucose feature.
 *
 * @param[in]   p_cgms   Service instance.
 *
 * @return      NRF_SUCCESS if characteristic was successfully added, otherwise an error code.
 */
static uint32_t glucose_feature_char_add(nrf_ble_cgms_t * p_cgms)
{
    uint8_t               init_value_len;
    uint8_t               encoded_initial_feature[NRF_BLE_CGMS_FEATURE_LEN];
    ble_add_char_params_t add_char_params;

    memset(&add_char_params, 0, sizeof(add_char_params));

    init_value_len = encode_feature_location_type(encoded_initial_feature, &(p_cgms->feature));

    add_char_params.uuid         = BLE_UUID_CGM_FEATURE;
    add_char_params.max_len      = init_value_len;
    add_char_params.init_len     = init_value_len;
    add_char_params.p_init_value = encoded_initial_feature;
    add_char_params.read_access  = SEC_JUST_WORKS;
    add_char_params.write_access = SEC_NO_ACCESS;


    return characteristic_add(p_cgms->service_handle,
                              &add_char_params,
                              &p_cgms->char_handles.feature);
}
static void addService(uint8_t uuid_type)
{
    ret_code_t err_code;
    ble_add_char_params_t params;
    
    // サービスを登録
    ble_uuid_t uuid;
    uuid.uuid = METADATA_SERVICE_UUID;
    uuid.type = uuid_type;
    err_code  = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &uuid, &context.service_handle);
    APP_ERROR_CHECK(err_code);
    
    // params初期設定
    memset(&params, 0 , sizeof(params));
    // UUID
    params.uuid_type = uuid_type;
    // 値はスタック側
    params.is_value_user     = false;
    
    // ターゲットログ
    params.uuid              = TARGET_LOG_ID_CHAR_UUID;
    params.max_len           = 1;
    params.char_props.read   = true;
    params.char_props.write  = true;
    params.char_props.notify = false;
    params.is_defered_read   = false;
    params.is_defered_write  = false;
    params.read_access       = SEC_OPEN;
    params.write_access      = SEC_OPEN;
    params.cccd_write_access = SEC_NO_ACCESS;
    err_code = characteristic_add(context.service_handle, &params, &context.target_log_id_char_handle);
    APP_ERROR_CHECK(err_code);
    
    // メタ属性:時間
    params.uuid              = TARGET_DATETIME_CHAR_UUID;
    params.max_len           = 7; // ble_date_timeのシリアライズされたバイナリサイズ
    params.char_props.read   = true;
    params.char_props.write  = false;
    params.char_props.notify = false;
    params.is_defered_read   = true;
    params.is_defered_write  = false;
    params.is_var_len        = false;
    params.read_access       = SEC_OPEN;
    params.write_access      = SEC_NO_ACCESS;
    params.cccd_write_access = SEC_NO_ACCESS;
    err_code = characteristic_add(context.service_handle, &params, &context.target_datetime_char_handle);
    APP_ERROR_CHECK(err_code);
    
    // メタ属性:概要
    params.uuid              = TARGET_ABSTRACT_CHAR_UUID;
    params.max_len           = GATT_MAX_DATA_LENGTH;
    params.is_var_len        = true;
    params.char_props.read   = true;
    params.char_props.write  = false;
    params.char_props.notify = false;
    params.is_defered_read   = true;
    params.is_defered_write  = false;
    params.is_var_len        = false;
    params.read_access       = SEC_OPEN;
    params.write_access      = SEC_NO_ACCESS;
    params.cccd_write_access = SEC_NO_ACCESS;
    err_code = characteristic_add(context.service_handle, &params, &context.target_abstract_char_handle);
    APP_ERROR_CHECK(err_code);
}
/**@brief Function for initializing the DFU (Nordic). */
uint32_t ble_dfu__nordic__init(ble_dfu__nordic__t * p_dfu__nordic_, const ble_dfu__nordic__init_t * p_dfu__nordic__init)
{
    uint32_t err_code;
    ble_uuid_t ble_uuid;

    // Initialize service structure
    p_dfu__nordic_->evt_handler = p_dfu__nordic__init->evt_handler;
    p_dfu__nordic_->conn_handle = BLE_CONN_HANDLE_INVALID;
    
    // Add a custom base UUID.
    ble_uuid128_t bds_base_uuid  = ble_agsensor_get_uuid(true);
    uint8_t       uuid_type;
    err_code = sd_ble_uuid_vs_add(&bds_base_uuid, &uuid_type);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }
    ble_uuid.type = uuid_type;
    ble_uuid.uuid = 0xBE4A;
        
    // Add service
    err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_dfu__nordic_->service_handle);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    } 

    // Add DFU Packet characteristic
     //dfu_packet_initial_value = p_dfu__nordic__init->ble_dfu__nordic__dfu_packet_initial_value;

     // dhaval test
     ble_dfu__nordic__dfu_packet_t dfu_packet_initial_value = p_dfu__nordic__init->ble_dfu__nordic__dfu_packet_initial_value;

    uint8_t dfu_packet_encoded_value[MAX_DFU_PACKET_LEN];
    ble_add_char_params_t add_dfu_packet_params;
    memset(&add_dfu_packet_params, 0, sizeof(add_dfu_packet_params));
    
    add_dfu_packet_params.uuid                = 0xD4C0;
    add_dfu_packet_params.uuid_type           = ble_uuid.type; 
    add_dfu_packet_params.max_len             = MAX_DFU_PACKET_LEN;
    add_dfu_packet_params.init_len            = dfu_packet_encode(&dfu_packet_initial_value, dfu_packet_encoded_value);
    add_dfu_packet_params.p_init_value        = dfu_packet_encoded_value; 
    add_dfu_packet_params.char_props.write    = 1; 
    add_dfu_packet_params.write_access        = SEC_OPEN; 
    // 1 for variable length and 0 for fixed length.
    add_dfu_packet_params.is_var_len          = 1; 

    err_code = characteristic_add(p_dfu__nordic_->service_handle, &add_dfu_packet_params, &(p_dfu__nordic_->dfu_packet_handles));
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    } 

    // Add DFU Control Point characteristic
     //dfu_control_point_initial_value = p_dfu__nordic__init->ble_dfu__nordic__dfu_control_point_initial_value;
     //Dhaval test
     ble_dfu__nordic__dfu_control_point_t dfu_control_point_initial_value = p_dfu__nordic__init->ble_dfu__nordic__dfu_control_point_initial_value;

    uint8_t dfu_control_point_encoded_value[MAX_DFU_CONTROL_POINT_LEN];
    ble_add_char_params_t add_dfu_control_point_params;
    memset(&add_dfu_control_point_params, 0, sizeof(add_dfu_control_point_params));
    
    add_dfu_control_point_params.uuid                = 0x1FE8;
    add_dfu_control_point_params.uuid_type           = ble_uuid.type;
    add_dfu_control_point_params.max_len             = MAX_DFU_CONTROL_POINT_LEN;
    add_dfu_control_point_params.init_len            = dfu_control_point_encode(&dfu_control_point_initial_value, dfu_control_point_encoded_value);
    add_dfu_control_point_params.p_init_value        = dfu_control_point_encoded_value; 
    add_dfu_control_point_params.char_props.notify   = 1; 
    add_dfu_control_point_params.char_props.write    = 1; 
    add_dfu_control_point_params.write_access        = SEC_OPEN; 
    add_dfu_control_point_params.cccd_write_access   = SEC_OPEN;
    // 1 for variable length and 0 for fixed length.
    add_dfu_control_point_params.is_var_len          = 1; 

    err_code = characteristic_add(p_dfu__nordic_->service_handle, &add_dfu_control_point_params, &(p_dfu__nordic_->dfu_control_point_handles));
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    } 

    return NRF_SUCCESS;
}
/**@brief Function for initializing the AgSensor. */
uint32_t ble_agsensor_init(ble_agsensor_t * p_agsensor, const ble_agsensor_init_t * p_agsensor_init)
{
    uint32_t err_code;
    ble_uuid_t ble_uuid;

    // Initialize service structure
    p_agsensor->evt_handler = p_agsensor_init->evt_handler;
    p_agsensor->conn_handle = BLE_CONN_HANDLE_INVALID;
    
    // Add a custom base UUID.
    ble_uuid128_t bds_base_uuid = {0x8D, 0x69, 0xDE, 0x3D, 0x57, 0x37, 0x4F, 0xBD, 0x54, 0x41, 0xE8, 0x73, 0x00, 0x00, 0xFE, 0x94};
    uint8_t       uuid_type;
    err_code = sd_ble_uuid_vs_add(&bds_base_uuid, &uuid_type);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }
    ble_uuid.type = uuid_type;
    ble_uuid.uuid = 0x9B64;
        
    // Add service
    err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_agsensor->service_handle);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    } 

    // Add configuration characteristic
    ble_agsensor_configuration_t configuration_initial_value = p_agsensor_init->ble_agsensor_configuration_initial_value;

    // Initialize value struct.
    memset(&configuration_initial_value, 0, sizeof(configuration_initial_value));
    // Dhaval test
    configuration_initial_value = p_agsensor_init->ble_agsensor_configuration_initial_value;
    configuration_initial_value.ble_agsensor_code = 0x0001;
    configuration_initial_value.data.ble_agsensor_date_time_Sec = getTimeInSec();
//    configuration_initial_value.ble_agsensor_data = "test";

    uint8_t configuration_encoded_value[MAX_CONFIGURATION_LEN];
    ble_add_char_params_t add_configuration_params;
    memset(&add_configuration_params, 0, sizeof(add_configuration_params));

    add_configuration_params.uuid                = 0x866D;
    add_configuration_params.uuid_type           = ble_uuid.type;
    add_configuration_params.max_len             = MAX_CONFIGURATION_LEN;
    add_configuration_params.init_len            = configuration_encode(&configuration_initial_value, configuration_encoded_value);
    add_configuration_params.p_init_value        = configuration_encoded_value;
////    add_configuration_params.char_props.indicate = 1;
//    add_configuration_params.char_props.write    = 1;
////    add_configuration_params.read_access         = SEC_OPEN;
//    add_configuration_params.write_access        = SEC_OPEN;
////    add_configuration_params.cccd_write_access   = SEC_OPEN;
//    // 1 for variable length and 0 for fixed length.
//    add_configuration_params.is_var_len          = 1;
//
//    add_configuration_params.char_props.read     = 1;
//    add_configuration_params.read_access         = SEC_OPEN;


    add_configuration_params.char_props.notify   = 1;
    add_configuration_params.char_props.indicate = 1;
    add_configuration_params.char_props.read     = 1;
    add_configuration_params.read_access         = SEC_OPEN;
    add_configuration_params.char_props.write    = 1;
    add_configuration_params.write_access        = SEC_OPEN;
    add_configuration_params.cccd_write_access   = SEC_OPEN;
    // 1 for variable length and 0 for fixed length.
    add_configuration_params.is_var_len          = 1;


    err_code = characteristic_add(p_agsensor->service_handle, &add_configuration_params, &(p_agsensor->configuration_handles));
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    } 

    // Add data characteristic
    //data_initial_value = p_agsensor_init->ble_agsensor_data_initial_value;

     ble_agsensor_data_t data_initial_value = p_agsensor_init->ble_agsensor_data_initial_value;

    uint8_t data_encoded_value[MAX_DATA_LEN];
    ble_add_char_params_t add_data_params;
    memset(&add_data_params, 0, sizeof(add_data_params));
    
    add_data_params.uuid                = 0x20D7;
    add_data_params.uuid_type           = ble_uuid.type; 
    add_data_params.max_len             = MAX_DATA_LEN;
    add_data_params.init_len            = data_encode(&data_initial_value, data_encoded_value);
    add_data_params.p_init_value        = data_encoded_value; 
    add_data_params.char_props.indicate = 1; 
    add_data_params.char_props.write    = 1; 
    add_data_params.write_access        = SEC_OPEN; 
    add_data_params.cccd_write_access   = SEC_OPEN;
    // 1 for variable length and 0 for fixed length.
    add_data_params.is_var_len          = 1; 

    err_code = characteristic_add(p_agsensor->service_handle, &add_data_params, &(p_agsensor->data_handles));
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    } 

    return NRF_SUCCESS;
}
/**@brief Function for initializing the Display Service. */
uint32_t ble_display_service_init(ble_display_service_t * p_display_service, const ble_display_service_init_t * p_display_service_init)
{
	uint32_t err_code;
	ble_uuid_t ble_uuid;

	    // Initialize service structure
	p_display_service->evt_handler = p_display_service_init->evt_handler;
	p_display_service->conn_handle = BLE_CONN_HANDLE_INVALID;
    
	// Add a custom base UUID.
	ble_uuid128_t bds_base_uuid = { { 0x22, 0x13, 0xDC, 0x64, 0xC5, 0x14, 0x2B, 0x90, 0x0C, 0x43, 0xCF, 0x10, 0x00, 0x00, 0x00, 0x0D } };
	uint8_t       uuid_type;
	err_code = sd_ble_uuid_vs_add(&bds_base_uuid, &uuid_type);
	if (err_code != NRF_SUCCESS)
	{
		return err_code;
	}
	ble_uuid.type = uuid_type;
	ble_uuid.uuid = 0x14CE;
        
	// Add service
	err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_display_service->service_handle);
	if (err_code != NRF_SUCCESS)
	{
		return err_code;
	} 

	    // Add Record Number characteristic
	ble_display_service_record_number_t record_number_initial_value = p_display_service_init->ble_display_service_record_number_initial_value; 

	uint8_t record_number_encoded_value[MAX_RECORD_NUMBER_LEN];
	ble_add_char_params_t add_record_number_params;
	memset(&add_record_number_params, 0, sizeof(add_record_number_params));
    
	add_record_number_params.uuid                = 0xAF2A;
	add_record_number_params.uuid_type           = ble_uuid.type; 
	add_record_number_params.max_len             = MAX_RECORD_NUMBER_LEN;
	add_record_number_params.init_len            = record_number_encode(&record_number_initial_value, record_number_encoded_value);
	add_record_number_params.p_init_value        = record_number_encoded_value; 
	add_record_number_params.char_props.write    = 1; 
	add_record_number_params.char_props.write_wo_resp    = 1; 
	add_record_number_params.write_access        = SEC_OPEN; 
	// 1 for variable length and 0 for fixed length.
	add_record_number_params.is_var_len          = 1; 

	err_code = characteristic_add(p_display_service->service_handle, &add_record_number_params, &(p_display_service->record_number_handles));
	if (err_code != NRF_SUCCESS)
	{
		return err_code;
	} 

	    // Add Record characteristic
	ble_display_service_record_t record_initial_value = p_display_service_init->ble_display_service_record_initial_value; 

	uint8_t record_encoded_value[MAX_RECORD_LEN];
	ble_add_char_params_t add_record_params;
	memset(&add_record_params, 0, sizeof(add_record_params));
    
	add_record_params.uuid                = 0x411C;
	add_record_params.uuid_type           = ble_uuid.type; 
	add_record_params.max_len             = MAX_RECORD_LEN;
	add_record_params.init_len            = record_encode(&record_initial_value, record_encoded_value);
	add_record_params.p_init_value        = record_encoded_value; 
	add_record_params.char_props.notify   = 1; 
	add_record_params.char_props.read     = 1; 
	add_record_params.read_access         = SEC_OPEN; 
	add_record_params.cccd_write_access   = SEC_OPEN;
	// 1 for variable length and 0 for fixed length.
	add_record_params.is_var_len          = 1; 

	err_code = characteristic_add(p_display_service->service_handle, &add_record_params, &(p_display_service->record_handles));
	if (err_code != NRF_SUCCESS)
	{
		return err_code;
	} 

	return NRF_SUCCESS;
}