Reputation: 64941
When scanning for BluetoothLE manufacturer advertisements on MacOS, the discovery callbacks are much less frequent than on iOS. For a transmitter advertising at 10 Hz, iOS gets nearly 10 discovery callbacks per second. On MacOS, it is typical to see 1-3 callbacks per second, but sometimes it can be many seconds between callbacks -- a few times I measured over 90 seconds between detections! Below is a graph I did showing the number of seconds between discoveries over a test run of about two hours.
Why are discovery times so unpredictable on MacOS compared to iOS? Is there any way to callbacks more reliable?
I recorded these data on macOS Sierra 10.12.6 on a MacBook Pro (Retina, 15-inch, Mid 2014) but I have heard colleagues complain of similar unreliability on newer MacBooks.
centralManager = CBCentralManager(delegate: self,
queue: DispatchQueue.global(qos: .default))
centralManager.scanForPeripherals(withServices: nil,
options: [CBCentralManagerScanOptionAllowDuplicatesKey: true])
...
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
let secsSinceDetection = Date().timeIntervalSince(self.lastDetectionTime)
lastDetectionTime = Date()
NSLog("LDT: \(secsSinceDetection))")
}
Upvotes: 2
Views: 817
Reputation: 174
I see the same problem with macOS High Sierra 10.13.3 on a MacBook Pro (15-inch, 2017). Even Apple's Bluetooth Explorer app (part of Hardware IO Tools) shows the same problem.
Some peripherals are affected more than others. Apple TV always seems to show up very quickly while other peripherals are slower or don't show up at all.
See the related question is answered here: CoreBluetooth advertising detection time where apparently CoreBluetooth is not listening continuously and shares an antenna and resources with Wi-Fi and regular Bluetooth. I originally thought that turning off BOTH Wi-Fi AND "Handoff" improved the ability to see advertisements as well as shortening the time to connect. "Handoff" is turned off in Apple - System Preferences - General by unchecking "Allow Handoff between this Mac and your iCloud devices", but this may not be true.
Note that the problem does not show up in iOS, possibly due to better BT and Wi-Fi co-existence support and between Handoff (Airdrop) and regular BLE usage. The issue appears to only be one of the proportion of BLE listening time during scan and connect. Once a connection is established, there does not appear to be as much interference. In part, this is due to the fact that after one connects there are automatic low-level BLE retries and frequency hopping between fixed-in-time connection intervals. During scanning and establishing a connection (both of which rely on seeing advertising packets) one sequentially rotates through the 3 BLE advertising channels on each scanInterval. Technically, the advertising channels do not overlap with Wi-Fi (see http://www.argenox.com/a-ble-advertising-primer/).
[EDITED FOR NEWER INFO] After more extensive testing it appears that the problem with macOS may not be so much interference from Wi-Fi or Handoff, but rather having scanWindow and scanInterval settings that behave more like how iOS works in the background. Since for some peripherals it sometimes takes up to 1.5 minutes to be found, a 30/300 ratio with 1 second advertising and up to 10 ms random shift (so figure 5 ms as an average shift) could take (300-30)/5 = 54 intervals (seconds) to get detected if the peripheral is not following Apple's advertising interval guidelines that are intentionally away from 300 ms multiples and with some bad luck on the random shifts could be somewhat longer, which is roughly what seems to be seen. Unfortunately, I have not found a way to force macOS to use a higher scanWindow/scanInterval ratio similar to iOS foreground.
[SECOND EDIT ADDITIONAL INFO] If one follows Apple's advertising time of 1022.5 ms in the peripheral, then even with iOS background or with macOS 30 ms scanWindow and 300 ms scanInterval, the median time is roughly 5 seconds while the maximum is around 19 seconds so could be somewhat longer with very bad luck of the 0-10 ms random shifts.
Upvotes: 2