This discussion got mixed up with a discussion about what Nordic means by a 'system attribute' (which is still not clear). In any case, in that discussion I was trying to save pairing/bonding information so I could restore it on a reconnect. The pairing keys worked. I grabbed the keys on the pairing complete event, saved them to a file, read them from that file, and gave them to the peer when asked on a reconnect in the BLE_GAP_EVT_SEC_INFO_REQUEST event.
But the CCCD information doesn't work that way. I can't restore the CCCD state using the same approach, because I cannot initialize the CCCD myself from the application (even prior to a connection). Instead I was told I need to get the 'system attributes' by calling this method sd_ble_gatts_sys_attr_get(), save them to a file, and restore them by calling this method sd_ble_gatts_sys_attr_set() when I get a BLE_GATTS_EVT_SYS_ATTR_MISSING event.
Fantastic! Sounds easy enough. However, I never get a BLE_GATTS_EVT_SYS_ATTR_MISSING event. I get this event BLE_GAP_EVT_SEC_INFO_REQUEST to restore the keys, so that works. What is missing?
You will get the BLE_GATTS_EVT_SYS_ATTR_MISSING event if the peer requests a read on any of the system attributes.
In the case where you send indications or notifications before the peer requests such a read, for instance you want to perform a sd_ble_gatts_service_changed(), you need to do the sd_ble_gatts_sys_attr_set() first.
In our SDK, this is done for instance inside service_changed_send_in_evt() in gatt_cache_manager.c (part of Peer Manager), where the function local_db_apply_in_evt() calls gscm_local_db_cache_apply() in gatts_cache_manager.c, which eventually calls sd_ble_gatts_sys_attr_set().
I do make the sd_ble_gatts_sys_attr_set() first and then attempt the service changed indication.
I get invalid handle for values of the handle from 0 to 13 and when I hit 14 I get the BLE _ERROR missing system attributes.
There are two independent issues happening here. First, I am using the pc-ble-driver. I make direct sd_* calls. I acutally find that easier in most cases than trying to figure out what the SDK is doing and porting it to the pc-ble-driver.
In any case
Issue #1:The call to sd_ble_gatts_sys_attr_set() should normally be done on the BLE_GATTS_EVT_SYS_ATTR_MISSING event, which indicates that the attributes are needed, but it can be done at any time after connection so your solution there should be fine.
Issue #2:Upon getting the BLE_ERROR_SYS_ATTRS_MISSING return code you should run sd_ble_gatts_sys_attr_set() first and then retry the operation.
If you are still experiencing issues with this, can you provide the code for reproducing the behavior? Then I can have a look here at might be the issue.
I certainly can provide the code. I will provide the entire VS project. Because I still am getting that error. How do I do that?
I restore the saved CCCDs with a 'set' in the connection event. Then I try and invoke the service changed. I redo the get and set before that call and cycle through tries of the handle since I do not know what the handle is. It turns out to be '13' as I have only one entry in the CCCD table but there is no way to (generically) know what attribute that table belongs to. Since there is only one is has to be the service changed since there are no others.
I do not use that approach because that will not work in all cases. A new API is clearly needed to get the the handle of the service-changed attribute or to get the UUID of the attribute referenced in the CCCD table. Neither exists yet the service changed API requires that handle.