Check if connection is bonded/paired

This is my environment:

  • IDE: VSC
  • SDK: NCS v2.2.0
  • iPhone 14 running iOS 16.6 as Central
  • nRF52-DK as Peripheral

When the Central connects to the Peripheral, I want the Peripheral to check if it has pairing/bonding info stored for that connection, and if so, set a flag.  What's the best was with NCS to check if a connection is a paired/bonded connection?

Best regards,

Mike

  • Hi Mike

    Usually you have a pairing or bonding complete event of some kindwhen a bonding/pairing is done on the peripheral side, so you could just set a flag whenever this event is triggered, as that is the easiest way I can think of going about this.

    Best regards,

    Simon

  • Hi Simon,

    Thanks for your reply :-)

    I've got something working, but not sure if its the most robust approach.

    In my application, the Peripheral goes into Hibernate mode at the end of a connection, so I effectively lose any variables I may have set up when the connection was active.  Plus, I'm not sure how I would associate a flag to each different Central (I can have any number of Centrals connect to my Peripheral) that the Peripheral is bonded to.

    The sequence of events I'm trying to deal with is:

    1. Central connects to Peripheral for first time.  Connection isn't encrypted, but if it tries to write/read to any characteristics it triggers a pairing/bonding request, as they all have ENCRYPT permissions set

    2. Any subsequent connections, the pairing/bonding is remembered for that Central, and it can read/write to characteristics as required.

    I also need the Peripheral to grab the CTS from the Central, which in iOS it can only do if paired/bonded.  That's why I need to check the pairing/bonding status, so I can flag to my "get CTS code" that things are OK to proceed

    The way I am doing it at the moment is, once the connection has been made, I attempt to discover the CTS on the Central.  Once this is completed, I check for:

    if (bt_conn_get_security(cts_c.conn) >= BT_SECURITY_L2) {
    	bonded_to_client = true;
    }

    I'm only doing L2 security on my devices as neither have any input/display functionality.  If bonded_to_client is set to TRUE, I can then run my "get CTS code".

    Not sure if there is a better way to achieve my goal?

    Cheers,

    Mike

  • Hi

    Pairing/bonding information is stored in the flash, so it shouldn't be erased when a device goes into a hibernate/sleep mode after disconnecting unless you specifically call an "erase_bonds()" function upon disconnects. There is also a GATT Bond Management Service that we can use to manage and delete bonds from the peripheral side for example. This sample shows how to use that.

    Best regards,

    Simon

  • Thanks Simon.

    If my reading of the BMS description is correct, then this is a service that allows the Central to request the Peripheral to remove bonding info.

    The scenario I am trying to trap is when the Central (e.g. an iOS device that has previously paired and bonded to the Peripheral) is told to "Forget This Device" when a connection is not active.  Then, at some point in the future, the Central attempts to make a connection - it has no recollection it was ever paired/bonded but the Peripheral still has the pairing/bonding info stored in flash.  What then happens is the connection is refused, and unless the bonding info on the Peripheral is removed, the Central can never connect to that Peripheral again.

    So, I'm trying to come up with a mechanism whereby the Peripheral detects the error situation and removes the bonding/pairing info for that Central only.

    So, I'm not sure the BMS is going to do this.  Or maybe I'm not understanding the BMS fully?

    Best regards,

    Mike

  • Mike Austin (LPI) said:
    So, I'm trying to come up with a mechanism whereby the Peripheral detects the error situation and removes the bonding/pairing info for that Central only.

    I think you can have some logic that you can increment a counter everytime you use bt_conn_get_security to compare the security level with L2 just after connection. Clear this counter when the pairing/bonded callback goes through.

    So when a new connection is made you can do something like this

    if (bt_conn_get_security(cts_c.conn) >= BT_SECURITY_L2) {
    	bonded_to_client = true;
    	
    	// too many attempts to reconnect without a successful bonding/pairing
    	if(++connection.some_counter == some_value)
    	{
    	   delete private keys for this connection;
    	   connection.some_counter=0;
    	}
    }

    Also make sure to reset the counter when bonding goes through. Just an rough idea.

Related