2026-03-02 6:32 AM - last edited on 2026-04-07 9:07 AM by Imen.D
Hi everyone,
I am working on a Beacon project using NUCLEO-WB05KN. My goal is to broadcast Eddystone-UID and allow a connected phone to update the Namespace ID and Instance ID via GATT characteristics.
The Setup:
I have a Custom Service with two characteristics: Namespace (10 bytes) and Instance (6 bytes).
The device broadcasts Eddystone-UID correctly in connectable mode.
I’ve added the GATT_NOTIFY_ATTRIBUTE_WRITE (0x01) mask to both characteristics.
I’m using hci_init(hci_user_evt_proc, NULL); for event handling.
The Problem:
When I write a value from the nRF Connect app, the write is successful on the phone side, but the aci_gatt_srv_attribute_modified_event callback is never triggered on the MCU side.
I have disabled EnterStopMode() to ensure the MCU stays awake.
I have tried implementing the callback in both app_stm32wb05n.c and stm32wb05n_events_cb.c (overriding the WEAK function), but still no luck.
My Device_Init Code:
/* Namespace Characteristic */ aci_gatt_srv_add_char_nwk(my_service_handle, UUID_TYPE_128, &ns_uuid, 10, CHAR_PROP_READ | CHAR_PROP_WRITE | CHAR_PROP_WRITE_WITHOUT_RESP, ATTR_PERMISSION_NONE, 0x01, // GATT_NOTIFY_ATTRIBUTE_WRITE 16, 1, &ns_char_handle);
Main Loop & Process:
/* MX_STM32WB05N_Process is called inside while(1) in main.c */ void MX_STM32WB05N_Process(void) { hci_user_evt_proc(); // Processing pending events User_Process(); // EnterStopMode() is commented out here }
Advertising Configuration:
static void Start_Beaconing(void) { Advertising_Set_Parameters_t Advertising_Set_Parameters[1]; /* Set to Connectable to allow GATT writes */ aci_gap_set_advertising_configuration(0, GAP_MODE_GENERAL_DISCOVERABLE, HCI_ADV_EVENT_PROP_LEGACY | HCI_ADV_EVENT_PROP_CONNECTABLE | HCI_ADV_EVENT_PROP_SCANNABLE, 250, 250, HCI_ADV_CH_ALL, HCI_ADDR_PUBLIC, NULL, HCI_INIT_FILTER_ACCEPT_LIST_NONE, 0, HCI_ADV_PHY_LE_1M, 0, HCI_ADV_PHY_LE_1M, 0, 0); /* current_adv_data is 31 bytes Eddystone-UID */ aci_gap_set_advertising_data_nwk(0, ADV_COMPLETE_DATA, 31, current_adv_data); /* Scan response for Local Name */ aci_gap_set_scan_response_data_nwk(0, ADV_COMPLETE_DATA, sizeof(scan_rsp), scan_rsp); Advertising_Set_Parameters[0].Advertising_Handle = 0; Advertising_Set_Parameters[0].Duration = 0; Advertising_Set_Parameters[0].Max_Extended_Advertising_Events = 0; aci_gap_set_advertising_enable(ENABLE, 1, Advertising_Set_Parameters); }
My Question:
Is there a specific registration step for callbacks in the STM32WB05 series that I am missing beyond hci_init?
Should I use a different event mask for Write without response or Write Request to trigger the attribute modified event?
Why would the stack accept the write but not propagate the event to the application layer?
Any help or example code for STM32WB05 specifically would be greatly appreciated.
Solved! Go to Solution.
2026-04-07 9:07 AM
Hello @burak_Guzeller ,
You can refer to the SampleApp application within the X-CUBE-WB05N SW package:
\x-cube-wb05n\Projects\NUCLEO-U575ZI\Applications\UART\SampleApp\ for an example of aci_gatt_srv_attribute_modified_event callback usage.
In this context on file Projects\NUCLEO-U575ZI\Applications\UART\SampleApp\STM32WB05N\App\gatt_db.c the following characteristic is defined:
STM32WB_memcpy(&char_uuid.Char_UUID_128, charUuidRX, 16);
ret = aci_gatt_srv_add_char_nwk(sampleServHandle, UUID_TYPE_128, &char_uuid, CHAR_VALUE_LENGTH, CHAR_PROP_WRITE | CHAR_PROP_WRITE_WITHOUT_RESP, ATTR_PERMISSION_NONE, GATT_NOTIFY_ATTRIBUTE_WRITE, 16, 1, &RXCharHandle);
if (ret != BLE_STATUS_SUCCESS) { goto fail ;}
and on file Projects\NUCLEO-U575ZI\Applications\UART\SampleApp\STM32WB05N\App\app_stm32wb05n.c the following callback is triggered with the related user action:
void aci_gatt_srv_attribute_modified_event(uint16_t Connection_Handle,
uint16_t CID,
uint16_t Attr_Handle,
uint16_t Attr_Data_Length,
uint8_t Attr_Data[])
{
Attribute_Modified_CB(Attr_Handle, Attr_Data_Length, Attr_Data);
} /* end aci_gatt_attribute_modified_event() */
where the function Attribute_Modified_CB() for the RXCharHandle characteristic will simply allow to toggle a led within the receiveData() function:
static void Attribute_Modified_CB(uint16_t handle, uint8_t data_length, uint8_t *att_data)
{
if(handle == RXCharHandle + 1)
{
receiveData(att_data, data_length);
}
...
}
static void receiveData(uint8_t* data_buffer, uint8_t Nb_bytes)
{
BSP_LED_Toggle(LED2);
for(int i = 0; i < Nb_bytes; i++)
{
PRINT_DBG("%c", data_buffer[i]);
}
}
Hope this helps you!
2026-04-07 9:07 AM
Hello @burak_Guzeller ,
You can refer to the SampleApp application within the X-CUBE-WB05N SW package:
\x-cube-wb05n\Projects\NUCLEO-U575ZI\Applications\UART\SampleApp\ for an example of aci_gatt_srv_attribute_modified_event callback usage.
In this context on file Projects\NUCLEO-U575ZI\Applications\UART\SampleApp\STM32WB05N\App\gatt_db.c the following characteristic is defined:
STM32WB_memcpy(&char_uuid.Char_UUID_128, charUuidRX, 16);
ret = aci_gatt_srv_add_char_nwk(sampleServHandle, UUID_TYPE_128, &char_uuid, CHAR_VALUE_LENGTH, CHAR_PROP_WRITE | CHAR_PROP_WRITE_WITHOUT_RESP, ATTR_PERMISSION_NONE, GATT_NOTIFY_ATTRIBUTE_WRITE, 16, 1, &RXCharHandle);
if (ret != BLE_STATUS_SUCCESS) { goto fail ;}
and on file Projects\NUCLEO-U575ZI\Applications\UART\SampleApp\STM32WB05N\App\app_stm32wb05n.c the following callback is triggered with the related user action:
void aci_gatt_srv_attribute_modified_event(uint16_t Connection_Handle,
uint16_t CID,
uint16_t Attr_Handle,
uint16_t Attr_Data_Length,
uint8_t Attr_Data[])
{
Attribute_Modified_CB(Attr_Handle, Attr_Data_Length, Attr_Data);
} /* end aci_gatt_attribute_modified_event() */
where the function Attribute_Modified_CB() for the RXCharHandle characteristic will simply allow to toggle a led within the receiveData() function:
static void Attribute_Modified_CB(uint16_t handle, uint8_t data_length, uint8_t *att_data)
{
if(handle == RXCharHandle + 1)
{
receiveData(att_data, data_length);
}
...
}
static void receiveData(uint8_t* data_buffer, uint8_t Nb_bytes)
{
BSP_LED_Toggle(LED2);
for(int i = 0; i < Nb_bytes; i++)
{
PRINT_DBG("%c", data_buffer[i]);
}
}
Hope this helps you!