Hello,
I'm using Da14531 as peripheral device and smart phone acts as the central. I want to transmit the data to peripheral device on the particular service and characteristic UUID. I'm using BLE_peripheral example available in the SDK.
How the user_catch_rest_hndl() function is identifying the services whether it is CUSTS1_VAL_WRITE_IND or CUSTS1_VAL_NTF_CFM?
To write the data to central device which custom message(CUSTS1_VALUE_REQ_IND/CUSTS1_VAL_SET_REQ/CUSTS1_VAL_WRITE_IND) I need to choose from custs1_task.h?
Where I can learn the difference between these messages?
Hi MA,Thank you for posting your question online and for your interest in our BLE products.The user_catch_rest_hndl function is identifying the messages we are getting from GAP manager. The implementation of this function is inside the ROM and it is not accessible.
#define app_process_catch_rest_cb user_catch_rest_hndl
.catch_rest_func = app_process_catch_rest_cb,
// LED State Characteristic Declaration [SVC1_IDX_LED_STATE_CHAR] = {(uint8_t*)&att_decl_char, ATT_UUID_16_LEN, PERM(RD, ENABLE), 0, 0, NULL}, // LED State Characteristic Value [SVC1_IDX_LED_STATE_VAL] = {SVC1_LED_STATE_UUID_128, ATT_UUID_128_LEN, PERM(WR, ENABLE) | PERM(WRITE_COMMAND, ENABLE), PERM(RI, ENABLE) | DEF_SVC1_LED_STATE_CHAR_LEN, 0, NULL}, // LED State Characteristic User Description [SVC1_IDX_LED_STATE_USER_DESC] = {(uint8_t*)&att_desc_user_desc, ATT_UUID_16_LEN, PERM(RD, ENABLE), sizeof(DEF_SVC1_LED_STATE_USER_DESC) - 1, sizeof(DEF_SVC1_LED_STATE_USER_DESC) - 1, (uint8_t *) DEF_SVC1_LED_STATE_USER_DESC},
void user_catch_rest_hndl(ke_msg_id_t const msgid, void const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { switch(msgid) { case CUSTS1_VAL_WRITE_IND: { struct custs1_val_write_ind const *msg_param = (struct custs1_val_write_ind const *)(param); switch (msg_param->handle) { ... case SVC1_IDX_LED_STATE_VAL: user_svc1_led_wr_ind_handler(msgid, msg_param, dest_id, src_id); break; ...
void user_svc1_led_wr_ind_handler(ke_msg_id_t const msgid, struct custs1_val_write_ind const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { uint8_t val = 0; memcpy(&val, ¶m->value[0], param->length); if (val == CUSTS1_LED_ON) { GPIO_SetActive(GPIO_LED_PORT, GPIO_LED_PIN); } else if (val == CUSTS1_LED_OFF) { GPIO_SetInactive(GPIO_LED_PORT, GPIO_LED_PIN); } }
/// Messages for CUSTS1 enum { /// Add a CUSTOMS instance into the database CUSTS1_CREATE_DB_REQ = KE_FIRST_MSG(TASK_ID_CUSTS1), /// Inform APP of database creation status CUSTS1_CREATE_DB_CFM, /// Start the Custom Service Task - at connection CUSTS1_ENABLE_REQ, /// Set/update characteristic value CUSTS1_VAL_SET_REQ, /// Peer device request to get a non-database value (RI enabled) CUSTS1_VALUE_REQ_IND, /// Response to non-database value request CUSTS1_VALUE_REQ_RSP, /// Inform profile task that the peer has subscribed/unsubscribed to notification CUSTS1_VAL_NTF_REQ, /// Response after receiving a CUSTS1_VAL_NTF_REQ message and a notification is triggered CUSTS1_VAL_NTF_CFM, /// Inform profile task that the peer has subscribed/unsubscribed to indication CUSTS1_VAL_IND_REQ, /// Response after receiving a CUSTS1_VAL_IND_REQ message and an indication is triggered CUSTS1_VAL_IND_CFM, /// Indicate that the characteristic value has been written CUSTS1_VAL_WRITE_IND, /// Inform the application that the profile service role task has been disabled after a disconnection CUSTS1_DISABLE_IND, /// Profile error report CUSTS1_ERROR_IND, /// Inform the application that there is an attribute info request that shall be processed CUSTS1_ATT_INFO_REQ, /// Inform back that the attribute info request has been processed CUSTS1_ATT_INFO_RSP, };
// Read 4 Characteristic Declaration [SVC3_IDX_READ_4_CHAR] = {(uint8_t*)&att_decl_char, ATT_UUID_16_LEN, PERM(RD, ENABLE), 0, 0, NULL}, // Read 4 Characteristic Value [SVC3_IDX_READ_4_VAL] = {SVC3_READ_VAL_4_UUID_128, ATT_UUID_128_LEN, PERM(RD, ENABLE), PERM(RI, ENABLE) | DEF_SVC3_READ_VAL_4_CHAR_LEN, 0, NULL}, // Read 4 Characteristic User Description [SVC3_IDX_READ_4_USER_DESC] = {(uint8_t*)&att_desc_user_desc, ATT_UUID_16_LEN, PERM(RD, ENABLE), sizeof(DEF_SVC3_READ_VAL_4_USER_DESC) - 1, sizeof(DEF_SVC3_READ_VAL_4_USER_DESC) - 1, (uint8_t *) DEF_SVC3_READ_VAL_4_USER_DESC},
... case CUSTS1_VALUE_REQ_IND: { struct custs1_value_req_ind const *msg_param = (struct custs1_value_req_ind const *) param; switch (msg_param->att_idx) { case SVC3_IDX_READ_4_VAL: { user_svc3_read_non_db_val_handler(msgid, msg_param, dest_id, src_id); } break; ...
void user_svc3_read_non_db_val_handler(ke_msg_id_t const msgid, struct custs1_value_req_ind const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Increase value by one non_db_val_counter++; struct custs1_value_req_rsp *rsp = KE_MSG_ALLOC_DYN(CUSTS1_VALUE_REQ_RSP, prf_get_task_from_id(TASK_ID_CUSTS1), TASK_APP, custs1_value_req_rsp, DEF_SVC3_READ_VAL_4_CHAR_LEN); // Provide the connection index. rsp->conidx = app_env[param->conidx].conidx; // Provide the attribute index. rsp->att_idx = param->att_idx; // Force current length to zero. rsp->length = sizeof(non_db_val_counter); // Provide the ATT error code. rsp->status = ATT_ERR_NO_ERROR; // Copy value memcpy(&rsp->value, &non_db_val_counter, rsp->length); // Send message ke_msg_send(rsp); }
I want to send the data to central device (smartphone) from the peripheral device( DA14531 evaluation board) on the particular characterisitcs.
OV_Renesas said:When connected with a central and write on this characteristic, the user_catch_rest_hndl function is being triggered with a case of CUSTS1_VAL_WRITE_IND :
As you mentioned earlier when the central device wants to write data to the peripheral device, then CUSTS1_VAL_WRITE_IND case will be true.
If the peripheral device wants to send the data, which case will be true?
void user_svc4_write(ke_msg_id_t const msgid, struct custs1_val_write_ind const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { if (param->value[0]) { uint8_t conidx = KE_IDX_GET(src_id); struct custs1_val_ind_req* req = KE_MSG_ALLOC_DYN(CUSTS1_VAL_IND_REQ, prf_get_task_from_id(TASK_ID_CUSTS1), TASK_APP, custs1_val_ind_req, 2); req->conidx = app_env[conidx].conidx; req->handle = SVC4_WRITE_VAL; req->length = 2; req->value[0] = 1; req->value[1] = 2; ke_msg_send(req); } }
I have wrote the above mentioned function to transmit the data to the central device.
Is this correct way of doing it?
The peripheral example available in the SDK will act as GATT server or GATT client?
For example if the DA14531 evaluation board acts as GATT server, How the smartphone will know that it has to acts as the server?
Hi MA,Thank you for the reply.The code snippet you have shared is utilizing the CUSTS1_VAL_IND_REQ which is the message being used when we want to read a characteristic value.You should use:
/// Set/update characteristic value CUSTS1_VAL_SET_REQ,
/// Inform profile task that the peer has subscribed/unsubscribed to indication CUSTS1_VAL_IND_REQ, /// Response after receiving a CUSTS1_VAL_IND_REQ message and an indication is triggered CUSTS1_VAL_IND_CFM,
Below I have mentioned the charactersitics permission , I have given for custom service and characteristics.
[SVC4_IDX_SVC] = {(uint8_t*)&att_decl_svc, ATT_UUID_128_LEN, PERM(RD, ENABLE), sizeof(custs1_svc4), sizeof(custs1_svc4), (uint8_t*)&custs1_svc4}, // Write 1 Characteristic Declaration [SVC4_WRITE_CHAR] = {(uint8_t*)&att_decl_char, ATT_UUID_16_LEN, PERM(RD, ENABLE), 0, 0, NULL}, // Write 1 Characteristic Value [SVC4_WRITE_VAL] = {custs1_svc4, ATT_UUID_128_LEN, PERM(WR, ENABLE) | PERM(WRITE_REQ, ENABLE), PERM(RI, ENABLE) | DEF_SVC4_WRITE_VAL_CHAR_LEN, 0, NULL}, // Write 1 Characteristic User Description [SVC4_WRITE_USER_DESC] = {(uint8_t*)&att_desc_user_desc, ATT_UUID_16_LEN, PERM(RD, ENABLE), sizeof(DEF_SVC4_WRITE_VAL_USER_DESC) - 1, sizeof(DEF_SVC4_WRITE_VAL_USER_DESC) - 1, (uint8_t *) DEF_SVC4_WRITE_VAL_USER_DESC},
In the user_catch_rest_hndl() function , I have added the case following case.
case CUSTS1_VAL_SET_REQ: { struct custs1_val_set_req const *msg_param = (struct custs1_val_set_req const *)(param); switch (msg_param->handle) { case SVC4_WRITE_VAL: {user_svc4_write(msgid, msg_param, dest_id, src_id); }break; } } break;
But this case is not getting implemented while debugging. I have wrote the following function to send the data to the server.
void user_svc4_write(ke_msg_id_t const msgid, struct custs1_val_set_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { if (param->value[0]) { uint8_t conidx = KE_IDX_GET(src_id); struct custs1_val_set_req* req= KE_MSG_ALLOC_DYN( CUSTS1_VAL_SET_REQ, prf_get_task_from_id(TASK_ID_CUSTS1), TASK_APP, custs1_val_set_req, 2); req->conidx = app_env[conidx].conidx; req->handle = SVC4_WRITE_VAL; req->length = 2; req->value[0] = 1; req->value[1] = 2; ke_msg_send(req); } }
Why the characteristics are not matching?
Why the data is not transmitted to the central device?
Please help me to solve the issue!!
Hi MA,
Thank you for the reply.According to the custom Characteristic you shared:You will have to set a case for CUSTS1_VALUE_REQ_IND on your user_catch_hndl and call the user_svc4_write function.On your user_svc4_write function you should use the CUSTS1_VALUE_REQ_RSP type to give the value you want to your characteristic.You will need those because you have given the permission RI.I do not understand why you got the if statement there.Also, if you had implemented some sort of timer that would call the user_svc4_write function then you should be able to update your characteristic, you cannot catch a CUSTS1_VAL_SET_REQ the way it is implemented.The if statement and
uint8_t conidx = KE_IDX_GET(src_id);