Bluetooth Peripheral detect connected state - ios

I created a function which turns an iPad without gps chip into a bluetooth peripheral and any device (iPhone or iPad) with gps chip into a broadcaster.
These 2 devices then connect with each other without asking to pair (as intended). (see this post for the code I wrote)
However I want to show the connected state in both the peripheral and broadcaster. The broadcaster has a function to check the connection state. The peripheral doesn't seem to have this.
Does anyone know of a way to determine at the peripheral side if the connection is still connected or not.

Related

iOS Detect Bluetooth connection/disconnection

Is it possible to be notified when a Bluetooth Device is connected or disconnected from iOS even when my app is in background ?
On Android, I use the ACTION_ACL_CONNECTED and ACTION_ACL_DISCONNECTED events. But I cannot find equivalents for iOS.
I found the CBCentralManager that can be used to monitor Bluetooth events, but my functions aren't called when a bluetooth device is connected/disconnected, only when I enable/disable the bluetooth. Is it an error on my side or is it normal ?
I also found the doc about Audio Route changes, that can also be an idea to detect the bluetooth connections/disconnections. Just check the kind of new route and detect the connected bluetooth devices at that time.
In the doc, I also found NSNotification types like IOBluetoothHostControllerXXX but nothing is explained about them. Did someone already used them ?
Is there something better or am I missing something ?
You cannot receive notifications about the connection and disconnection of Bluetooth peripherals generally. You can get connection and disconnection events for BLE peripherals that your app connects to.
For example, if your app initiates a connection to a heart rate sensor then you will get a call to your CBCentralManagerDelegate connection function when the connection succeeds. If that device subsequently is switched off or goes out of range then you will get a call to the disconnection delegate method.
If some other app initiates and makes the connection then you will not get a callback.
As you mentioned, you can monitor audio route changes to infer that a Bluetooth audio device has been connected/disconnected, but this will also fire when headphones are plugged in.

Disconnect time for iOS BLE

I've noticed that when you disconnect for a bluetooth device in an application the iOS device will continue to hold that connection for around 10 seconds. I've attempted to get around this by writing to a characteristic that causes the bluetooth module to cancel the connection with the iOS device instead but that isn't working (mostly because I changed the module and the iOS doesn't see the change because I assume the device is cached somewhere). Is there a way to make it disconnect instantly in code? I am using the swift command
manager.cancelPeripheralConnection(peripheral) currently.
Unfortunately, there isn't. The only way to tell the system to disconnect a peripheral is via the cancelPeripheralConnection method that you are already using. Yet, if you call this method it doesn't necessarily mean that the peripheral will be disconnect.
Background
On iOS the whole BLE connection management is maintained by the operating system. That means that no single application "owns" a connection. All BLE functionality is multiplexed to allow more than one application to gain access to centrals and peripherals.
For example, if you have installed a fitness application that tracks data from your heart rate sensor in the background then you can also "connect" to the heart rate sensor in your app but you will be unable to trigger a real disconnect as long as the fitness app maintains a connection.
The disconnect delay you have noticed is basically an optimization of the operating system. If no application holds a connection to the peripheral anymore it will wait for some time (to avoid unnecessary connect/disconnect cycles) and then trigger the disconnect on the bluetooth chip.
Hope that helps.
In iOS when you call the CBCentralManager method cancelPeripheralConnection(CBPeripheral), it does not always immediately terminate the connection. As Apple's documentation states:
Because other apps may still have a connection to the peripheral, canceling
a local connection does not guarantee that the underlying physical link is
immediately disconnected. From the app’s perspective, however, the
peripheral is considered disconnected, and the central manager object calls
the centralManager:didDisconnectPeripheral:error: method of its delegate
object.
If you have a need to immediately terminate a connection programmatically, say to free up the peripheral to be connected from another central device or to reset one's own security layer, then you need to follow the procedure described in the following StackOverflow thread:
iOS 6 - Bluetooth LE disconnect
which is for the app to send your own proprietary command to the peripheral that tells the peripheral to disconnect through normal means (e.g. "GAPRole_TerminateConnection" or "GAP_TerminateLinkReq" or "LL_Disconnect" or "HCI_Disconnect[_*]" with reason HCI_DISCONNECT_REMOTE_USER_TERM). This always works and is not delayed by the connection supervision timeout because it is a formal disconnection notifying the central device (i.e. iOS). The supervision timeout (up to 6 seconds in iOS; on Android the default is 20 seconds) only comes into play if the disconnection is unplanned as with going out of range or if the peripheral does a disconnect without notifying the remote device as with "LL_EXT_DisconnectImmed" (only available in some BLE peripheral implementations).

Auto connect to BLE device in iOS app

I am writing an iOS application which will communicate to a device using Bluetooth Low Energy (BLE).
When my connected device is out of range, my application is getting disconnect event.
But I am not getting any connect event when the device comes back to the range.
Please suggest any approach to detect when the device comes back to the range.
when you get the event that the device is no reachable anymore, you can launch a method which continuously checks if the device is still not reachable.
For example: while(isConnected==false)...
You say that you get a notification if the device disconnects, so you can use that event to launch such a method
When you receive the disconnect event, just restart the scan function:scanForPeripheralsWithServices or you can setup the scan mode to accept duplicate key by [_manager scanForPeripheralsWithServices:self.targetDeviceServiceIDs options:#{CBCentralManagerScanOptionAllowDuplicatesKey:#YES}]. which means the same device would be discovered for many time until you stop scanning.
Just reconnect in your disconnect method if the connection times out. There's no need to start a scan. It will automatically try to reconnect until it gets in range.
When your device get disconnected or goto out of range of Bluetooth then you don't need to scan for Peripheral devices because it already scanned for the BLE devices.
Call function [centralObj connectPeripheral:peripheral options:nil]; into didDisconnectPeripheral delegate method when BLE device disconnected.

iOS CoreBluetooth and preventing other devices to connect to your peripheral

I am creating a core bluetooth application and connecting to a peripheral device, is there a way for the peripheral to reject which centrals may connect to it? What if a random person scanned and found my peripheral devices broadcasted UUID and then broadcasted that UUID and tried to connect to it, how would I prevent this?
No, the iOS peripheral cannot prohibit centrals from connecting to it. However it has some tricks to disable the connection. When a dynamic characteristic is read:
return an error instead of the value of the characteristic,
don't respond to the request. This will cause the connection to stall and then break up after about 30 seconds.
Think of the advertisement as a real advertisement in the media. As many can see it as want. This is the same for iBeacons. You shouldn't rely any security on being hidden. (Wifi SSID broadcasting can be turned off but if your hotspot is not encrypted and authenticated, people with find you.)

What, exactly, is a BLE connected device on iOS?

The CBCentralManager retrieveConnectedPeripherals method says it gets "the list of the peripherals currently connected to the system." The definition of system is a bit ambiguous here.
Does this mean I get a list of peripherals connected to my app, or a list of peripherals connected to any app?
If I can get peripherals connected to another app, does this also mean multiple apps can connect to the same peripheral?
Can this only happen if the app is in the foreground, or do I need to allow for the possibility that a background app is sending commands to a peripheral I think my app owns?
BLE 4.0 enabled devices are usually connected with CBCentralManager unboundly. What is bounded and unbounded connection, you can know from this link.
One BLE 4.0 enabled device can be connected with only one master device thus enhancing secured connectivity. You should follow this link.
Whether in foreground of background, if the connection exists, the BLE slave device won't get connected with another app or device.

Resources