Hi,
Using nRF52840 with SDK15.0.0.
I started my projetc based on BLE tutorial characteristics.
I created my service and add 2 characteristics successfully.
My module is advertising and i can see its characteristics correctly.
One charac is CHARACTERISTIC_READER_RESULT, i can see its value correctly with nRF application but i try to change its value with a notification and it doesn't work.
I got err 0x00003002 err_code return from function sd_ble_gatts_hvx. it's stand for BLE_ERROR_INVALID_CONN_HANDLE but i don't know where is the problem ...
here is my code :
static uint32_t our_char_add(ble_os_t * p_our_service)
{
uint32_t err_code;
ble_uuid128_t base_uuid = BLE_UUID_OUR_BASE_UUID;
//----------------------------------------------------------------------
//FIRST CHARAC
//CHARACTERISTIC_READER_RESULT : BLE module send a message utf8 to mobile application by notification
// OUR_JOB: Step 2.A, Add a custom characteristic UUID
ble_uuid_t char_uuid_2;
char_uuid_2.uuid = BLE_UUID_CHARACTERISTIC_READER_RESULT;
err_code = sd_ble_uuid_vs_add(&base_uuid, &char_uuid_2.type);
APP_ERROR_CHECK(err_code);
// OUR_JOB: Step 2.F Add read/write properties to our characteristic
ble_gatts_char_md_t char_md_2;
memset(&char_md_2, 0, sizeof(char_md_2));
char_md_2.char_props.read = 1;
//char_md_2.char_props.write = 1;
char_md_2.char_props.write = 0;
// OUR_JOB: Step 3.A, Configuring Client Characteristic Configuration Descriptor metadata and add to char_md structure
ble_gatts_attr_md_t cccd_md_2;
memset(&cccd_md_2, 0, sizeof(cccd_md_2));
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md_2.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md_2.write_perm);
cccd_md_2.vloc = BLE_GATTS_VLOC_STACK;
char_md_2.p_cccd_md = &cccd_md_2;
char_md_2.char_props.notify = 1;
// OUR_JOB: Step 2.B, Configure the attribute metadata
ble_gatts_attr_md_t attr_md_2;
memset(&attr_md_2, 0, sizeof(attr_md_2));
attr_md_2.vloc = BLE_GATTS_VLOC_STACK;
// OUR_JOB: Step 2.G, Set read/write security levels to our characteristic
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md_2.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md_2.write_perm);
// OUR_JOB: Step 2.C, Configure the characteristic value attribute
ble_gatts_attr_t attr_char_value_2;
memset(&attr_char_value_2, 0, sizeof(attr_char_value_2));
attr_char_value_2.p_uuid = &char_uuid_2;
attr_char_value_2.p_attr_md = &attr_md_2;
// OUR_JOB: Step 2.H, Set characteristic length in number of bytes
attr_char_value_2.max_len = 10;
attr_char_value_2.init_len = 10;
uint8_t value_2[10] = {0x44,0x6f,0x6e,0x65,0x44,0x6f,0x6e,0x65,0x44,0x6f};
attr_char_value_2.p_value = value_2;
// OUR_JOB: Step 2.E, Add our new characteristic to the service
err_code = sd_ble_gatts_characteristic_add(p_our_service->service_handle,
&char_md_2,
&attr_char_value_2,
&p_our_service->char_handles);
APP_ERROR_CHECK(err_code);
//----------------------------------------------------------------------
//SECOND CHARAC
//CHARASTERISTIC_IDENTIFIER : mobile phone will write Badge ID on it
// OUR_JOB: Step 2.A, Add a custom characteristic UUID
ble_uuid_t char_uuid;
char_uuid.uuid = BLE_UUID_CHARACTERISTIC_IDENTIFIER;
err_code = sd_ble_uuid_vs_add(&base_uuid, &char_uuid.type);
APP_ERROR_CHECK(err_code);
// OUR_JOB: Step 2.F Add read/write properties to our characteristic
ble_gatts_char_md_t char_md;
memset(&char_md, 0, sizeof(char_md));
//char_md.char_props.read = 1;
char_md.char_props.read = 0;
char_md.char_props.write = 1;
// OUR_JOB: Step 3.A, Configuring Client Characteristic Configuration Descriptor metadata and add to char_md structure
ble_gatts_attr_md_t cccd_md;
memset(&cccd_md, 0, sizeof(cccd_md));
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);
cccd_md.vloc = BLE_GATTS_VLOC_STACK;
char_md.p_cccd_md = &cccd_md;
char_md.char_props.notify = 0;
// OUR_JOB: Step 2.B, Configure the attribute metadata
ble_gatts_attr_md_t attr_md;
memset(&attr_md, 0, sizeof(attr_md));
attr_md.vloc = BLE_GATTS_VLOC_STACK;
// OUR_JOB: Step 2.G, Set read/write security levels to our characteristic
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
// OUR_JOB: Step 2.C, Configure the characteristic value attribute
ble_gatts_attr_t attr_char_value;
memset(&attr_char_value, 0, sizeof(attr_char_value));
attr_char_value.p_uuid = &char_uuid;
attr_char_value.p_attr_md = &attr_md;
// OUR_JOB: Step 2.H, Set characteristic length in number of bytes
attr_char_value.max_len = 10;
attr_char_value.init_len = 10;
uint8_t value[4] = {0x44,0x6f,0x6e,0x65};
attr_char_value.p_value = value;
// OUR_JOB: Step 2.E, Add our new characteristic to the service
err_code = sd_ble_gatts_characteristic_add(p_our_service->service_handle,
&char_md,
&attr_char_value,
&p_our_service->char_handles);
APP_ERROR_CHECK(err_code);
//--------------------------------------------------------------------------------------------
//SEGGER_RTT_WriteString(0, "APPEL UPDATE POUR NOTIF\n");
//int32_t temperature = 0;
//our_temperature_characteristic_update(&p_our_service, &temperature);
return NRF_SUCCESS;
}
/**@brief Function for initiating our new service.
*
* @param[in] p_our_service Our Service structure.
*
*/
void our_service_init(ble_os_t * p_our_service)
{
uint32_t err_code; // Variable to hold return codes from library and softdevice functions
SEGGER_RTT_WriteString(0, "debut our_service_init().\n");
// FROM_SERVICE_TUTORIAL: Declare 16-bit service and 128-bit base UUIDs and add them to the BLE stack
ble_uuid_t service_uuid;
ble_uuid128_t base_uuid = BLE_UUID_OUR_BASE_UUID;
service_uuid.uuid = BLE_UUID_OUR_SERVICE_UUID;
err_code = sd_ble_uuid_vs_add(&base_uuid, &service_uuid.type);
APP_ERROR_CHECK(err_code);
// OUR_JOB: Step 3.B, Set our service connection handle to default value. I.e. an invalid handle since we are not yet in a connection.
p_our_service->conn_handle = BLE_CONN_HANDLE_INVALID;
// FROM_SERVICE_TUTORIAL: Add our service
err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
&service_uuid,
&p_our_service->service_handle);
APP_ERROR_CHECK(err_code);
SEGGER_RTT_WriteString(0, "our_service_init() après service_add.\n");
// OUR_JOB: Call the function our_char_add() to add our new characteristic to the service.
our_char_add(p_our_service);
}
// ALREADY_DONE_FOR_YOU: Function to be called when updating characteristic value
void our_temperature_characteristic_update(ble_os_t *p_our_service, int32_t *temperature_value)
{
SEGGER_RTT_WriteString(0, "DEBUT FONCTION NOTIFICATION\n");
// OUR_JOB: Step 3.E, Update characteristic value
if (p_our_service->conn_handle != BLE_CONN_HANDLE_INVALID)
{
SEGGER_RTT_WriteString(0, "DEBUT NOTIFICATION\n");
uint16_t len = 10;
ble_gatts_hvx_params_t hvx_params;
memset(&hvx_params, 0, sizeof(hvx_params));
hvx_params.handle = p_our_service->char_handles.value_handle;
hvx_params.type = BLE_GATT_HVX_NOTIFICATION;
hvx_params.offset = 0;
hvx_params.p_len = &len;
//hvx_params.p_data = (uint8_t*)temperature_value;
uint8_t gdedata[10] = {0x47,0x6f,0x6f,0x64,0x44,0x6f,0x6e,0x65,0x44,0x6f};
hvx_params.p_data = gdedata;
uint32_t err_code;
err_code = sd_ble_gatts_hvx(p_our_service->conn_handle, &hvx_params);
SEGGER_RTT_printf(0, "err_code f° notification : 0x%#08x\n", err_code);
}
}