What, exactly, is a BLE connected device on iOS? - 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.

Related

Can a single BLE central connect with multiple BLE peripherals via bluetooth low energy?

I am using core bluetooth framework in my iOS application project. I have following questions regarding bluetooth low energy-
Is it possible for a single central to connect multiple peripherals in iOS?
Can multiple central device connect with a single peripheral?
Can a single iOS device act as central as well as peripheral at the same time?
If yes, then what will happen if both of 2 such devices try to connect as central to each other?
Can we communicate via BLE when the app is in background?
Is it possible for a single central to connect multiple peripherals in iOS?
Yes.
Can multiple central device connect with a single peripheral?
That completely depends on whether the peripheral supports it (but for most common embedded devices, no).
Can a single iOS device act as central as well as peripheral at the same time?
Yes.
If yes, then what will happen if both of 2 such devices try to connect as central to each other?
They'll generally connect twice. In one connection, one will be central and one will be peripheral. In the other connection, the reverse. This is a pretty unusual way to design a system, but it is legal will often work, despite being illegal (see Youssif's comment below for reference).
Can we communicate via BLE when the app is in background?
Yes, within various restrictions.
Yes, it's possible to connect one Central to multiple Peripherals.
Not confirmed.But single Peripheral can connect only with one Central device and multiple Peripherals can connect with one Central.It means that Central can communicate with multiple Peripherals at the same time.
Yes, a single iOS device can work both as Central and Peripheral at the same time.
It communicates one by one.
Yes, we can communicate via BLE in background mode in iOS device.

CoreBluetooth peripheral service becomes empty while reconnecting/restoring

In my iOS app I am able to successfully connect to BLE peripherals, discover service and subscribe to characteristics so that app gets notified whenever there is a change in characteristic value. All these happens with no issues as long as app runs in background.
But issue occurs when state restoration happens. In centralManager:willRestoreState: method, I am able to retrieve previously connected peripherals using the method retrieveConnectedPeripheralsWithServices:. But nothing happens when I call discoverServices: method on the retrieved peripheral. peripheral:didDiscoverServices: method never gets called. The value of retrieved peripheral's services property is also null. Does iOS not cache the services and characteristics ?
Note: Our BLE peripheral advertises service initially. When the app launches for first time, it reads value from peripheral and writes user specific data to a characteristic. Post writing, peripheral stops advertising services. But firmware engineer claims that even though service is stopped by peripheral, peripheral retrieved from state restoration should have the cached service. Is it true ?
Have you checked the connection state of the peripherals that you have retrieved via retrieveConnectedPeripheralsWithServices:? The CoreBluetooth framework has some quirks that you need to be aware of, one being the behaviour of the retrieveConnectedPeripheralsWithServices: method:
When you obtain the peripherals via the aforementioned method they might only be connected on the system level (iOS) but not within your app (see the Discussion section in the API documentation). Therefore, you still have to call connect on the peripherals before you can use them properly. Here is the corresponding part from the API documentation:
The list of connected peripherals can include those that are connected by other apps and that will need to be connected locally using the connectPeripheral:options: method before they can be used.
Regarding the caching of services: iOS caches any discovered service and corresponding characteristic. There are only to ways to force iOS to update the cache:
a BLE power cycle, e.g., turning off and on BLE in the Settings App or restarting your iOS device
send a Services Changed notification via the GAP service from the peripheral side (requires an active connection)
Note: You can also activate log messages from the Bluetooth Stack via the Bluetooth Configuration Profile. They can be quite helpful when debugging BLE related issues especially with custom hardware involved (even though the logs are a bit cumbersome to use).

CoreBluetooth `retrieveConnectedPeripheralsWithServices` returns disconnected peripherals

I wonder about the semantics of CBManager's retrieveConnectedPeripheralsWithServices. Everytime I'm using this I get CBPeripheral instances back with state CBPeripheralStateDisconnected.
It's not a problem to connect again, but isn't this method supposed to return connected peripherals?
Unfortunately, this is intended behaviour. It is a bit counterintuitive I have to admit but the peripheral state is always related to your app. That means if you have connected/paired/bonded the peripheral using another app or via the bluetooth system settings, it will still show as disconnected within your app. If you have connected some peripherals within your app they will show as connected.

Activating an iOS app when Bluetooth connection connects

Is such a thing possible? I know certain apps such as VOIP apps have permission to run constantly, but I'm uncertain my app idea would be allowed to always run.
It depends on what you mean by "Activating an app".
You can operate as a Bluetooth Central in background mode and your app can receive notifications that a Bluetooth Low Energy service has been detected (if you are scanning for that service) or a device has connected (if you have a pending connect for that device).
You can then interact with the peripheral briefly (transfer a small amount of information for example) or display a notification to the user, but you cannot bring your app to the foreground preempting whatever the user is currently doing.
This project demonstrates CoreBluetooth background connection - https://github.com/paulw11/BTBackground

Can iOS do central and peripheral work on same app at same time?

Can iOS (iPhone or iPad) app have Core Bluetooth (BTLE) central manger and peripheral manager objects at same time?
Can they operate asynchronously, or does main app thread need to make them share (switch back and forth).
Sharing conceptual algorithm would be:
disable peripheral manager, enable central manager and do central functions,
and then,
disable central mgr, enable peripheral mgr, and do peripheral functions (that is, send automatic nofications, and wait for and respond to remote characteristic commands),
repeat...
BACKGROUND GORY DETAILS:
We have a local system with multiple iOS devices and multiple non-iOS devices that need to inter-communicate by BTLE.
The non-iOS devices all use Broadcom BCM20732 Bluetooth LE chip.
But hardware is not ready yet, so I'm using iOS devices to emulate the non-iOS, which requires simultaneous central AND peripheral functionality, ie.
1. act as central to periodically interrogate multiple other non-iOS devices in system.
2. act as peripheral to respond to requests for data from iOS user interface devices.
I got it working. I just started with the Apple "BTLE central peripheral transfer", then first delted the -35 db bug that it has (search for "-35" then delete the if(){ return }), then I combined both the central.m and the peripheral.m into a single UIViewController .m file, added a UISwitch to select one of two service UUID's, and modified the peripheral sender to automatically increment the text field (after init'ing it to ASCII '0').
I had two iPad mini's continuously each sending the incrementing number to the other side. It got up to over 900 transfers and then hung. But I've seen the Apple "BTLE c p transfer" always hang after a few minutes, requiring iPad restart to continue. I ended app at both iPad's and cycled power, re-started app, and they got up to 1600 increments, and then hung.
To solve the hang, I'll add resource control to prevent central and peripheral managers from connecting at same time, as per Abo's recommendation.
Yes they can but if your phone is now in peripheral mode and is connected, you have to make sure that it disconnects before switching to central mode and trying to connect with other devices and vice versa.

Resources