...how do Bluetooth speakers with only an On button rebuild a broken pair?
If you want to build a robot with no user interface that connects to a tablet, you build the Pi to enable automatic PIN-less pairing. The only interaction should be the user with the tablet (Android BTW) to tap "OK" to establish the pair. Then our Tablet app opens a Chat channel with our controller's script, and the Tablet drives the robot.
You enable automatic pairing like this (which only a totally irresponsible programmer would put into
hciconfig hci0 up hciconfig hci0 piscan hciconfig hci0 sspmode 1
up sends electricity into the Bluetooth leads;
piscan enables advertisement so the Tablet knows the Controller wants to pair, and
sspmode 1 automatically commits the Controller side of the pair. (The alternatives to
sspmode 1 are either nasty scripts that abuse
bluetoothctl, or installing a mouse, keyboard, & monitor, and clicking on the Pi desktop's "Pair?" requester.)
Per the defaults in
/etc/bluetooth/*.conf, all those advertising settings are now permanent.
With all that, our tablet connects to our Bluetooth client inside the robot. Users just find it in Bluetooth-space by its name.
Then - typically in the field - the Tablet suddenly decides the pair doesn't exist. In the Tablet's Bluetooth settings, the Controller appears in the pairable list. But tapping it raises a requester, but tapping on OK won't re-pair. The device icon on the Tablet says "Couldn't pair. Check settings for this device and try again."
Our only ways to get into the controller are Wi-Fi-SSH or Mouse-Keyboard-Monitor. Both ways are super-expensive in the field, which could be anywhere on planet Earth.
The working theory is that the Tablet dismissed its half of the pair, but the Controller still clings to its half of the pair credentials.
Why don't cheap bluetooth speakers with no user interface have this problem? If the Tablet neglects the pair, why their controller can always get it back?
When I install the Play store app Bluetooth Force Pin Pair by Solvaig JSC, its pair app repeats the same errors but with one additional clue: It decorates the Controller name with "waiting for the supported uuid..."
If I get inside the Pi I can remove the broken pair with:
sudo bluetoothctl remove <macAddress>
Then the next headless pair request works.
But I can't do that in production for any reason if the pair works. So I need to figure out how my script inside the Pi can tell something that Bluetooth can't tell: That a pair (which might not be connected yet) is half-broken.
(the alternative is a reset button on the robot and user training)
For those who don't understand the question, I did the experiment with a Bluetooth speaker:
- pair the tablet with a Bluetooth speaker
- turn the speaker off
- unpair the tablet from the speaker
- turn the speaker on
- pair the tablet successfully with the speaker
The Raspberry Pi controller cannot do this experiment; it refuses the pair attempt because it thinks the tablet is already paired.
bluetoothctlshould provide all the functionality you need. Pairing is a one-time process to exchange keys between two Bluetooth devices. Subsequently those two devices only need to connect using those keys. So what is your Android app doing?