I am having trouble getting peer manager bonding to work, wonder if you can help.
I'm using nRF52840 (on PAN1780 eval boards), SDK 17.0.2, Nordic SES 5.30a
First a summary of my goals. I am trying to establish a 1:1 link between two BLE nodes, just to send 4 bytes of data back an forth on a regular basis (e.g. once a second). The 1:1 "pairing" is set at the factory (though can be re-paired in the field should a node need replacing), and must not allow any other connections at either end (e.g. by bored students). I chose a simple peripheral-central connection, using the NUS (Nordic UART Services) module. I got this working nicely, initially using address filtering for the 1:1 connection. I decided to use peer manager bonding and whitelists at both ends, to provide a reliable 1:1 connection, which I believe is the proper way to do this?
Initially I tried copying code into my app from the heart rate examples ble_app_hrs and ble_app_hrs_c (which use peer manager bonding, and whitelisting at central end), but could not get it to work. See my post https://devzone.nordicsemi.com/f/nordic-q-a/73528/peer-manager-bonding---no-pm-events-when-connecting/303605
I started again with vanilla copies of ble_app_hrs and ble_app_hrs_c. First I added whitelisting to the ble_app_hrs peripheral end, copied from the HID Keyboard Example ble_app_hids_keyboard. Whilst this has some rough edges it is basically working, see these "snap1" project snapshots (peripheral and central)
https://www.dropbox.com/s/1nts5yisttgc80n/snap1-periph-hrs-bonding.zip
https://www.dropbox.com/s/b4x16u0du9htqc1/snap1-central-hrs-bonding.zip
Note these projects have absolute paths to the SDK (Z:\dev\libraries\Nordic\nRF5_SDK_17.0.2_d674dde\), do a search&replace to suit your environment.
I then replaced the HRS/BAS/DIS services with the NUS service, and this broke things, the nodes now connect without any security, no pm events, no bonding or whitelisting.
https://www.dropbox.com/s/ym1t9unbchzju75/snap3-periph-nus-bonding-broken.zip
https://www.dropbox.com/s/c7znuwisu4d94e9/snap3-central-nus-bonding-broken.zip
If bonds are in flash already (e.g. if I run snap1 first, then run snap3 without deleting bonds), then it works OK, but if I delete those bonds then the nodes just connect with no peer manager interaction.
Here are some logs to illustrate the problem (with PM_LOG_LEVEL 4 debug)
Starting with an existing bond entry, periph logs:
<info> app: BLE started <info> app: whitelist_set() peer_cnt 1, MAX_PEERS 8 <info> app: Fast advertising with whitelist. <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Peer rank, action: Update, no change <warning> peer_manager_gcm: The local database has changed, so some subscriptions to notifications and indications could not be restored for conn_handle 0 <warning> peer_manager_handler: Local DB could not be applied: conn_handle: 0, peer_id: 0 <info> app: Connected. <info> peer_manager_handler: Connection secured: role: Peripheral, conn_handle: 0, procedure: Encryption <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Peer rank, action: Update, no change <info> app: GATT ATT MTU, handle 0x0 new MTU 247, data_len 244. <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Local database, action: Update <info> app: SBLE TX (this is where the nodes start tx/rx NUS data) <info> app: SBLE RX
<info> app: BLE started <info> app: Starting scan. <info> app: whitelist_load() peer_cnt 1, MAX_PEERS 8 <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Peer rank, action: Update, no change <info> app: Connected. <info> peer_manager_handler: Connection secured: role: Central, conn_handle: 0, procedure: Encryption <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Peer rank, action: Update, no change <info> app: Data length for connection 0x0 updated to 251. <info> app: GATT ATT MTU on connection 0x0 changed to 247. <info> app: Discovery complete. <info> app: Connected to device with Nordic UART Service. <info> app: SBLE RX <info> app: SBLE TX
There are some warnings (I guess because the services have changed), but both ends get a "peer_manager_handler: Connection secured"
But starting without any bond entries, periph logs:
<info> app: BLE started <info> app: whitelist_set() peer_cnt 0, MAX_PEERS 8 <info> app: Fast advertising. <info> app: Connected. <info> app: GATT ATT MTU, handle 0x0 new MTU 247, data_len 244. <info> app: SBLE TX (this is where the nodes start tx/rx NUS data) <info> app: SBLE RX
Central logs:
<info> app: Starting scan. <info> app: Connected. <info> app: GATT ATT MTU on connection 0x0 changed to 247. <info> app: Data length for connection 0x0 updated to 251. <info> app: Discovery complete. <info> app: Connected to device with Nordic UART Service. <info> app: SBLE RX <info> app: SBLE TX
As you can see, connected without a peep from the peer manager....
I then spotted this thread https://devzone.nordicsemi.com/f/nordic-q-a/43221/how-to-make-pairing-mandatory
and I changed ble_nus_init() read&write_access from SEC_OPEN to SEC_JUST_WORKS - this does at least stop the unbonded TX/RX connections, but the central and periph still don't attempt to bond when they connect the first time (i.e. without whitelisted bonded entries). Nothing from peer manager...
So my main QUESTION - what am I doing wrong here? Why don't the nodes attempt to bond when they connect the first time? How do I enforce ONLY 1:1 bonded connections?
I'm sorry but I clearly don't understand how to do this properly, any pointers welcome.
While on the subject of peer managed bonding, couple of other rough edges I'd appreciate help with;
Firstly, I want a single-entry whitelist (to ensure 1:1 connection), but when pairing I don't want to forget old peer until the new one is fully bonded (just in case the node was accidentally put in pairing mode). To achieve this, I tried using "allow_repairing", see this post, but that has got a bit messy, is there a cleaner way?
https://devzone.nordicsemi.com/f/nordic-q-a/73538/hid-keyboard-example---how-to-create-new-bond-without-deleting-old-bond
Secondly, with the basic ble_app_hrs_c bonding & whitelisting, another unauthorised central could still connect to the peer. I stopped this by adding case PM_EVT_CONN_SEC_FAILED to pm_evt_handler(), which calls sd_ble_gap_disconnect(). This works in snap1, but of course is of no use in snap3 as a connection is made without even calling pm_evt_handler()! Is there a better way to do this? I guess this relates to my main question - how do I enforce ONLY 1:1 bonded connections?
Stepping back, am I taking the right approach? All I want is a secure reliable 1:1 connection to send 4 bytes payload back and forth. I didn't expect it to be this bespoke. Are there any other examples I should be looking at? HRS and HID keyboard seem to be the ones most often mentioned in discussions about this.
I would really appreciate some help - I have spent weeks on this, and I am struggling to fully understand how the peer manager interacts with connections. Many thanks