CoreBluetooth never calls didDiscoverServices on iPhone5S - ios

Most of the time, the app we are coding works quite well with our BLE peripheral. Often for iPhone 5S users the device gets in a funk and whenever we scan for services, the didDiscoverServices: delegate method is never called. Rebooting the device or deleting all settings (General -> Reset -> Reset all settings) fixes the problem temporarily.
Once the device exhibits this problem, even other apps (eg. LightBlue) are affected; no peripherals are able to discover services until a reboot.
For context, our BLE peripheral does not currently support pairing.
What is causing this problem? Are there any ways to avoid causing the instability? Once it happens, is there a way that the app can recover from it automatically?
Some issues with similar symptoms: App doesn't Discover Services When Reconnecting and Not Scanning for Services in iPad Air
Update: Just FYI, I'm still working on this problem, but something we did caused it to happen way less (therefore it's not really a priority ATM). I don't know what caused the added stability yet.

It's probably an iOS bug
1) Enable bluetooth logging on your device
https://developer.apple.com/bug-reporting/ios/bluetooth/
2) Use a packet sniffer to observe the connection between iOS and BLE peripheral

Related

App doesn't reconnect to a Bluetooth device when it is in the background

I have an app that uses Bluetooth (BLE). All BLE communication works fine. State restoration is also implemented and works well. The app has automatic re-connection implementation: whenever the CBError.peripheralDisconnected error occurs, the app tries to reconnect to the peripheral by calling cbCentralManager.connect(cbPeripheral).
Since iOS 15/16 there is a problem. Let's assume that the app is connected to a specific BLE device. I turn off the device (at this moment the automatic re-connection started) and move the app to the background. After several hours (e.g. over the night) I turn on the BLE device and the connection isn't established. I can see this on my Bluetooth device and in the iOS Bluetooth settings. Only when I open the app again, the connection is established immediately. Nothing happens in between. Only the connect call of the CBCentralManager after the Bluetooth device is turned off. The whole thing works when the app is in the background for 3 - 5 hours. If it is over approx. 5 hours, the connection is no longer established as soon as the app is in the background.
At first I thought that the app or the BLE connection is simply killed by the system after a long time. However, the state restoration for Bluetooth is implemented and works (I tested it).
Does anyone have any idea what this could be? Are there perhaps any new settings for state restoration or Bluetooth background mode since iOS 15/16?
Many thanks in advance.

CoreBluetooth and Wifi interference

I'm really stuck with a problem, thus, needless to say, I need your help.
I'm using CoreBluetooth to communicate between two iDevices, it is the same app, running as a central on one device and as a peripheral on the other device. In some cases the central loses connection to the peripheral with the following error:
Error Domain=CBErrorDomain Code=10 "The connection has failed unexpectedly." UserInfo=0x14ee8fe0 {NSLocalizedDescription=The connection has failed unexpectedly.}
In this particular case, the peripheral was an iPad 4 and the central was an iPad mini.
I tracked down the problem and it turns out, that once I encounter this issue, the problem will persist every time I connect, regardless of restarting the app or even the bluetooth on both sides, HOWEVER, the interesting part is, if I turn off Wifi on the central device, the connection doesn't time out anymore.
Do you have any suggestions, workarounds? Both devices are running iOS 7.1.1
This is a well known issue, and it has a solution that is confirmed to work for the Mac side.
sudo defaults write /Library/Preferences/com.apple.airport.bt.plist bluetoothCoexMgmt Hybrid
After you run this script, the issue will go away and BT connections will remain stable.
And here is the explanation:
Background: after a lot of snooping and head scratching, here's what I found: the issue here seems to be that the system isn't using the same Bluetooth/Airport coexistance mode for BLE as it uses for BT Classic. One tell tale sign: if you have any BT Classic devices connected and active, the bug won't repro (neither for the Classic device nor any connected BLE device). The moment the Classic device disconnects, the bug repros (ie all the BLE connections are also dropped).
Further, I was able to find reference in the symbol table of an airport configd agent to an override setting for the coexistance mode. If you set the mode manually as above to 'hybrid' (the same mode that is usually invoked when a classic device is connected), the bug no longer repros.
All credits go to William Henderson from Knock for this trick.
There were cases when the same effect was perceived on iOS devices as well. This some times happens when the Core Bluetooth connections are not stable. Sometimes this can lead to the WiFi connection being unusable. But it's hard to reproduce, at least I wasn't able to, and your question does not concern it either.

