2021-08-13 09:48 PM
Hello, currently I am working on stm32wb55 MCU. I want to read, write and notify the sensors data to peripheral(phone) from the central device(stm32wb55). I have done read and write characteristics in service but I didn't know how to enable notify characteristic and how to send data from to notify to a peripheral device.
2021-09-21 02:18 AM
In a client server architecture, the client (central role) read and write data to a peripheral server and the server notifies the client with any new value from a local sensor. There is no other way. In your use case, the peripheral (WB55) should send notification to the mobile phone.
2021-09-21 04:12 AM
Thanks for your response, Remi Quintin.
My peripheral device (WB55) is able to send notify but I have to send continuous ADC values to the mobile phone. How I can be done this? or which function will perform notification characteristic? I have no experience in this so, could you explain how can I do this.
Again, Thanks for your support.😊
2021-09-21 08:00 AM
To get notification from a peripheral, a central must first enable it on the server side for the specific characteristic. To achieve this, the client has to write the Client Characteristic Configuration Descriptor (CCCD located on server side) of the characteristic for which it request its notification.
So your smartphone application (client) must set the CCCD of the ADC characteristic with notifications enabled. Then the peripheral (server) is able to send notifications whenever a new ADC value is available.
From a SW standpoint:
When a characteristic is added on the server with aci_gatt_add_char function with the "char properties" field set to CHAR_PROP_NOTIFY, a Client Characteristic Configuration Descriptor is added which can be modified by the client later on.
The to receive notification on client side, the client device, which has discovered all characteristics, can enable or disable the notification with the aci_gatt_write_char_desc function.
AND the server uses aci_gatt_update_char_value function to notify the client of a new update value for the characteristic.
2021-09-21 08:05 AM
To be more specific for your case
On the Client Side:
The aci_gatt_write_char_desc procedure sets the Client Characteristic Configuration Descriptor (CCCD) of the "Notify" Service to enabled or disabled.
This would be for a WB55 being a client. But it is up to you to find the way on your smartphone.
On the Server side (WB55 in your case):
When the Client Characteristic Configuration Descriptor (CCCD) of the ADC characteristic is modified, an ACI_GATT_ATTRIBUTE_MODIFIED_EVENT (which can be found for example in p2p_stm.c as case EVT_BLUE_GATT_ATTRIBUTE_MODIFIED:) is triggered. Ultimately this leads to setting P2P_Server_App_Context.Notification_Status to 1 or 0 if the notifications were enabled or disabled respectively.
Note: The P2P_Server_App_Context.Notification_Status flag is not the Client Characteristic Configuration Descriptor (CCDC) value.
Then, each time the ADC value is modified/updated, the server calls aci_gatt_update_char_value function to notify the client of this new ADC value.
2021-09-21 08:18 AM
Note the only way for the server to keep the notifications enabled is to pair and bond with client devices (the process has to be done once).
To minimize the number of write accesses to the FLASH memory and protect its lifetime, the Client Configuration Characteristic Descriptor values are not saved in the FLASH memory on the fly but only on a disconnection event coming from the client or the server.
Moreover, all the characteristics configurations are not saved in FLASH, so after a power reset, these configurations are lost
So if a reset or a power reset happens on a bonded device before any disconnection event, all the Client Configuration Characteristic Descriptor values are lost.
2023-03-03 10:14 AM
Did you manage to do it. I am stuck here for 2 months now.
2023-03-03 10:34 AM
Hi Remi,How can I send ADC values using BLE in STM32WB. There are no videos or material showing this. Can you show me in this file where I can add my values. Lets say 10 15 and 20.
static SVCCTL_EvtAckStatus_t Custom_STM_Event_Handler(void *Event)
{
SVCCTL_EvtAckStatus_t return_value;
hci_event_pckt *event_pckt;
evt_blecore_aci *blecore_evt;
aci_gatt_read_permit_req_event_rp0 *read_req;
Custom_STM_App_Notification_evt_t Notification;
/* USER CODE BEGIN Custom_STM_Event_Handler_1 */
aci_gatt_read_permit_req_event_rp0 *my_read_req; //PASSING MY READ REQUEST WHEN THE EVENT TO HAPPEN SVCCTL_EvtNotAck
/* USER CODE END Custom_STM_Event_Handler_1 */
return_value = SVCCTL_EvtNotAck;
event_pckt = (hci_event_pckt *)(((hci_uart_pckt*)Event)->data);
switch (event_pckt->evt)
{
case HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE:
blecore_evt = (evt_blecore_aci*)event_pckt->data;
switch (blecore_evt->ecode)
{
case ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE:
/* USER CODE BEGIN EVT_BLUE_GATT_ATTRIBUTE_MODIFIED_BEGIN */
/* USER CODE END EVT_BLUE_GATT_ATTRIBUTE_MODIFIED_BEGIN */
/* USER CODE BEGIN EVT_BLUE_GATT_ATTRIBUTE_MODIFIED_END */
/* USER CODE END EVT_BLUE_GATT_ATTRIBUTE_MODIFIED_END */
break;
case ACI_GATT_READ_PERMIT_REQ_VSEVT_CODE :
/* USER CODE BEGIN EVT_BLUE_GATT_READ_PERMIT_REQ_BEGIN */
/* USER CODE END EVT_BLUE_GATT_READ_PERMIT_REQ_BEGIN */
read_req = (aci_gatt_read_permit_req_event_rp0*)blecore_evt->data;
if (read_req->Attribute_Handle == (CustomContext.CustomMycharwriteHdle + CHARACTERISTIC_VALUE_ATTRIBUTE_OFFSET))
{
return_value = SVCCTL_EvtAckFlowEnable;
/*USER CODE BEGIN CUSTOM_STM_Service_1_Char_1_ACI_GATT_READ_PERMIT_REQ_VSEVT_CODE_1 */
/*USER CODE END CUSTOM_STM_Service_1_Char_1_ACI_GATT_READ_PERMIT_REQ_VSEVT_CODE_1*/
aci_gatt_allow_read(read_req->Connection_Handle);
/*USER CODE BEGIN CUSTOM_STM_Service_1_Char_1_ACI_GATT_READ_PERMIT_REQ_VSEVT_CODE_2 */
/*USER CODE END CUSTOM_STM_Service_1_Char_1_ACI_GATT_READ_PERMIT_REQ_VSEVT_CODE_2*/
} /* if (read_req->Attribute_Handle == (CustomContext.CustomMycharwriteHdle + CHARACTERISTIC_VALUE_ATTRIBUTE_OFFSET))*/
/* USER CODE BEGIN EVT_BLUE_GATT_READ_PERMIT_REQ_END */
/* USER CODE END EVT_BLUE_GATT_READ_PERMIT_REQ_END */
break;
case ACI_GATT_WRITE_PERMIT_REQ_VSEVT_CODE:
/* USER CODE BEGIN EVT_BLUE_GATT_WRITE_PERMIT_REQ_BEGIN */
/* USER CODE END EVT_BLUE_GATT_WRITE_PERMIT_REQ_BEGIN */
/* USER CODE BEGIN EVT_BLUE_GATT_WRITE_PERMIT_REQ_END */
/* USER CODE END EVT_BLUE_GATT_WRITE_PERMIT_REQ_END */
break;
/* USER CODE BEGIN BLECORE_EVT */
/* USER CODE END BLECORE_EVT */
default:
/* USER CODE BEGIN EVT_DEFAULT */
/* USER CODE END EVT_DEFAULT */
break;
}
/* USER CODE BEGIN EVT_VENDOR*/
/* USER CODE END EVT_VENDOR*/
break; /* HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE */
/* USER CODE BEGIN EVENT_PCKT_CASES*/
/* USER CODE END EVENT_PCKT_CASES*/
default:
/* USER CODE BEGIN EVENT_PCKT*/
/* USER CODE END EVENT_PCKT*/
break;
}
/* USER CODE BEGIN Custom_STM_Event_Handler_2 */
/* USER CODE END Custom_STM_Event_Handler_2 */
return(return_value);
}/*
OR
tBleStatus Custom_STM_App_Update_Char(Custom_STM_Char_Opcode_t CharOpcode, uint8_t *pPayload)
{
tBleStatus ret = BLE_STATUS_INVALID_PARAMS;
/* USER CODE BEGIN Custom_STM_App_Update_Char_1 */
/* USER CODE END Custom_STM_App_Update_Char_1 */
switch (CharOpcode)
{
case CUSTOM_STM_MYCHARWRITE:
ret = aci_gatt_update_char_value(CustomContext.CustomMysvcHdle,
CustomContext.CustomMycharwriteHdle,
0, /* charValOffset */
SizeMycharwrite, /* charValueLen */
(uint8_t *) pPayload);
if (ret != BLE_STATUS_SUCCESS)
{
APP_DBG_MSG(" Fail : aci_gatt_update_char_value MYCHARWRITE command, result : 0x%x \n\r", ret);
}
else
{
APP_DBG_MSG(" Success: aci_gatt_update_char_value MYCHARWRITE command\n\r");
}
/* USER CODE BEGIN CUSTOM_STM_App_Update_Service_1_Char_1*/
/* USER CODE END CUSTOM_STM_App_Update_Service_1_Char_1*/
break;
default:
break;
}
/* USER CODE BEGIN Custom_STM_App_Update_Char_2 */
/* USER CODE END Custom_STM_App_Update_Char_2 */
return ret;
}