I have a peripheral (nRF51822, S130, using the peer manager) that should be paired/bonded with at most one central. This means that if I want to pair the terminal with central#2, I should somehow delete central#1 to not allow to connect. So, I think I cannot use whitelisting. I tried to use pm_peers_delete on the event PM_EVT_CONN_SEC_START to delete all previously bonded data, but obviously it failed!
Could you please help me to know how to use pm_peer_delete in order to delete all already paired/bonded centrals when I want to pair with a new central?
1. Where do I need to call pm_peer_delete(pm_peer_id_t peer_id);
2. How can I get all peer_id that have already been saved not the new one?
1. As you can see on infocenter, the pm_peer_delete should not be called when you are in a connected, or connectable state, so you either have to call it when you decide to allow another device…
As mentioned, you should not do the peer delete call when you are connected or in a connectable state (scanning or advertising). Therefore, the best time to do this is on the event: BLE_GAP_EVT_DISCONNECTED…
1. As you can see on infocenter, the pm_peer_delete should not be called when you are in a connected, or connectable state, so you either have to call it when you decide to allow another device to connect, or after you have connected and disconnected from the new device.
2. I am not sure exactly what you mean here. Do you want to get the peer ID of every peer except the latest, so that you can delete all other IDs?
In that case I suggest that you look into the functions pm_peer_rank_highest() and pm_peer_ranks_get() for this.
Once you connect to a device that you want to "keep", then call pm_peer_rank_highest() with that peer ID. Then you call pm_peer_ranks_get(), which will give you the peer with the highest and the lowest rank. As long as the peer with the highest rank does not have the same ID as the peer with the lowest rank, call pm_peer_delete() with the ID of the lowest rank. Once the highest rank ID and the lowest rank ID is equal, this means that you only have one peer stored.
Great, thanks Edvin. I exactly followed the steps you mentioned and it worked. However, I think I am not doing this procedure on the right place. I do that on receiving the event PM_EVT_CONN_SEC_SUCCEEDED in pm_evt_handler(pm_evt_t const * p_evt). However, it will be called every time my devices are connected. Although it is also fine, I expect to delete the peers only once I am pairing with a new device. Can you please let me know where is the best place to to the procedure?
As mentioned, you should not do the peer delete call when you are connected or in a connectable state (scanning or advertising). Therefore, the best time to do this is on the event: BLE_GAP_EVT_DISCONNECTED.
Although it doesn't seem intuitive, this is the safest state to call the pm_peer_delete. Even though you do not delete the peer which you are connected to, deleting a peer while connected to another peer may cause some unexpected behavior.
So the procedure should be something like this:
Connected to peer 1.
Decide to change peer. Disconnect.
start scanning (without whitelist)
receive advertising packets from peer 2
connect to peer 2
stay connected for as long as you want.
disconnect from peer 2
delete bonding data from peer 1.
You can of course delete peer 1 at the moment that you disconnect from peer 1. If you do that, you may use the function pm_peers_delete() to delete all the peers. But if you need to use the peer information from peer 1 to make sure that you are actually connected to peer 2, you might want to store the peer 1 data until you are connected to peer 2. Hence, you must wait until you disconnect again to delete the bonding data for peer 1.
To ensure that you only delete the peers when you have connected to a new peer, you can set a flag telling the device to delete bonding data on the next disconnect.
Thanks Edvin, I will follow these steps. Just a question about the flag you mentioned. I still need to know the event generated after a new pairing. So, I can set the flag when a new peer is paired and will delete other peers upon disconnection. This helps not to erase upon every disconnection.
I gave this some thoughts, and I think that you might as well check pm_ranks_get() on every disconnect. If the highest and lowest IDs are the same, then you don't need to delete anything. This will work as your flag.
But I assume that you do something when you decide to connect to a new peripheral (push a button or something, saying that anyone can connect?). When you get this button press, you can set the flag. On the next disconnect, you delete the old peer, and clear the flag.
I suggest that you look at the ble_app_hrs_c example in the SDK. It has some different scanning modes.This example scans for any HRS device on the first startup. After connection, the bonding data is stored in the peer manager.
If you turn off the peripheral, and turn on another DK programmed with the same peripheral example, but advertising with a different address, the central will ignore this device. If you hold button 2, it will temporarily disable the whitelist, allowing the central to connect to any device (with the correct BLE service). Note that this example does not delete any peers, unless you press button 1 then button 2, it will delete all the peers in the whitelist.
This is the action that I thought you could use to set the flag. When you disable the whitelist, you probably want to connect to a new device, and you can assume that you can delete the old peer on the next disconnected event.