locationManager:rangingBeaconsDidFailForRegion:withError: kCLErrorDomain 16

I have read CLLocationManager kCLErrorDomain Codes? as well as Apple Docs
I check to make sure ranging is available before calling startRangingBeaconsInRegion: and I am also checking if ranging is available while in the locationManager:rangingBeaconsDidFailForRegion:withError: method. Returns true both times.
When I get the set of monitoredRegions, my beacon is in the set (so registering for monitoring is working).
I have read that error 16 can mean ranging is unavailable, bluetooth could be off, location services could be off, airplane mode could be on, I have checked them all and all are available and running (obviously not in airplane mode).
What could be causing the ranging to fail, every time I run the app?
It seems that I started to face this issue after I updated my device to iOS 7.1 (iPhone 5S). rangingBeaconsDidFailForRegion: gets called with error.domain equal to #"kCLErrorDomain" and with error.code as kCLErrorRangingUnavailable (16) (even though Airplane mode is not on and Bluetooth is up and running).
I followed davidgyoung's advice to just boot (I did a hard boot pressing Home + Power until the device shuts down and displays the Apple logo, but also a normal boot works) the device, and now it seems to work correctly.
This appears to be a bug in iOS 7.1 and iOS 7.1.1, see here https://stackoverflow.com/a/22949187/1461050. The only workaround - for now - is to reboot the device.
Apple has now released iOS 7.1.2, which should fix this problem (awaiting for confirmation).
Just to eliminate any possibility that it could be something in your code, try a reference app like my Locate for iBeacon. If it also does not work, you probably have an OS or hardware problem.
To troubleshoot this, first reboot your phone and try again. Then try pairing to a regular Bluetooth device (headphones, Mac, etc). If regular Bluetooth pairing works, it may be a Bluetooth LE issue.
Your iOS device must be either an iPhone 4s+ or an iPad 3+ (needed for BLE).
The problem is closely related to the CoreBluetooth Unknown Error 1309.
In some circumstance, seems that the CoreBluetooth Stack become corrupted and the only solution is to reboot the device.
There're plenty of users that are reporting such behaviour. We've fired a bug to Apple Radar and we're waiting for response.
You can also report the problem to Apple Radar so that they will notice this bug.

Core Bluetooth unable to discover peripheral

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.

Iphone(ios 5.0) Bluetooth Low Energy: can not get data from the device

I got the bluetooth low energy Heart Rate Monitor working using corebluetooth.framework on IOS 5.0. But some times I get the following problems.
1) Sometimes when I start the scan (with scanForPeripheralsWithServices method), It can not discover any BLE(Bluetooth Low Energy) devices until I turn off and turn on the Iphone Bluetooth manually. Occasionaly I had to reboot the phone also if the bluetooth turn off and turn on did not work.
2) Sometimes When I try to connect to the device for which I have stored the UUID previously, I was able to connect to the device, i.e, didConnectPeripheral delegate method was called but It never discovers any services even though I call [peripheral discoverServices:nil] i.e, I am not getting any data from the device in the delegate method didDiscoverServices. For this also I had to reboot the phone.
Try checking the archives here:
http://lists.apple.com/archives/bluetooth-dev
and if you don't find it, send the question there. Many Apple Bluetooth engineers answer questions on that mailing list.
1) It has something to do with the pairing routine on bluetooth low energy and the iPhone. The iPhone changes its ID every interval, I don't know how often, but it does. Have you tried just resetting/rebooting the slave device? This often works for me.
The slave device also has a limited broadcast period, e.g 20-30 seconds.
2) Again, check that you have reset the slave. I don't know if you have built the device your self or bought a heart rate belt, but this is most often the solution.
Oh and by the way, I had an issue where the didDiscoverServices actually jumped over an if-sentence, where I checked for a specific service. This did not fix it self until I rebooted the phone. Really weird behaviour, but I haven't found any other solution to this yet.

Resources