We are developing a device which communicates with our iOS/watchOS apps via Bluetooth LE and has to stream a lot of sensor data for an extended time period (hours). Everything works fine under iOS 15.x, but we've found out that iOS 16 betas (and the RC) changed something in the negotiation process: previously we've used 15 ms Connection Interval, but iOS 16 (and watchOS 8) most of the time negotiates 24 ms, which is too wide for our bandwidth. The long connection interval causes packet loss (9-33%), and after 3 failed retries (3x30 sec) our hardware drops the connection.
I've checked all forums and documentation available but didn't found any indication that something changed. Is there any new parameters we can look into to fix this issue?
EDIT: Changed 30 ms to 24
You've probably set both Interval Min and Interval Max at 15ms. Apple explicitly says that this may caused devices to negotiate to 30ms (see section 41.6 Connection Parameters):
If an accessory requests both an Interval Min and Interval Max of 15 ms, some devices will scale the interval to 30 ms to balance power and performance constraints.
Basically, asking for "as fast as possible, no margin" translates into "yeah, everyone asks for that, how about moderately fast?"
However, you may ask for a faster CI if you include HID:
If Bluetooth Low Energy HID is one of the connected services of an accessory, a connection interval down to 11.25 ms may be accepted by the device.
Though I believe what iOS 16 is doing exactly matches Apple's spec (they always said that 15ms could be negotiated to 30ms), you should still open a Feedback+DTS to discuss the impact on your product and use case. Sometimes these things are by accident, and sometimes they're experiments that get rolled back.
We had the same issue with our product. We used a 7.5-15ms interval that was accepted by iOS15 & below, though it didn't meet the Apple Design Parameters (we thought we could get away with it since it was working). We had to change it to 15-30ms for the issue to be resolved, though now the amount of time it takes to transfer data for Androids has doubled.
As Rob mentions in this thread, it seems that for iOS16.0, Apple decided to strictly follow their guidelines and not allow anything outside those "set" requirements, even though they allowed it in the past. However, it seems that Apple has reverted back to how iOS15 was operating with iOS16.1. (There is no documentation that says this though - just know through testing)
If you need a quick fix right now, if you have users, have them update to iOS16.1. Your device should operate as it should when it used to run on iOS15.
For a long term solution, I would follow Rob's suggestion.
Related
I'm currently developing a react native app in combination with a device. The device and the app communicate via BLE. So far everything works as expected but I'm having issues with the connection stability of the iOS app and the device. What would happen is that the device would connect and I can update some characteristics but it would regularly either disconnect with a CBErrorDomain 7 or the response for a write would timeout. The implementation on the app or device side does not seem to be the problem as Android works stable and the device also disconnects when connecting with the LightBlue app.
I've already updated the BLE connection parameters as suggested here:
https://developer.apple.com/library/archive/qa/qa1931/_index.html.
This has increased the stability but did not resolve the problems completely. I've tried playing around with the values but so far no luck.
The current set of parameters we are using are:
conn_min_interval: 15
conn_max_interval: 15
conn_latency: 0
supervision_timeout: 2000
adv_min_interval: 1285
adv_max_interval: 1285
My question now would be if somebody has an idea what other things I could check or which parameter to tune?
Are you checking the maximumWriteValueLength and making sure your writes are smaller than this? A likely cause of your problems is overwhelming the device and it fails to keep up with sending ACKs. What version of Bluetooth does your device support, and does it implement DLE (Data Length Extension)?
Your conn_min_interval and conn_max_interval are suspicious. Asking for 15ms with no leeway is likely to negotiate to 30ms instead. (See 41.6 Connection Parameters) Is your device comfortable with being re-negotiated to something other than 15ms? Can your device actually keep up with 15ms and no connection latency if it does get that? I'm betting it can't. Try setting your connection interval to 30ms (or even a bit slower), and you might even try setting your connection latency to 1 to make the connection a bit more forgiving (though I'd focus more on slowing the CI than increasing latency; increasing latency would be more of a hack in this case).
All my suspicions are around your peripheral not keeping up with its side of the connection. If you have any synchronous activities in response to the data, you need to make sure that it's not blocking your BLE stack from sending the required responses.
Finally, I've found the answer to my problem. The problem was that the pairing procedure of the BLE server was faulty and thus iOS was unable to have a stable connection. Now that this is fixed the connection is very stable.
I'm still unsure why iOS was able to have any communication at all without the pairing but I hope that this helps some people in the future.
I am looking at speeding up the connection time between my iOS application and the peripheral.
I have looked up Apples Documentation on the subject: https://developer.apple.com/library/content/qa/qa1931/_index.html
Originally (prior to reading the doc above) I had the advertising interval set to 2 seconds to, what I had thought would be, a good compromise between power consumption and connection time. Having read the documentation further I have changed the interval to 1285 ms.
#define ADVERTISING_INTERVAL 2056 ble_obj.setAdvertisingInterval(ADVERTISING_INTERVAL);
The device is always discovered quickly by the app but the problem comes when trying to connect.
However, I have seen no increase in speed in connection time between my application and the peripheral device. Connections between the devices can take anything from 3-4 seconds up to 30+ seconds.
Is there something I am missing? Either on the peripheral or the central side?
Peripheral BT chip is the Nordic Semiconductor NRF51822.
On examining the devices advertisement packet on the Nordic Semiconductor app I can see that the advertisement interval normally varies from 1275 ms to about 1295 ms (as expected? due to the random time added to the advertisement packet)
NOTE
Have also tried with an advertising interval of 152.5 ms and am still not seeing any major improvement in connection speed. I am , obviously, seeing a marked improvement in speed of discovery
What you observe is normal. Don't expect fast connection setup with an advertising interval of more than a second.
Core Bluetooth uses a high duty scan window/interval for the initiation the first seconds. If it doesn't connect then it continues to scan with much more power restrictive parameters.
After spending hours around the web, I cannot find any documentation about the background BLE scanning rules used by IOS.
As it is not possible to set the scan window on IOS, I am looking for the rules defined by Apple when IOS is scanning in background.
Context
I am working on a wearable peripheral which can be disconnected sometimes when it is out of reach with the phone. The goal is to reconnect quickly (less than 5s) when the peripheral is close enough to the phone. The peripheral has battery constraints so I cannot advertise every 20ms forever, so I am looking for a clever way to reconnect my peripheral to the phone.
If I know how the background scanning mode is working, I would be able to define a smart advertising interval in order to save battery.
Use case
If my peripheral advertises every 1285ms, how long does it will take to be discovered by my IOS application in background mode for 10 minutes?
Not sure exactly what your question is.
I suppose you have read Apple's "Bluetooth Accessory Design Guidelines for Apple Products"?
https://developer.apple.com/hardwaredrivers/BluetoothDesignGuidelines.pdf
In it, they state:
3.5 Advertising Interval
The advertising interval of the accessory should be carefully
considered, because it affects the time to discovery and connect
performance. For a battery-powered accessory, its battery resources
should also be considered.
To be discovered by the Apple product, the accessory should first use
the recommended advertising interval of 20 ms for at least 30 seconds.
If it is not discovered within the initial 30 seconds, Apple
recommends using one of the following longer intervals to increase
chances of discovery by the Apple product:
152.5 ms
211.25 ms
318.75 ms
417.5 ms
546.25 ms
760 ms
852.5 ms
1022.5 ms
1285 ms
Note: Longer advertising intervals usually result in longer discovery and connect times.
Upon discovering the BLE device, iOS will notify apps that are looking for it (based on the advertised service UUID), which will then be able to connect to it.
Apple recommend a 100 ms interval for iBeacons.
This (pretty old, from 2012) discussion states that:
the median discovery time when the phone is in standby is about 60
times the advertising interval. The 95-percentile discovery time when
the phone is in standby mode is about 300 times the advertising
interval
This (slightly more recent, but from Dec 2013) answer states that:
While scanning in the foreground will likely immediately discover a
device advertising next to it, discovery in the background can take up
to ~60 times longer.
There's a problem when (average) advertising interval is near to an integer multiple of the scan interval, then chances are that discovery-time can rise infinitely (, i.e. scanner will never see the advertising, as ADV always occurs outside the scan window).
Probably the ADV-interval list from Apple's design guideline shows optimum values, but it does not tell how to determine discovery-times. That's a mess!
I'd even go further and say: If the Smartphone (Apple or any other) manufacturer does not exactly specify the scan parameters (interval, window, and eventually filter settings) for each power mode, then you're lost and cannot correctly estimate discovery performance.
So my question came up looking an the console output of some iOS 7.0.x devices via iPhone Configuration Utility the other day. I was puzzled to see several indications that the WiFi daemon registers WiFi rssi activity out of the blue for no apparent reason (no background apps active / push messages pending and so on). These all appear as coupled records in the console in the form of:
Mar xx xx:xx:xx iDevice wifid[xx] <Notice>: WiFi:[406330748.823677]:
Mar xx xx:xx:xx iDevice wifid[xx] <Notice>: Too frequent(1.822344 secs) rssi event from driver
Mar xx xx:xx:xx iDevice wifid[xx] <Notice>: WiFi:[406330748.895756]:
Mar xx xx:xx:xx iDevice wifid[xx] <Notice>: Too frequent(0.835468 secs) rssi event from driver, ignoring
...and so on. What got me worried is that the lines above are duplicated every second or so and appear to never end.
Now I'm no programmer in any kind of form, but knowing some of the basics of UNIX and all I've managed to conclude that the WiFi daemon takes up substantial CPU time as shown in an top breakdown using the terminal, which in turn would suggest that this may (or not) be a reason I've also been experiencing poor battery life on some of these devices as of late.
Next up I would obviously ask you all if anyone's familiar with the behavior noted above and if so what would be the source of this "noise"..
The Short Answer
At least one app is repeatedly querying WiFi for signal strength, and it's chewing up a lot of battery life.
The Longer Answer
1. What is RSSI
RSSI stands for Received Signal Strength Indication. It is a measure of the power present in a wireless signal. RSSI queries are made each time the wireless driver tries to determine reachability. You can learn more about it here:
http://en.wikipedia.org/wiki/Received_signal_strength_indication
2. Why So Many RSSI Events?
In this case, a WiFi RSSI driver is caused by querying for reachability - basically, trying to find out if a wireless connection is available.
There are numerous cases of poorly-written apps querying for reachability/connectivity every few miliseconds. You can find examples that query too often all over the web. I'll just put up one here:
http://forums.coronalabs.com/topic/33356-check-for-internet-connection/
3. Impact on Battery Life
Apple's documentation is very explicit about radio usage. The more you use the wireless radio in the phone, the shorter the batter life. They go so far as to say:
Minimizing radio usage is especially important when developing an app for an iOS device, because radio usage has an adverse effect on an iOS device’s battery life.
(Source: https://developer.apple.com/library/ios/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/BestPracticesForInteractingWithARemotePeripheralDevice/BestPracticesForInteractingWithARemotePeripheralDevice.html)
4. What You Can Do About It
There are several steps you can take if this is shortening your battery life:
Use the logs to determine which apps are abusing the radio and remove them.
If it is an app you have written, carefully look for any repeated calls to the web, especially reachability or signal strength calls.
If the app is not your app and you must keep it installed, use airplane mode when you can to conserve battery (the LEAST desirable option).
Hope that helps!
I'm effectively copying my reply from jailbreakqa.com in http://www.jailbreakqa.com/questions/256971/too-frequent-rssi-event-from-driver
"Being plagued by other issued alongside the aforementioned rssi thing this time around I semi-restored back to iOS7.1.2 and set up the phone as new with the same AppleID as suggested by theiphoneguy above (keeping a backup of my SMS and photos database). Surely three days in the fresh install already the previous rssi issue seems to be now gone for good and I'm enjoying a rather clean activity console with not many things populating it apart from the usual noise..Only considerable downside to it was that I had to waste a full day bringing the system back to speed with the installed tweaks and settings as I am now on a complete 'fresh' install with no references back to the old backups...
...that and the fact that whatever happens I can't seem to be able to make iCloud tabs work (deleted and reisntalled iCloud, disabled safari within iCloud and restarted it to no avail.). In all this seems to have made my device quite a bit 'snappier', too (probably since my old backups dated back to iOS2 :D )...quite pleased with current status, however quite a bit of hassle, can't really suggest that anyone goes down this path.. :/ "
I know this does NOT qualify as an answer per-se, but may serve as evidence for others having the same issue in the future.
I've encountered a pretty large issue and have been trying to find a solution for 2 months now with no luck. I've submitted it as a bug, ( https://bugzilla.xamarin.com/show_bug.cgi?id=4910 ) but was hoping maybe someone here could shed some light on the cause of the problem, or suggest a work-around.
In a nutshell, to encounter the error:
Create a basic .Net socket connection between two devices
Create and initialize a GameKit.GKSession object on a least one device.
What occurs is the transfer of the data on the .NET socket becomes erratic and too slow to be usable. I've performed many tests across different devices (see link below) and it affects all of them (iPad 3 affected the least). I've tested it between an iPhone and a Windows PC and it still occurs. MonoTouch's GameKit code is somehow affecting the Socket code.
As you can see from the spreadsheet, speed drop from a few milliseconds to send 1 MB to several minutes to forever.
As soon as the GameKit.GKSession is set to null, any backedlogged data on the socket flows freely again and the sockets act normally once more.
Sample Windows and iOS/MonoTouch Apps demonstrating problem: https://dl.dropbox.com/u/8617393/SocketBug/SocketBug.zip
Test results across different devices (PDF Spreadsheet):
https://dl.dropbox.com/u/8617393/SocketBug/SocketBugTestResults.pdf
This issue seems so hard even Apple decided to circumvent it: http://developer.apple.com/library/ios/#qa/qa1753/_index.html#//apple_ref/doc/uid/DTS40011315
The revealing sentence is this: "This change was made to reduce interference with Wi-Fi."
To assist with anyone that comes across this problem, the issue only manifests itself when the GKSession.Available is set to true. This is required for the device to be discoverable, but not to maintain a connection. With this in mind, a temporary work-around can be used where the GKSession.Available is only set to true when required, and set to false as soon as the connection has been made.
In my scenario, I have a socket connection to the server on both devices. I use this connection to send a message from device A to device B, asking it to become discoverable via bluetooth for the next 10 seconds. As soon as the message is sent, device A begins looking for device B and connects as soon as it finds it. Once the connection is established (or 10 seconds elapses without a connection), device B turns off discoverability and the socket behaves as normal.
In my circumstances, this is an acceptable (pending no real fix) workaround to the problem.