IOS BLE - Why can`t I recieve all the data from peripheral? - ios

I`m building an app that receives data from custom BLE device continuously and sometimes the app misses some data? the connection persists(no disconnection occurs) but some data is being missed.
How can that be? does the BLE protocol guarantee that the master will receive all the data?
How can I improve that and make sure that all data will be received?

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.

App communicates using CoreBluetooth in background

I have worked on an app which read heart rate from server kinds of bluetooth low energy HRM(Heart Rate Monitor)by bluetooth notification.
And I have added the "App communicates using CoreBluetooth" into the app's "Background Modes".
It works fine when the app is in foreground, but when the app is in background, one of the Heart Rate Monitors is always to be disconnect with the app in sever minutes.
So I debugged the app and find that, this kind of HRM is always push notification irregularly.The interval between notifications is from 1 second to 20+ second.
I know that when the app is in background, iOS will stop the bluetooth connection if it is too long between bluetooth notifications.
So my question is: Is it possible to keep the connection when the app is in background?
Is reconnection the only way to solve my problem?
Detecting the disconnection and reconnecting to the peripheral will make your app more robust as it will handle the case where the peripheral goes out of range and then returns in addition to the case you are seeing.
When the peripheral is disconnected your centralManager:didDisconnectPeripheral method will be called on your delegate. In this method you can call connectPeripheral:options again to re-establish the connection. iOS will either do this immediately if the device is still in range or automatically later, once the device comes back into range.
Once your centralManager:didConnectPeripheral method is called you can re-establish the characteristic monitoring.
Edit Clarify that you can call connectPeripheral immediately

Prevent other apps from receiving data from the accessory my app is talking to

My iOS app is connected and exchanging sensitive data with a BLE accessory, I want the data communication to be secured so I use an encrypted BLE connection (=paired).
But is there a way for my app to be the only app that can receive the data from the accessory?
I want to make sure it is not possible for another app running in the background to receive the data sent by the accessory.
Core Bluetooth will provide access to any apps that are on the device but if you implement your communication using additional authentication or encryption, then it will be harder for other apps to make successful connections to the peripheral.
I think it helps to think of the peripheral as an ssh server. Anyone can open a connection to it but they will be connected only if the correct credentials are provided to the server. Your peripheral should work similarly. The required method for the authentication depends on your requirements.

IOS: Sending byte data to an embedded device through bluetooth

I am building an app that connects an iOS device to a smartwatch through bluetooth which returns blood pressure, heart rate, etc.
Once I establish a connection with the watch from an iOS device (using the CoreBluetooth Framework), I should be able to complete the handshake with the watch by sending 7 different byte arrays to the watch in succession for which the watch responds back by sending the corresponding byte data.
For example, the first byte array would contain a command to retrieve firmware version of the watch and the watch responds back with its version and so on. The problem is I'm not able to figure out how to send a byte array to the watch once the bluetooth connection is made and by the way, the watch is BLE 4.0 device.
I built the same app in android where once a bluetooth connection was made, a bluetooth socket was registered and I got input stream and output stream from this socket.
By using these, I was able to send and retrieve byte data to and from the watch.
Is there anyway to achieve the same in iOS?
Thanks for any help in advance!

Transmitting data with CoreBluetooth

I'm developing an iOS app with an accompanying Bluetooth LE peripheral. The one step I don't seem to be able to solve is how to actually transmit the data from my app to the peripheral or vice versa.
What I've built so far is a test app that can connect to my sample Bluetooth peripheral, and read all of its services/characteristics/descriptors. It can toggle notifications for a given characteristic, and write to given characteristics. It is just this last step of "transmit n bytes to the peripheral, and receive m bytes from the peripheral" that I can't seem to figure out.
Looking at the External Accessory Framework (what I would use if Apple would actually give me MFi approval for this project), they give you input and output streams on a given session to communicate with the accessory, but no such object exists for CoreBluetooth.
Is this simply an oversight on Apple's part on the functionality of CoreBluetooth? Or do I simply need to develop my own Bluetooth service profile to handle the inflow/outflow of data to and from the peripheral?
LE is fundamentally designed to work with these GATT based profiles, which are suited for monitoring sensors, not for data streams. While LE does allow for additional L2CAP streams to be opened for custom protocols, Apple's CoreBluetooth doesn't provide access to do so.
You can build a custom profile with private services and characteristics and have it work kind of like SSP; that's the way I'm using my BLE module to get data from some sensors to my app. The module I bought (Microchip's RN-4020) already has a custom profile made specifically for this known as MLDP (Microchip Low-energy Data Profile).
The way I get the data in my iOS app is by subscribing to the private characteristic, thus being notified when the values are updated. So far it has been working great, and the data rate can go up to 20 kbps according to Microchip (I haven't tested its limits, since I don't need much speed). Here's a link to Microchip's product page: http://www.microchip.com/wwwproducts/Devices.aspx?product=RN4020
Good luck!
You can use the bluetooth.org 'Immediate Alert Service' uuid=1802 with characteristic uuid=2A06 with property=write_no_response to send one byte values to your peripheral device from your iPhone. The peripheral device must be programmed to act on the data that is sent. For example, you might use a button on an iPhone app to send a hex address that causes one or more port pins to turn on or off on the peripheral. While this is not using the Alert Service as it was intended, it does provide an easy way to test out data transfer to a peripheral device. The same process could be used to send sequential data bytes similar to a serial data stream. I have not yet tried sending more complex data streams. The write_no_response does not provide any feedback to the app as to whether the data was received by the peripheral.
The IOS TemperatureSensor.xproj is an example of code for reading temperature data from a peripheral. The OSX HealthThermometerClient.xproj has the code needed to decode the somewhat complex thermometer data structure. The IOS TI-BLE-Demo.xproj TIBLECBKeyfob.m has code for reading and writing characteristic values, such as, reading temperature or battery levels from a peripheral device.

Resources