I am designing an iOS framework to handle multiple BLE devices (all of the same kind). Everything is working very well at the moment, except one thing:
The client wants a list with available devices. But how can I detect when a device, that has been discovered in the past, is not available anymore?
Another problem occurs, when I try to connect to a device that is not available anymore. Documentation says: Connection attempts never time out and
And yes, I never get an error via didFailToConnectPeripheral.
I did some research but couldn't figure out how handle these problems via CoreBluetooth properly. So I developed my own solutions, but I am not sure if that is the right way (or at least a good way, cause there may be several ways to do it).
1. Detecting devices that are not available anymore
I scan with
[_centralManager scanForPeripheralsWithServices:services options:@{CBCentralManagerScanOptionAllowDuplicatesKey: @(TRUE)}];
so I receive advertisments all the time as long as a device is not connected. I check with a timer that the advertisement reoccured in a given time interval (large enough corresponding to the devices ad interval). If the advertisement didn't occur in the interval, I remove the device from the list.
2. Detecting connection timeout Well, that's a pretty easy one I think. I use my own timeout function and cancel the connection request if the timer expires.
If somebody ever came across these problem, I would be very interested in your opinion and/or your solution of course.
UPDATE 2014-12-17:
In the meantime I worked on my own solution using timers and it seems to work pretty well.
Connection timeout is straight forward. Simply set a timer to 5 seconds or whatever you think is good for you. If the timer expires and the device did not connect, simply cancel the connection and tell the user that there was a problem.
Detecting devices that go out of range was a bit trickier. For every discovered device I start a timer that fires after double the time, the device sends advertisements. If the device does send another advertisement till the timer expires, it probably went out of range or was turned off or connected to another device.
I don't want to answer my own question because I hope that maybe Apple will one day take care of those problems.
The correct way to determine whether a device is available is to store the peripheral identifier
value. Before you attempt to reconnect, call retrievePeripheralsWithIdentifiers
. However, this still does not guarantee that the device will be in range by the time you attempt to connect!
Connection attempts do not time out at the OS level, and this is explicitly documented.
Some apps may need to use the Core Bluetooth framework to perform long-term actions in the background. As an example, imagine you are developing a home security app for an iOS device that communicates with a door lock (equipped with Bluetooth low energy technology). The app and the lock interact to automatically lock the door when the user leaves home and unlock the door when the user returns—all while the app is in the background. When the user leaves home, the iOS device may eventually become out of range of the lock, causing the connection to the lock to be lost. At this point, the app can simply call the connectPeripheral:options: method of the CBCentralManager class, and because connection requests do not time out, the iOS device will reconnect when the user returns home.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With