I am not new to iOS, but am relatively new to CoreBluetooth and BTLE in general. Using devices running iOS 10 or later ( currently 11.2 ), I have found that if bluetooth is toggled off and on, the bonded peripheral can no longer be accessed.
After doing a bit of debugging, it seems that once bonded, the security information saved on both ends includes the address of each peer. The iOS side remembers the peripheral just fine, but after turning Bluetooth off and on again, the address of the iOS device changes itself, so to the peripheral its currently registered bonded peer (address) no longer exists. For this reason, connection between the two is no longer possible until the bonding information on the peripheral side is cleared ( Peripheral device performs direct advertisement once bonded so that only its bonded peer can see it ).
I would like to know
A) is there anyway to retain the same address on the iOS side after toggling Bluetooth off/on
B) If the address cannot be retained/recalled, what is the usual method for dealing with this sort of situation?
I have searched through the Core Bluetooth Programming reference and have googled this problem to the best of my ability, but to no avail.
Peripheral output via serial connection while bonded with the iOS central:
BTA=001EC0461948 Name=The_Lock1948 Connected=7DD350CC912D,1
Bonded=7DD350CC912D,1 Server Service=00000001 Features=20000000
TxPower=4
iOS Bluetooth off/on, then reconnect with the exact same iOS device:
BTA=001EC0461948 Name=The_Lock1948 Connected=5DDC08C0B0A3,1
Bonded=7DD350CC912D,1 Server Service=00000001 Features=24000000
TxPower=4
As you can see, the "Connected" address has changed while the peripheral remains bonded to the previous address. The only difference between the two is a toggle of the BT setting. When I say BT power off/on, I mean really turn the power off and on, not the "Allow New Connections" setting in iOS 11+.
By the way, just to add to this, I have seen 2 other BTLE peripheral devices ( keyboards ) that cannot reconnect after a iOS BT power toggle until they are reset in some fashion.
Related
I am working on an audio device project with dual-mode Bluetooth. I want to create a seamless connection experience with iOS devices, so I use CTKD with iOS. This gives us the ability to connect both BR/EDR and BLE without leaving our app in the system settings.
It works perfectly if the initial pairing happened inside the app. I got both BR/EDR and BLE connected and working and only one device shows on the Bluetooth page.
But if I pair the Bluetooth(BR/EDR) first in the system settings and then go to the app to pair BLE. The app initiated a new CTKD process, which creates a new BLE connection beside the BR/EDR connection.
My question is if I pair BR/EDR first in the Bluetooth settings, is there a way that I can only pair BLE and didn't trigger the CTKD while keeping the one device displayed on the Bluetooth settings page? Or anything else that can get the same result?
Our IOS application communicates with some device (Intel NUC) over BLE, writing to some characteristics. We use encrypted characteristics which enforce system pairing at the moment we write to characteristic for the first time.
Another piece of software on the same device is using classic BT to synchronize contacts (Phone Book Access Profile) and stream music from iPhone to Intel NUC. This also requires system pairing (separate from the one needed for BLE connection).
Once devices are paired both for BLE and classic BT profiles (two separate pairing processes) everything works fine. The problem arise when we disconnect from the peripheral either manually from system BT settings, or, event worse, by going with the iPhone out of range of NUC device. The devices stays disconnected in BT settings, event if we are back so that both devices are in range. It should not be a problem as we are paired for BLE communication so we should be able to connect with device that is currently disconnected but in range. However, when trying to connect over BLE then we get the error:
Domain=CBATTErrorDomain Code=14 "Peer removed pairing information" UserInfo={NSLocalizedDescription=Peer removed pairing information}
We connect to the device returned from CBCentralManager.retrievePeripherals(:withIdentifiers) method
Once we manually connect in system BT settings everything stars working again.
We tried using
CBConnectPeripheralOptionEnableTransportBridgingKey flag passed to CBCentralManager.connect() method, but it's getting even worse. There are problems in system pairing for classic BT profiles and even if we manage to do it somehow, connecting over BLE time outs.
Any idea what might be the reason of the problem?
In your case,Peripheral device is removing pairing information(By User or from BLE). It may be related to Peripheral device firmware. This error "Domain=CBATTErrorDomain Code=14 "Peer removed pairing information" UserInfo={NSLocalizedDescription=Peer removed pairing information}" is not available in iOS(<13). In iOS (13+), you can handle or show an alert message to users regarding pairing information removed. So, At least users can get some idea, why Peripheral Device is not able to established bonding with central.
Example: Peer removed Pairing information. Open Bluetooth settings and forget the device before reconnecting etc. Otherwise users will confused.
I am trying to discover a bluetooth device and connect to it through the use of CBCentralManager. The device is a headset. It can be discovered through bluetooth scan on the phone. The device name is "A1-25". When I connect "A1-25" directly from phone bluetooth settings, I can play songs with it, it's working fine.
However, when I started scanning peripherals using CBCentralManager. I can't see a peripheral named "A1-25". But rather, I saw a peripheral named "EQ_Test_llyan". But before, when I scan nearby devices from the bluetooth settings, "EQ_Test_llyan" did not come out.
2017-12-13 16:35:07.233021+0800 Test[1405:500801] started scanning
2017-12-13 16:35:17.469375+0800 Test[1405:500801] discovered peripheral with name EQ_Test_llyan advertisementData:{
kCBAdvDataIsConnectable = 1;
kCBAdvDataLocalName = "EQ_Test_llyan";
kCBAdvDataManufacturerData = <b0024551 5f544553 54>;
}
2017-12-13 16:35:17.470672+0800 Test[1405:500801] connecting with device!!!!!!!
2017-12-13 16:35:17.654884+0800 Test[1405:500801] connected to peripheral name:EQ_Test_llyan id:7326E741-BF68-D9E8-D7A6-5F27227685A7
2017-12-13 16:35:17.656526+0800 Test[1405:500801] discovering services for peripheral name:EQ_Test_llyan
2017-12-13 16:35:18.193311+0800 Test[1405:500801] discovered services:(
) for peripheral name:EQ_Test_llyan
The peripheral "EQ_Test_llyan" has no services (see above log), so I can't communicate with it. Now, when I went back to the bluetooth devices in the phone settings I am now connected to "EQ_Test_llyan", but not to "A1-25". Now, I try to play the music, the sound does not come out from the headset.
When I turned off the headset, I will be disconnected from "EQ_Test_llyan" and "A1-25" will be gone. Therefore I conclude that "EQ_Test_llyan" and "A1-25" comes from the same device.
Take note that I can connect to both at the same time. I will just connect to "EQ_Test_llyan" programmatically, then it will appear on the settings. Then I manually connect to "A1-25" from the phone settings. It will be like what it shows on the picture below. When I play the music, I can still hear sound coming out from headset. So, it's working fine as long as I am connected to "A1-25", but not to "EQ_Test_llyan" alone.
So my questions are:
Is CBPeripheral referring to the actual device? Because if it is,
why can't I scan "A1-25" but I can scan "EQ_Test_llyan"?
Take note that when the phone is connected to "A1-25", it has an "i"
beside it, this means that the connection can be terminated. But
when the phone is connected to "EQ_Test_llyan", there's no "i"
beside it. So, it can't be disconnected unless you turned off the
device. So, what's the difference between the two? Is "AI-25" the
real device, while "EQ_Test_llyan" is just a connection? I don't
understand.
You can not discover "A1-25" from the CBCentralManager because it is a headset as you've mentioned. Headset uses Headset Profile (HSP), which is known as "Bluetooth Classic" profile, while Core Bluetooth is suitable only for Bluetooth Low Energy (BLE, Bluetooth 4.0) General Attribute Profile (GATT). If you examine the CoreBluetooth API, you'll discover it's all about services and characteristics. It has no abstractions for sound-related profiles.
On the other hand, GATT is very general and abstract profile, and can be used by a device of any kind, each time for some very specific data — speed, temperature, heart rate, some device configuration, and virtually any other values. So you can pair to GATT devices only from an app that aware of that exact device. You just have nothing to do with such generic service from your phone settings screen.
I am working with hardware that is in the process of being developed. The board uses a TI CC2541 as the bluetooth chip.
Prior to a test the board is discoverable by two devices and I am able to connect to the board and perform a test where I write and read characteristics (GATT). I perform the test again, everything goes fine until I reconnect to the device and attempt to discover its services. At that point, the board is offline and neither lightblue nor my own app can detect the device. I did a factory reset on one of the iOS devices (iPads) and it is still unable to recognize the board.
Should a factory reset remove all corebluetooth caching that has happened on the device, allowing iOS to re-cache and rediscover the board?
Can this possibly be a corebluetooth problem or a problem with my app?
Your problem seems to be related to the external peripheral. Factory reset will remove any cached data from the iOS device so as long as the peripheral behaves correctly, the rediscovery should happen as planned. This is all I can tell from the info you shared.
This issue seems to be related to hanging / adding characteristics on a peripheral during development.
I have had a similar issue and instead of clearing the cache on the iOS device, I change the Bluetooth address of the peripheral. This allows the discovery to work as expected.
Is is possible to "pair" a Bluetooth BLE device such that they automatically connect when in range? (ie. an iPhone app sets up a connection to the Bluetooth device and from then on, the iPhone automatically reconnects to the device if in range, even if the app hasn't been opened in days and is fully closed).
Once reconnected, the device could either using Event Backgrounding to prompt the user to open the app or otherwise interact with a possibly backgrounded app (as described here).
Anecdotally, I've used Bluetooth keyboards that automatically reconnect to my laptop when back in range. These are not necessarily BLE devices, is this something that's possible in BLE land?
Could this be possible if the iPhone were the server instead of the device? What if this were done using traditional Bluetooth under the MFI program?
There are number of relevant comments here and on the Apple Bluetooth-dev mailing list, but nothing that cleared it up for me. Thank you for your help.
I posted my question on Bluetooth-dev, I'm leaving the response here for posteriority: http://lists.apple.com/archives/bluetooth-dev/2012/Sep/msg00117.html