2023-04-03 05:42 AM
Hello,
Not a question but since I searched for this information and could not locate it anywhere, I post it here to maybe help others.
When calling aci_gatt_init(void), it is said that the Service Changed Characteristic is added automatically.
/**
* @brief ACI_GATT_INIT
* Initialize the GATT layer for server and client roles. It adds also the GATT
* service with Service Changed Characteristic.
[...]
The "Service Changed" characteristic is thus always added with the very same handle (which is a requirement for it to be usable), but after that it is basically never mentioned again anywhere in the code or documentation. No info on what this handle is, nor what the payload should be to use it.
So here is how to use it from the Server side (to say that things changed), for those like me who want to experiment with variable lists of services in their BLE devices.
#define GENERIC_ATTRIBUTE_SERVICE_HANDLE (0x0001)
#define SERVICE_CHANGED_CHARACTERISTIC_HANDLE (0x0002)
tBleStatus ble_indicate_service_changed() {
// In Bluetooth Core Specification v5.3 (Core_v5.3.pdf) [Vol 3, Part G, 7.1] Service Changed
// It is explained that the value to indicate a service change is
// the range of 16bits values of the handles that changed.
// Full range: { 0x0001, 0xFFFF } according to https://www.oreilly.com/library/view/getting-started-with/9781491900550/ch04.html
tBleStatus return_value = BLE_STATUS_FAILED;
uint8_t payload[] = {0x00, 0x01, 0xFF, 0xFF}; // range of Handles to re-discover
return_value = aci_gatt_update_char_value(
GENERIC_ATTRIBUTE_SERVICE_HANDLE,
SERVICE_CHANGED_CHARACTERISTIC_HANDLE,
0, /* charValOffset */
sizeof(payload),
payload);
if (return_value != BLE_STATUS_SUCCESS) {
LOG_ERROR(" ble_indicate_service_changed failed: ret= %#X", return_value);
} else {
LOG_DEBUG(" Success sending: ble_indicate_service_changed");
}
return return_value;
}
(You need to change the logging functions LOG_ERROR and LOG_DEBUG to match your own implementation).
You could use a variable payload (here I only ask for a full update of all services) for more efficient use.
Service Changed is a characteristic with the property INDICATE, which is like NOTIFY (sent to the client whenever written to in the Server) but with the distinction that the Client should acknowledge the indication.
So if the Client received it and acknowledged it, you will get an event back, in pseudo-code from ble_app.c:
SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void *p_Pckt) {
p_event_pckt = (hci_event_pckt*) ((hci_uart_pckt*) p_Pckt)->data;
switch (p_event_pckt->evt) {
case HCI_LE_META_EVT_CODE: {
p_meta_evt = (evt_le_meta_event*) p_event_pckt->data;
case HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE:
p_blecore_evt = (evt_blecore_aci*) p_event_pckt->data;
switch (p_blecore_evt->ecode) {
case ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE:
// event received after Indication is acknowledged by Client, but not sure about the details here though...
Note that this is not the ONLY action that will yield that ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE, there might be a way to be certain (maybe info about what is confirmed by this event in the payload ?) but I did not go that far myself, sorry.
I think this feature should be cleaned up and added to
Limitations:
I verified that it worked with an Android 13 phone using nRFConnect.
I can attest that if the Client does things right (I can't tell you what those things are though, I only crossed my fingers that Android and nRFconnect would know...) then when my device writes to the Service Changed Characteristic, nRFconnect detects the need for re-discovering the services, and triggers a GattServicesDicovery() as expected.
However it did not work as I would have expected in multiple cases.
Hope that can help some.
Cheers
2023-06-12 04:32 AM
As i was exploring the feature myself, your summary was very helpful!
can you tell me if you managed to remove this service /characteristic or know how?